1818#include < test/fuzz/FuzzedDataProvider.h>
1919#include < test/fuzz/fuzz.h>
2020#include < test/fuzz/util.h>
21+ #include < test/fuzz/util/wallet.h>
2122#include < test/util/setup_common.h>
2223#include < tinyformat.h>
2324#include < uint256.h>
@@ -53,121 +54,6 @@ void initialize_setup()
5354 g_setup = testing_setup.get ();
5455}
5556
56- void ImportDescriptors (CWallet& wallet, const std::string& seed_insecure)
57- {
58- const std::vector<std::string> DESCS{
59- " pkh(%s/%s/*)" ,
60- " sh(wpkh(%s/%s/*))" ,
61- " tr(%s/%s/*)" ,
62- " wpkh(%s/%s/*)" ,
63- };
64-
65- for (const std::string& desc_fmt : DESCS) {
66- for (bool internal : {true , false }) {
67- const auto descriptor{(strprintf)(desc_fmt, " [5aa9973a/66h/4h/2h]" + seed_insecure, int {internal})};
68-
69- FlatSigningProvider keys;
70- std::string error;
71- auto parsed_desc = std::move (Parse (descriptor, keys, error, /* require_checksum=*/ false ).at (0 ));
72- assert (parsed_desc);
73- assert (error.empty ());
74- assert (parsed_desc->IsRange ());
75- assert (parsed_desc->IsSingleType ());
76- assert (!keys.keys .empty ());
77- WalletDescriptor w_desc{std::move (parsed_desc), /* creation_time=*/ 0 , /* range_start=*/ 0 , /* range_end=*/ 1 , /* next_index=*/ 0 };
78- assert (!wallet.GetDescriptorScriptPubKeyMan (w_desc));
79- LOCK (wallet.cs_wallet );
80- auto spk_manager{wallet.AddWalletDescriptor (w_desc, keys, /* label=*/ " " , internal)};
81- assert (spk_manager);
82- wallet.AddActiveScriptPubKeyMan (spk_manager->GetID (), *Assert (w_desc.descriptor ->GetOutputType ()), internal);
83- }
84- }
85- }
86-
87- /* *
88- * Wraps a descriptor wallet for fuzzing.
89- */
90- struct FuzzedWallet {
91- std::shared_ptr<CWallet> wallet;
92- FuzzedWallet (const std::string& name, const std::string& seed_insecure)
93- {
94- auto & chain{*Assert (g_setup->m_node .chain )};
95- wallet = std::make_shared<CWallet>(&chain, name, CreateMockableWalletDatabase ());
96- {
97- LOCK (wallet->cs_wallet );
98- wallet->SetWalletFlag (WALLET_FLAG_DESCRIPTORS);
99- auto height{*Assert (chain.getHeight ())};
100- wallet->SetLastBlockProcessed (height, chain.getBlockHash (height));
101- }
102- wallet->m_keypool_size = 1 ; // Avoid timeout in TopUp()
103- assert (wallet->IsWalletFlagSet (WALLET_FLAG_DESCRIPTORS));
104- ImportDescriptors (*wallet, seed_insecure);
105- }
106- CTxDestination GetDestination (FuzzedDataProvider& fuzzed_data_provider)
107- {
108- auto type{fuzzed_data_provider.PickValueInArray (OUTPUT_TYPES)};
109- if (fuzzed_data_provider.ConsumeBool ()) {
110- return *Assert (wallet->GetNewDestination (type, " " ));
111- } else {
112- return *Assert (wallet->GetNewChangeDestination (type));
113- }
114- }
115- CScript GetScriptPubKey (FuzzedDataProvider& fuzzed_data_provider) { return GetScriptForDestination (GetDestination (fuzzed_data_provider)); }
116- void FundTx (FuzzedDataProvider& fuzzed_data_provider, CMutableTransaction tx)
117- {
118- // The fee of "tx" is 0, so this is the total input and output amount
119- const CAmount total_amt{
120- std::accumulate (tx.vout .begin (), tx.vout .end (), CAmount{}, [](CAmount t, const CTxOut& out) { return t + out.nValue ; })};
121- const uint32_t tx_size (GetVirtualTransactionSize (CTransaction{tx}));
122- std::set<int > subtract_fee_from_outputs;
123- if (fuzzed_data_provider.ConsumeBool ()) {
124- for (size_t i{}; i < tx.vout .size (); ++i) {
125- if (fuzzed_data_provider.ConsumeBool ()) {
126- subtract_fee_from_outputs.insert (i);
127- }
128- }
129- }
130- std::vector<CRecipient> recipients;
131- for (size_t idx = 0 ; idx < tx.vout .size (); idx++) {
132- const CTxOut& tx_out = tx.vout [idx];
133- CTxDestination dest;
134- ExtractDestination (tx_out.scriptPubKey , dest);
135- CRecipient recipient = {dest, tx_out.nValue , subtract_fee_from_outputs.count (idx) == 1 };
136- recipients.push_back (recipient);
137- }
138- CCoinControl coin_control;
139- coin_control.m_allow_other_inputs = fuzzed_data_provider.ConsumeBool ();
140- CallOneOf (
141- fuzzed_data_provider, [&] { coin_control.destChange = GetDestination (fuzzed_data_provider); },
142- [&] { coin_control.m_change_type .emplace (fuzzed_data_provider.PickValueInArray (OUTPUT_TYPES)); },
143- [&] { /* no op (leave uninitialized) */ });
144- coin_control.fAllowWatchOnly = fuzzed_data_provider.ConsumeBool ();
145- coin_control.m_include_unsafe_inputs = fuzzed_data_provider.ConsumeBool ();
146- {
147- auto & r{coin_control.m_signal_bip125_rbf };
148- CallOneOf (
149- fuzzed_data_provider, [&] { r = true ; }, [&] { r = false ; }, [&] { r = std::nullopt ; });
150- }
151- coin_control.m_feerate = CFeeRate{
152- // A fee of this range should cover all cases
153- fuzzed_data_provider.ConsumeIntegralInRange <CAmount>(0 , 2 * total_amt),
154- tx_size,
155- };
156- if (fuzzed_data_provider.ConsumeBool ()) {
157- *coin_control.m_feerate += GetMinimumFeeRate (*wallet, coin_control, nullptr );
158- }
159- coin_control.fOverrideFeeRate = fuzzed_data_provider.ConsumeBool ();
160- // Add solving data (m_external_provider and SelectExternal)?
161-
162- int change_position{fuzzed_data_provider.ConsumeIntegralInRange <int >(-1 , tx.vout .size () - 1 )};
163- bilingual_str error;
164- // Clear tx.vout since it is not meant to be used now that we are passing outputs directly.
165- // This sets us up for a future PR to completely remove tx from the function signature in favor of passing inputs directly
166- tx.vout .clear ();
167- (void )FundTransaction (*wallet, tx, recipients, change_position, /* lockUnspents=*/ false , coin_control);
168- }
169- };
170-
17157FUZZ_TARGET (wallet_notifications, .init = initialize_setup)
17258{
17359 FuzzedDataProvider fuzzed_data_provider{buffer.data (), buffer.size ()};
@@ -176,10 +62,12 @@ FUZZ_TARGET(wallet_notifications, .init = initialize_setup)
17662 // total amount.
17763 const auto total_amount{ConsumeMoney (fuzzed_data_provider, /* max=*/ MAX_MONEY / 100000 )};
17864 FuzzedWallet a{
65+ *g_setup->m_node .chain ,
17966 " fuzzed_wallet_a" ,
18067 " tprv8ZgxMBicQKsPd1QwsGgzfu2pcPYbBosZhJknqreRHgsWx32nNEhMjGQX2cgFL8n6wz9xdDYwLcs78N4nsCo32cxEX8RBtwGsEGgybLiQJfk" ,
18168 };
18269 FuzzedWallet b{
70+ *g_setup->m_node .chain ,
18371 " fuzzed_wallet_b" ,
18472 " tprv8ZgxMBicQKsPfCunYTF18sEmEyjz8TfhGnZ3BoVAhkqLv7PLkQgmoG2Ecsp4JuqciWnkopuEwShit7st743fdmB9cMD4tznUkcs33vK51K9" ,
18573 };
0 commit comments