Bitcoin Core 28.99.0
P2P Digital Currency
txdownloadman.cpp
Go to the documentation of this file.
1// Copyright (c) 2023 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6#include <node/context.h>
7#include <node/mempool_args.h>
8#include <node/miner.h>
12#include <test/fuzz/fuzz.h>
13#include <test/fuzz/util.h>
15#include <test/util/mining.h>
16#include <test/util/script.h>
18#include <test/util/txmempool.h>
19#include <util/hasher.h>
20#include <util/rbf.h>
21#include <txmempool.h>
22#include <validation.h>
23#include <validationinterface.h>
24
25namespace {
26
27const TestingSetup* g_setup;
28
29constexpr size_t NUM_COINS{50};
30COutPoint COINS[NUM_COINS];
31
32static TxValidationResult TESTED_TX_RESULTS[] = {
33 // Skip TX_RESULT_UNSET
43 // Skip TX_NO_MEMPOOL
46};
47
48// Precomputed transactions. Some may conflict with each other.
49std::vector<CTransactionRef> TRANSACTIONS;
50
51// Limit the total number of peers because we don't expect coverage to change much with lots more peers.
52constexpr int NUM_PEERS = 16;
53
54// Precomputed random durations (positive and negative, each ~exponentially distributed).
55std::chrono::microseconds TIME_SKIPS[128];
56
57static CTransactionRef MakeTransactionSpending(const std::vector<COutPoint>& outpoints, size_t num_outputs, bool add_witness)
58{
60 // If no outpoints are given, create a random one.
61 for (const auto& outpoint : outpoints) {
62 tx.vin.emplace_back(outpoint);
63 }
64 if (add_witness) {
65 tx.vin[0].scriptWitness.stack.push_back({1});
66 }
67 for (size_t o = 0; o < num_outputs; ++o) tx.vout.emplace_back(CENT, P2WSH_OP_TRUE);
68 return MakeTransactionRef(tx);
69}
70static std::vector<COutPoint> PickCoins(FuzzedDataProvider& fuzzed_data_provider)
71{
72 std::vector<COutPoint> ret;
73 ret.push_back(fuzzed_data_provider.PickValueInArray(COINS));
74 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10) {
75 ret.push_back(fuzzed_data_provider.PickValueInArray(COINS));
76 }
77 return ret;
78}
79
80void initialize()
81{
82 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
83 g_setup = testing_setup.get();
84 for (uint32_t i = 0; i < uint32_t{NUM_COINS}; ++i) {
85 COINS[i] = COutPoint{Txid::FromUint256((HashWriter() << i).GetHash()), i};
86 }
87 size_t outpoints_index = 0;
88 // 2 transactions same txid different witness
89 {
90 auto tx1{MakeTransactionSpending({COINS[outpoints_index]}, /*num_outputs=*/5, /*add_witness=*/false)};
91 auto tx2{MakeTransactionSpending({COINS[outpoints_index]}, /*num_outputs=*/5, /*add_witness=*/true)};
92 Assert(tx1->GetHash() == tx2->GetHash());
93 TRANSACTIONS.emplace_back(tx1);
94 TRANSACTIONS.emplace_back(tx2);
95 outpoints_index += 1;
96 }
97 // 2 parents 1 child
98 {
99 auto tx_parent_1{MakeTransactionSpending({COINS[outpoints_index++]}, /*num_outputs=*/1, /*add_witness=*/true)};
100 TRANSACTIONS.emplace_back(tx_parent_1);
101 auto tx_parent_2{MakeTransactionSpending({COINS[outpoints_index++]}, /*num_outputs=*/1, /*add_witness=*/false)};
102 TRANSACTIONS.emplace_back(tx_parent_2);
103 TRANSACTIONS.emplace_back(MakeTransactionSpending({COutPoint{tx_parent_1->GetHash(), 0}, COutPoint{tx_parent_2->GetHash(), 0}},
104 /*num_outputs=*/1, /*add_witness=*/true));
105 }
106 // 1 parent 2 children
107 {
108 auto tx_parent{MakeTransactionSpending({COINS[outpoints_index++]}, /*num_outputs=*/2, /*add_witness=*/true)};
109 TRANSACTIONS.emplace_back(tx_parent);
110 TRANSACTIONS.emplace_back(MakeTransactionSpending({COutPoint{tx_parent->GetHash(), 0}},
111 /*num_outputs=*/1, /*add_witness=*/true));
112 TRANSACTIONS.emplace_back(MakeTransactionSpending({COutPoint{tx_parent->GetHash(), 1}},
113 /*num_outputs=*/1, /*add_witness=*/true));
114 }
115 // chain of 5 segwit
116 {
117 COutPoint& last_outpoint = COINS[outpoints_index++];
118 for (auto i{0}; i < 5; ++i) {
119 auto tx{MakeTransactionSpending({last_outpoint}, /*num_outputs=*/1, /*add_witness=*/true)};
120 TRANSACTIONS.emplace_back(tx);
121 last_outpoint = COutPoint{tx->GetHash(), 0};
122 }
123 }
124 // chain of 5 non-segwit
125 {
126 COutPoint& last_outpoint = COINS[outpoints_index++];
127 for (auto i{0}; i < 5; ++i) {
128 auto tx{MakeTransactionSpending({last_outpoint}, /*num_outputs=*/1, /*add_witness=*/false)};
129 TRANSACTIONS.emplace_back(tx);
130 last_outpoint = COutPoint{tx->GetHash(), 0};
131 }
132 }
133 // Also create a loose tx for each outpoint. Some of these transactions conflict with the above
134 // or have the same txid.
135 for (const auto& outpoint : COINS) {
136 TRANSACTIONS.emplace_back(MakeTransactionSpending({outpoint}, /*num_outputs=*/1, /*add_witness=*/true));
137 }
138
139 // Create random-looking time jumps
140 int i = 0;
141 // TIME_SKIPS[N] for N=0..15 is just N microseconds.
142 for (; i < 16; ++i) {
143 TIME_SKIPS[i] = std::chrono::microseconds{i};
144 }
145 // TIME_SKIPS[N] for N=16..127 has randomly-looking but roughly exponentially increasing values up to
146 // 198.416453 seconds.
147 for (; i < 128; ++i) {
148 int diff_bits = ((i - 10) * 2) / 9;
149 uint64_t diff = 1 + (CSipHasher(0, 0).Write(i).Finalize() >> (64 - diff_bits));
150 TIME_SKIPS[i] = TIME_SKIPS[i - 1] + std::chrono::microseconds{diff};
151 }
152}
153
154void CheckPackageToValidate(const node::PackageToValidate& package_to_validate, NodeId peer)
155{
156 Assert(package_to_validate.m_senders.size() == 2);
157 Assert(package_to_validate.m_senders.front() == peer);
158 Assert(package_to_validate.m_senders.back() < NUM_PEERS);
159
160 // Package is a 1p1c
161 const auto& package = package_to_validate.m_txns;
162 Assert(IsChildWithParents(package));
163 Assert(package.size() == 2);
164}
165
166FUZZ_TARGET(txdownloadman, .init = initialize)
167{
169 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
170
171 // Initialize txdownloadman
172 bilingual_str error;
173 CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node), error};
174 const auto max_orphan_count = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 300);
175 FastRandomContext det_rand{true};
176 node::TxDownloadManager txdownloadman{node::TxDownloadOptions{pool, det_rand, max_orphan_count, true}};
177
178 std::chrono::microseconds time{244466666};
179
180 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
181 {
182 NodeId rand_peer = fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, NUM_PEERS - 1);
183
184 // Transaction can be one of the premade ones or a randomly generated one
185 auto rand_tx = fuzzed_data_provider.ConsumeBool() ?
186 MakeTransactionSpending(PickCoins(fuzzed_data_provider),
187 /*num_outputs=*/fuzzed_data_provider.ConsumeIntegralInRange(1, 500),
188 /*add_witness=*/fuzzed_data_provider.ConsumeBool()) :
189 TRANSACTIONS.at(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, TRANSACTIONS.size() - 1));
190
191 CallOneOf(
192 fuzzed_data_provider,
193 [&] {
195 .m_preferred = fuzzed_data_provider.ConsumeBool(),
196 .m_relay_permissions = fuzzed_data_provider.ConsumeBool(),
197 .m_wtxid_relay = fuzzed_data_provider.ConsumeBool()
198 };
199 txdownloadman.ConnectedPeer(rand_peer, info);
200 },
201 [&] {
202 txdownloadman.DisconnectedPeer(rand_peer);
203 txdownloadman.CheckIsEmpty(rand_peer);
204 },
205 [&] {
206 txdownloadman.ActiveTipChange();
207 },
208 [&] {
209 CBlock block;
210 block.vtx.push_back(rand_tx);
211 txdownloadman.BlockConnected(std::make_shared<CBlock>(block));
212 },
213 [&] {
214 txdownloadman.BlockDisconnected();
215 },
216 [&] {
217 txdownloadman.MempoolAcceptedTx(rand_tx);
218 },
219 [&] {
220 TxValidationState state;
221 state.Invalid(fuzzed_data_provider.PickValueInArray(TESTED_TX_RESULTS), "");
222 bool first_time_failure{fuzzed_data_provider.ConsumeBool()};
223
224 node::RejectedTxTodo todo = txdownloadman.MempoolRejectedTx(rand_tx, state, rand_peer, first_time_failure);
225 Assert(first_time_failure || !todo.m_should_add_extra_compact_tx);
226 },
227 [&] {
228 GenTxid gtxid = fuzzed_data_provider.ConsumeBool() ?
229 GenTxid::Txid(rand_tx->GetHash()) :
230 GenTxid::Wtxid(rand_tx->GetWitnessHash());
231 txdownloadman.AddTxAnnouncement(rand_peer, gtxid, time, /*p2p_inv=*/fuzzed_data_provider.ConsumeBool());
232 },
233 [&] {
234 txdownloadman.GetRequestsToSend(rand_peer, time);
235 },
236 [&] {
237 txdownloadman.ReceivedTx(rand_peer, rand_tx);
238 const auto& [should_validate, maybe_package] = txdownloadman.ReceivedTx(rand_peer, rand_tx);
239 // The only possible results should be:
240 // - Don't validate the tx, no package.
241 // - Don't validate the tx, package.
242 // - Validate the tx, no package.
243 // The only combination that doesn't make sense is validate both tx and package.
244 Assert(!(should_validate && maybe_package.has_value()));
245 if (maybe_package.has_value()) CheckPackageToValidate(*maybe_package, rand_peer);
246 },
247 [&] {
248 txdownloadman.ReceivedNotFound(rand_peer, {rand_tx->GetWitnessHash()});
249 },
250 [&] {
251 const bool expect_work{txdownloadman.HaveMoreWork(rand_peer)};
252 const auto ptx = txdownloadman.GetTxToReconsider(rand_peer);
253 // expect_work=true doesn't necessarily mean the next item from the workset isn't a
254 // nullptr, as the transaction could have been removed from orphanage without being
255 // removed from the peer's workset.
256 if (ptx) {
257 // However, if there was a non-null tx in the workset, HaveMoreWork should have
258 // returned true.
259 Assert(expect_work);
260 }
261 }
262 );
263 // Jump forwards or backwards
264 auto time_skip = fuzzed_data_provider.PickValueInArray(TIME_SKIPS);
265 if (fuzzed_data_provider.ConsumeBool()) time_skip *= -1;
266 time += time_skip;
267 }
268 // Disconnect everybody, check that all data structures are empty.
269 for (NodeId nodeid = 0; nodeid < NUM_PEERS; ++nodeid) {
270 txdownloadman.DisconnectedPeer(nodeid);
271 txdownloadman.CheckIsEmpty(nodeid);
272 }
273 txdownloadman.CheckIsEmpty();
274}
275
276// Give node 0 relay permissions, and nobody else. This helps us remember who is a RelayPermissions
277// peer without tracking anything (this is only for the txdownload_impl target).
278static bool HasRelayPermissions(NodeId peer) { return peer == 0; }
279
280static void CheckInvariants(const node::TxDownloadManagerImpl& txdownload_impl, size_t max_orphan_count)
281{
282 const TxOrphanage& orphanage = txdownload_impl.m_orphanage;
283
284 // Orphanage usage should never exceed what is allowed
285 Assert(orphanage.Size() <= max_orphan_count);
286
287 // We should never have more than the maximum in-flight requests out for a peer.
288 for (NodeId peer = 0; peer < NUM_PEERS; ++peer) {
289 if (!HasRelayPermissions(peer)) {
291 }
292 }
293 txdownload_impl.m_txrequest.SanityCheck();
294}
295
296FUZZ_TARGET(txdownloadman_impl, .init = initialize)
297{
299 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
300
301 // Initialize a TxDownloadManagerImpl
302 bilingual_str error;
303 CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node), error};
304 const auto max_orphan_count = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 300);
305 FastRandomContext det_rand{true};
306 node::TxDownloadManagerImpl txdownload_impl{node::TxDownloadOptions{pool, det_rand, max_orphan_count, true}};
307
308 std::chrono::microseconds time{244466666};
309
310 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
311 {
312 NodeId rand_peer = fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, NUM_PEERS - 1);
313
314 // Transaction can be one of the premade ones or a randomly generated one
315 auto rand_tx = fuzzed_data_provider.ConsumeBool() ?
316 MakeTransactionSpending(PickCoins(fuzzed_data_provider),
317 /*num_outputs=*/fuzzed_data_provider.ConsumeIntegralInRange(1, 500),
318 /*add_witness=*/fuzzed_data_provider.ConsumeBool()) :
319 TRANSACTIONS.at(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, TRANSACTIONS.size() - 1));
320
321 CallOneOf(
322 fuzzed_data_provider,
323 [&] {
325 .m_preferred = fuzzed_data_provider.ConsumeBool(),
326 .m_relay_permissions = HasRelayPermissions(rand_peer),
327 .m_wtxid_relay = fuzzed_data_provider.ConsumeBool()
328 };
329 txdownload_impl.ConnectedPeer(rand_peer, info);
330 },
331 [&] {
332 txdownload_impl.DisconnectedPeer(rand_peer);
333 txdownload_impl.CheckIsEmpty(rand_peer);
334 },
335 [&] {
336 txdownload_impl.ActiveTipChange();
337 // After a block update, nothing should be in the rejection caches
338 for (const auto& tx : TRANSACTIONS) {
339 Assert(!txdownload_impl.RecentRejectsFilter().contains(tx->GetWitnessHash().ToUint256()));
340 Assert(!txdownload_impl.RecentRejectsFilter().contains(tx->GetHash().ToUint256()));
341 Assert(!txdownload_impl.RecentRejectsReconsiderableFilter().contains(tx->GetWitnessHash().ToUint256()));
343 }
344 },
345 [&] {
346 CBlock block;
347 block.vtx.push_back(rand_tx);
348 txdownload_impl.BlockConnected(std::make_shared<CBlock>(block));
349 // Block transactions must be removed from orphanage
350 Assert(!txdownload_impl.m_orphanage.HaveTx(rand_tx->GetWitnessHash()));
351 },
352 [&] {
353 txdownload_impl.BlockDisconnected();
354 Assert(!txdownload_impl.RecentConfirmedTransactionsFilter().contains(rand_tx->GetWitnessHash().ToUint256()));
355 Assert(!txdownload_impl.RecentConfirmedTransactionsFilter().contains(rand_tx->GetHash().ToUint256()));
356 },
357 [&] {
358 txdownload_impl.MempoolAcceptedTx(rand_tx);
359 },
360 [&] {
361 TxValidationState state;
362 state.Invalid(fuzzed_data_provider.PickValueInArray(TESTED_TX_RESULTS), "");
363 bool first_time_failure{fuzzed_data_provider.ConsumeBool()};
364
365 bool reject_contains_wtxid{txdownload_impl.RecentRejectsFilter().contains(rand_tx->GetWitnessHash().ToUint256())};
366
367 node::RejectedTxTodo todo = txdownload_impl.MempoolRejectedTx(rand_tx, state, rand_peer, first_time_failure);
368 Assert(first_time_failure || !todo.m_should_add_extra_compact_tx);
369 if (!reject_contains_wtxid) Assert(todo.m_unique_parents.size() <= rand_tx->vin.size());
370 },
371 [&] {
372 GenTxid gtxid = fuzzed_data_provider.ConsumeBool() ?
373 GenTxid::Txid(rand_tx->GetHash()) :
374 GenTxid::Wtxid(rand_tx->GetWitnessHash());
375 txdownload_impl.AddTxAnnouncement(rand_peer, gtxid, time, /*p2p_inv=*/fuzzed_data_provider.ConsumeBool());
376 },
377 [&] {
378 const auto getdata_requests = txdownload_impl.GetRequestsToSend(rand_peer, time);
379 // TxDownloadManager should not be telling us to request things we already have.
380 // Exclude m_lazy_recent_rejects_reconsiderable because it may request low-feerate parent of orphan.
381 for (const auto& gtxid : getdata_requests) {
382 Assert(!txdownload_impl.AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false));
383 }
384 },
385 [&] {
386 const auto& [should_validate, maybe_package] = txdownload_impl.ReceivedTx(rand_peer, rand_tx);
387 // The only possible results should be:
388 // - Don't validate the tx, no package.
389 // - Don't validate the tx, package.
390 // - Validate the tx, no package.
391 // The only combination that doesn't make sense is validate both tx and package.
392 Assert(!(should_validate && maybe_package.has_value()));
393 if (should_validate) {
394 Assert(!txdownload_impl.AlreadyHaveTx(GenTxid::Wtxid(rand_tx->GetWitnessHash()), /*include_reconsiderable=*/true));
395 }
396 if (maybe_package.has_value()) {
397 CheckPackageToValidate(*maybe_package, rand_peer);
398
399 const auto& package = maybe_package->m_txns;
400 // Parent is in m_lazy_recent_rejects_reconsiderable and child is in m_orphanage
401 Assert(txdownload_impl.RecentRejectsReconsiderableFilter().contains(rand_tx->GetWitnessHash().ToUint256()));
402 Assert(txdownload_impl.m_orphanage.HaveTx(maybe_package->m_txns.back()->GetWitnessHash()));
403 // Package has not been rejected
405 // Neither is in m_lazy_recent_rejects
406 Assert(!txdownload_impl.RecentRejectsFilter().contains(package.front()->GetWitnessHash().ToUint256()));
407 Assert(!txdownload_impl.RecentRejectsFilter().contains(package.back()->GetWitnessHash().ToUint256()));
408 }
409 },
410 [&] {
411 txdownload_impl.ReceivedNotFound(rand_peer, {rand_tx->GetWitnessHash()});
412 },
413 [&] {
414 const bool expect_work{txdownload_impl.HaveMoreWork(rand_peer)};
415 const auto ptx{txdownload_impl.GetTxToReconsider(rand_peer)};
416 // expect_work=true doesn't necessarily mean the next item from the workset isn't a
417 // nullptr, as the transaction could have been removed from orphanage without being
418 // removed from the peer's workset.
419 if (ptx) {
420 // However, if there was a non-null tx in the workset, HaveMoreWork should have
421 // returned true.
422 Assert(expect_work);
423 Assert(txdownload_impl.AlreadyHaveTx(GenTxid::Wtxid(ptx->GetWitnessHash()), /*include_reconsiderable=*/false));
424 // Presumably we have validated this tx. Use "missing inputs" to keep it in the
425 // orphanage longer. Later iterations might call MempoolAcceptedTx or
426 // MempoolRejectedTx with a different error.
427 TxValidationState state_missing_inputs;
428 state_missing_inputs.Invalid(TxValidationResult::TX_MISSING_INPUTS, "");
429 txdownload_impl.MempoolRejectedTx(ptx, state_missing_inputs, rand_peer, fuzzed_data_provider.ConsumeBool());
430 }
431 }
432 );
433
434 auto time_skip = fuzzed_data_provider.PickValueInArray(TIME_SKIPS);
435 if (fuzzed_data_provider.ConsumeBool()) time_skip *= -1;
436 time += time_skip;
437 CheckInvariants(txdownload_impl, max_orphan_count);
438 }
439 // Disconnect everybody, check that all data structures are empty.
440 for (NodeId nodeid = 0; nodeid < NUM_PEERS; ++nodeid) {
441 txdownload_impl.DisconnectedPeer(nodeid);
442 txdownload_impl.CheckIsEmpty(nodeid);
443 }
444 txdownload_impl.CheckIsEmpty();
445}
446
447} // namespace
int ret
#define Assert(val)
Identity function.
Definition: check.h:85
Definition: block.h:69
std::vector< CTransactionRef > vtx
Definition: block.h:72
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
bool contains(Span< const unsigned char > vKey) const
Definition: bloom.cpp:226
SipHash-2-4.
Definition: siphash.h:15
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:77
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
Definition: siphash.cpp:28
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:304
Fast randomness source.
Definition: random.h:377
T ConsumeIntegralInRange(T min, T max)
T PickValueInArray(const T(&array)[size])
A generic txid reference (txid or wtxid).
Definition: transaction.h:428
static GenTxid Wtxid(const uint256 &hash)
Definition: transaction.h:435
static GenTxid Txid(const uint256 &hash)
Definition: transaction.h:434
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:101
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
Definition: txorphanage.h:28
size_t Size() const
Return how many entries exist in the orphange.
Definition: txorphanage.h:70
bool HaveTx(const Wtxid &wtxid) const
Check if we already have an orphan transaction (by wtxid only)
void SanityCheck() const
Run internal consistency check (testing only).
Definition: txrequest.cpp:724
size_t Count(NodeId peer) const
Count how many announcements a peer has (REQUESTED, CANDIDATE, and COMPLETED combined).
Definition: txrequest.cpp:722
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
Definition: validation.h:89
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
CRollingBloomFilter & RecentConfirmedTransactionsFilter()
bool AddTxAnnouncement(NodeId peer, const GenTxid &gtxid, std::chrono::microseconds now, bool p2p_inv)
Consider adding this tx hash to txrequest.
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Marks a tx as ReceivedResponse in txrequest.
void DisconnectedPeer(NodeId nodeid)
TxRequestTracker m_txrequest
Tracks candidates for requesting and downloading transaction data.
std::pair< bool, std::optional< PackageToValidate > > ReceivedTx(NodeId nodeid, const CTransactionRef &ptx)
void MempoolAcceptedTx(const CTransactionRef &tx)
CRollingBloomFilter & RecentRejectsReconsiderableFilter()
RejectedTxTodo MempoolRejectedTx(const CTransactionRef &ptx, const TxValidationState &state, NodeId nodeid, bool first_time_failure)
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo &info)
bool AlreadyHaveTx(const GenTxid &gtxid, bool include_reconsiderable)
Check whether we already have this gtxid in:
TxOrphanage m_orphanage
Manages unvalidated tx data (orphan transactions for which we are downloading ancestors).
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
CTransactionRef GetTxToReconsider(NodeId nodeid)
CRollingBloomFilter & RecentRejectsFilter()
transaction_identifier represents the two canonical transaction identifier types (txid,...
const uint256 & ToUint256() const LIFETIMEBOUND
static transaction_identifier FromUint256(const uint256 &id)
TxValidationResult
A "reason" why a transaction was invalid, suitable for determining whether the provider of the transa...
Definition: validation.h:23
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_CONFLICT
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_WITNESS_MUTATED
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
@ TX_CONSENSUS
invalid by consensus rules
@ TX_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
void initialize()
Definition: fuzz.cpp:111
#define FUZZ_TARGET(...)
Definition: fuzz.h:35
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
Definition: fuzz.h:22
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
Definition: txdownloadman.h:30
int64_t NodeId
Definition: net.h:97
static CTransactionRef MakeTransactionSpending(const std::vector< COutPoint > &outpoints, FastRandomContext &det_rand)
bool IsChildWithParents(const Package &package)
Context-free check that a package is exactly one child and its parents; not all parents need to be pr...
Definition: packages.cpp:119
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of these transactions' wtxids, concatenated in lexicographical order (treating the wtxid...
Definition: packages.cpp:151
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:424
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
static constexpr CAmount CENT
Definition: setup_common.h:46
node::NodeContext m_node
Definition: setup_common.h:65
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxOut > vout
Definition: transaction.h:380
Txid GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:69
std::vector< CTxIn > vin
Definition: transaction.h:379
Testing setup that configures a complete environment.
Definition: setup_common.h:120
Bilingual messages:
Definition: translation.h:21
std::vector< NodeId > m_senders
Definition: txdownloadman.h:59
std::vector< uint256 > m_unique_parents
Definition: txdownloadman.h:95
bool m_should_add_extra_compact_tx
Definition: txdownloadman.h:94
const bool m_preferred
Whether this peer is preferred for transaction download.
Definition: txdownloadman.h:51
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
Definition: util.h:35
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
Definition: random.cpp:19
@ ZEROS
Seed with a compile time constant of zeros.
static const CScript P2WSH_OP_TRUE
Definition: script.h:12
CTxMemPool::Options MemPoolOptionsForTest(const NodeContext &node)
Definition: txmempool.cpp:20