30 constexpr
size_t NUM_COINS{50};
50 std::vector<CTransactionRef> TRANSACTIONS;
53 constexpr
int NUM_PEERS = 16;
56 std::chrono::microseconds TIME_SKIPS[128];
62 for (
const auto& outpoint : outpoints) {
63 tx.
vin.emplace_back(outpoint);
66 tx.
vin[0].scriptWitness.stack.push_back({1});
73 std::vector<COutPoint>
ret;
83 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
84 g_setup = testing_setup.get();
85 for (uint32_t i = 0; i < uint32_t{NUM_COINS}; ++i) {
88 size_t outpoints_index = 0;
93 Assert(tx1->GetHash() == tx2->GetHash());
94 TRANSACTIONS.emplace_back(tx1);
95 TRANSACTIONS.emplace_back(tx2);
101 TRANSACTIONS.emplace_back(tx_parent_1);
103 TRANSACTIONS.emplace_back(tx_parent_2);
110 TRANSACTIONS.emplace_back(tx_parent);
118 COutPoint& last_outpoint = COINS[outpoints_index++];
119 for (
auto i{0}; i < 5; ++i) {
121 TRANSACTIONS.emplace_back(tx);
127 COutPoint& last_outpoint = COINS[outpoints_index++];
128 for (
auto i{0}; i < 5; ++i) {
130 TRANSACTIONS.emplace_back(tx);
136 for (
const auto& outpoint : COINS) {
143 for (; i < 16; ++i) {
144 TIME_SKIPS[i] = std::chrono::microseconds{i};
148 for (; i < 128; ++i) {
149 int diff_bits = ((i - 10) * 2) / 9;
151 TIME_SKIPS[i] = TIME_SKIPS[i - 1] + std::chrono::microseconds{diff};
162 const auto&
package = package_to_validate.m_txns;
164 Assert(package.size() == 2);
180 std::chrono::microseconds time{244466666};
187 auto rand_tx = fuzzed_data_provider.
ConsumeBool() ?
194 fuzzed_data_provider,
198 .m_relay_permissions = fuzzed_data_provider.
ConsumeBool(),
199 .m_wtxid_relay = fuzzed_data_provider.
ConsumeBool()
201 txdownloadman.ConnectedPeer(rand_peer, info);
204 txdownloadman.DisconnectedPeer(rand_peer);
205 txdownloadman.CheckIsEmpty(rand_peer);
208 txdownloadman.ActiveTipChange();
212 block.
vtx.push_back(rand_tx);
213 txdownloadman.BlockConnected(std::make_shared<CBlock>(block));
216 txdownloadman.BlockDisconnected();
219 txdownloadman.MempoolAcceptedTx(rand_tx);
224 bool first_time_failure{fuzzed_data_provider.
ConsumeBool()};
226 node::RejectedTxTodo todo = txdownloadman.MempoolRejectedTx(rand_tx, state, rand_peer, first_time_failure);
233 txdownloadman.AddTxAnnouncement(rand_peer, gtxid, time);
236 txdownloadman.GetRequestsToSend(rand_peer, time);
239 txdownloadman.ReceivedTx(rand_peer, rand_tx);
240 const auto& [should_validate, maybe_package] = txdownloadman.ReceivedTx(rand_peer, rand_tx);
246 Assert(!(should_validate && maybe_package.has_value()));
247 if (maybe_package.has_value()) CheckPackageToValidate(*maybe_package, rand_peer);
250 txdownloadman.ReceivedNotFound(rand_peer, {rand_tx->GetWitnessHash()});
253 const bool expect_work{txdownloadman.HaveMoreWork(rand_peer)};
254 const auto ptx = txdownloadman.GetTxToReconsider(rand_peer);
267 if (fuzzed_data_provider.
ConsumeBool()) time_skip *= -1;
271 for (
NodeId nodeid = 0; nodeid < NUM_PEERS; ++nodeid) {
272 txdownloadman.DisconnectedPeer(nodeid);
273 txdownloadman.CheckIsEmpty(nodeid);
275 txdownloadman.CheckIsEmpty();
280 static bool HasRelayPermissions(
NodeId peer) {
return peer == 0; }
291 for (
NodeId peer = 0; peer < NUM_PEERS; ++peer) {
292 if (!HasRelayPermissions(peer)) {
312 std::chrono::microseconds time{244466666};
319 auto rand_tx = fuzzed_data_provider.
ConsumeBool() ?
326 fuzzed_data_provider,
330 .m_relay_permissions = HasRelayPermissions(rand_peer),
331 .m_wtxid_relay = fuzzed_data_provider.
ConsumeBool()
342 for (
const auto& tx : TRANSACTIONS) {
351 block.
vtx.push_back(rand_tx);
367 bool first_time_failure{fuzzed_data_provider.
ConsumeBool()};
382 const auto getdata_requests = txdownload_impl.
GetRequestsToSend(rand_peer, time);
385 for (
const auto& gtxid : getdata_requests) {
390 const auto& [should_validate, maybe_package] = txdownload_impl.
ReceivedTx(rand_peer, rand_tx);
396 Assert(!(should_validate && maybe_package.has_value()));
397 if (should_validate) {
400 if (maybe_package.has_value()) {
401 CheckPackageToValidate(*maybe_package, rand_peer);
403 const auto&
package = maybe_package->m_txns;
418 const bool expect_work{txdownload_impl.
HaveMoreWork(rand_peer)};
439 if (fuzzed_data_provider.
ConsumeBool()) time_skip *= -1;
442 CheckInvariants(txdownload_impl, max_orphan_count);
444 for (
NodeId nodeid = 0; nodeid < NUM_PEERS; ++nodeid) {
std::shared_ptr< const CTransaction > CTransactionRef
bool contains(Span< const unsigned char > vKey) const
invalid by consensus rules
static GenTxid Wtxid(const uint256 &hash)
std::vector< Txid > m_unique_parents
size_t Count(NodeId peer) const
Count how many announcements a peer has (REQUESTED, CANDIDATE, and COMPLETED combined).
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of the concatenated wtxids of transactions, with wtxids treated as a little-endian numbe...
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 ...
std::pair< bool, std::optional< PackageToValidate > > ReceivedTx(NodeId nodeid, const CTransactionRef &ptx)
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...
CRollingBloomFilter & RecentConfirmedTransactionsFilter()
transaction was not validated because package failed
TxRequestTracker m_txrequest
Tracks candidates for requesting and downloading transaction data.
static const CScript P2WSH_OP_TRUE
TxOrphanage m_orphanage
Manages unvalidated tx data (orphan transactions for which we are downloading ancestors).
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
transaction was missing some of its inputs
RejectedTxTodo MempoolRejectedTx(const CTransactionRef &ptx, const TxValidationState &state, NodeId nodeid, bool first_time_failure)
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
violated mempool's fee/size/descendant/RBF/etc limits
inputs (covered by txid) failed policy rules
transaction spends a coinbase too early, or violates locktime/sequence locks
bool AddTxAnnouncement(NodeId peer, const GenTxid >xid, std::chrono::microseconds now)
Consider adding this tx hash to txrequest.
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
void SanityCheck() const
Check consistency between PeerOrphanInfo and m_orphans.
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Marks a tx as ReceivedResponse in txrequest.
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
void SanityCheck() const
Run internal consistency check (testing only).
Class responsible for deciding what transactions to request and, once downloaded, whether and how to ...
const bool m_preferred
Whether this peer is preferred for transaction download.
CRollingBloomFilter & RecentRejectsFilter()
A writer stream (for serialization) that computes a 256-bit hash.
CRollingBloomFilter & RecentRejectsReconsiderableFilter()
bool HaveMoreWork(NodeId nodeid)
static CTransactionRef MakeTransactionSpending(const std::vector< COutPoint > &outpoints, FastRandomContext &det_rand)
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Txid GetHash() const
Compute the hash of this CMutableTransaction.
An outpoint - a combination of a transaction hash and an index n into its vout.
bool m_should_add_extra_compact_tx
std::vector< CTxOut > vout
fails some policy, but might be acceptable if submitted in a (different) package
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Transaction is missing a witness.
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
std::vector< CTransactionRef > vtx
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
static transaction_identifier FromUint256(const uint256 &id)
std::vector< NodeId > m_senders
A mutable version of CTransaction.
static constexpr CAmount CENT
const uint256 & ToUint256() const LIFETIMEBOUND
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
void MempoolAcceptedTx(const CTransactionRef &tx)
CTransactionRef GetTxToReconsider(NodeId nodeid)
size_t Size() const
Return how many entries exist in the orphange.
T ConsumeIntegralInRange(T min, T max)
Seed with a compile time constant of zeros.
T PickValueInArray(const T(&array)[size])
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo &info)
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
bool AlreadyHaveTx(const GenTxid >xid, bool include_reconsiderable)
Check whether we already have this gtxid in:
void DisconnectedPeer(NodeId nodeid)
otherwise didn't meet our local policy rules
bool HaveTx(const Wtxid &wtxid) const
Check if we already have an orphan transaction (by wtxid only)
A generic txid reference (txid or wtxid).
Testing setup that configures a complete environment.
static GenTxid Txid(const uint256 &hash)
#define Assert(val)
Identity function.
CTxMemPool::Options MemPoolOptionsForTest(const NodeContext &node)
TxValidationResult
A "reason" why a transaction was invalid, suitable for determining whether the provider of the transa...