Bitcoin Core 32.1.0
P2P Digital Currency
Loading...
Searching...
No Matches
mini_miner.cpp
Go to the documentation of this file.
1// Copyright (c) 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 <node/mini_miner.h>
6
7#include <consensus/amount.h>
8#include <kernel/cs_main.h>
9#include <policy/feerate.h>
11#include <script/script.h>
12#include <sync.h>
14#include <test/fuzz/fuzz.h>
15#include <test/fuzz/util.h>
16#include <test/util/script.h>
17#include <test/util/random.h>
19#include <test/util/time.h>
20#include <test/util/txmempool.h>
21#include <txmempool.h>
22#include <uint256.h>
23#include <util/check.h>
24#include <util/translation.h>
25
26#include <algorithm>
27#include <cstddef>
28#include <cstdint>
29#include <deque>
30#include <functional>
31#include <map>
32#include <optional>
33#include <utility>
34#include <vector>
35
36namespace {
37
38std::deque<COutPoint> g_available_coins;
39void initialize_miner()
40{
41 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
42 for (uint32_t i = 0; i < uint32_t{100}; ++i) {
43 g_available_coins.emplace_back(Txid::FromUint256(uint256::ZERO), i);
44 }
45}
46
47// Test that the MiniMiner can run with various outpoints and feerates.
48FUZZ_TARGET(mini_miner, .init = initialize_miner)
49{
51 FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
52 FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)};
53 bilingual_str error;
54 CTxMemPool pool{CTxMemPool::Options{}, error};
55 Assert(error.empty());
56 std::vector<COutPoint> outpoints;
57 std::deque<COutPoint> available_coins = g_available_coins;
58 LOCK2(::cs_main, pool.cs);
59 // Cluster size cannot exceed 500
60 LIMITED_WHILE (!available_coins.empty(), 100) {
62 const size_t num_inputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, available_coins.size());
63 const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 50);
64 for (size_t n{0}; n < num_inputs; ++n) {
65 auto prevout = available_coins.front();
66 mtx.vin.emplace_back(prevout, CScript());
67 available_coins.pop_front();
68 }
69 for (uint32_t n{0}; n < num_outputs; ++n) {
70 mtx.vout.emplace_back(100, P2WSH_OP_TRUE);
71 }
72 CTransactionRef tx = MakeTransactionRef(mtx);
74 const CAmount fee{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};
76 TryAddToMempool(pool, entry.Fee(fee).FromTx(tx));
77
78 // All outputs are available to spend
79 for (uint32_t n{0}; n < num_outputs; ++n) {
80 if (fuzzed_data_provider.ConsumeBool()) {
81 available_coins.emplace_back(tx->GetHash(), n);
82 }
83 }
84
85 if (fuzzed_data_provider.ConsumeBool() && !tx->vout.empty()) {
86 // Add outpoint from this tx (may or not be spent by a later tx)
87 outpoints.emplace_back(tx->GetHash(),
88 (uint32_t)fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, tx->vout.size()));
89 } else {
90 // Add some random outpoint (will be interpreted as confirmed or not yet submitted
91 // to mempool).
92 auto outpoint = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
93 if (outpoint.has_value() && std::find(outpoints.begin(), outpoints.end(), *outpoint) == outpoints.end()) {
94 outpoints.push_back(*outpoint);
95 }
96 }
97 }
98
99 const CFeeRate target_feerate{CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/1000)}};
100 std::optional<CAmount> total_bumpfee;
101 CAmount sum_fees = 0;
102 {
103 node::MiniMiner mini_miner{pool, outpoints};
104 assert(mini_miner.IsReadyToCalculate());
105 const auto bump_fees = mini_miner.CalculateBumpFees(target_feerate);
106 for (const auto& outpoint : outpoints) {
107 auto it = bump_fees.find(outpoint);
108 assert(it != bump_fees.end());
109 assert(it->second >= 0);
110 sum_fees += it->second;
111 }
112 assert(!mini_miner.IsReadyToCalculate());
113 }
114 {
115 node::MiniMiner mini_miner{pool, outpoints};
116 assert(mini_miner.IsReadyToCalculate());
117 total_bumpfee = mini_miner.CalculateTotalBumpFees(target_feerate);
118 assert(total_bumpfee.has_value());
119 assert(!mini_miner.IsReadyToCalculate());
120 }
121 // Overlapping ancestry across multiple outpoints can only reduce the total bump fee.
122 assert (sum_fees >= *total_bumpfee);
123}
124} // namespace
constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition amount.h:26
bool MoneyRange(const CAmount &nValue)
Definition amount.h:27
int64_t CAmount
Amount in satoshis (Can be negative).
Definition amount.h:12
TryAddToMempool(pool, CTxMemPoolEntry(tx, fee, 0, 1, 0, false, 4, lp))
#define Assert(val)
Identity function.
Definition check.h:116
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
Definition feerate.h:32
CScript()=default
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition txmempool.h:187
kernel::MemPoolOptions Options
Definition txmempool.h:299
Helper to initialize the global NodeClock, let a duration elapse, and reset it after use in a test.
Definition time.h:54
T ConsumeIntegralInRange(T min, T max)
A minimal version of BlockAssembler, using the same ancestor set scoring algorithm.
Definition mini_miner.h:78
std::map< COutPoint, CAmount > CalculateBumpFees(const CFeeRate &target_feerate)
Construct a new block template and, for each outpoint corresponding to a transaction that did not mak...
std::optional< CAmount > CalculateTotalBumpFees(const CFeeRate &target_feerate)
Construct a new block template and, calculate the cost of bumping all transactions that did not make ...
bool IsReadyToCalculate() const
Returns true if CalculateBumpFees may be called, false if not.
Definition mini_miner.h:124
static transaction_identifier FromUint256(const uint256 &id)
static const uint256 ZERO
Definition uint256.h:204
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 fee
Definition basic.cpp:11
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< CTxIn > vin
Definition txmempool.h:19
CTxMemPoolEntry FromTx(const CMutableTransaction &tx) const
Definition txmempool.cpp:34
TestMemPoolEntryHelper & Fee(CAmount _fee)
Definition txmempool.h:33
Bilingual messages:
Definition translation.h:24
bool empty() const
Definition translation.h:35
#define LOCK2(cs1, cs2)
Definition sync.h:269
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
CAmount ConsumeMoney(FuzzedDataProvider &fuzzed_data_provider, const std::optional< CAmount > &max) noexcept
Definition util.cpp:29
std::optional< T > ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider, const P &params, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition util.h:106
@ ZEROS
Seed with a compile time constant of zeros.
Definition random.h:19
assert(!tx.IsCoinBase())