Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
headerssync.cpp
Go to the documentation of this file.
1#include <arith_uint256.h>
2#include <chain.h>
3#include <chainparams.h>
4#include <headerssync.h>
5#include <test/fuzz/fuzz.h>
6#include <test/fuzz/util.h>
8#include <uint256.h>
9#include <util/chaintype.h>
10#include <util/time.h>
11#include <validation.h>
12
13#include <iterator>
14#include <vector>
15
17{
18 static const auto testing_setup = MakeNoLogFileContext<>(
19 /*chain_type=*/ChainType::MAIN);
20}
21
23 const CBlockHeader& genesis_header,
24 const std::vector<CBlockHeader>& all_headers,
25 std::vector<CBlockHeader>& new_headers)
26{
27 Assume(!new_headers.empty());
28
29 const CBlockHeader* prev_header{
30 all_headers.empty() ? &genesis_header : &all_headers.back()};
31
32 for (auto& header : new_headers) {
33 header.hashPrevBlock = prev_header->GetHash();
34
35 prev_header = &header;
36 }
37}
38
40{
41public:
42 FuzzedHeadersSyncState(const unsigned commit_offset, const CBlockIndex* chain_start, const arith_uint256& minimum_required_work)
43 : HeadersSyncState(/*id=*/0, Params().GetConsensus(), chain_start, minimum_required_work)
44 {
45 const_cast<unsigned&>(m_commit_offset) = commit_offset;
46 }
47};
48
50{
51 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
52 auto mock_time{ConsumeTime(fuzzed_data_provider)};
53
54 CBlockHeader genesis_header{Params().GenesisBlock()};
55 CBlockIndex start_index(genesis_header);
56
57 if (mock_time < start_index.GetMedianTimePast()) return;
58 SetMockTime(mock_time);
59
60 const uint256 genesis_hash = genesis_header.GetHash();
61 start_index.phashBlock = &genesis_hash;
62
63 arith_uint256 min_work{UintToArith256(ConsumeUInt256(fuzzed_data_provider))};
64 FuzzedHeadersSyncState headers_sync(
65 /*commit_offset=*/fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(1, 1024),
66 /*chain_start=*/&start_index,
67 /*minimum_required_work=*/min_work);
68
69 // Store headers for potential redownload phase.
70 std::vector<CBlockHeader> all_headers;
71 std::vector<CBlockHeader>::const_iterator redownloaded_it;
72 bool presync{true};
73 bool requested_more{true};
74
75 while (requested_more) {
76 std::vector<CBlockHeader> headers;
77
78 // Consume headers from fuzzer or maybe replay headers if we got to the
79 // redownload phase.
80 if (presync || fuzzed_data_provider.ConsumeBool()) {
81 auto deser_headers = ConsumeDeserializable<std::vector<CBlockHeader>>(fuzzed_data_provider);
82 if (!deser_headers || deser_headers->empty()) return;
83
84 if (fuzzed_data_provider.ConsumeBool()) {
85 MakeHeadersContinuous(genesis_header, all_headers, *deser_headers);
86 }
87
88 headers.swap(*deser_headers);
89 } else if (auto num_headers_left{std::distance(redownloaded_it, all_headers.cend())}; num_headers_left > 0) {
90 // Consume some headers from the redownload buffer (At least one
91 // header is consumed).
92 auto begin_it{redownloaded_it};
93 std::advance(redownloaded_it, fuzzed_data_provider.ConsumeIntegralInRange<int>(1, num_headers_left));
94 headers.insert(headers.cend(), begin_it, redownloaded_it);
95 }
96
97 if (headers.empty()) return;
98 auto result = headers_sync.ProcessNextHeaders(headers, fuzzed_data_provider.ConsumeBool());
99 requested_more = result.request_more;
100
101 if (result.request_more) {
102 if (presync) {
103 all_headers.insert(all_headers.cend(), headers.cbegin(), headers.cend());
104
105 if (headers_sync.GetState() == HeadersSyncState::State::REDOWNLOAD) {
106 presync = false;
107 redownloaded_it = all_headers.cbegin();
108
109 // If we get to redownloading, the presynced headers need
110 // to have the min amount of work on them.
111 assert(CalculateClaimedHeadersWork(all_headers) >= min_work);
112 }
113 }
114
115 (void)headers_sync.NextHeadersRequestLocator();
116 }
117 }
118}
arith_uint256 UintToArith256(const uint256 &a)
const CChainParams & Params()
Return the currently selected parameters.
#define Assume(val)
Assume is the identity function.
Definition check.h:89
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition block.h:22
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition chain.h:141
int64_t GetMedianTimePast() const
Definition chain.h:278
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
Definition chain.h:144
const CBlock & GenesisBlock() const
Definition chainparams.h:98
T ConsumeIntegralInRange(T min, T max)
FuzzedHeadersSyncState(const unsigned commit_offset, const CBlockIndex *chain_start, const arith_uint256 &minimum_required_work)
HeadersSyncState:
@ REDOWNLOAD
REDOWNLOAD means the peer has given us a high-enough-work chain, and now we're redownloading the head...
const unsigned m_commit_offset
The (secret) offset on the heights for which to create commitments.
ProcessingResult ProcessNextHeaders(const std::vector< CBlockHeader > &received_headers, bool full_headers_message)
Process a batch of headers, once a sync via this mechanism has started.
State GetState() const
Return the current state of our download.
CBlockLocator NextHeadersRequestLocator() const
Issue the next GETHEADERS message to our peer.
256-bit unsigned big integer.
256-bit opaque blob.
Definition uint256.h:178
#define FUZZ_TARGET(...)
Definition fuzz.h:35
std::unique_ptr< T > MakeNoLogFileContext(const ChainType chain_type=ChainType::REGTEST, TestOpts opts={})
Make a test setup that has disk access to the debug.log file disabled.
static void initialize_headers_sync_state_fuzz()
void MakeHeadersContinuous(const CBlockHeader &genesis_header, const std::vector< CBlockHeader > &all_headers, std::vector< CBlockHeader > &new_headers)
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
Definition util.cpp:34
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition util.h:169
std::optional< T > ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider, const P &params, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition util.h:103
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition time.cpp:32
arith_uint256 CalculateClaimedHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the claimed work on a given set of headers.
assert(!tx.IsCoinBase())