6#include <chainparams.h>
43const std::vector<std::shared_ptr<CBlock>>* g_chain;
47void sanity_check_snapshot()
53 const auto&
node{tmp_setup->m_node};
54 for (
auto& block: *g_chain) {
60 auto&
cs{
node.chainman->ActiveChainstate()};
61 cs.ForceFlushStateToDisk(
false);
64 Assert(stats.nHeight == cp_au_data.height);
65 Assert(stats.nTransactions + 1 == cp_au_data.m_chain_tx_count);
66 Assert(stats.hashBlock == cp_au_data.blockhash);
70template <
bool INVALID>
71void initialize_chain()
79 sanity_check_snapshot();
81 static const auto setup{
85 .setup_validation_interface =
false,
86 .min_validation_cache =
true,
90 auto& chainman{*
setup->m_node.chainman};
91 for (
const auto& block : chain) {
93 bool processed{chainman.ProcessNewBlockHeaders({{*block}},
true, dummy)};
95 const auto* index{
WITH_LOCK(
::cs_main,
return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
102template <
bool INVALID>
109 bool dirty_chainman{
false};
110 auto& chainman{*
setup.m_node.chainman};
114 Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
121 outfile << std::span{metadata};
123 auto msg_start = chainman.GetParams().MessageStart();
125 uint256 base_blockhash{g_chain->at(base_blockheight - 1)->GetHash()};
133 outfile << std::span{file_data};
136 for (
const auto& block : *g_chain) {
137 auto coinbase{block->vtx.at(0)};
138 outfile << coinbase->GetHash();
141 outfile <<
Coin(coinbase->vout[0], height, 1);
149 const auto& coinbase{g_chain->back()->vtx.back()};
150 outfile << coinbase->GetHash();
153 outfile <<
Coin{coinbase->vout[0], 999, 0};
155 assert(outfile.fclose() == 0);
158 const auto ActivateFuzzedSnapshot{[&] {
160 auto msg_start = chainman.GetParams().MessageStart();
164 }
catch (
const std::ios_base::failure&) {
167 return !!chainman.ActivateSnapshot(infile, metadata,
true);
173 for (
const auto& block : *g_chain) {
175 bool processed{chainman.ProcessNewBlockHeaders({{*block}},
true, dummy)};
177 const auto* index{
WITH_LOCK(
::cs_main,
return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
180 dirty_chainman =
true;
184 if (ActivateFuzzedSnapshot()) {
186 Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull());
187 const auto& coinscache{chainman.ActiveChainstate().CoinsTip()};
188 for (
const auto& block : *g_chain) {
189 Assert(coinscache.HaveCoin(
COutPoint{block->vtx.at(0)->GetHash(), 0}));
190 const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())};
193 if (index->nHeight == chainman.ActiveChainstate().SnapshotBase()->nHeight) {
194 auto params{chainman.GetParams().AssumeutxoForHeight(index->nHeight)};
195 Assert(params.has_value());
196 Assert(params.value().m_chain_tx_count == index->m_chain_tx_count);
198 Assert(index->m_chain_tx_count == 0);
201 Assert(g_chain->size() == coinscache.GetCacheSize());
202 dirty_chainman =
true;
204 Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
207 Assert(!ActivateFuzzedSnapshot());
213 if (dirty_chainman) {
214 setup.m_node.chainman.reset();
215 setup.m_make_chainman();
216 setup.LoadVerifyActivateChainstate();
229FUZZ_TARGET(utxo_snapshot , .
init = initialize_chain<false>) { utxo_snapshot_fuzz<false>(buffer); }
230FUZZ_TARGET(utxo_snapshot_invalid, .
init = initialize_chain<true>) { utxo_snapshot_fuzz<true>(buffer); }
const TestingSetup * g_setup
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const ChainType chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
#define Assert(val)
Identity function.
fs::path GetDataDirNet() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Get data directory path with appended network identifier.
Non-refcounted RAII wrapper for FILE*.
An outpoint - a combination of a transaction hash and an index n into its vout.
T ConsumeIntegralInRange(T min, T max)
Helper to initialize the global NodeClock, let a duration elapse, and reset it after use in a test.
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
std::span< const uint8_t > FuzzBufferType
FILE * fopen(const fs::path &p, const char *mode)
static bool ComputeUTXOStats(CCoinsView *view, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point, std::unique_ptr< CCoinsViewCursor > pcursor)
Calculate statistics about the unspent transaction output set.
static const auto INVALID
A stack representing the lack of any (dis)satisfactions.
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Testing setup that configures a complete environment.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
NodeSeconds ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
std::vector< B > ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, const std::optional< size_t > &max_length=std::nullopt) noexcept
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
std::vector< std::shared_ptr< CBlock > > CreateBlockChain(size_t total_height, const CChainParams ¶ms)
Create a blockchain, starting from genesis.
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
@ ZEROS
Seed with a compile time constant of zeros.
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
FuzzedDataProvider & fuzzed_data_provider