Skip to content

Commit 41a8d2b

Browse files
author
MarcoFalke
committed
Merge #21582: Fix assumeutxo crash due to missing base_blockhash
fa9b74f Fix assumeutxo crash due to missing base_blockhash (MarcoFalke) fa8fffe refactor: Prefer clean assert over UB in coinstats (MarcoFalke) Pull request description: This fixes an UB (which results in a crash with sanitizers enabled). Can be reproduced by cherry-picking the test without the other code changes. The fix: * Adds an `Assert` to transform the UB into a clean crash, even when sanitizers are disabled * Adds an early-fail condition to avoid the crash ACKs for top commit: jamesob: ACK fa9b74f ([`jamesob/ackr/21582.1.MarcoFalke.fix_assumeutxo_crash_due`](https://github.com/jamesob/bitcoin/tree/ackr/21582.1.MarcoFalke.fix_assumeutxo_crash_due)) ryanofsky: Code review ACK fa9b74f with no code changes since last review, just splitting up combocommit a little. Tree-SHA512: dd36808a09f49c647543a9eaa6fdb785b3f1109af48ba4cc983153b22a144da9ca61af22034dcfaa0e192a65b1ee7de744f187555079aff55bec0efa0ce87cd4
2 parents 245a5cd + fa9b74f commit 41a8d2b

File tree

3 files changed

+16
-26
lines changed

3 files changed

+16
-26
lines changed

src/node/coinstats.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats&
9494
{
9595
LOCK(cs_main);
9696
assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman));
97-
stats.nHeight = blockman.LookupBlockIndex(stats.hashBlock)->nHeight;
97+
const CBlockIndex* block = blockman.LookupBlockIndex(stats.hashBlock);
98+
stats.nHeight = Assert(block)->nHeight;
9899
}
99100

100101
PrepareHash(hash_obj, stats);

src/test/validation_chainstatemanager_tests.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Determi
259259
// Coins count is smaller than coins in file
260260
metadata.m_coins_count -= 1;
261261
}));
262+
BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
263+
m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
264+
// Wrong hash
265+
metadata.m_base_blockhash = uint256::ONE;
266+
}));
262267

263268
BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root));
264269

src/validation.cpp

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5423,6 +5423,15 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
54235423

54245424
assert(coins_cache.GetBestBlock() == base_blockhash);
54255425

5426+
CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash));
5427+
5428+
if (!snapshot_start_block) {
5429+
// Needed for GetUTXOStats to determine the height
5430+
LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n",
5431+
base_blockhash.ToString());
5432+
return false;
5433+
}
5434+
54265435
CCoinsStats stats;
54275436
auto breakpoint_fnc = [] { /* TODO insert breakpoint here? */ };
54285437

@@ -5435,31 +5444,6 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
54355444
return false;
54365445
}
54375446

5438-
// Ensure that the base blockhash appears in the known chain of valid headers. We're willing to
5439-
// wait a bit here because the snapshot may have been loaded on startup, before we've
5440-
// received headers from the network.
5441-
5442-
int max_secs_to_wait_for_headers = 60 * 10;
5443-
CBlockIndex* snapshot_start_block = nullptr;
5444-
5445-
while (max_secs_to_wait_for_headers > 0) {
5446-
snapshot_start_block = WITH_LOCK(::cs_main,
5447-
return m_blockman.LookupBlockIndex(base_blockhash));
5448-
--max_secs_to_wait_for_headers;
5449-
5450-
if (!snapshot_start_block) {
5451-
std::this_thread::sleep_for(std::chrono::seconds(1));
5452-
} else {
5453-
break;
5454-
}
5455-
}
5456-
5457-
if (snapshot_start_block == nullptr) {
5458-
LogPrintf("[snapshot] timed out waiting for snapshot start blockheader %s\n",
5459-
base_blockhash.ToString());
5460-
return false;
5461-
}
5462-
54635447
// Assert that the deserialized chainstate contents match the expected assumeutxo value.
54645448

54655449
int base_height = snapshot_start_block->nHeight;

0 commit comments

Comments
 (0)