Skip to content

Commit a4d9f1a

Browse files
committed
Spark: fail closed on deferred batch verification
1 parent 2fade3d commit a4d9f1a

5 files changed

Lines changed: 48 additions & 14 deletions

File tree

src/batchproof_container.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,23 @@ void BatchProofContainer::init() {
2020
void BatchProofContainer::finalize() {
2121
if (fCollectProofs) {
2222
sparkTransactions.insert(sparkTransactions.end(), tempSparkTransactions.begin(), tempSparkTransactions.end());
23+
tempSparkTransactions.clear();
2324
}
2425
fCollectProofs = false;
2526
}
2627

27-
void BatchProofContainer::verify() {
28-
if (!fCollectProofs) {
29-
batch_spark();
28+
bool BatchProofContainer::verify() {
29+
if (fCollectProofs) {
30+
fCollectProofs = false;
31+
return true;
3032
}
31-
fCollectProofs = false;
33+
34+
return batch_spark();
35+
}
36+
37+
bool BatchProofContainer::verify_pending() {
38+
finalize();
39+
return batch_spark();
3240
}
3341

3442
void BatchProofContainer::add(const spark::SpendTransaction& tx) {
@@ -42,12 +50,12 @@ void BatchProofContainer::remove(const spark::SpendTransaction& tx) {
4250
sparkTransactions.end());
4351
}
4452

45-
void BatchProofContainer::batch_spark() {
53+
bool BatchProofContainer::batch_spark() {
4654
if (!sparkTransactions.empty()){
4755
LogPrintf("Spark batch verification started.\n");
4856
uiInterface.UpdateProgressBarLabel("Batch verifying Spark Proofs...");
4957
} else {
50-
return;
58+
return true;
5159
}
5260

5361
std::unordered_map<uint64_t, std::vector<spark::Coin>> cover_sets;
@@ -75,10 +83,11 @@ void BatchProofContainer::batch_spark() {
7583

7684
if (!passed) {
7785
LogPrintf("Spark batch verification failed.");
78-
throw std::invalid_argument("Spark batch verification failed, please run Firo with -reindex -batching=0");
86+
return false;
7987
}
8088

8189
if (!sparkTransactions.empty())
8290
LogPrintf("Spark batch verification finished successfully.\n");
8391
sparkTransactions.clear();
84-
}
92+
return true;
93+
}

src/batchproof_container.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ class BatchProofContainer {
1515

1616
void finalize();
1717

18-
void verify();
18+
bool verify();
19+
bool verify_pending();
1920

2021
void add(const spark::SpendTransaction& tx);
2122
void remove(const spark::SpendTransaction& tx);
22-
void batch_spark();
23+
bool batch_spark();
2324
public:
2425
bool fCollectProofs = 0;
2526

src/init.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
#include "validationinterface.h"
4242
#include "validation.h"
4343
#include "mtpstate.h"
44-
#include "batchproof_container.h"
4544
#include <crypto/progpow/include/ethash/progpow.hpp>
4645
#include "leveldb/env.h"
4746

@@ -264,8 +263,9 @@ void Shutdown()
264263
StopHTTPServer();
265264
llmq::StopLLMQSystem();
266265

267-
BatchProofContainer::get_instance()->finalize();
268-
BatchProofContainer::get_instance()->verify();
266+
CValidationState sparkBatchState;
267+
if (!VerifyPendingSparkBatch(sparkBatchState, "shutdown"))
268+
LogPrintf("Shutdown continuing after Spark batch verification failure: %s\n", FormatStateMessage(sparkBatchState));
269269

270270
#ifdef ENABLE_WALLET
271271
if (pwalletMain)
@@ -761,6 +761,11 @@ void ThreadImport(std::vector <boost::filesystem::path> vImportFiles) {
761761
LoadExternalBlockFile(chainparams, file, &pos);
762762
nFile++;
763763
}
764+
CValidationState state;
765+
if (!VerifyPendingSparkBatch(state, "clearing reindex flag")) {
766+
LogPrintf("Reindexing stopped before clearing reindex flag: %s\n", FormatStateMessage(state));
767+
return;
768+
}
764769
pblocktree->WriteReindexing(false);
765770
fReindex = false;
766771
LogPrintf("Reindexing finished\n");

src/validation.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2234,6 +2234,17 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std
22342234
return state.Error(strMessage);
22352235
}
22362236

2237+
bool VerifyPendingSparkBatch(CValidationState& state, const std::string& reason)
2238+
{
2239+
BatchProofContainer* batchProofContainer = BatchProofContainer::get_instance();
2240+
if (!batchProofContainer->verify_pending()) {
2241+
return AbortNode(state,
2242+
strprintf("Spark batch verification failed before %s", reason),
2243+
_("Spark batch verification failed. Please restart with -reindex -batching=0 to identify the invalid Spark spend."));
2244+
}
2245+
return true;
2246+
}
2247+
22372248
enum DisconnectResult
22382249
{
22392250
DISCONNECT_OK, // All good.
@@ -3084,6 +3095,8 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int n
30843095
bool fPeriodicFlush = mode == FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000;
30853096
// Combine all conditions that result in a full cache flush.
30863097
bool fDoFullFlush = (mode == FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
3098+
if ((fDoFullFlush || fPeriodicWrite) && !VerifyPendingSparkBatch(state, "flushing block index or chainstate"))
3099+
return false;
30873100
// Write blocks and block index to disk.
30883101
if (fDoFullFlush || fPeriodicWrite) {
30893102
// Depend on nMinDiskSpace to ensure we can write block index
@@ -3798,7 +3811,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
37983811
// Do batch verification if we reach 1 day old block,
37993812
BatchProofContainer* batchProofContainer = BatchProofContainer::get_instance();
38003813
batchProofContainer->fCollectProofs = ((GetSystemTimeInSeconds() - pindexNewTip->GetBlockTime()) > 86400) && GetBoolArg("-batching", true);
3801-
batchProofContainer->verify();
3814+
if (!batchProofContainer->verify()) {
3815+
return AbortNode(state,
3816+
"Spark batch verification failed",
3817+
_("Spark batch verification failed. Please restart with -reindex -batching=0 to identify the invalid Spark spend."));
3818+
}
38023819

38033820
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
38043821

src/validation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ bool IsInitialBlockDownload();
303303
bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
304304
/** Find the best known block, and make it the tip of the block chain */
305305
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
306+
/** Verify any pending deferred Spark proof batch before persisting validation state. */
307+
bool VerifyPendingSparkBatch(CValidationState& state, const std::string& reason);
306308
CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params& consensusParams, bool fMTP, bool fShorterBlockDistance);
307309
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, int nTime = 1475020800);
308310
CAmount GetMasternodePayment(int nHeight, int nTime, CAmount blockValue);

0 commit comments

Comments
 (0)