27 std::vector<COutPoint> g_outpoints_coinbase_init_mature;
33 lastRollingFeeUpdate =
GetTime();
34 blockSinceLastRollingFeeBump =
true;
38 void initialize_tx_pool()
40 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
41 g_setup = testing_setup.get();
47 g_outpoints_coinbase_init_mature.push_back(prevout);
54 std::set<COutPoint>& m_mempool_outpoints;
56 explicit OutpointsUpdater(std::set<COutPoint>& r)
57 : m_mempool_outpoints{r} {}
64 for (uint32_t index{0}; index < tx.
info.
m_tx->vout.size(); ++index) {
72 for (
const auto& input : tx->vin) {
74 m_mempool_outpoints.insert(input.prevout);
77 for (uint32_t index{0}; index < tx->vout.size(); ++index) {
78 m_mempool_outpoints.erase(
COutPoint{tx->GetHash(), index});
84 std::set<CTransactionRef>& m_added;
86 explicit TransactionsDelta(std::set<CTransactionRef>& a)
104 const auto time =
ConsumeTime(fuzzed_data_provider,
106 std::numeric_limits<decltype(chainstate.
m_chain.
Tip()->
nTime)>::max());
118 mempool_opts.limits.ancestor_size_vbytes = fuzzed_data_provider.
ConsumeIntegralInRange<
unsigned>(0, 202) * 1'000;
120 mempool_opts.limits.descendant_size_vbytes = fuzzed_data_provider.
ConsumeIntegralInRange<
unsigned>(0, 202) * 1'000;
126 mempool_opts.check_ratio = 1;
127 mempool_opts.require_standard = fuzzed_data_provider.
ConsumeBool();
139 MockTime(fuzzed_data_provider, chainstate);
142 std::set<COutPoint> mempool_outpoints;
143 std::map<COutPoint, CAmount> outpoints_value;
144 for (
const auto& outpoint : g_outpoints_coinbase_init_mature) {
145 Assert(mempool_outpoints.insert(outpoint).second);
146 outpoints_value[outpoint] = 50 *
COIN;
149 auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
150 node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
153 MockedTxPool& tx_pool = *
static_cast<MockedTxPool*
>(&tx_pool_);
155 chainstate.SetMempool(&tx_pool);
159 Assert(!mempool_outpoints.empty());
161 std::vector<CTransactionRef> txs;
165 std::set<COutPoint> package_outpoints;
166 while (txs.size() < num_txs) {
171 bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
179 const auto num_in = last_tx ? package_outpoints.size() : fuzzed_data_provider.
ConsumeIntegralInRange<
int>(1, mempool_outpoints.size());
182 auto& outpoints = last_tx ? package_outpoints : mempool_outpoints;
184 Assert(!outpoints.empty());
187 for (
size_t i = 0; i < num_in; ++i) {
189 auto pop = outpoints.begin();
191 const auto outpoint = *pop;
192 outpoints.erase(pop);
194 amount_in += outpoints_value.at(outpoint);
198 const auto script_sig =
CScript{};
207 tx_mut.
vin.push_back(in);
211 bool dup_input = fuzzed_data_provider.
ConsumeBool();
213 tx_mut.
vin.push_back(tx_mut.
vin.back());
218 tx_mut.
vin.emplace_back();
222 if (last_tx && amount_in > 1000 && fuzzed_data_provider.
ConsumeBool()) {
230 const auto amount_out = (amount_in - amount_fee) / num_out;
231 for (
int i = 0; i < num_out; ++i) {
237 for (
const auto& in : tx->vin) {
242 for (
size_t i = 0; i < tx->vout.size(); ++i) {
243 package_outpoints.emplace(tx->GetHash(), i);
247 for (
size_t i = 0; i < tx->vout.size(); ++i) {
248 outpoints_value[
COutPoint(tx->GetHash(), i)] = tx->vout[i].nValue;
256 MockTime(fuzzed_data_provider, chainstate);
259 tx_pool.RollingFeeUpdate();
262 const auto& txid = fuzzed_data_provider.
ConsumeBool() ?
263 txs.back()->GetHash() :
264 PickValue(fuzzed_data_provider, mempool_outpoints).hash;
266 tx_pool.PrioritiseTransaction(txid.ToUint256(), delta);
270 std::set<CTransactionRef> added;
271 auto txr = std::make_shared<TransactionsDelta>(added);
272 node.validation_signals->RegisterSharedValidationInterface(txr);
277 auto single_submit = txs.size() == 1 && fuzzed_data_provider.
ConsumeBool();
280 std::optional<CFeeRate> client_maxfeerate{};
286 return ProcessNewPackage(chainstate, tx_pool, txs, single_submit, client_maxfeerate));
291 false, !single_submit));
294 node.validation_signals->SyncWithValidationInterfaceQueue();
295 node.validation_signals->UnregisterSharedValidationInterface(txr);
299 Assert(passed != added.empty());
300 Assert(passed == res.m_state.IsValid());
302 Assert(added.size() == 1);
303 Assert(txs.back() == *added.begin());
309 const bool expect_valid{result_package.m_state.IsValid()};
313 Assert(result_package.m_tx_results.size() == txs.size() || result_package.m_tx_results.empty());
319 node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
int64_t CAmount
Amount in satoshis (Can be negative)
static constexpr CAmount COIN
The amount of satoshis in one BTC.
#define Assert(val)
Identity function.
int64_t GetMedianTimePast() const
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
int Height() const
Return the maximal height in the chain.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
An outpoint - a combination of a transaction hash and an index n into its vout.
Serialized script, used inside transaction inputs and outputs.
static const int32_t CURRENT_VERSION
An input of a transaction.
CScriptWitness scriptWitness
Only serialized through CTransaction.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Implement this to subscribe to events generated in validation and mempool.
virtual void TransactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence)
Notifies listeners of a transaction leaving mempool.
virtual void TransactionAddedToMempool(const NewMempoolTransactionInfo &tx, uint64_t mempool_sequence)
Notifies listeners of a transaction having been added to mempool.
Chainstate stores and provides an API to update our local knowledge of the current best chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
T ConsumeIntegralInRange(T min, T max)
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).
unsigned int nBytesPerSigOp
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
A mutable version of CTransaction.
std::vector< CTxOut > vout
std::vector< std::vector< unsigned char > > stack
Testing setup that configures a complete environment.
const CTransactionRef m_tx
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors.
Options struct containing options for constructing a CTxMemPool.
NodeContext struct containing references to chain state and connection state.
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
uint32_t ConsumeSequence(FuzzedDataProvider &fuzzed_data_provider) noexcept
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
COutPoint MineBlock(const NodeContext &node, const CScript &coinbase_scriptPubKey)
Returns the generated coin.
static const std::vector< std::vector< uint8_t > > P2WSH_EMPTY_TRUE_STACK
static const std::vector< std::vector< uint8_t > > P2WSH_EMPTY_TWO_STACK
static const CScript P2WSH_EMPTY
CTxMemPool::Options MemPoolOptionsForTest(const NodeContext &node)
std::optional< std::string > CheckPackageMempoolAcceptResult(const Package &txns, const PackageMempoolAcceptResult &result, bool expect_valid, const CTxMemPool *mempool)
Check expected properties for every PackageMempoolAcceptResult, regardless of value.
void CheckMempoolV3Invariants(const CTxMemPool &tx_pool)
For every transaction in tx_pool, check v3 invariants:
#define EXCLUSIVE_LOCKS_REQUIRED(...)
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
MempoolAcceptResult AcceptToMemoryPool(Chainstate &active_chainstate, const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(
Try to add a transaction to the mempool.