From ad67ff377c2b271cb4683da2fb25fd295557f731 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Tue, 17 Aug 2021 16:23:02 -0400 Subject: [PATCH] validation: remove snapshot datadirs upon validation failure If a UTXO snapshot fails to validate, don't leave the resulting datadir on disk as this will confuse initialization on next startup and we'll get an assertion error. --- src/validation.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index 7e9c6b891ec..b94950d1b4f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4876,7 +4876,22 @@ bool ChainstateManager::ActivateSnapshot( } } if (!snapshot_ok) { - WITH_LOCK(::cs_main, this->MaybeRebalanceCaches()); + LOCK(::cs_main); + this->MaybeRebalanceCaches(); + + // PopulateAndValidateSnapshot can return (in error) before the leveldb datadir + // has been created, so only attempt removal if we got that far. + if (auto snapshot_datadir = node::FindSnapshotChainstateDir()) { + // We have to destruct leveldb::DB in order to release the db lock, otherwise + // DestroyDB() (in DeleteCoinsDBFromDisk()) will fail. See `leveldb::~DBImpl()`. + // Destructing the chainstate (and so resetting the coinsviews object) does this. + snapshot_chainstate.reset(); + bool removed = DeleteCoinsDBFromDisk(*snapshot_datadir, /*is_snapshot=*/true); + if (!removed) { + AbortNode(strprintf("Failed to remove snapshot chainstate dir (%s). " + "Manually remove it before restarting.\n", fs::PathToString(*snapshot_datadir))); + } + } return false; }