diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index bf3a340cb8..2b729e3b7a 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -495,12 +495,19 @@ public: }; m_assumeutxo_data = { - { + { // For use by unit tests .height = 110, .hash_serialized = AssumeutxoHash{uint256S("0x6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1")}, .nChainTx = 111, .blockhash = uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c") }, + { + // For use by fuzz target src/test/fuzz/utxo_snapshot.cpp + .height = 200, + .hash_serialized = AssumeutxoHash{uint256S("0x4f34d431c3e482f6b0d67b64609ece3964dc8d7976d02ac68dd7c9c1421738f2")}, + .nChainTx = 201, + .blockhash = uint256S("0x5e93653318f294fb5aa339d00bbf8cf1c3515488ad99412c37608b139ea63b27"), + }, { // For use by test/functional/feature_assumeutxo.py .height = 299, diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index fa608385d9..522c9c54ee 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -41,13 +41,39 @@ FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) { AutoFile outfile{fsbridge::fopen(snapshot_path, "wb")}; - const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; - outfile << Span{file_data}; + // Metadata + if (fuzzed_data_provider.ConsumeBool()) { + std::vector metadata{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; + outfile << Span{metadata}; + } else { + DataStream data_stream{}; + auto msg_start = chainman.GetParams().MessageStart(); + int base_blockheight{fuzzed_data_provider.ConsumeIntegralInRange(1, 2 * COINBASE_MATURITY)}; + uint256 base_blockhash{g_chain->at(base_blockheight - 1)->GetHash()}; + uint64_t m_coins_count{fuzzed_data_provider.ConsumeIntegralInRange(1, 3 * COINBASE_MATURITY)}; + SnapshotMetadata metadata{msg_start, base_blockhash, base_blockheight, m_coins_count}; + outfile << metadata; + } + // Coins + if (fuzzed_data_provider.ConsumeBool()) { + std::vector file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; + outfile << Span{file_data}; + } else { + int height{0}; + for (const auto& block : *g_chain) { + auto coinbase{block->vtx.at(0)}; + outfile << coinbase->GetHash(); + WriteCompactSize(outfile, 1); // number of coins for the hash + WriteCompactSize(outfile, 0); // index of coin + outfile << Coin(coinbase->vout[0], height, /*fCoinBaseIn=*/1); + height++; + } + } } const auto ActivateFuzzedSnapshot{[&] { AutoFile infile{fsbridge::fopen(snapshot_path, "rb")}; - auto msg_start = Params().MessageStart(); + auto msg_start = chainman.GetParams().MessageStart(); SnapshotMetadata metadata{msg_start}; try { infile >> metadata; @@ -73,16 +99,20 @@ FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) Assert(*chainman.ActiveChainstate().m_from_snapshot_blockhash == *chainman.SnapshotBlockhash()); const auto& coinscache{chainman.ActiveChainstate().CoinsTip()}; - int64_t chain_tx{}; for (const auto& block : *g_chain) { Assert(coinscache.HaveCoin(COutPoint{block->vtx.at(0)->GetHash(), 0})); const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())}; - const auto num_tx{Assert(index)->nTx}; - Assert(num_tx == 1); - chain_tx += num_tx; + Assert(index); + Assert(index->nTx == 0); + if (index->nHeight == chainman.GetSnapshotBaseHeight()) { + auto params{chainman.GetParams().AssumeutxoForHeight(index->nHeight)}; + Assert(params.has_value()); + Assert(params.value().nChainTx == index->nChainTx); + } else { + Assert(index->nChainTx == 0); + } } Assert(g_chain->size() == coinscache.GetCacheSize()); - Assert(chain_tx == chainman.ActiveTip()->nChainTx); } else { Assert(!chainman.SnapshotBlockhash()); Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash); diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py index 9ac8d27e9c..8bbb0b157c 100755 --- a/test/functional/feature_assumeutxo.py +++ b/test/functional/feature_assumeutxo.py @@ -117,7 +117,7 @@ class AssumeutxoTest(BitcoinTestFramework): with open(bad_snapshot_path, 'wb') as f: f.write(valid_snapshot_contents[:11] + bogus_height.to_bytes(4, "little") + bytes.fromhex(bad_block_hash)[::-1] + valid_snapshot_contents[47:]) - msg = f"Unable to load UTXO snapshot: assumeutxo block hash in snapshot metadata not recognized (hash: {bad_block_hash}, height: {bogus_height}). The following snapshot heights are available: 110, 299." + msg = f"Unable to load UTXO snapshot: assumeutxo block hash in snapshot metadata not recognized (hash: {bad_block_hash}, height: {bogus_height}). The following snapshot heights are available: 110, 200, 299." assert_raises_rpc_error(-32603, msg, node.loadtxoutset, bad_snapshot_path) self.log.info(" - snapshot file with wrong number of coins")