diff options
author | Fabian Jahr <fjahr@protonmail.com> | 2024-06-18 14:24:55 +0200 |
---|---|---|
committer | Fabian Jahr <fjahr@protonmail.com> | 2024-06-19 22:32:33 +0200 |
commit | 80315c011863d69e7785673283e4c9033fbcd5ac (patch) | |
tree | f316c62c3aa2fe1f9ce27c4d4f1e92d7953efe28 /src | |
parent | 9c5cdf07f30f816cd134e2cd2dca9c27ef7067a5 (diff) | |
download | bitcoin-80315c011863d69e7785673283e4c9033fbcd5ac.tar.xz |
refactor: Move early loadtxoutset checks into ActiveSnapshot
Also changes the return type of ActiveSnapshot to allow returning the
error message to the user of the loadtxoutset RPC.
Diffstat (limited to 'src')
-rw-r--r-- | src/rpc/blockchain.cpp | 31 | ||||
-rw-r--r-- | src/test/fuzz/utxo_snapshot.cpp | 2 | ||||
-rw-r--r-- | src/test/util/chainstate.h | 4 | ||||
-rw-r--r-- | src/validation.cpp | 30 | ||||
-rw-r--r-- | src/validation.h | 2 |
5 files changed, 31 insertions, 38 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e785678614..4de636b69f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -62,9 +62,7 @@ using kernel::CoinStatsHashType; using node::BlockManager; using node::NodeContext; using node::SnapshotMetadata; -using util::Join; using util::MakeUnorderedList; -using util::ToString; struct CUpdatedBlock { @@ -2821,34 +2819,15 @@ static RPCHelpMan loadtxoutset() throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Unable to parse metadata: %s", e.what())); } - uint256 base_blockhash = metadata.m_base_blockhash; - int base_blockheight = metadata.m_base_blockheight; - if (!chainman.GetParams().AssumeutxoForBlockhash(base_blockhash).has_value()) { - auto available_heights = chainman.GetParams().GetAvailableSnapshotHeights(); - std::string heights_formatted = Join(available_heights, ", ", [&](const auto& i) { return ToString(i); }); - throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to load UTXO snapshot, " - "assumeutxo block hash in snapshot metadata not recognized (hash: %s, height: %s). The following snapshot heights are available: %s.", - base_blockhash.ToString(), - base_blockheight, - heights_formatted)); - } - CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, - return chainman.m_blockman.LookupBlockIndex(base_blockhash)); - - if (!snapshot_start_block) { - throw JSONRPCError( - RPC_INTERNAL_ERROR, - strprintf("The base block header (%s) must appear in the headers chain. Make sure all headers are syncing, and call this RPC again.", - base_blockhash.ToString())); - } - if (!chainman.ActivateSnapshot(afile, metadata, false)) { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to load UTXO snapshot " + fs::PathToString(path)); + auto activation_result{chainman.ActivateSnapshot(afile, metadata, false)}; + if (!activation_result) { + throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf(_("Unable to load UTXO snapshot: %s\n"), util::ErrorString(activation_result)).original); } UniValue result(UniValue::VOBJ); result.pushKV("coins_loaded", metadata.m_coins_count); - result.pushKV("tip_hash", snapshot_start_block->GetBlockHash().ToString()); - result.pushKV("base_height", snapshot_start_block->nHeight); + result.pushKV("tip_hash", metadata.m_base_blockhash.ToString()); + result.pushKV("base_height", metadata.m_base_blockheight); result.pushKV("path", fs::PathToString(path)); return result; }, diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index 8c9c67a91c..fa608385d9 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -54,7 +54,7 @@ FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) } catch (const std::ios_base::failure&) { return false; } - return chainman.ActivateSnapshot(infile, metadata, /*in_memory=*/true); + return !!chainman.ActivateSnapshot(infile, metadata, /*in_memory=*/true); }}; if (fuzzed_data_provider.ConsumeBool()) { diff --git a/src/test/util/chainstate.h b/src/test/util/chainstate.h index 03b44fc894..a4636365ca 100644 --- a/src/test/util/chainstate.h +++ b/src/test/util/chainstate.h @@ -124,11 +124,11 @@ CreateAndActivateUTXOSnapshot( new_active.m_chain.SetTip(*(tip->pprev)); } - bool res = node.chainman->ActivateSnapshot(auto_infile, metadata, in_memory_chainstate); + auto res = node.chainman->ActivateSnapshot(auto_infile, metadata, in_memory_chainstate); // Restore the old tip. new_active.m_chain.SetTip(*tip); - return res; + return !!res; } diff --git a/src/validation.cpp b/src/validation.cpp index c34d60f137..53db1cb5b1 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -5647,23 +5647,38 @@ Chainstate& ChainstateManager::InitializeChainstate(CTxMemPool* mempool) return destroyed && !fs::exists(db_path); } -bool ChainstateManager::ActivateSnapshot( +util::Result<void> ChainstateManager::ActivateSnapshot( AutoFile& coins_file, const SnapshotMetadata& metadata, bool in_memory) { uint256 base_blockhash = metadata.m_base_blockhash; + int base_blockheight = metadata.m_base_blockheight; if (this->SnapshotBlockhash()) { - LogPrintf("[snapshot] can't activate a snapshot-based chainstate more than once\n"); - return false; + return util::Error{_("Can't activate a snapshot-based chainstate more than once")}; } { LOCK(::cs_main); + + if (!GetParams().AssumeutxoForBlockhash(base_blockhash).has_value()) { + auto available_heights = GetParams().GetAvailableSnapshotHeights(); + std::string heights_formatted = util::Join(available_heights, ", ", [&](const auto& i) { return util::ToString(i); }); + return util::Error{strprintf(_("assumeutxo block hash in snapshot metadata not recognized (hash: %s, height: %s). The following snapshot heights are available: %s."), + base_blockhash.ToString(), + base_blockheight, + heights_formatted)}; + } + + CBlockIndex* snapshot_start_block = m_blockman.LookupBlockIndex(base_blockhash); + if (!snapshot_start_block) { + return util::Error{strprintf(_("The base block header (%s) must appear in the headers chain. Make sure all headers are syncing, and call loadtxoutset again."), + base_blockhash.ToString())}; + } + if (Assert(m_active_chainstate->GetMempool())->size() > 0) { - LogPrintf("[snapshot] can't activate a snapshot when mempool not empty\n"); - return false; + return util::Error{_("Can't activate a snapshot when mempool not empty.")}; } } @@ -5713,7 +5728,6 @@ bool ChainstateManager::ActivateSnapshot( } auto cleanup_bad_snapshot = [&](const char* reason) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { - LogPrintf("[snapshot] activation failed - %s\n", reason); this->MaybeRebalanceCaches(); // PopulateAndValidateSnapshot can return (in error) before the leveldb datadir @@ -5729,7 +5743,7 @@ bool ChainstateManager::ActivateSnapshot( "Manually remove it before restarting.\n"), fs::PathToString(*snapshot_datadir))); } } - return false; + return util::Error{_(reason)}; }; if (!this->PopulateAndValidateSnapshot(*snapshot_chainstate, coins_file, metadata)) { @@ -5772,7 +5786,7 @@ bool ChainstateManager::ActivateSnapshot( m_snapshot_chainstate->CoinsTip().DynamicMemoryUsage() / (1000 * 1000)); this->MaybeRebalanceCaches(); - return true; + return {}; } static void FlushSnapshotToDisk(CCoinsViewCache& coins_cache, bool snapshot_loaded) diff --git a/src/validation.h b/src/validation.h index ab7891539a..2f5f2e2b95 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1054,7 +1054,7 @@ public: //! faking nTx* block index data along the way. //! - Move the new chainstate to `m_snapshot_chainstate` and make it our //! ChainstateActive(). - [[nodiscard]] bool ActivateSnapshot( + [[nodiscard]] util::Result<void> ActivateSnapshot( AutoFile& coins_file, const node::SnapshotMetadata& metadata, bool in_memory); //! Once the background validation chainstate has reached the height which |