mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 11:57:28 -03:00
Merge bitcoin/bitcoin#30329: fuzz: improve utxo_snapshot target
de71d4dece
fuzz: improve utxo_snapshot target (Martin Zumsande) Pull request description: Add the possibility of giving more guidance to the creation of the metadata and/or coins, so that the fuzzer gets the chance to reach more error conditions in ActivateSnapshot and sometimes successfully creates a valid snapshot. This also changes the asserts for the success case that were outdated (after #29370) and only didn't result in a crash because the fuzzer wasn't able to reach this code before. ACKs for top commit: maflcko: re-ACKde71d4dece
🎆 fjahr: utACKde71d4dece
TheCharlatan: ACKde71d4dece
Tree-SHA512: 346974d594164544d8cd3df7d8362c905fd93116215e9f5df308dfdac55bab04d727bfd7fd001cf11318682d11ee329b4b4a43308124c04d64b67840ab8a58a0
This commit is contained in:
commit
5239e935cf
3 changed files with 47 additions and 10 deletions
|
@ -495,12 +495,19 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
m_assumeutxo_data = {
|
m_assumeutxo_data = {
|
||||||
{
|
{ // For use by unit tests
|
||||||
.height = 110,
|
.height = 110,
|
||||||
.hash_serialized = AssumeutxoHash{uint256S("0x6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1")},
|
.hash_serialized = AssumeutxoHash{uint256S("0x6657b736d4fe4db0cbc796789e812d5dba7f5c143764b1b6905612f1830609d1")},
|
||||||
.nChainTx = 111,
|
.nChainTx = 111,
|
||||||
.blockhash = uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c")
|
.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
|
// For use by test/functional/feature_assumeutxo.py
|
||||||
.height = 299,
|
.height = 299,
|
||||||
|
|
|
@ -41,13 +41,39 @@ FUZZ_TARGET(utxo_snapshot, .init = initialize_chain)
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoFile outfile{fsbridge::fopen(snapshot_path, "wb")};
|
AutoFile outfile{fsbridge::fopen(snapshot_path, "wb")};
|
||||||
const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
|
// Metadata
|
||||||
|
if (fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
std::vector<uint8_t> 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<int>(1, 2 * COINBASE_MATURITY)};
|
||||||
|
uint256 base_blockhash{g_chain->at(base_blockheight - 1)->GetHash()};
|
||||||
|
uint64_t m_coins_count{fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(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<uint8_t> file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
|
||||||
outfile << Span{file_data};
|
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{[&] {
|
const auto ActivateFuzzedSnapshot{[&] {
|
||||||
AutoFile infile{fsbridge::fopen(snapshot_path, "rb")};
|
AutoFile infile{fsbridge::fopen(snapshot_path, "rb")};
|
||||||
auto msg_start = Params().MessageStart();
|
auto msg_start = chainman.GetParams().MessageStart();
|
||||||
SnapshotMetadata metadata{msg_start};
|
SnapshotMetadata metadata{msg_start};
|
||||||
try {
|
try {
|
||||||
infile >> metadata;
|
infile >> metadata;
|
||||||
|
@ -73,16 +99,20 @@ FUZZ_TARGET(utxo_snapshot, .init = initialize_chain)
|
||||||
Assert(*chainman.ActiveChainstate().m_from_snapshot_blockhash ==
|
Assert(*chainman.ActiveChainstate().m_from_snapshot_blockhash ==
|
||||||
*chainman.SnapshotBlockhash());
|
*chainman.SnapshotBlockhash());
|
||||||
const auto& coinscache{chainman.ActiveChainstate().CoinsTip()};
|
const auto& coinscache{chainman.ActiveChainstate().CoinsTip()};
|
||||||
int64_t chain_tx{};
|
|
||||||
for (const auto& block : *g_chain) {
|
for (const auto& block : *g_chain) {
|
||||||
Assert(coinscache.HaveCoin(COutPoint{block->vtx.at(0)->GetHash(), 0}));
|
Assert(coinscache.HaveCoin(COutPoint{block->vtx.at(0)->GetHash(), 0}));
|
||||||
const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())};
|
const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())};
|
||||||
const auto num_tx{Assert(index)->nTx};
|
Assert(index);
|
||||||
Assert(num_tx == 1);
|
Assert(index->nTx == 0);
|
||||||
chain_tx += num_tx;
|
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(g_chain->size() == coinscache.GetCacheSize());
|
||||||
Assert(chain_tx == chainman.ActiveTip()->nChainTx);
|
|
||||||
} else {
|
} else {
|
||||||
Assert(!chainman.SnapshotBlockhash());
|
Assert(!chainman.SnapshotBlockhash());
|
||||||
Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
|
Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
|
||||||
|
|
|
@ -117,7 +117,7 @@ class AssumeutxoTest(BitcoinTestFramework):
|
||||||
with open(bad_snapshot_path, 'wb') as f:
|
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:])
|
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)
|
assert_raises_rpc_error(-32603, msg, node.loadtxoutset, bad_snapshot_path)
|
||||||
|
|
||||||
self.log.info(" - snapshot file with wrong number of coins")
|
self.log.info(" - snapshot file with wrong number of coins")
|
||||||
|
|
Loading…
Reference in a new issue