Branch data Line data Source code
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 : :
5 : : #include <test/fuzz/FuzzedDataProvider.h>
6 : : #include <test/fuzz/fuzz.h>
7 : : #include <test/fuzz/util.h>
8 : : #include <test/util/setup_common.h>
9 : : #include <test/util/time.h>
10 : : #include <test/util/txmempool.h>
11 : : #include <validation.h>
12 : : #include <wallet/coincontrol.h>
13 : : #include <wallet/fees.h>
14 : : #include <wallet/test/util.h>
15 : : #include <wallet/wallet.h>
16 : :
17 : : namespace wallet {
18 : : namespace {
19 : :
20 : : struct FeeEstimatorTestingSetup : public TestingSetup {
21 [ + - ]: 1 : FeeEstimatorTestingSetup(const ChainType chain_type, TestOpts opts) : TestingSetup{chain_type, opts}
22 : : {
23 : 1 : }
24 : :
25 : 1 : ~FeeEstimatorTestingSetup() {
26 [ + - ]: 1 : m_node.fee_estimator.reset();
27 : 1 : }
28 : :
29 : 119 : void SetFeeEstimator(std::unique_ptr<CBlockPolicyEstimator> fee_estimator)
30 : : {
31 : 119 : m_node.fee_estimator = std::move(fee_estimator);
32 : : }
33 : : };
34 : :
35 : : FeeEstimatorTestingSetup* g_setup;
36 : :
37 : : class FuzzedBlockPolicyEstimator : public CBlockPolicyEstimator
38 : : {
39 : : FuzzedDataProvider& fuzzed_data_provider;
40 : :
41 : : public:
42 : 119 : FuzzedBlockPolicyEstimator(FuzzedDataProvider& provider)
43 [ + - ]: 238 : : CBlockPolicyEstimator(fs::path{}, false), fuzzed_data_provider(provider) {}
44 : :
45 : 347 : CFeeRate estimateSmartFee(int confTarget, FeeCalculation* feeCalc, bool conservative) const override
46 : : {
47 : 347 : return CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/1'000'000)};
48 : : }
49 : :
50 : 119 : unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const override
51 : : {
52 : 119 : return fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, 1000);
53 : : }
54 : : };
55 : :
56 : 1 : void initialize_setup()
57 : : {
58 [ + - + - : 1 : static const auto testing_setup = MakeNoLogFileContext<FeeEstimatorTestingSetup>();
+ - ]
59 : 1 : g_setup = testing_setup.get();
60 : 1 : }
61 : :
62 [ + - ]: 577 : FUZZ_TARGET(wallet_fees, .init = initialize_setup)
63 : : {
64 : 119 : SeedRandomStateForTest(SeedRand::ZEROS);
65 : 119 : FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
66 : 119 : NodeClockContext clock_ctx{ConsumeTime(fuzzed_data_provider)};
67 : 119 : auto& node{g_setup->m_node};
68 [ + - ]: 119 : Chainstate* chainstate = &node.chainman->ActiveChainstate();
69 : :
70 : 119 : bilingual_str error;
71 : 119 : CTxMemPool::Options mempool_opts{
72 : 119 : .incremental_relay_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, 1'000'000)},
73 : 119 : .min_relay_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, 1'000'000)},
74 : 119 : .dust_relay_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, 1'000'000)}
75 [ + - ]: 119 : };
76 [ + - ]: 119 : node.mempool = std::make_unique<CTxMemPool>(mempool_opts, error);
77 [ + - ]: 119 : std::unique_ptr<CBlockPolicyEstimator> fee_estimator = std::make_unique<FuzzedBlockPolicyEstimator>(fuzzed_data_provider);
78 : 119 : g_setup->SetFeeEstimator(std::move(fee_estimator));
79 [ + + ]: 119 : auto target_feerate{CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/1'000'000)}};
80 [ + + + + ]: 119 : if (target_feerate > node.mempool->m_opts.incremental_relay_feerate &&
81 [ + + ]: 38 : target_feerate > node.mempool->m_opts.min_relay_feerate) {
82 [ + - ]: 25 : MockMempoolMinFee(target_feerate, *node.mempool);
83 : : }
84 [ + - + - ]: 119 : std::unique_ptr<CWallet> wallet_ptr{std::make_unique<CWallet>(node.chain.get(), "", CreateMockableWalletDatabase())};
85 [ + - ]: 119 : CWallet& wallet{*wallet_ptr};
86 : 119 : {
87 [ + - ]: 119 : LOCK(wallet.cs_wallet);
88 [ - + + - ]: 238 : wallet.SetLastBlockProcessed(chainstate->m_chain.Height(), chainstate->m_chain.Tip()->GetBlockHash());
89 : 0 : }
90 : :
91 [ + + ]: 119 : if (fuzzed_data_provider.ConsumeBool()) {
92 : 9 : wallet.m_fallback_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
93 : : }
94 : :
95 [ + + ]: 119 : if (fuzzed_data_provider.ConsumeBool()) {
96 : 6 : wallet.m_discard_rate = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
97 : : }
98 [ + - ]: 119 : (void)GetDiscardRate(wallet);
99 : :
100 : 119 : const auto tx_bytes{fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits<int32_t>::max())};
101 [ + + ]: 119 : if (fuzzed_data_provider.ConsumeBool()) {
102 : 8 : wallet.m_min_fee = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
103 : : }
104 : :
105 [ + - ]: 119 : (void)GetRequiredFee(wallet, tx_bytes);
106 [ + - ]: 119 : (void)GetRequiredFeeRate(wallet);
107 : :
108 [ + - ]: 119 : CCoinControl coin_control;
109 [ + + ]: 119 : if (fuzzed_data_provider.ConsumeBool()) {
110 [ - + ]: 5 : coin_control.m_feerate = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
111 : : }
112 [ + + ]: 119 : if (fuzzed_data_provider.ConsumeBool()) {
113 : 10 : coin_control.m_confirm_target = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 999'000);
114 : : }
115 [ + + ]: 119 : if (fuzzed_data_provider.ConsumeBool()) {
116 [ + + ]: 11 : coin_control.m_fee_mode = fuzzed_data_provider.ConsumeBool() ? FeeEstimateMode::CONSERVATIVE : FeeEstimateMode::ECONOMICAL;
117 : : }
118 : :
119 : 119 : FeeCalculation fee_calculation;
120 [ + + ]: 119 : FeeCalculation* maybe_fee_calculation{fuzzed_data_provider.ConsumeBool() ? nullptr : &fee_calculation};
121 [ + - ]: 119 : (void)GetMinimumFeeRate(wallet, coin_control, maybe_fee_calculation);
122 [ + - ]: 119 : (void)GetMinimumFee(wallet, tx_bytes, coin_control, maybe_fee_calculation);
123 [ + - ]: 357 : }
124 : : } // namespace
125 : : } // namespace wallet
|