Bitcoin Core  29.1.0
P2P Digital Currency
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 {
41 public:
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 {
52  FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
53  auto mock_time{ConsumeTime(fuzzed_data_provider)};
54 
55  CBlockHeader genesis_header{Params().GenesisBlock()};
56  CBlockIndex start_index(genesis_header);
57 
58  if (mock_time < start_index.GetMedianTimePast()) return;
59  SetMockTime(mock_time);
60 
61  const uint256 genesis_hash = genesis_header.GetHash();
62  start_index.phashBlock = &genesis_hash;
63 
64  arith_uint256 min_work{UintToArith256(ConsumeUInt256(fuzzed_data_provider))};
65  FuzzedHeadersSyncState headers_sync(
66  /*commit_offset=*/fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(1, 1024),
67  /*chain_start=*/&start_index,
68  /*minimum_required_work=*/min_work);
69 
70  // Store headers for potential redownload phase.
71  std::vector<CBlockHeader> all_headers;
72  std::vector<CBlockHeader>::const_iterator redownloaded_it;
73  bool presync{true};
74  bool requested_more{true};
75 
76  while (requested_more) {
77  std::vector<CBlockHeader> headers;
78 
79  // Consume headers from fuzzer or maybe replay headers if we got to the
80  // redownload phase.
81  if (presync || fuzzed_data_provider.ConsumeBool()) {
82  auto deser_headers = ConsumeDeserializable<std::vector<CBlockHeader>>(fuzzed_data_provider);
83  if (!deser_headers || deser_headers->empty()) return;
84 
85  if (fuzzed_data_provider.ConsumeBool()) {
86  MakeHeadersContinuous(genesis_header, all_headers, *deser_headers);
87  }
88 
89  headers.swap(*deser_headers);
90  } else if (auto num_headers_left{std::distance(redownloaded_it, all_headers.cend())}; num_headers_left > 0) {
91  // Consume some headers from the redownload buffer (At least one
92  // header is consumed).
93  auto begin_it{redownloaded_it};
94  std::advance(redownloaded_it, fuzzed_data_provider.ConsumeIntegralInRange<int>(1, num_headers_left));
95  headers.insert(headers.cend(), begin_it, redownloaded_it);
96  }
97 
98  if (headers.empty()) return;
99  auto result = headers_sync.ProcessNextHeaders(headers, fuzzed_data_provider.ConsumeBool());
100  requested_more = result.request_more;
101 
102  if (result.request_more) {
103  if (presync) {
104  all_headers.insert(all_headers.cend(), headers.cbegin(), headers.cend());
105 
106  if (headers_sync.GetState() == HeadersSyncState::State::REDOWNLOAD) {
107  presync = false;
108  redownloaded_it = all_headers.cbegin();
109 
110  // If we get to redownloading, the presynced headers need
111  // to have the min amount of work on them.
112  assert(CalculateClaimedHeadersWork(all_headers) >= min_work);
113  }
114  }
115 
116  (void)headers_sync.NextHeadersRequestLocator();
117  }
118  }
119 }
assert(!tx.IsCoinBase())
FUZZ_TARGET(headers_sync_state,.init=initialize_headers_sync_state_fuzz)
Definition: headerssync.cpp:49
CBlockLocator NextHeadersRequestLocator() const
Issue the next GETHEADERS message to our peer.
const CBlock & GenesisBlock() const
Definition: chainparams.h:98
arith_uint256 UintToArith256(const uint256 &a)
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:40
static void initialize_headers_sync_state_fuzz()
Definition: headerssync.cpp:16
uint256 hashPrevBlock
Definition: block.h:26
arith_uint256 CalculateClaimedHeadersWork(std::span< const CBlockHeader > headers)
Return the sum of the claimed work on a given set of headers.
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
256-bit unsigned big integer.
int64_t GetMedianTimePast() const
Definition: chain.h:278
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
Definition: random.cpp:19
256-bit opaque blob.
Definition: uint256.h:201
REDOWNLOAD means the peer has given us a high-enough-work chain, and now we&#39;re redownloading the head...
void MakeHeadersContinuous(const CBlockHeader &genesis_header, const std::vector< CBlockHeader > &all_headers, std::vector< CBlockHeader > &new_headers)
Definition: headerssync.cpp:22
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.
Definition: headerssync.cpp:69
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
Definition: util.cpp:34
auto result
Definition: common-types.h:74
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:140
const CChainParams & Params()
Return the currently selected parameters.
FuzzedHeadersSyncState(const unsigned commit_offset, const CBlockIndex *chain_start, const arith_uint256 &minimum_required_work)
Definition: headerssync.cpp:42
const unsigned m_commit_offset
The (secret) offset on the heights for which to create commitments.
Definition: headerssync.h:183
HeadersSyncState:
Definition: headerssync.h:101
Seed with a compile time constant of zeros.
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.h:171
State GetState() const
Return the current state of our download.
Definition: headerssync.h:119
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:21
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
Definition: chain.h:144