aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames O'Beirne <james.obeirne@pm.me>2021-08-17 16:23:02 -0400
committerJames O'Beirne <james.obeirne@pm.me>2022-09-13 13:30:25 -0400
commitad67ff377c2b271cb4683da2fb25fd295557f731 (patch)
tree43dfea6b6b3550913d61ace0c7ebb2be8cd4c55c
parent34d159033106cc595cfa852695610bfe419c989c (diff)
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.
-rw-r--r--src/validation.cpp17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index 7e9c6b891e..b94950d1b4 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;
}