39 std::vector<COutPoint> outpoints;
41 for (uint8_t i = 0; i < 4; i++) {
42 outpoints.emplace_back(
uint256{i}, 0);
45 const bool duplicate_input = fuzzed_data_provider.ConsumeBool();
47 LIMITED_WHILE(outpoints.size() < 200
'000 && fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS) 49 // construct transaction 50 const CTransactionRef tx = [&] { 51 CMutableTransaction tx_mut; 52 const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size()); 53 const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size()); 54 // pick unique outpoints from outpoints as input 55 for (uint32_t i = 0; i < num_in; i++) { 56 auto& prevout = PickValue(fuzzed_data_provider, outpoints); 57 tx_mut.vin.emplace_back(prevout); 58 // pop the picked outpoint if duplicate input is not allowed 59 if (!duplicate_input) { 60 std::swap(prevout, outpoints.back()); 64 // output amount will not affect txorphanage 65 for (uint32_t i = 0; i < num_out; i++) { 66 tx_mut.vout.emplace_back(CAmount{0}, CScript{}); 68 // restore previously popped outpoints 69 for (auto& in : tx_mut.vin) { 70 outpoints.push_back(in.prevout); 72 auto new_tx = MakeTransactionRef(tx_mut); 73 // add newly constructed transaction to outpoints 74 for (uint32_t i = 0; i < num_out; i++) { 75 outpoints.emplace_back(new_tx->GetHash(), i); 80 // trigger orphanage functions 81 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS) 83 NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<NodeId>(); 88 orphanage.AddChildrenToWorkSet(*tx); 92 CTransactionRef ref = orphanage.GetTxToReconsider(peer_id); 94 bool have_tx = orphanage.HaveTx(GenTxid::Txid(ref->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(ref->GetHash())); 100 bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 101 // AddTx should return false if tx is too big or already have it 102 // tx weight is unknown, we only check when tx is already in orphanage 104 bool add_tx = orphanage.AddTx(tx, peer_id); 105 // have_tx == true -> add_tx == false 106 Assert(!have_tx || !add_tx); 108 have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 110 bool add_tx = orphanage.AddTx(tx, peer_id); 111 // if have_tx is still false, it must be too big 112 Assert(!have_tx == (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT)); 113 Assert(!have_tx || !add_tx); 117 bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 118 // EraseTx should return 0 if m_orphans doesn't have the tx
129 orphanage.EraseForPeer(peer_id);
134 auto limit = fuzzed_data_provider.ConsumeIntegral<
unsigned int>();
135 orphanage.LimitOrphans(limit);
136 Assert(orphanage.Size() <= limit);
static GenTxid Wtxid(const uint256 &hash)
void initialize_orphanage()
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
int EraseTx(const uint256 &txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase an orphan by txid.
std::unique_ptr< T > MakeNoLogFileContext(const ChainType chain_type=ChainType::REGTEST, const std::vector< const char *> &extra_args={})
Make a test setup that has disk access to the debug.log file disabled.
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
bool HaveTx(const GenTxid >xid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if we already have an orphan transaction (by txid or wtxid)
FUZZ_TARGET(txorphan,.init=initialize_orphanage)
static GenTxid Txid(const uint256 &hash)
#define Assert(val)
Identity function.