Bitcoin Core  31.0.0
P2P Digital Currency
fees.cpp
Go to the documentation of this file.
1 // Copyright (c) 2022-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 
6 #include <test/fuzz/fuzz.h>
7 #include <test/fuzz/util.h>
9 #include <test/util/txmempool.h>
10 #include <validation.h>
11 #include <wallet/coincontrol.h>
12 #include <wallet/fees.h>
13 #include <wallet/test/util.h>
14 #include <wallet/wallet.h>
15 
16 namespace wallet {
17 namespace {
18 
19 struct FeeEstimatorTestingSetup : public TestingSetup {
20  FeeEstimatorTestingSetup(const ChainType chain_type, TestOpts opts) : TestingSetup{chain_type, opts}
21  {
22  }
23 
24  ~FeeEstimatorTestingSetup() {
25  m_node.fee_estimator.reset();
26  }
27 
28  void SetFeeEstimator(std::unique_ptr<CBlockPolicyEstimator> fee_estimator)
29  {
30  m_node.fee_estimator = std::move(fee_estimator);
31  }
32 };
33 
34 FeeEstimatorTestingSetup* g_setup;
35 
36 class FuzzedBlockPolicyEstimator : public CBlockPolicyEstimator
37 {
39 
40 public:
41  FuzzedBlockPolicyEstimator(FuzzedDataProvider& provider)
42  : CBlockPolicyEstimator(fs::path{}, false), fuzzed_data_provider(provider) {}
43 
44  CFeeRate estimateSmartFee(int confTarget, FeeCalculation* feeCalc, bool conservative) const override
45  {
46  return CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/1'000'000)};
47  }
48 
49  unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const override
50  {
51  return fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, 1000);
52  }
53 };
54 
55 void initialize_setup()
56 {
57  static const auto testing_setup = MakeNoLogFileContext<FeeEstimatorTestingSetup>();
58  g_setup = testing_setup.get();
59 }
60 
61 FUZZ_TARGET(wallet_fees, .init = initialize_setup)
62 {
64  FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
66  auto& node{g_setup->m_node};
67  Chainstate* chainstate = &node.chainman->ActiveChainstate();
68 
69  bilingual_str error;
70  CTxMemPool::Options mempool_opts{
72  .min_relay_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, 1'000'000)},
73  .dust_relay_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, 1'000'000)}
74  };
75  node.mempool = std::make_unique<CTxMemPool>(mempool_opts, error);
76  std::unique_ptr<CBlockPolicyEstimator> fee_estimator = std::make_unique<FuzzedBlockPolicyEstimator>(fuzzed_data_provider);
77  g_setup->SetFeeEstimator(std::move(fee_estimator));
78  auto target_feerate{CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/1'000'000)}};
79  if (target_feerate > node.mempool->m_opts.incremental_relay_feerate &&
80  target_feerate > node.mempool->m_opts.min_relay_feerate) {
81  MockMempoolMinFee(target_feerate, *node.mempool);
82  }
83  std::unique_ptr<CWallet> wallet_ptr{std::make_unique<CWallet>(node.chain.get(), "", CreateMockableWalletDatabase())};
84  CWallet& wallet{*wallet_ptr};
85  {
86  LOCK(wallet.cs_wallet);
87  wallet.SetLastBlockProcessed(chainstate->m_chain.Height(), chainstate->m_chain.Tip()->GetBlockHash());
88  }
89 
91  wallet.m_fallback_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
92  }
93 
95  wallet.m_discard_rate = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
96  }
97  (void)GetDiscardRate(wallet);
98 
99  const auto tx_bytes{fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits<int32_t>::max())};
101  wallet.m_min_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
102  }
103 
104  (void)GetRequiredFee(wallet, tx_bytes);
105  (void)GetRequiredFeeRate(wallet);
106 
107  CCoinControl coin_control;
109  coin_control.m_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
110  }
112  coin_control.m_confirm_target = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 999'000);
113  }
114  if (fuzzed_data_provider.ConsumeBool()) {
115  coin_control.m_fee_mode = fuzzed_data_provider.ConsumeBool() ? FeeEstimateMode::CONSERVATIVE : FeeEstimateMode::ECONOMICAL;
116  }
117 
118  FeeCalculation fee_calculation;
119  FeeCalculation* maybe_fee_calculation{fuzzed_data_provider.ConsumeBool() ? nullptr : &fee_calculation};
120  (void)GetMinimumFeeRate(wallet, coin_control, maybe_fee_calculation);
121  (void)GetMinimumFee(wallet, tx_bytes, coin_control, maybe_fee_calculation);
122 }
123 } // namespace
124 } // namespace wallet
void MockMempoolMinFee(const CFeeRate &target_feerate, CTxMemPool &mempool)
Mock the mempool minimum feerate by adding a transaction and calling TrimToSize(0), simulating the mempool "reaching capacity" and evicting by descendant feerate.
Definition: txmempool.cpp:225
Bilingual messages:
Definition: translation.h:24
node::NodeContext m_node
Definition: bitcoin-gui.cpp:43
FUZZ_TARGET(coin_grinder)
int Height() const
Return the maximal height in the chain.
Definition: chain.h:425
CFeeRate GetDiscardRate(const CWallet &wallet)
Return the maximum feerate for discarding change.
Definition: fees.cpp:78
const TestingSetup * g_setup
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:625
CFeeRate GetRequiredFeeRate(const CWallet &wallet)
Return the minimum required feerate taking into account the minimum relay feerate and user set minimu...
Definition: fees.cpp:24
uint256 GetBlockHash() const
Definition: chain.h:198
std::unique_ptr< CBlockPolicyEstimator > fee_estimator
Definition: context.h:70
ChainType
Definition: chaintype.h:11
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:550
#define LOCK(cs)
Definition: sync.h:258
The BlockPolicyEstimator is used for estimating the feerate needed for a transaction to be included i...
NodeSeconds ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
Definition: util.cpp:34
Definition: messages.h:21
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
Definition: random.cpp:19
FeePerVSize m_feerate
Fee rate in sats/vB (satoshis per N virtualbytes)
Definition: feerate.h:35
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase(MockableData records)
Definition: util.cpp:211
FeeEstimateHorizon
FuzzedDataProvider & fuzzed_data_provider
Definition: fees.cpp:38
CAmount ConsumeMoney(FuzzedDataProvider &fuzzed_data_provider, const std::optional< CAmount > &max) noexcept
Definition: util.cpp:29
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:396
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac...
Definition: feerate.h:31
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:44
CAmount GetRequiredFee(const CWallet &wallet, unsigned int nTxBytes)
Return the minimum required absolute fee for this size based on the required fee rate.
Definition: fees.cpp:13
Options struct containing options for constructing a CTxMemPool.
T ConsumeIntegralInRange(T min, T max)
Seed with a compile time constant of zeros.
node::NodeContext m_node
Definition: setup_common.h:66
Testing setup that configures a complete environment.
Definition: setup_common.h:121
CFeeRate incremental_relay_feerate
static constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition: amount.h:15