Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
package_eval.cpp
Go to the documentation of this file.
1// Copyright (c) 2023-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <chain.h>
6#include <consensus/amount.h>
9#include <node/mining_types.h>
10#include <policy/feerate.h>
11#include <policy/packages.h>
12#include <policy/policy.h>
13#include <policy/settings.h>
14#include <policy/truc_policy.h>
16#include <script/script.h>
17#include <sync.h>
19#include <test/fuzz/fuzz.h>
20#include <test/fuzz/util.h>
23#include <test/util/mining.h>
24#include <test/util/random.h>
25#include <test/util/script.h>
27#include <test/util/txmempool.h>
28#include <txmempool.h>
29#include <util/check.h>
30#include <util/hasher.h>
31#include <util/time.h>
32#include <util/translation.h>
33#include <validation.h>
34#include <validationinterface.h>
35
36#include <cstddef>
37#include <cstdint>
38#include <functional>
39#include <iterator>
40#include <limits>
41#include <map>
42#include <memory>
43#include <optional>
44#include <set>
45#include <span>
46#include <string>
47#include <unordered_map>
48#include <utility>
49#include <vector>
51
52namespace {
53
55std::vector<COutPoint> g_outpoints_coinbase_init_mature;
56constexpr ReachabilityGoal EPHEMERAL_PACKAGE_EVAL_PROCESSES_VALID_PACKAGE{"ephemeral_package_eval processes a valid package"};
57constexpr ReachabilityGoal TX_PACKAGE_EVAL_PROCESSES_VALID_PACKAGE{"tx_package_eval processes a valid package"};
58
59struct MockedTxPool : public CTxMemPool {
61 {
62 LOCK(cs);
65 }
66};
67
69{
70 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
71 g_setup = testing_setup.get();
72 SetMockTime(WITH_LOCK(g_setup->m_node.chainman->GetMutex(), return g_setup->m_node.chainman->ActiveTip()->Time()));
73
74 for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
76 .coinbase_output_script = P2WSH_EMPTY,
77 })};
78 if (i < COINBASE_MATURITY) {
79 // Remember the txids to avoid expensive disk access later on
80 g_outpoints_coinbase_init_mature.push_back(prevout);
81 }
82 }
83 g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
84}
85
87{
90}
91
93{
96}
97
98struct OutpointsUpdater final : public CValidationInterface {
99 std::set<COutPoint>& m_mempool_outpoints;
100
101 explicit OutpointsUpdater(std::set<COutPoint>& r)
102 : m_mempool_outpoints{r} {}
103
104 void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t /* mempool_sequence */) override
105 {
106 // for coins spent we always want to be able to rbf so they're not removed
107
108 // outputs from this tx can now be spent
109 for (uint32_t index{0}; index < tx.info.m_tx->vout.size(); ++index) {
110 m_mempool_outpoints.insert(COutPoint{tx.info.m_tx->GetHash(), index});
111 }
112 }
113
114 void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t /* mempool_sequence */) override
115 {
116 // outpoints spent by this tx are now available
117 for (const auto& input : tx->vin) {
118 // Could already exist if this was a replacement
119 m_mempool_outpoints.insert(input.prevout);
120 }
121 // outpoints created by this tx no longer exist
122 for (uint32_t index{0}; index < tx->vout.size(); ++index) {
123 m_mempool_outpoints.erase(COutPoint{tx->GetHash(), index});
124 }
125 }
126};
127
128struct TransactionsDelta final : public CValidationInterface {
129 std::set<CTransactionRef>& m_added;
130
131 explicit TransactionsDelta(std::set<CTransactionRef>& a)
132 : m_added{a} {}
133
134 void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t /* mempool_sequence */) override
135 {
136 // Transactions may be entered and booted any number of times
137 m_added.insert(tx.info.m_tx);
138 }
139
140 void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t /* mempool_sequence */) override
141 {
142 // Transactions may be entered and booted any number of times
143 m_added.erase(tx);
144 }
145};
146
148{
149 const auto time = ConsumeTime(fuzzed_data_provider,
150 chainstate.m_chain.Tip()->GetMedianTimePast() + 1,
151 std::numeric_limits<decltype(chainstate.m_chain.Tip()->nTime)>::max());
152 SetMockTime(time);
153}
154
155std::unique_ptr<CTxMemPool> MakeMempool(FuzzedDataProvider& fuzzed_data_provider, const NodeContext& node)
156{
157 // Take the default options for tests...
159
160
161 // ...override specific options for this specific fuzz suite
163 mempool_opts.limits.descendant_count = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50);
164 mempool_opts.max_size_bytes = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 200) * 1'000'000;
165 mempool_opts.expiry = std::chrono::hours{fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 999)};
166 // Only interested in 2 cases: sigop cost 0 or when single legacy sigop cost is >> 1KvB
168
169 mempool_opts.check_ratio = 1;
170 mempool_opts.require_standard = fuzzed_data_provider.ConsumeBool();
171
172 bilingual_str error;
173 // ...and construct a CTxMemPool from it
174 auto mempool{std::make_unique<CTxMemPool>(std::move(mempool_opts), error)};
175 // ... ignore the error since it might be beneficial to fuzz even when the
176 // mempool size is unreasonably small
177 Assert(error.empty() || error.original.starts_with("-maxmempool must be at least "));
178 return mempool;
179}
180
181std::unique_ptr<CTxMemPool> MakeEphemeralMempool(const NodeContext& node)
182{
183 // Take the default options for tests...
185
187
188 // Require standardness rules otherwise ephemeral dust is no-op
189 mempool_opts.require_standard = true;
190
191 // And set minrelay to 0 to allow ephemeral parent tx even with non-TRUC
192 mempool_opts.min_relay_feerate = CFeeRate(0);
193
194 bilingual_str error;
195 // ...and construct a CTxMemPool from it
196 auto mempool{std::make_unique<CTxMemPool>(std::move(mempool_opts), error)};
197 Assert(error.empty());
198 return mempool;
199}
200
201// Scan mempool for a tx that has spent dust and return a
202// prevout of the child that isn't the dusty parent itself.
203// This is used to double-spend the child out of the mempool,
204// leaving the parent childless.
205// This assumes CheckMempoolEphemeralInvariants has passed for tx_pool.
206std::optional<COutPoint> GetChildEvictingPrevout(const CTxMemPool& tx_pool)
207{
208 LOCK(tx_pool.cs);
209 for (const auto& tx_info : tx_pool.infoAll()) {
210 const auto& entry = *Assert(tx_pool.GetEntry(tx_info.tx->GetHash()));
211 std::vector<uint32_t> dust_indexes{GetDust(*tx_info.tx, tx_pool.m_opts.dust_relay_feerate)};
212 if (!dust_indexes.empty()) {
213 const auto& children = tx_pool.GetChildren(entry);
214 if (!children.empty()) {
215 Assert(children.size() == 1);
216 // Find an input that doesn't spend from parent's txid
217 const auto& only_child = children.begin()->get().GetTx();
218 for (const auto& tx_input : only_child.vin) {
219 if (tx_input.prevout.hash != tx_info.tx->GetHash()) {
220 return tx_input.prevout;
221 }
222 }
223 }
224 }
225 }
226
227 return std::nullopt;
228}
229
231{
233 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
234 const auto& node = g_setup->m_node;
235 auto& chainstate{static_cast<DummyChainState&>(node.chainman->ActiveChainstate())};
236
238
239 // All RBF-spendable outpoints outside of the unsubmitted package
240 std::set<COutPoint> mempool_outpoints;
241 std::unordered_map<COutPoint, CAmount, SaltedOutpointHasher> outpoints_value;
242 for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
243 Assert(mempool_outpoints.insert(outpoint).second);
244 outpoints_value[outpoint] = 50 * COIN;
245 }
246
247 auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
248 node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
249
251 MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(tx_pool_.get());
252
253 chainstate.SetMempool(&tx_pool);
254
255 bool valid_package{false};
256
258 Assert(!mempool_outpoints.empty());
259
260 std::vector<CTransactionRef> txs;
261
262 // Find something we may want to double-spend with two input single tx
264
265 // Make small packages
267
268 std::set<COutPoint> package_outpoints;
269 while (txs.size() < num_txs) {
270 // Create transaction to add to the mempool
271 txs.emplace_back([&] {
274 tx_mut.nLockTime = 0;
275 // Last transaction in a package needs to be a child of parents to get further in validation
276 // so the last transaction to be generated(in a >1 package) must spend all package-made outputs
277 // Note that this test currently only spends package outputs in last transaction.
278 bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
279 const auto num_in = outpoint_to_rbf ? 2 :
281 fuzzed_data_provider.ConsumeIntegralInRange<int>(1, 4);
283
284 auto& outpoints = last_tx ? package_outpoints : mempool_outpoints;
285
286 Assert((int)outpoints.size() >= num_in && num_in > 0);
287
289 for (int i = 0; i < num_in; ++i) {
290 // Pop random outpoint. We erase them to avoid double-spending
291 // while in this loop, but later add them back (unless last_tx).
292 auto pop = outpoints.begin();
293 std::advance(pop, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, outpoints.size() - 1));
294 auto outpoint = *pop;
295
296 if (i == 0 && outpoint_to_rbf) {
297 outpoint = *outpoint_to_rbf;
298 outpoints.erase(outpoint);
299 } else {
300 outpoints.erase(pop);
301 }
302 // no need to update or erase from outpoints_value
303 amount_in += outpoints_value.at(outpoint);
304
305 // Create input
306 CTxIn in;
307 in.prevout = outpoint;
309
310 tx_mut.vin.push_back(in);
311 }
312
314 const auto amount_out = (amount_in - amount_fee) / num_out;
315 for (int i = 0; i < num_out; ++i) {
316 tx_mut.vout.emplace_back(amount_out, P2WSH_EMPTY);
317 }
318
319 // Note output amounts can naturally drop to dust on their own.
322 tx_mut.vout.insert(tx_mut.vout.begin() + dust_index, CTxOut(0, P2WSH_EMPTY));
323 }
324
325 auto tx = MakeTransactionRef(tx_mut);
326 // Restore previously removed outpoints, except in-package outpoints (to allow RBF)
327 if (!last_tx) {
328 for (const auto& in : tx->vin) {
329 Assert(outpoints.insert(in.prevout).second);
330 }
331 // Cache the in-package outpoints being made
332 for (size_t i = 0; i < tx->vout.size(); ++i) {
333 package_outpoints.emplace(tx->GetHash(), i);
334 }
335 }
336 // We need newly-created values for the duration of this run
337 for (size_t i = 0; i < tx->vout.size(); ++i) {
338 outpoints_value[COutPoint(tx->GetHash(), i)] = tx->vout[i].nValue;
339 }
340 return tx;
341 }());
342 }
343
345 const auto& txid = fuzzed_data_provider.ConsumeBool() ?
346 txs.back()->GetHash() :
348 const auto delta = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-50 * COIN, +50 * COIN);
349 // We only prioritise out of mempool transactions since PrioritiseTransaction doesn't
350 // filter for ephemeral dust
351 if (tx_pool.exists(txid)) {
352 const auto tx_info{tx_pool.info(txid)};
353 if (GetDust(*tx_info.tx, tx_pool.m_opts.dust_relay_feerate).empty()) {
354 tx_pool.PrioritiseTransaction(txid, delta);
355 }
356 }
357 }
358
359 auto single_submit = txs.size() == 1;
360
362 return ProcessNewPackage(chainstate, tx_pool, txs, /*test_accept=*/single_submit, /*client_maxfeerate=*/{}));
363 valid_package |= result_package.m_state.IsValid();
364
365 const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, txs.back(), GetTime(),
366 /*bypass_limits=*/false, /*test_accept=*/!single_submit));
367
369 // We don't know anything about the validity since transactions were randomly generated, so
370 // just use result_package.m_state here. This makes the expect_valid check meaningless, but
371 // we can still verify that the contents of m_tx_results are consistent with m_state.
372 const bool expect_valid{result_package.m_state.IsValid()};
374 }
375
376 node.validation_signals->SyncWithValidationInterfaceQueue();
377
379 }
380
381 node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
382
383 WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
385}
386
387
389{
391 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
392 const auto& node = g_setup->m_node;
393 auto& chainstate{static_cast<DummyChainState&>(node.chainman->ActiveChainstate())};
394
396
397 // All RBF-spendable outpoints outside of the unsubmitted package
398 std::set<COutPoint> mempool_outpoints;
399 std::unordered_map<COutPoint, CAmount, SaltedOutpointHasher> outpoints_value;
400 for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
401 Assert(mempool_outpoints.insert(outpoint).second);
402 outpoints_value[outpoint] = 50 * COIN;
403 }
404
405 auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
406 node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
407
408 auto tx_pool_{MakeMempool(fuzzed_data_provider, node)};
409 MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(tx_pool_.get());
410
411 chainstate.SetMempool(&tx_pool);
412
413 bool valid_package{false};
414
416 Assert(!mempool_outpoints.empty());
417
418 std::vector<CTransactionRef> txs;
419
420 // Make packages of 1-to-26 transactions
421 const auto num_txs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 26);
422 std::set<COutPoint> package_outpoints;
423 while (txs.size() < num_txs) {
424 // Create transaction to add to the mempool
425 txs.emplace_back([&] {
429 // Last transaction in a package needs to be a child of parents to get further in validation
430 // so the last transaction to be generated(in a >1 package) must spend all package-made outputs
431 // Note that this test currently only spends package outputs in last transaction.
432 bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
435
436 auto& outpoints = last_tx ? package_outpoints : mempool_outpoints;
437
438 Assert(!outpoints.empty());
439
441 for (size_t i = 0; i < num_in; ++i) {
442 // Pop random outpoint. We erase them to avoid double-spending
443 // while in this loop, but later add them back (unless last_tx).
444 auto pop = outpoints.begin();
445 std::advance(pop, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, outpoints.size() - 1));
446 const auto outpoint = *pop;
447 outpoints.erase(pop);
448 // no need to update or erase from outpoints_value
449 amount_in += outpoints_value.at(outpoint);
450
451 // Create input
453 const auto script_sig = CScript{};
455
456 CTxIn in;
457 in.prevout = outpoint;
458 in.nSequence = sequence;
461
462 tx_mut.vin.push_back(in);
463 }
464
465 // Duplicate an input
467 if (dup_input) {
468 tx_mut.vin.push_back(tx_mut.vin.back());
469 }
470
471 // Refer to a non-existent input
473 tx_mut.vin.emplace_back();
474 }
475
476 // Make a p2pk output to make sigops adjusted vsize to violate TRUC rules, potentially, which is never spent
478 tx_mut.vout.emplace_back(1000, CScript() << std::vector<unsigned char>(33, 0x02) << OP_CHECKSIG);
479 // Don't add any other outputs.
480 num_out = 1;
481 amount_in -= 1000;
482 }
483
485 const auto amount_out = (amount_in - amount_fee) / num_out;
486 for (int i = 0; i < num_out; ++i) {
487 tx_mut.vout.emplace_back(amount_out, P2WSH_EMPTY);
488 }
489 auto tx = MakeTransactionRef(tx_mut);
490 // Restore previously removed outpoints, except in-package outpoints
491 if (!last_tx) {
492 for (const auto& in : tx->vin) {
493 // It's a fake input, or a new input, or a duplicate
494 Assert(in == CTxIn() || outpoints.insert(in.prevout).second || dup_input);
495 }
496 // Cache the in-package outpoints being made
497 for (size_t i = 0; i < tx->vout.size(); ++i) {
498 package_outpoints.emplace(tx->GetHash(), i);
499 }
500 }
501 // We need newly-created values for the duration of this run
502 for (size_t i = 0; i < tx->vout.size(); ++i) {
503 outpoints_value[COutPoint(tx->GetHash(), i)] = tx->vout[i].nValue;
504 }
505 return tx;
506 }());
507 }
508
511 }
513 tx_pool.RollingFeeUpdate();
514 }
516 const auto& txid = fuzzed_data_provider.ConsumeBool() ?
517 txs.back()->GetHash() :
519 const auto delta = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-50 * COIN, +50 * COIN);
520 tx_pool.PrioritiseTransaction(txid, delta);
521 }
522
523 // Remember all added transactions
524 std::set<CTransactionRef> added;
525 auto txr = std::make_shared<TransactionsDelta>(added);
526 node.validation_signals->RegisterSharedValidationInterface(txr);
527
528 // When there are multiple transactions in the package, we call ProcessNewPackage(txs, test_accept=false)
529 // and AcceptToMemoryPool(txs.back(), test_accept=true). When there is only 1 transaction, we might flip it
530 // (the package is a test accept and ATMP is a submission).
531 auto single_submit = txs.size() == 1 && fuzzed_data_provider.ConsumeBool();
532
533 // Exercise client_maxfeerate logic
534 std::optional<CFeeRate> client_maxfeerate{};
537 }
538
541 valid_package |= result_package.m_state.IsValid();
542
543 // Always set bypass_limits to false because it is not supported in ProcessNewPackage and
544 // can be a source of divergence.
545 const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, txs.back(), GetTime(),
546 /*bypass_limits=*/false, /*test_accept=*/!single_submit));
547 const bool passed = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
548
549 node.validation_signals->SyncWithValidationInterfaceQueue();
550 node.validation_signals->UnregisterSharedValidationInterface(txr);
551
552 // There is only 1 transaction in the package. We did a test-package-accept and a ATMP
553 if (single_submit) {
554 Assert(passed != added.empty());
555 Assert(passed == res.m_state.IsValid());
556 if (passed) {
557 Assert(added.size() == 1);
558 Assert(txs.back() == *added.begin());
559 }
560 } else if (result_package.m_state.GetResult() != PackageValidationResult::PCKG_POLICY) {
561 // We don't know anything about the validity since transactions were randomly generated, so
562 // just use result_package.m_state here. This makes the expect_valid check meaningless, but
563 // we can still verify that the contents of m_tx_results are consistent with m_state.
564 const bool expect_valid{result_package.m_state.IsValid()};
566 } else {
567 // This is empty if it fails early checks, or "full" if transactions are looked at deeper
568 Assert(result_package.m_tx_results.size() == txs.size() || result_package.m_tx_results.empty());
569 }
570
572
573 // Dust checks only make sense when dust is enforced
574 if (tx_pool.m_opts.require_standard) {
576 }
577 }
578
579 node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
580
581 WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
583}
584} // namespace
int64_t CAmount
Amount in satoshis (Can be negative)
Definition amount.h:12
constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition amount.h:15
static void pool cs
const TestingSetup * g_setup
#define Assert(val)
Identity function.
Definition check.h:119
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
Definition feerate.h:32
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition transaction.h:30
Serialized script, used inside transaction inputs and outputs.
Definition script.h:406
static constexpr uint32_t CURRENT_VERSION
An input of a transaction.
Definition transaction.h:63
uint32_t nSequence
Definition transaction.h:67
CScript scriptSig
Definition transaction.h:66
CScriptWitness scriptWitness
Only serialized through CTransaction.
Definition transaction.h:68
COutPoint prevout
Definition transaction.h:65
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition txmempool.h:188
An output of a transaction.
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.
Definition validation.h:550
T ConsumeIntegralInRange(T min, T max)
constexpr int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
Definition consensus.h:19
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition cs_main.cpp:8
#define FUZZ_TARGET(...)
Definition fuzz.h:35
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
Definition fuzz.h:22
uint64_t sequence
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
is used externally by mining IPC clients, so it should only declare simple data definitions.
Definition basic.cpp:11
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).
unsigned int nBytesPerSigOp
Definition settings.cpp:10
std::vector< uint32_t > GetDust(const CTransaction &tx, CFeeRate dust_relay_rate)
Get the vout index numbers of all dust outputs.
Definition policy.cpp:71
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
void ObserveReachabilityGoal(bool reached, const ReachabilityGoal &goal)
Record whether a registered goal is satisfied by at least one fuzz input.
void RegisterReachabilityGoal(const ReachabilityGoal &goal)
Register a goal before executing any fuzz inputs.
@ OP_CHECKSIG
Definition script.h:191
node::NodeContext m_node
A mutable version of CTransaction.
std::vector< std::vector< unsigned char > > stack
Definition script.h:581
A reachability condition explicitly registered by a fuzz target.
Testing setup that configures a complete environment.
const CTransactionRef m_tx
Bilingual messages:
Definition translation.h:24
bool empty() const
Definition translation.h:35
std::string original
Definition translation.h:25
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.
Definition context.h:57
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
Definition context.h:89
std::unique_ptr< ChainstateManager > chainman
Definition context.h:74
#define LOCK(cs)
Definition sync.h:268
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition sync.h:299
SeedRandomStateForTest(SeedRand::ZEROS)
NodeSeconds ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
Definition util.cpp:34
uint32_t ConsumeSequence(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition util.cpp:155
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
Definition util.h:57
COutPoint MineBlock(const NodeContext &node, const node::BlockCreateOptions &assembler_options)
Returns the generated coin.
Definition mining.cpp:123
@ ZEROS
Seed with a compile time constant of zeros.
static const std::vector< std::vector< uint8_t > > P2WSH_EMPTY_TRUE_STACK
Definition script.h:31
static const std::vector< std::vector< uint8_t > > P2WSH_EMPTY_TWO_STACK
Definition script.h:32
static const CScript P2WSH_EMPTY
Definition script.h:23
void CheckMempoolTRUCInvariants(const CTxMemPool &tx_pool)
For every transaction in tx_pool, check TRUC invariants:
CTxMemPool::Options MemPoolOptionsForTest(const NodeContext &node)
Definition txmempool.cpp:21
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.
Definition txmempool.cpp:44
void CheckMempoolEphemeralInvariants(const CTxMemPool &tx_pool)
Check that we never get into a state where an ephemeral dust transaction would be mined without the s...
#define EXCLUSIVE_LOCKS_REQUIRED(...)
constexpr decltype(CTransaction::version) TRUC_VERSION
Definition truc_policy.h:20
void SetMockTime(std::chrono::time_point< NodeClock, std::chrono::seconds > mock)
Definition time.cpp:52
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition time.cpp:88
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82
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.
FuzzedDataProvider & fuzzed_data_provider
Definition fees.cpp:46