Branch data Line data Source code
1 : : // Copyright (c) 2024-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/fuzz/util/wallet.h>
9 : : #include <test/util/random.h>
10 : : #include <test/util/setup_common.h>
11 : : #include <wallet/coincontrol.h>
12 : : #include <wallet/context.h>
13 : : #include <wallet/spend.h>
14 : : #include <wallet/test/util.h>
15 : : #include <wallet/wallet.h>
16 : : #include <validation.h>
17 : : #include <addresstype.h>
18 : :
19 : : using util::ToString;
20 : :
21 : : namespace wallet {
22 : : namespace {
23 : : const TestingSetup* g_setup;
24 : :
25 : 1 : void initialize_setup()
26 : : {
27 [ + - + - ]: 2 : static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
28 : 1 : g_setup = testing_setup.get();
29 [ + - ]: 2 : }
30 : :
31 [ + - ]: 2032 : FUZZ_TARGET(wallet_create_transaction, .init = initialize_setup)
32 : : {
33 : 1620 : SeedRandomStateForTest(SeedRand::ZEROS);
34 : 1620 : FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
35 : 1620 : const auto& node = g_setup->m_node;
36 : 1620 : Chainstate& chainstate{node.chainman->ActiveChainstate()};
37 : 1620 : ArgsManager& args = *node.args;
38 [ + - + - ]: 3240 : args.ForceSetArg("-dustrelayfee", ToString(fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY)));
39 : 1620 : FuzzedWallet fuzzed_wallet{
40 : 1620 : *g_setup->m_node.chain,
41 : : "fuzzed_wallet_a",
42 : : "tprv8ZgxMBicQKsPd1QwsGgzfu2pcPYbBosZhJknqreRHgsWx32nNEhMjGQX2cgFL8n6wz9xdDYwLcs78N4nsCo32cxEX8RBtwGsEGgybLiQJfk",
43 [ + - + - ]: 3240 : };
44 : :
45 [ + - ]: 1620 : CCoinControl coin_control;
46 [ + + ]: 1620 : if (fuzzed_data_provider.ConsumeBool()) coin_control.m_version = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
47 : 1620 : coin_control.m_avoid_partial_spends = fuzzed_data_provider.ConsumeBool();
48 : 1620 : coin_control.m_include_unsafe_inputs = fuzzed_data_provider.ConsumeBool();
49 [ + + ]: 1620 : if (fuzzed_data_provider.ConsumeBool()) coin_control.m_confirm_target = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 999'000);
50 [ + + + - ]: 3240 : coin_control.destChange = fuzzed_data_provider.ConsumeBool() ? fuzzed_wallet.GetDestination(fuzzed_data_provider) : ConsumeTxDestination(fuzzed_data_provider);
51 [ + + ]: 1620 : if (fuzzed_data_provider.ConsumeBool()) coin_control.m_change_type = fuzzed_data_provider.PickValueInArray(OUTPUT_TYPES);
52 [ + + - + ]: 1620 : if (fuzzed_data_provider.ConsumeBool()) coin_control.m_feerate = CFeeRate(ConsumeMoney(fuzzed_data_provider, /*max=*/COIN));
53 : 1620 : coin_control.m_allow_other_inputs = fuzzed_data_provider.ConsumeBool();
54 : 1620 : coin_control.m_locktime = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
55 : 1620 : coin_control.fOverrideFeeRate = fuzzed_data_provider.ConsumeBool();
56 : :
57 : 1620 : int next_locktime{0};
58 : 1620 : CAmount all_values{0};
59 [ + + + - ]: 25656 : LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
60 : : {
61 [ + - ]: 24048 : CMutableTransaction tx;
62 : 24048 : tx.nLockTime = next_locktime++;
63 [ + - ]: 24048 : tx.vout.resize(1);
64 : 24048 : CAmount n_value{ConsumeMoney(fuzzed_data_provider)};
65 : 24048 : all_values += n_value;
66 [ + + ]: 24048 : if (all_values > MAX_MONEY) return;
67 [ + - ]: 24036 : tx.vout[0].nValue = n_value;
68 [ + - + - ]: 24036 : tx.vout[0].scriptPubKey = GetScriptForDestination(fuzzed_wallet.GetDestination(fuzzed_data_provider));
69 [ + - ]: 24036 : LOCK(fuzzed_wallet.wallet->cs_wallet);
70 [ + - ]: 24036 : auto txid{tx.GetHash()};
71 [ + - + - : 72108 : auto ret{fuzzed_wallet.wallet->mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid), std::forward_as_tuple(MakeTransactionRef(std::move(tx)), TxStateConfirmed{chainstate.m_chain.Tip()->GetBlockHash(), chainstate.m_chain.Height(), /*index=*/0}))};
+ - - + ]
72 [ - + ]: 24036 : assert(ret.second);
73 : 48072 : }
74 : :
75 : 1608 : std::vector<CRecipient> recipients;
76 [ + + + + ]: 13666 : LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
77 : 12058 : CTxDestination destination;
78 [ + - ]: 12058 : CallOneOf(
79 : : fuzzed_data_provider,
80 : 7519 : [&] {
81 : 7519 : destination = fuzzed_wallet.GetDestination(fuzzed_data_provider);
82 : 7519 : },
83 : 2973 : [&] {
84 : 2973 : CScript script;
85 [ + - ]: 2973 : script << OP_RETURN;
86 : 2973 : destination = CNoDestination{script};
87 : 2973 : },
88 : 1566 : [&] {
89 : 1566 : destination = ConsumeTxDestination(fuzzed_data_provider);
90 : 1566 : }
91 : : );
92 [ + - ]: 24116 : recipients.push_back({destination,
93 : 12058 : /*nAmount=*/ConsumeMoney(fuzzed_data_provider),
94 : 12058 : /*fSubtractFeeFromAmount=*/fuzzed_data_provider.ConsumeBool()});
95 : 12058 : }
96 : :
97 : 1608 : std::optional<unsigned int> change_pos;
98 [ + + ]: 1608 : if (fuzzed_data_provider.ConsumeBool()) change_pos = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
99 [ + - ]: 1608 : (void)CreateTransaction(*fuzzed_wallet.wallet, recipients, change_pos, coin_control);
100 [ + - + - : 15298 : }
+ - ]
101 : : } // namespace
102 : : } // namespace wallet
|