29std::vector<COutPoint> g_outpoints_coinbase_init_mature;
35 lastRollingFeeUpdate =
GetTime();
36 blockSinceLastRollingFeeBump =
true;
40void initialize_tx_pool()
43 g_setup = testing_setup.get();
49 g_outpoints_coinbase_init_mature.push_back(prevout);
56 std::set<COutPoint>& m_mempool_outpoints;
58 explicit OutpointsUpdater(std::set<COutPoint>& r)
59 : m_mempool_outpoints{r} {}
66 for (uint32_t index{0}; index < tx.
info.
m_tx->vout.size(); ++index) {
74 for (
const auto& input : tx->vin) {
76 m_mempool_outpoints.insert(input.prevout);
79 for (uint32_t index{0}; index < tx->vout.size(); ++index) {
80 m_mempool_outpoints.erase(
COutPoint{tx->GetHash(), index});
86 std::set<CTransactionRef>& m_added;
88 explicit TransactionsDelta(std::set<CTransactionRef>& a)
106 const auto time =
ConsumeTime(fuzzed_data_provider,
108 std::numeric_limits<
decltype(chainstate.
m_chain.
Tip()->
nTime)>::max());
120 mempool_opts.limits.ancestor_size_vbytes = fuzzed_data_provider.
ConsumeIntegralInRange<
unsigned>(0, 202) * 1'000;
122 mempool_opts.limits.descendant_size_vbytes = fuzzed_data_provider.
ConsumeIntegralInRange<
unsigned>(0, 202) * 1'000;
128 mempool_opts.check_ratio = 1;
129 mempool_opts.require_standard = fuzzed_data_provider.
ConsumeBool();
133 auto mempool{std::make_unique<CTxMemPool>(std::move(mempool_opts), error)};
146 MockTime(fuzzed_data_provider, chainstate);
149 std::set<COutPoint> mempool_outpoints;
150 std::map<COutPoint, CAmount> outpoints_value;
151 for (
const auto& outpoint : g_outpoints_coinbase_init_mature) {
152 Assert(mempool_outpoints.insert(outpoint).second);
153 outpoints_value[outpoint] = 50 *
COIN;
156 auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
157 node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
159 auto tx_pool_{MakeMempool(fuzzed_data_provider,
node)};
160 MockedTxPool& tx_pool = *
static_cast<MockedTxPool*
>(tx_pool_.get());
162 chainstate.SetMempool(&tx_pool);
166 Assert(!mempool_outpoints.empty());
168 std::vector<CTransactionRef> txs;
172 std::set<COutPoint> package_outpoints;
173 while (txs.size() < num_txs) {
178 bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
186 const auto num_in = last_tx ? package_outpoints.size() : fuzzed_data_provider.
ConsumeIntegralInRange<
int>(1, mempool_outpoints.size());
189 auto& outpoints = last_tx ? package_outpoints : mempool_outpoints;
191 Assert(!outpoints.empty());
194 for (
size_t i = 0; i < num_in; ++i) {
196 auto pop = outpoints.begin();
198 const auto outpoint = *pop;
199 outpoints.erase(pop);
201 amount_in += outpoints_value.at(outpoint);
205 const auto script_sig =
CScript{};
214 tx_mut.
vin.push_back(in);
218 bool dup_input = fuzzed_data_provider.
ConsumeBool();
220 tx_mut.
vin.push_back(tx_mut.
vin.back());
225 tx_mut.
vin.emplace_back();
229 if (last_tx && amount_in > 1000 && fuzzed_data_provider.
ConsumeBool()) {
237 const auto amount_out = (amount_in - amount_fee) / num_out;
238 for (
int i = 0; i < num_out; ++i) {
244 for (
const auto& in : tx->vin) {
249 for (
size_t i = 0; i < tx->vout.size(); ++i) {
250 package_outpoints.emplace(tx->GetHash(), i);
254 for (
size_t i = 0; i < tx->vout.size(); ++i) {
255 outpoints_value[
COutPoint(tx->GetHash(), i)] = tx->vout[i].nValue;
263 MockTime(fuzzed_data_provider, chainstate);
266 tx_pool.RollingFeeUpdate();
269 const auto& txid = fuzzed_data_provider.
ConsumeBool() ?
270 txs.back()->GetHash() :
271 PickValue(fuzzed_data_provider, mempool_outpoints).hash;
273 tx_pool.PrioritiseTransaction(txid.ToUint256(), delta);
277 std::set<CTransactionRef> added;
278 auto txr = std::make_shared<TransactionsDelta>(added);
279 node.validation_signals->RegisterSharedValidationInterface(txr);
284 auto single_submit = txs.size() == 1 && fuzzed_data_provider.
ConsumeBool();
287 std::optional<CFeeRate> client_maxfeerate{};
293 return ProcessNewPackage(chainstate, tx_pool, txs, single_submit, client_maxfeerate));
298 false, !single_submit));
301 node.validation_signals->SyncWithValidationInterfaceQueue();
302 node.validation_signals->UnregisterSharedValidationInterface(txr);
306 Assert(passed != added.empty());
307 Assert(passed == res.m_state.IsValid());
309 Assert(added.size() == 1);
310 Assert(txs.back() == *added.begin());
316 const bool expect_valid{result_package.m_state.IsValid()};
320 Assert(result_package.m_tx_results.size() == txs.size() || result_package.m_tx_results.empty());
326 node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
328 WITH_LOCK(
::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
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.
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 uint32_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.
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.
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
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.
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
void CheckMempoolTRUCInvariants(const CTxMemPool &tx_pool)
For every transaction in tx_pool, check TRUC invariants:
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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
static constexpr decltype(CTransaction::version) TRUC_VERSION
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)
Try to add a transaction to the mempool.