40 std::vector<COutPoint> outpoints;
42 for (uint8_t i = 0; i < 4; i++) {
46 const bool duplicate_input = fuzzed_data_provider.ConsumeBool();
48 LIMITED_WHILE(outpoints.size() < 200
'000 && fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS) 50 // construct transaction 51 const CTransactionRef tx = [&] { 52 CMutableTransaction tx_mut; 53 const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size()); 54 const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size()); 55 // pick unique outpoints from outpoints as input 56 for (uint32_t i = 0; i < num_in; i++) { 57 auto& prevout = PickValue(fuzzed_data_provider, outpoints); 58 tx_mut.vin.emplace_back(prevout); 59 // pop the picked outpoint if duplicate input is not allowed 60 if (!duplicate_input) { 61 std::swap(prevout, outpoints.back()); 65 // output amount will not affect txorphanage 66 for (uint32_t i = 0; i < num_out; i++) { 67 tx_mut.vout.emplace_back(CAmount{0}, CScript{}); 69 // restore previously popped outpoints 70 for (auto& in : tx_mut.vin) { 71 outpoints.push_back(in.prevout); 73 auto new_tx = MakeTransactionRef(tx_mut); 74 // add newly constructed transaction to outpoints 75 for (uint32_t i = 0; i < num_out; i++) { 76 outpoints.emplace_back(new_tx->GetHash(), i); 81 // trigger orphanage functions 82 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS) 84 NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<NodeId>(); 89 orphanage.AddChildrenToWorkSet(*tx); 93 CTransactionRef ref = orphanage.GetTxToReconsider(peer_id); 95 bool have_tx = orphanage.HaveTx(GenTxid::Txid(ref->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(ref->GetWitnessHash())); 101 bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetWitnessHash())); 102 // AddTx should return false if tx is too big or already have it 103 // tx weight is unknown, we only check when tx is already in orphanage 105 bool add_tx = orphanage.AddTx(tx, peer_id); 106 // have_tx == true -> add_tx == false 107 Assert(!have_tx || !add_tx); 109 have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetWitnessHash())); 111 bool add_tx = orphanage.AddTx(tx, peer_id); 112 // if have_tx is still false, it must be too big 113 Assert(!have_tx == (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT)); 114 Assert(!have_tx || !add_tx); 118 bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetWitnessHash())); 119 // EraseTx should return 0 if m_orphans doesn't have the tx
130 orphanage.EraseForPeer(peer_id);
135 auto limit = fuzzed_data_provider.ConsumeIntegral<
unsigned int>();
136 orphanage.LimitOrphans(limit, limit_orphans_rng);
137 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...
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.
int EraseTx(const Txid &txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase an orphan by txid.
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
static transaction_identifier FromUint256(const uint256 &id)
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.