mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Merge bitcoin/bitcoin#21953: fuzz: Add utxo_snapshot target
fa91994b1b
fuzz: Add utxo_snapshot target (MarcoFalke) Pull request description: ACKs for top commit: jamesob: ACKfa91994b1b
Tree-SHA512: a00f077102a4e4e321bd1464c3fa11e7a5b9e04324b9be87aa28cfdc77630db7fc772d3a3768dc6ec36bbdd2d67b7e0719f0cf3fd87b4a1087365b934e137b5c
This commit is contained in:
commit
be4171679b
@ -303,6 +303,7 @@ test_fuzz_fuzz_SOURCES = \
|
||||
test/fuzz/tx_out.cpp \
|
||||
test/fuzz/tx_pool.cpp \
|
||||
test/fuzz/txrequest.cpp \
|
||||
test/fuzz/utxo_snapshot.cpp \
|
||||
test/fuzz/validation_load_mempool.cpp \
|
||||
test/fuzz/versionbits.cpp
|
||||
endif # ENABLE_FUZZ_BINARY
|
||||
|
@ -454,8 +454,8 @@ public:
|
||||
{AssumeutxoHash{uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")}, 110},
|
||||
},
|
||||
{
|
||||
210,
|
||||
{AssumeutxoHash{uint256S("0x9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2")}, 210},
|
||||
200,
|
||||
{AssumeutxoHash{uint256S("0x51c8d11d8b5c1de51543c579736e786aa2736206d1e11e627568029ce092cf62")}, 200},
|
||||
},
|
||||
};
|
||||
|
||||
|
87
src/test/fuzz/utxo_snapshot.cpp
Normal file
87
src/test/fuzz/utxo_snapshot.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2021 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <chainparams.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/mining.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <validation.h>
|
||||
#include <validationinterface.h>
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<std::shared_ptr<CBlock>>* g_chain;
|
||||
|
||||
void initialize_chain()
|
||||
{
|
||||
const auto params{CreateChainParams(ArgsManager{}, CBaseChainParams::REGTEST)};
|
||||
static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)};
|
||||
g_chain = &chain;
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
std::unique_ptr<const TestingSetup> setup{MakeNoLogFileContext<const TestingSetup>()};
|
||||
const auto& node = setup->m_node;
|
||||
auto& chainman{*node.chainman};
|
||||
|
||||
const auto snapshot_path = GetDataDir() / "fuzzed_snapshot.dat";
|
||||
|
||||
Assert(!chainman.SnapshotBlockhash());
|
||||
|
||||
{
|
||||
CAutoFile outfile{fsbridge::fopen(snapshot_path, "wb"), SER_DISK, CLIENT_VERSION};
|
||||
const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
|
||||
outfile << Span<const uint8_t>{file_data};
|
||||
}
|
||||
|
||||
const auto ActivateFuzzedSnapshot{[&] {
|
||||
CAutoFile infile{fsbridge::fopen(snapshot_path, "rb"), SER_DISK, CLIENT_VERSION};
|
||||
SnapshotMetadata metadata;
|
||||
try {
|
||||
infile >> metadata;
|
||||
} catch (const std::ios_base::failure&) {
|
||||
return false;
|
||||
}
|
||||
return chainman.ActivateSnapshot(infile, metadata, /* in_memory */ true);
|
||||
}};
|
||||
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
for (const auto& block : *g_chain) {
|
||||
BlockValidationState dummy;
|
||||
bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy, ::Params())};
|
||||
Assert(processed);
|
||||
const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
|
||||
Assert(index);
|
||||
}
|
||||
}
|
||||
|
||||
if (ActivateFuzzedSnapshot()) {
|
||||
LOCK(::cs_main);
|
||||
Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull());
|
||||
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(g_chain->size() == coinscache.GetCacheSize());
|
||||
Assert(chain_tx == chainman.ActiveTip()->nChainTx);
|
||||
} else {
|
||||
Assert(!chainman.SnapshotBlockhash());
|
||||
Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
|
||||
}
|
||||
// Snapshot should refuse to load a second time regardless of validity
|
||||
Assert(!ActivateFuzzedSnapshot());
|
||||
}
|
||||
} // namespace
|
@ -11,8 +11,10 @@
|
||||
#include <node/context.h>
|
||||
#include <pow.h>
|
||||
#include <script/standard.h>
|
||||
#include <test/util/script.h>
|
||||
#include <util/check.h>
|
||||
#include <validation.h>
|
||||
#include <versionbits.h>
|
||||
|
||||
CTxIn generatetoaddress(const NodeContext& node, const std::string& address)
|
||||
{
|
||||
@ -23,6 +25,37 @@ CTxIn generatetoaddress(const NodeContext& node, const std::string& address)
|
||||
return MineBlock(node, coinbase_script);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params)
|
||||
{
|
||||
std::vector<std::shared_ptr<CBlock>> ret{total_height};
|
||||
auto time{params.GenesisBlock().nTime};
|
||||
for (size_t height{0}; height < total_height; ++height) {
|
||||
CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())};
|
||||
|
||||
CMutableTransaction coinbase_tx;
|
||||
coinbase_tx.vin.resize(1);
|
||||
coinbase_tx.vin[0].prevout.SetNull();
|
||||
coinbase_tx.vout.resize(1);
|
||||
coinbase_tx.vout[0].scriptPubKey = P2WSH_OP_TRUE;
|
||||
coinbase_tx.vout[0].nValue = GetBlockSubsidy(height + 1, params.GetConsensus());
|
||||
coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0;
|
||||
block.vtx = {MakeTransactionRef(std::move(coinbase_tx))};
|
||||
|
||||
block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION;
|
||||
block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash();
|
||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||
block.nTime = ++time;
|
||||
block.nBits = params.GenesisBlock().nBits;
|
||||
block.nNonce = 0;
|
||||
|
||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) {
|
||||
++block.nNonce;
|
||||
assert(block.nNonce);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
|
||||
{
|
||||
auto block = PrepareBlock(node, coinbase_scriptPubKey);
|
||||
|
@ -7,12 +7,17 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CBlock;
|
||||
class CChainParams;
|
||||
class CScript;
|
||||
class CTxIn;
|
||||
struct NodeContext;
|
||||
|
||||
/** Create a blockchain, starting from genesis */
|
||||
std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params);
|
||||
|
||||
/** Returns the generated coin */
|
||||
CTxIn MineBlock(const NodeContext&, const CScript& coinbase_scriptPubKey);
|
||||
|
||||
|
@ -136,11 +136,11 @@ BOOST_AUTO_TEST_CASE(test_assumeutxo)
|
||||
|
||||
const auto out110 = *ExpectedAssumeutxo(110, *params);
|
||||
BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618");
|
||||
BOOST_CHECK_EQUAL(out110.nChainTx, (unsigned int)110);
|
||||
BOOST_CHECK_EQUAL(out110.nChainTx, 110U);
|
||||
|
||||
const auto out210 = *ExpectedAssumeutxo(210, *params);
|
||||
BOOST_CHECK_EQUAL(out210.hash_serialized.ToString(), "9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2");
|
||||
BOOST_CHECK_EQUAL(out210.nChainTx, (unsigned int)210);
|
||||
const auto out210 = *ExpectedAssumeutxo(200, *params);
|
||||
BOOST_CHECK_EQUAL(out210.hash_serialized.ToString(), "51c8d11d8b5c1de51543c579736e786aa2736206d1e11e627568029ce092cf62");
|
||||
BOOST_CHECK_EQUAL(out210.nChainTx, 200U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user