Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 6,221 Lines • ▼ Show 20 Lines | auto handle_invalid_snapshot = [&]() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { | ||||
_("%s failed to validate the -assumeutxo snapshot state. " | _("%s failed to validate the -assumeutxo snapshot state. " | ||||
"This indicates a hardware problem, or a bug in the software, or " | "This indicates a hardware problem, or a bug in the software, or " | ||||
"a bad software modification that allowed an invalid snapshot to " | "a bad software modification that allowed an invalid snapshot to " | ||||
"be loaded. As a result of this, the node will shut down and " | "be loaded. As a result of this, the node will shut down and " | ||||
"stop using any state that was built on the snapshot, resetting " | "stop using any state that was built on the snapshot, resetting " | ||||
"the chain height from %d to %d. On the next restart, the node " | "the chain height from %d to %d. On the next restart, the node " | ||||
"will resume syncing from %d without using any snapshot data. " | "will resume syncing from %d without using any snapshot data. " | ||||
"Please report this incident to %s, including how you obtained " | "Please report this incident to %s, including how you obtained " | ||||
"the snapshot. The invalid snapshot chainstate has been left on " | "the snapshot. The invalid snapshot chainstate will be left on " | ||||
"disk in case it is helpful in diagnosing the issue that caused " | "disk in case it is helpful in diagnosing the issue that caused " | ||||
"this error."), | "this error."), | ||||
PACKAGE_NAME, snapshot_tip_height, snapshot_base_height, | PACKAGE_NAME, snapshot_tip_height, snapshot_base_height, | ||||
snapshot_base_height, PACKAGE_BUGREPORT); | snapshot_base_height, PACKAGE_BUGREPORT); | ||||
LogPrintf("[snapshot] !!! %s\n", user_error.original); | LogPrintf("[snapshot] !!! %s\n", user_error.original); | ||||
LogPrintf("[snapshot] deleting snapshot, reverting to validated chain, " | LogPrintf("[snapshot] deleting snapshot, reverting to validated chain, " | ||||
"and stopping node\n"); | "and stopping node\n"); | ||||
m_active_chainstate = m_ibd_chainstate.get(); | m_active_chainstate = m_ibd_chainstate.get(); | ||||
m_snapshot_chainstate->m_disabled = true; | m_snapshot_chainstate->m_disabled = true; | ||||
assert(!this->IsUsable(m_snapshot_chainstate.get())); | assert(!this->IsUsable(m_snapshot_chainstate.get())); | ||||
assert(this->IsUsable(m_ibd_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); | shutdown_fnc(user_error); | ||||
}; | }; | ||||
if (index_new.GetBlockHash() != snapshot_blockhash) { | if (index_new.GetBlockHash() != snapshot_blockhash) { | ||||
LogPrintf( | LogPrintf( | ||||
"[snapshot] supposed base block %s does not match the " | "[snapshot] supposed base block %s does not match the " | ||||
"snapshot base block %s (height %d). Snapshot is not valid.\n", | "snapshot base block %s (height %d). Snapshot is not valid.\n", | ||||
▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | ChainstateManager::ActivateExistingSnapshot(CTxMemPool *mempool, | ||||
m_snapshot_chainstate = std::make_unique<Chainstate>(mempool, m_blockman, | m_snapshot_chainstate = std::make_unique<Chainstate>(mempool, m_blockman, | ||||
*this, base_blockhash); | *this, base_blockhash); | ||||
LogPrintf("[snapshot] switching active chainstate to %s\n", | LogPrintf("[snapshot] switching active chainstate to %s\n", | ||||
m_snapshot_chainstate->ToString()); | m_snapshot_chainstate->ToString()); | ||||
m_active_chainstate = m_snapshot_chainstate.get(); | m_active_chainstate = m_snapshot_chainstate.get(); | ||||
return *m_snapshot_chainstate; | return *m_snapshot_chainstate; | ||||
} | } | ||||
void Chainstate::InvalidateCoinsDBOnDisk() { | util::Result<void> Chainstate::InvalidateCoinsDBOnDisk() { | ||||
AssertLockHeld(::cs_main); | AssertLockHeld(::cs_main); | ||||
// Should never be called on a non-snapshot chainstate. | // Should never be called on a non-snapshot chainstate. | ||||
assert(m_from_snapshot_blockhash); | assert(m_from_snapshot_blockhash); | ||||
auto storage_path_maybe = this->CoinsDB().StoragePath(); | auto storage_path_maybe = this->CoinsDB().StoragePath(); | ||||
// Should never be called with a non-existent storage path. | // Should never be called with a non-existent storage path. | ||||
assert(storage_path_maybe); | assert(storage_path_maybe); | ||||
fs::path snapshot_datadir = *storage_path_maybe; | fs::path snapshot_datadir = *storage_path_maybe; | ||||
Show All 12 Lines | util::Result<void> Chainstate::InvalidateCoinsDBOnDisk() { | ||||
try { | try { | ||||
fs::rename(snapshot_datadir, invalid_path); | fs::rename(snapshot_datadir, invalid_path); | ||||
} catch (const fs::filesystem_error &e) { | } catch (const fs::filesystem_error &e) { | ||||
auto src_str = fs::PathToString(snapshot_datadir); | auto src_str = fs::PathToString(snapshot_datadir); | ||||
auto dest_str = fs::PathToString(invalid_path); | auto dest_str = fs::PathToString(invalid_path); | ||||
LogPrintf("%s: error renaming file '%s' -> '%s': %s\n", __func__, | LogPrintf("%s: error renaming file '%s' -> '%s': %s\n", __func__, | ||||
src_str, dest_str, e.what()); | src_str, dest_str, e.what()); | ||||
AbortNode(strprintf("Rename of '%s' -> '%s' failed. " | return util::Error{strprintf(_("Rename of '%s' -> '%s' failed. " | ||||
"You should resolve this by manually moving or " | "You should resolve this by manually " | ||||
"deleting the invalid " | "moving or deleting the invalid " | ||||
"snapshot directory %s, otherwise you will " | "snapshot directory %s, otherwise you " | ||||
"encounter the same error again " | "will encounter the same error again " | ||||
"on the next startup.", | "on the next startup."), | ||||
src_str, dest_str, src_str)); | src_str, dest_str, src_str)}; | ||||
} | } | ||||
return {}; | |||||
} | } | ||||
const CBlockIndex *ChainstateManager::GetSnapshotBaseBlock() const { | const CBlockIndex *ChainstateManager::GetSnapshotBaseBlock() const { | ||||
const auto blockhash_op = this->SnapshotBlockhash(); | const auto blockhash_op = this->SnapshotBlockhash(); | ||||
if (!blockhash_op) { | if (!blockhash_op) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return Assert(m_blockman.LookupBlockIndex(*blockhash_op)); | return Assert(m_blockman.LookupBlockIndex(*blockhash_op)); | ||||
▲ Show 20 Lines • Show All 95 Lines • Show Last 20 Lines |