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 <wallet/coincontrol.h>
10 : : #include <wallet/test/util.h>
11 : :
12 : : namespace wallet {
13 : : namespace {
14 : :
15 : : const TestingSetup* g_setup;
16 : :
17 : 1 : void initialize_coincontrol()
18 : : {
19 [ + - + - : 1 : static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
+ - ]
20 : 1 : g_setup = testing_setup.get();
21 : 1 : }
22 : :
23 [ + - ]: 752 : FUZZ_TARGET(coincontrol, .init = initialize_coincontrol)
24 : : {
25 : 292 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
26 : 292 : const auto& node = g_setup->m_node;
27 : 292 : ArgsManager& args = *node.args;
28 : :
29 : : // for GetBoolArg to return true sometimes
30 [ + + + - : 698 : args.ForceSetArg("-avoidpartialspends", fuzzed_data_provider.ConsumeBool()?"1":"0");
+ - ]
31 : :
32 : 292 : CCoinControl coin_control;
33 : 292 : COutPoint out_point;
34 : :
35 [ + + + - ]: 2840 : LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
36 : : {
37 [ + - ]: 2548 : CallOneOf(
38 : : fuzzed_data_provider,
39 : 55 : [&] {
40 : 55 : std::optional<COutPoint> optional_out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
41 [ + + ]: 55 : if (!optional_out_point) {
42 : : return;
43 : : }
44 : 30 : out_point = *optional_out_point;
45 : : },
46 : 222 : [&] {
47 : 222 : (void)coin_control.HasSelected();
48 : 222 : },
49 : 94 : [&] {
50 : 94 : (void)coin_control.IsSelected(out_point);
51 : 94 : },
52 : 72 : [&] {
53 : 72 : (void)coin_control.IsExternalSelected(out_point);
54 : 72 : },
55 : 74 : [&] {
56 : 74 : (void)coin_control.GetExternalOutput(out_point);
57 : 74 : },
58 : 356 : [&] {
59 : 356 : (void)coin_control.Select(out_point);
60 [ - + ]: 356 : assert(coin_control.IsSelected(out_point));
61 : 356 : },
62 : 514 : [&] {
63 [ + - ]: 514 : const CTxOut tx_out{ConsumeMoney(fuzzed_data_provider), ConsumeScript(fuzzed_data_provider)};
64 [ + - ]: 514 : auto& input = coin_control.Select(out_point);
65 : 514 : const auto set_tx_out{fuzzed_data_provider.ConsumeBool()};
66 [ + + ]: 514 : if (set_tx_out) {
67 [ + - ]: 497 : input.SetTxOut(tx_out);
68 : : }
69 [ + - ]: 514 : auto has_tx_out{input.HasTxOut()};
70 [ + - ]: 514 : auto is_external_selected{coin_control.IsExternalSelected(out_point)};
71 [ + + ]: 514 : if (set_tx_out) {
72 [ - + ]: 497 : assert(has_tx_out);
73 [ + - - + ]: 497 : assert(input.GetTxOut() == tx_out);
74 [ - + ]: 497 : assert(is_external_selected);
75 [ + + ]: 17 : } else if (!has_tx_out) {
76 [ - + ]: 15 : assert(!is_external_selected);
77 : : }
78 : 514 : },
79 : 121 : [&] {
80 : 121 : coin_control.UnSelect(out_point);
81 [ - + ]: 121 : assert(!coin_control.IsSelected(out_point));
82 : 121 : },
83 : 386 : [&] {
84 : 386 : coin_control.UnSelectAll();
85 [ - + ]: 386 : assert(!coin_control.HasSelected());
86 : 386 : },
87 : 82 : [&] {
88 : 82 : const std::vector<COutPoint> selected = coin_control.ListSelected();
89 [ + + ]: 127 : for (const auto& out : selected) {
90 [ + - - + ]: 45 : assert(coin_control.IsSelected(out));
91 : : }
92 : 82 : },
93 : 41 : [&] {
94 : 41 : int64_t weight{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
95 : 41 : coin_control.SetInputWeight(out_point, weight);
96 [ + - ]: 41 : assert(coin_control.GetInputWeight(out_point) == weight);
97 : 41 : },
98 : 24 : [&] {
99 : 24 : const bool is_selected = coin_control.IsSelected(out_point);
100 [ - + - - ]: 24 : assert(!coin_control.GetInputWeight(out_point) || is_selected);
101 [ + + - + ]: 24 : assert(!coin_control.GetSequence(out_point) || is_selected);
102 : 24 : },
103 : 149 : [&] {
104 : 149 : const auto scripts = coin_control.GetScripts(out_point);
105 [ + - + + : 149 : assert(coin_control.IsSelected(out_point) || (!scripts.first && !scripts.second));
+ - - + ]
106 : 149 : },
107 : 140 : [&] {
108 [ + + - + ]: 140 : assert(coin_control.HasSelectedOrder() || !coin_control.GetSelectionPos(out_point));
109 : 140 : },
110 : 31 : [&] {
111 [ + + - + ]: 31 : assert(!coin_control.GetSelectionPos(out_point) || coin_control.IsSelected(out_point));
112 : 31 : },
113 : 27 : [&] {
114 : 27 : auto& input = coin_control.Select(out_point);
115 : 27 : uint32_t sequence{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
116 : 27 : input.SetSequence(sequence);
117 [ + - ]: 27 : assert(input.GetSequence() == sequence);
118 [ + - ]: 27 : assert(coin_control.GetSequence(out_point) == sequence);
119 : 27 : },
120 : 100 : [&] {
121 : 100 : auto& input = coin_control.Select(out_point);
122 : 100 : const CScript script{ConsumeScript(fuzzed_data_provider)};
123 [ + - ]: 100 : input.SetScriptSig(script);
124 [ + - - + ]: 100 : assert(input.HasScripts());
125 [ + - - + ]: 100 : assert(input.GetScripts().first == script);
126 [ + - - + ]: 200 : assert(coin_control.GetScripts(out_point).first == script);
127 : 100 : },
128 : 16 : [&] {
129 : 16 : auto& input = coin_control.Select(out_point);
130 : 16 : const CScriptWitness script_wit{ConsumeScriptWitness(fuzzed_data_provider)};
131 [ + - ]: 16 : input.SetScriptWitness(script_wit);
132 [ + - - + ]: 16 : assert(input.HasScripts());
133 [ + - - + ]: 16 : assert(input.GetScripts().second->stack == script_wit.stack);
134 [ + - - + ]: 32 : assert(coin_control.GetScripts(out_point).second->stack == script_wit.stack);
135 : 16 : },
136 : 44 : [&] {
137 : 44 : auto& input = coin_control.Select(out_point);
138 : 44 : unsigned int pos{fuzzed_data_provider.ConsumeIntegral<unsigned int>()};
139 : 44 : input.SetPosition(pos);
140 [ + - ]: 44 : assert(input.GetPosition() == pos);
141 [ + - ]: 44 : assert(coin_control.GetSelectionPos(out_point) == pos);
142 : 44 : });
143 : : }
144 : 292 : }
145 : : } // namespace
146 : : } // namespace wallet
|