40 std::vector<COutPoint> outpoints;
41 outpoints.reserve(200
'000); 43 // initial outpoints used to construct transactions later 44 for (uint8_t i = 0; i < 4; i++) { 45 outpoints.emplace_back(Txid::FromUint256(uint256{i}), 0); 48 CTransactionRef ptx_potential_parent = nullptr; 50 std::vector<CTransactionRef> tx_history; 57 const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size());
58 const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, 256);
61 tx_mut.
vin.reserve(num_in);
62 for (uint32_t i = 0; i < num_in; i++) {
63 auto& prevout =
PickValue(fuzzed_data_provider, outpoints);
68 tx_mut.
vout.reserve(num_out);
69 for (uint32_t i = 0; i < num_out; i++) {
74 for (uint32_t i = 0; i < num_out; i++) {
75 outpoints.emplace_back(new_tx->GetHash(), i);
80 tx_history.push_back(tx);
82 const auto wtxid{tx->GetWitnessHash()};
86 if (ptx_potential_parent) {
91 NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<
NodeId>();
93 assert(std::any_of(child->vin.cbegin(), child->vin.cend(), [&](
const auto& input) {
94 return input.prevout.hash == ptx_potential_parent->GetHash();
102 NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<
NodeId>();
104 const auto total_peer_bytes_start{orphanage.
UsageByPeer(peer_id)};
108 fuzzed_data_provider,
118 bool have_tx = orphanage.
HaveTx(tx->GetWitnessHash());
122 bool add_tx = orphanage.
AddTx(tx, peer_id);
124 Assert(!have_tx || !add_tx);
132 if (orphanage.
UsageByPeer(peer_id) == tx_weight + total_peer_bytes_start) {
143 have_tx = orphanage.
HaveTx(tx->GetWitnessHash());
145 bool add_tx = orphanage.
AddTx(tx, peer_id);
148 Assert(!have_tx || !add_tx);
152 bool have_tx = orphanage.
HaveTx(tx->GetWitnessHash());
153 bool have_tx_and_peer = orphanage.
HaveTxFromPeer(tx->GetWitnessHash(), peer_id);
156 bool added_announcer = orphanage.
AddAnnouncer(tx->GetWitnessHash(), peer_id);
158 Assert(have_tx || !added_announcer);
160 Assert(!have_tx_and_peer || !added_announcer);
165 if (added_announcer) {
173 bool have_tx = orphanage.
HaveTx(tx->GetWitnessHash());
177 auto bytes_from_peer_before{orphanage.
UsageByPeer(peer_id)};
181 if (have_tx_and_peer) {
190 have_tx = orphanage.
HaveTx(tx->GetWitnessHash());
194 Assert(!have_tx && !have_tx_and_peer && !orphanage.
EraseTx(wtxid));
205 int num_txs = fuzzed_data_provider.ConsumeIntegralInRange<
unsigned int>(0, 1000);
206 for (
int i{0}; i < num_txs; ++i) {
207 auto& tx_to_remove =
PickValue(fuzzed_data_provider, tx_history);
208 block.
vtx.push_back(tx_to_remove);
211 for (
const auto& tx_removed : block.
vtx) {
212 Assert(!orphanage.
HaveTx(tx_removed->GetWitnessHash()));
219 auto limit = fuzzed_data_provider.ConsumeIntegral<
unsigned int>();
227 if (!ptx_potential_parent || fuzzed_data_provider.ConsumeBool()) {
228 ptx_potential_parent = tx;
231 const bool have_tx{orphanage.
HaveTx(tx->GetWitnessHash())};
232 const bool get_tx_nonnull{orphanage.
GetTx(tx->GetWitnessHash()) !=
nullptr};
233 Assert(have_tx == get_tx_nonnull);
std::shared_ptr< const CTransaction > CTransactionRef
CTransactionRef GetTxToReconsider(NodeId peer)
Extract a transaction from a peer's work set Returns nullptr if there are no transactions to work on...
int EraseTx(const Wtxid &wtxid)
Erase an orphan by wtxid.
bool AddAnnouncer(const Wtxid &wtxid, NodeId peer)
Add an additional announcer to an orphan if it exists.
unsigned int TotalOrphanUsage() const
Get the total usage (weight) of all orphans.
void initialize_orphanage()
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
static const uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
std::vector< CTransactionRef > GetChildrenFromSamePeer(const CTransactionRef &parent, NodeId nodeid) const
Get all children that spend from this tx and were received from nodeid.
void AddChildrenToWorkSet(const CTransaction &tx, FastRandomContext &rng)
Add any orphans that list a particular tx as a parent into the from peer's work set.
static int32_t GetTransactionWeight(const CTransaction &tx)
int64_t CAmount
Amount in satoshis (Can be negative)
CTransactionRef GetTx(const Wtxid &wtxid) const
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
unsigned int UsageByPeer(NodeId peer) const
Total usage (weight) of orphans for which this peer is an announcer.
void SanityCheck() const
Check consistency between PeerOrphanInfo and m_orphans.
void LimitOrphans(unsigned int max_orphans, FastRandomContext &rng)
Limit the orphanage to the given maximum.
void EraseForPeer(NodeId peer)
Maybe erase all orphans announced by a peer (eg, after that peer disconnects).
bool HaveTxFromPeer(const Wtxid &wtxid, NodeId peer) const
Check if a {tx, peer} exists in the orphanage.
std::vector< CTxOut > vout
bool AddTx(const CTransactionRef &tx, NodeId peer)
Add a new orphan transaction.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
static constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
std::vector< CTransactionRef > vtx
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
Serialized script, used inside transaction inputs and outputs.
static const uint32_t DEFAULT_MAX_ORPHAN_TRANSACTIONS
Default for -maxorphantx, maximum number of orphan transactions kept in memory.
A mutable version of CTransaction.
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
size_t Size() const
Return how many entries exist in the orphange.
FUZZ_TARGET(txorphan,.init=initialize_orphanage)
void EraseForBlock(const CBlock &block)
Erase all orphans included in or invalidated by a new block.
bool HaveTx(const Wtxid &wtxid) const
Check if we already have an orphan transaction (by wtxid only)
#define Assert(val)
Identity function.
std::unique_ptr< T > MakeNoLogFileContext(const ChainType chain_type=ChainType::REGTEST, TestOpts opts={})
Make a test setup that has disk access to the debug.log file disabled.