mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 15:04:44 +01:00
Merge bitcoin/bitcoin#27862: validation: Stricter assumeutxo error handling when renaming chainstates
1c7d08b9ac
validation: Stricter assumeutxo error handling in InvalidateCoinsDBOnDisk (Ryan Ofsky)9047337d36
validation: Stricter assumeutxo error handling in LoadChainstate (Ryan Ofsky) Pull request description: There are two places in assumeutxo code where it is calling `AbortNode` to trigger asynchronous shutdowns without returning errors to calling functions. One case, in `LoadChainstate`, happens when snapshot validation succeeds, and there is an error trying to replace the background chainstate with the snapshot chainstate. The other case, in `InvalidateCoinsDBOnDisk`, happens when snapshot validatiion fails, and there is an error trying to remove the snapshot chainstate. In both cases the node is being forced to shut down, so it makes sense for these functions to raise errors so callers can know that an error happened without having to infer it from the shutdown state. Noticed these cases while reviewing #27861, which replaces the `AbortNode` function with a `FatalError` function. ACKs for top commit: achow101: ACK1c7d08b9ac
TheCharlatan: ACK1c7d08b9ac
jamesob: ACK1c7d08b9ac
([`jamesob/ackr/27862.1.ryanofsky.validation_stricter_assu`](https://github.com/jamesob/bitcoin/tree/ackr/27862.1.ryanofsky.validation_stricter_assu)) Tree-SHA512: fb1dcde3fa0e77b4ba0c48507d289552b939c2866781579c8e994edc209abc3cd29cf81c89380057199323a8eec484956abb1fd3a43c957ecd0e7f7bbfd63fd8
This commit is contained in:
commit
6a473373d4
5 changed files with 16 additions and 10 deletions
|
@ -1545,7 +1545,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
}
|
||||
}
|
||||
|
||||
if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB || status == node::ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE) {
|
||||
if (status == node::ChainstateLoadStatus::FAILURE_FATAL || status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB || status == node::ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE) {
|
||||
return InitError(error);
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
|
|||
} else if (snapshot_completion == SnapshotCompletionResult::SUCCESS) {
|
||||
LogPrintf("[snapshot] cleaning up unneeded background chainstate, then reinitializing\n");
|
||||
if (!chainman.ValidatedSnapshotCleanup()) {
|
||||
AbortNode("Background chainstate cleanup failed unexpectedly.");
|
||||
return {ChainstateLoadStatus::FAILURE_FATAL, Untranslated("Background chainstate cleanup failed unexpectedly.")};
|
||||
}
|
||||
|
||||
// Because ValidatedSnapshotCleanup() has torn down chainstates with
|
||||
|
|
|
@ -42,7 +42,8 @@ struct ChainstateLoadOptions {
|
|||
//! and exit cleanly in the interrupted case.
|
||||
enum class ChainstateLoadStatus {
|
||||
SUCCESS,
|
||||
FAILURE,
|
||||
FAILURE, //!< Generic failure which reindexing may fix
|
||||
FAILURE_FATAL, //!< Fatal error which should not prompt to reindex
|
||||
FAILURE_INCOMPATIBLE_DB,
|
||||
FAILURE_INSUFFICIENT_DBCACHE,
|
||||
INTERRUPTED,
|
||||
|
|
|
@ -5412,7 +5412,7 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation(
|
|||
"restart, the node will resume syncing from %d "
|
||||
"without using any snapshot data. "
|
||||
"Please report this incident to %s, including how you obtained the snapshot. "
|
||||
"The invalid snapshot chainstate has been left on disk in case it is "
|
||||
"The invalid snapshot chainstate will be left on disk in case it is "
|
||||
"helpful in diagnosing the issue that caused this error."),
|
||||
PACKAGE_NAME, snapshot_tip_height, snapshot_base_height, snapshot_base_height, PACKAGE_BUGREPORT
|
||||
);
|
||||
|
@ -5425,7 +5425,10 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation(
|
|||
assert(!this->IsUsable(m_snapshot_chainstate.get()));
|
||||
assert(this->IsUsable(m_ibd_chainstate.get()));
|
||||
|
||||
m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
|
||||
auto rename_result = m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
|
||||
if (!rename_result) {
|
||||
user_error = strprintf(Untranslated("%s\n%s"), user_error, util::ErrorString(rename_result));
|
||||
}
|
||||
|
||||
shutdown_fnc(user_error);
|
||||
};
|
||||
|
@ -5627,7 +5630,7 @@ bool IsBIP30Unspendable(const CBlockIndex& block_index)
|
|||
(block_index.nHeight==91812 && block_index.GetBlockHash() == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"));
|
||||
}
|
||||
|
||||
void Chainstate::InvalidateCoinsDBOnDisk()
|
||||
util::Result<void> Chainstate::InvalidateCoinsDBOnDisk()
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
// Should never be called on a non-snapshot chainstate.
|
||||
|
@ -5656,13 +5659,14 @@ void Chainstate::InvalidateCoinsDBOnDisk()
|
|||
|
||||
LogPrintf("%s: error renaming file '%s' -> '%s': %s\n",
|
||||
__func__, src_str, dest_str, e.what());
|
||||
AbortNode(strprintf(
|
||||
return util::Error{strprintf(_(
|
||||
"Rename of '%s' -> '%s' failed. "
|
||||
"You should resolve this by manually moving or deleting the invalid "
|
||||
"snapshot directory %s, otherwise you will encounter the same error again "
|
||||
"on the next startup.",
|
||||
src_str, dest_str, src_str));
|
||||
"on the next startup."),
|
||||
src_str, dest_str, src_str)};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
const CBlockIndex* ChainstateManager::GetSnapshotBaseBlock() const
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <util/check.h>
|
||||
#include <util/fs.h>
|
||||
#include <util/hasher.h>
|
||||
#include <util/result.h>
|
||||
#include <util/translation.h>
|
||||
#include <versionbits.h>
|
||||
|
||||
|
@ -810,7 +811,7 @@ private:
|
|||
* In case of an invalid snapshot, rename the coins leveldb directory so
|
||||
* that it can be examined for issue diagnosis.
|
||||
*/
|
||||
void InvalidateCoinsDBOnDisk() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
[[nodiscard]] util::Result<void> InvalidateCoinsDBOnDisk() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
friend ChainstateManager;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue