Skip to content

Commit 6a47337

Browse files
committed
Merge bitcoin/bitcoin#27862: validation: Stricter assumeutxo error handling when renaming chainstates
1c7d08b validation: Stricter assumeutxo error handling in InvalidateCoinsDBOnDisk (Ryan Ofsky) 9047337 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: ACK 1c7d08b TheCharlatan: ACK 1c7d08b jamesob: ACK 1c7d08b ([`jamesob/ackr/27862.1.ryanofsky.validation_stricter_assu`](https://github.com/jamesob/bitcoin/tree/ackr/27862.1.ryanofsky.validation_stricter_assu)) Tree-SHA512: fb1dcde3fa0e77b4ba0c48507d289552b939c2866781579c8e994edc209abc3cd29cf81c89380057199323a8eec484956abb1fd3a43c957ecd0e7f7bbfd63fd8
2 parents a7261da + 1c7d08b commit 6a47337

File tree

5 files changed

+16
-10
lines changed

5 files changed

+16
-10
lines changed

src/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15451545
}
15461546
}
15471547

1548-
if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB || status == node::ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE) {
1548+
if (status == node::ChainstateLoadStatus::FAILURE_FATAL || status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB || status == node::ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE) {
15491549
return InitError(error);
15501550
}
15511551

src/node/chainstate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
207207
} else if (snapshot_completion == SnapshotCompletionResult::SUCCESS) {
208208
LogPrintf("[snapshot] cleaning up unneeded background chainstate, then reinitializing\n");
209209
if (!chainman.ValidatedSnapshotCleanup()) {
210-
AbortNode("Background chainstate cleanup failed unexpectedly.");
210+
return {ChainstateLoadStatus::FAILURE_FATAL, Untranslated("Background chainstate cleanup failed unexpectedly.")};
211211
}
212212

213213
// Because ValidatedSnapshotCleanup() has torn down chainstates with

src/node/chainstate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ struct ChainstateLoadOptions {
4242
//! and exit cleanly in the interrupted case.
4343
enum class ChainstateLoadStatus {
4444
SUCCESS,
45-
FAILURE,
45+
FAILURE, //!< Generic failure which reindexing may fix
46+
FAILURE_FATAL, //!< Fatal error which should not prompt to reindex
4647
FAILURE_INCOMPATIBLE_DB,
4748
FAILURE_INSUFFICIENT_DBCACHE,
4849
INTERRUPTED,

src/validation.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5412,7 +5412,7 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation(
54125412
"restart, the node will resume syncing from %d "
54135413
"without using any snapshot data. "
54145414
"Please report this incident to %s, including how you obtained the snapshot. "
5415-
"The invalid snapshot chainstate has been left on disk in case it is "
5415+
"The invalid snapshot chainstate will be left on disk in case it is "
54165416
"helpful in diagnosing the issue that caused this error."),
54175417
PACKAGE_NAME, snapshot_tip_height, snapshot_base_height, snapshot_base_height, PACKAGE_BUGREPORT
54185418
);
@@ -5425,7 +5425,10 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation(
54255425
assert(!this->IsUsable(m_snapshot_chainstate.get()));
54265426
assert(this->IsUsable(m_ibd_chainstate.get()));
54275427

5428-
m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
5428+
auto rename_result = m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
5429+
if (!rename_result) {
5430+
user_error = strprintf(Untranslated("%s\n%s"), user_error, util::ErrorString(rename_result));
5431+
}
54295432

54305433
shutdown_fnc(user_error);
54315434
};
@@ -5627,7 +5630,7 @@ bool IsBIP30Unspendable(const CBlockIndex& block_index)
56275630
(block_index.nHeight==91812 && block_index.GetBlockHash() == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"));
56285631
}
56295632

5630-
void Chainstate::InvalidateCoinsDBOnDisk()
5633+
util::Result<void> Chainstate::InvalidateCoinsDBOnDisk()
56315634
{
56325635
AssertLockHeld(::cs_main);
56335636
// Should never be called on a non-snapshot chainstate.
@@ -5656,13 +5659,14 @@ void Chainstate::InvalidateCoinsDBOnDisk()
56565659

56575660
LogPrintf("%s: error renaming file '%s' -> '%s': %s\n",
56585661
__func__, src_str, dest_str, e.what());
5659-
AbortNode(strprintf(
5662+
return util::Error{strprintf(_(
56605663
"Rename of '%s' -> '%s' failed. "
56615664
"You should resolve this by manually moving or deleting the invalid "
56625665
"snapshot directory %s, otherwise you will encounter the same error again "
5663-
"on the next startup.",
5664-
src_str, dest_str, src_str));
5666+
"on the next startup."),
5667+
src_str, dest_str, src_str)};
56655668
}
5669+
return {};
56665670
}
56675671

56685672
const CBlockIndex* ChainstateManager::GetSnapshotBaseBlock() const

src/validation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <util/check.h>
3232
#include <util/fs.h>
3333
#include <util/hasher.h>
34+
#include <util/result.h>
3435
#include <util/translation.h>
3536
#include <versionbits.h>
3637

@@ -810,7 +811,7 @@ class Chainstate
810811
* In case of an invalid snapshot, rename the coins leveldb directory so
811812
* that it can be examined for issue diagnosis.
812813
*/
813-
void InvalidateCoinsDBOnDisk() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
814+
[[nodiscard]] util::Result<void> InvalidateCoinsDBOnDisk() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
814815

815816
friend ChainstateManager;
816817
};

0 commit comments

Comments
 (0)