-
Notifications
You must be signed in to change notification settings - Fork 535
Algod: state-proof key deletion safety #4601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 21 commits
8742b91
b91d71c
beb794a
0199319
5ad38a1
c8729b5
597008e
dd00c9d
cf10986
c9d553f
0e8a113
9e5ec61
f14b837
65d8b21
21cc86e
48ef64d
6dd5a9e
38b4f3d
d1dbb90
b9fb7a7
cc22234
100c282
c5f89f1
abb58c1
ae5aa9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -366,8 +366,7 @@ func (spw *Worker) builder(latest basics.Round) { | |
| continue | ||
| } | ||
|
|
||
| spw.deleteOldSigs(&hdr) | ||
| spw.deleteOldBuilders(&hdr) | ||
| spw.deleteStaleStateProofBuildData(&hdr) | ||
|
|
||
| // Broadcast signatures based on the previous block(s) that | ||
| // were agreed upon. This ensures that, if we send a signature | ||
|
|
@@ -450,31 +449,59 @@ func (spw *Worker) broadcastSigs(brnd basics.Round, proto config.ConsensusParams | |
| } | ||
| } | ||
|
|
||
| func (spw *Worker) deleteOldSigs(currentHdr *bookkeeping.BlockHeader) { | ||
| oldestRoundToRemove := GetOldestExpectedStateProof(currentHdr) | ||
| func (spw *Worker) deleteStaleStateProofBuildData(currentHdr *bookkeeping.BlockHeader) { | ||
| proto := config.Consensus[currentHdr.CurrentProtocol] | ||
| stateProofNextRound := currentHdr.StateProofTracking[protocol.StateProofBasic].StateProofNextRound | ||
| if proto.StateProofInterval == 0 || stateProofNextRound == 0 { | ||
| return | ||
| } | ||
|
|
||
| if spw.LastCleanupRound == stateProofNextRound { | ||
| return | ||
| } | ||
|
|
||
| spw.deleteStaleSigs(stateProofNextRound) | ||
| spw.deleteStaleKeys(stateProofNextRound) | ||
| spw.deleteStaleBuilders(stateProofNextRound) | ||
| spw.LastCleanupRound = stateProofNextRound | ||
| } | ||
|
|
||
| func (spw *Worker) deleteStaleSigs(latestRoundToKeep basics.Round) { | ||
| err := spw.db.Atomic(func(ctx context.Context, tx *sql.Tx) error { | ||
| return deletePendingSigsBeforeRound(tx, oldestRoundToRemove) | ||
| return deletePendingSigsBeforeRound(tx, latestRoundToKeep) | ||
| }) | ||
| if err != nil { | ||
| spw.log.Warnf("deletePendingSigsBeforeRound(%d): %v", oldestRoundToRemove, err) | ||
| spw.log.Warnf("deletePendingSigsBeforeRound(%d): %v", latestRoundToKeep, err) | ||
| } | ||
| } | ||
|
|
||
| func (spw *Worker) deleteOldBuilders(currentHdr *bookkeeping.BlockHeader) { | ||
| oldestRoundToRemove := GetOldestExpectedStateProof(currentHdr) | ||
| func (spw *Worker) deleteStaleKeys(latestRoundToKeep basics.Round) { | ||
| keys := spw.accts.StateProofKeys(latestRoundToKeep) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't we miss out on purging stale data from accounts that can't sign latestRoundToKeep but still have old keys in their DB? |
||
| for _, key := range keys { | ||
| roundToRemove, err := key.StateProofSecrets.FirstRoundInKeyLifetime() | ||
| if err != nil { | ||
| spw.log.Errorf("deleteOldKeys: could not calculate keylifetime for account %v on round %s: %v", key.ParticipationID, roundToRemove, err) | ||
| continue | ||
| } | ||
| err = spw.accts.DeleteStateProofKey(key.ParticipationID, basics.Round(roundToRemove)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to use roundToRemove? Why not latestRoundToKeep instead?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we delete roundToRemove we might delete a key that should be used for a later state proof. |
||
| if err != nil { | ||
| spw.log.Warnf("deleteOldKeys: could not remove key for account %v on round %s: %v", key.ParticipationID, roundToRemove, err) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func (spw *Worker) deleteStaleBuilders(latestRoundToKeep basics.Round) { | ||
| spw.mu.Lock() | ||
| defer spw.mu.Unlock() | ||
|
|
||
| for rnd := range spw.builders { | ||
| if rnd < oldestRoundToRemove { | ||
| if rnd < latestRoundToKeep { | ||
| delete(spw.builders, rnd) | ||
| } | ||
| } | ||
|
|
||
| err := spw.db.Atomic(func(ctx context.Context, tx *sql.Tx) error { | ||
| return deleteBuilders(tx, oldestRoundToRemove) | ||
| return deleteBuilders(tx, latestRoundToKeep) | ||
| }) | ||
| if err != nil { | ||
| spw.log.Warnf("deleteOldBuilders: failed to delete builders from database: %v", err) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.