-
-
Notifications
You must be signed in to change notification settings - Fork 368
Consensus: Fail closed on Spark batch verification #1863
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
base: master
Are you sure you want to change the base?
Changes from all commits
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 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,15 +20,23 @@ void BatchProofContainer::init() { | |||||||||||||||
| void BatchProofContainer::finalize() { | ||||||||||||||||
| if (fCollectProofs) { | ||||||||||||||||
| sparkTransactions.insert(sparkTransactions.end(), tempSparkTransactions.begin(), tempSparkTransactions.end()); | ||||||||||||||||
| tempSparkTransactions.clear(); | ||||||||||||||||
| } | ||||||||||||||||
| fCollectProofs = false; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| void BatchProofContainer::verify() { | ||||||||||||||||
| if (!fCollectProofs) { | ||||||||||||||||
| batch_spark(); | ||||||||||||||||
| bool BatchProofContainer::verify() { | ||||||||||||||||
| if (fCollectProofs) { | ||||||||||||||||
| fCollectProofs = false; | ||||||||||||||||
| return true; | ||||||||||||||||
| } | ||||||||||||||||
| fCollectProofs = false; | ||||||||||||||||
|
|
||||||||||||||||
| return batch_spark(); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| bool BatchProofContainer::verify_pending() { | ||||||||||||||||
| finalize(); | ||||||||||||||||
| return batch_spark(); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| void BatchProofContainer::add(const spark::SpendTransaction& tx) { | ||||||||||||||||
|
|
@@ -42,12 +50,12 @@ void BatchProofContainer::remove(const spark::SpendTransaction& tx) { | |||||||||||||||
| sparkTransactions.end()); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| void BatchProofContainer::batch_spark() { | ||||||||||||||||
| bool BatchProofContainer::batch_spark() { | ||||||||||||||||
| if (!sparkTransactions.empty()){ | ||||||||||||||||
| LogPrintf("Spark batch verification started.\n"); | ||||||||||||||||
| uiInterface.UpdateProgressBarLabel("Batch verifying Spark Proofs..."); | ||||||||||||||||
| } else { | ||||||||||||||||
| return; | ||||||||||||||||
| return true; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| std::unordered_map<uint64_t, std::vector<spark::Coin>> cover_sets; | ||||||||||||||||
|
|
@@ -75,10 +83,11 @@ void BatchProofContainer::batch_spark() { | |||||||||||||||
|
|
||||||||||||||||
| if (!passed) { | ||||||||||||||||
| LogPrintf("Spark batch verification failed."); | ||||||||||||||||
| throw std::invalid_argument("Spark batch verification failed, please run Firo with -reindex -batching=0"); | ||||||||||||||||
| return false; | ||||||||||||||||
|
Comment on lines
84
to
+86
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. Missing newline in log message. The failure log message on line 85 is missing a trailing 🔧 Suggested fix if (!passed) {
- LogPrintf("Spark batch verification failed.");
+ LogPrintf("Spark batch verification failed.\n");
return false;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (!sparkTransactions.empty()) | ||||||||||||||||
| LogPrintf("Spark batch verification finished successfully.\n"); | ||||||||||||||||
| sparkTransactions.clear(); | ||||||||||||||||
| } | ||||||||||||||||
| return true; | ||||||||||||||||
| } | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2234,6 +2234,17 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std | |
| return state.Error(strMessage); | ||
| } | ||
|
|
||
| bool VerifyPendingSparkBatch(CValidationState& state, const std::string& reason) | ||
| { | ||
| BatchProofContainer* batchProofContainer = BatchProofContainer::get_instance(); | ||
| if (!batchProofContainer->verify_pending()) { | ||
| return AbortNode(state, | ||
| strprintf("Spark batch verification failed before %s", reason), | ||
| _("Spark batch verification failed. Please restart with -reindex -batching=0 to identify the invalid Spark spend.")); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| enum DisconnectResult | ||
| { | ||
| DISCONNECT_OK, // All good. | ||
|
|
@@ -3084,6 +3095,8 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int n | |
| bool fPeriodicFlush = mode == FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000; | ||
| // Combine all conditions that result in a full cache flush. | ||
| bool fDoFullFlush = (mode == FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune; | ||
| if ((fDoFullFlush || fPeriodicWrite) && !VerifyPendingSparkBatch(state, "flushing block index or chainstate")) | ||
|
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.
When this guard is reached from Useful? React with 👍 / 👎. 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.
When pruning is triggered with a pending Spark batch, this guard runs after the pruning branch has already persisted Useful? React with 👍 / 👎. |
||
| return false; | ||
| // Write blocks and block index to disk. | ||
| if (fDoFullFlush || fPeriodicWrite) { | ||
| // Depend on nMinDiskSpace to ensure we can write block index | ||
|
|
@@ -3798,7 +3811,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, | |
| // Do batch verification if we reach 1 day old block, | ||
| BatchProofContainer* batchProofContainer = BatchProofContainer::get_instance(); | ||
| batchProofContainer->fCollectProofs = ((GetSystemTimeInSeconds() - pindexNewTip->GetBlockTime()) > 86400) && GetBoolArg("-batching", true); | ||
| batchProofContainer->verify(); | ||
| if (!batchProofContainer->verify()) { | ||
| return AbortNode(state, | ||
| "Spark batch verification failed", | ||
| _("Spark batch verification failed. Please restart with -reindex -batching=0 to identify the invalid Spark spend.")); | ||
| } | ||
|
Comment on lines
+3814
to
+3818
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. Move the failure check before post-connect side effects escape. Line 3814 verifies the batch only after Based on PR objectives, pending Spark batches must be verified before validation progress is allowed to advance durably. 🤖 Prompt for AI Agents |
||
|
|
||
| // When we reach this point, we switched to a new tip (stored in pindexNewTip). | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
verify_pending()can be called from shutdown or later flush paths afterConnectBlock()has returned early. SinceConnectBlock()only callsbatchProofContainer->finalize()at its successful end (src/validation.cpp:2971), an old block that collected Spark spends and then failed a later validation check leaves those spends intempSparkTransactions; this unconditionalfinalize()promotes proofs from the rejected block into the global pending batch. A subsequent forced verification can then abort the node because of a proof that was never part of an accepted block, so stale temp proofs should be cleared on failed connections or only finalized by the successful connect path.Useful? React with 👍 / 👎.