Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
wallet.h
Go to the documentation of this file.
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#ifndef BITCOIN_TEST_FUZZ_UTIL_WALLET_H
6#define BITCOIN_TEST_FUZZ_UTIL_WALLET_H
7
8#include <outputtype.h>
9#include <policy/policy.h>
11#include <test/fuzz/fuzz.h>
12#include <test/fuzz/util.h>
13#include <util/check.h>
14#include <wallet/coincontrol.h>
15#include <wallet/fees.h>
17#include <wallet/spend.h>
18#include <wallet/test/util.h>
19#include <wallet/wallet.h>
20
21#include <array>
22#include <cstddef>
23#include <cstdint>
24#include <memory>
25#include <string>
26#include <vector>
27
28namespace wallet {
29
34 static constexpr size_t DESTINATION_POOL_SIZE{16};
35 static constexpr uint64_t REBUILD_INTERVAL{1000};
36
37 std::shared_ptr<CWallet> wallet;
38
39 FuzzedWallet(interfaces::Chain& chain, const std::string& name, const std::string& seed_insecure)
41 {
42 Build();
43 }
44
45 void Reset()
46 {
48 Build();
49 return;
50 }
51 m_cursors.fill(0);
52 m_change_cursors.fill(0);
53 {
54 LOCK(wallet->cs_wallet);
55 wallet->ClearInMemoryTxStateForTest();
56 assert(wallet->mapWallet.empty());
57 assert(wallet->GetTXOs().empty());
58 }
59 }
60
62 {
64 const bool external{fuzzed_data_provider.ConsumeBool()};
65 const size_t i{TypeIndex(type)};
66 auto& pool{external ? m_dests : m_change_dests};
67 auto& cursor{external ? m_cursors.at(i) : m_change_cursors.at(i)};
68 const CTxDestination& dest{pool.at(i).at(cursor % DESTINATION_POOL_SIZE)};
69 ++cursor;
70 return dest;
71 }
72
74
76 {
77 int64_t total{0};
78 for (const DescriptorScriptPubKeyMan* spkm : m_spkms) total += spkm->GetEndRange();
79 return total;
80 }
81
82private:
83 using DestinationPool = std::array<std::vector<CTxDestination>, OUTPUT_TYPES.size()>;
84
86 const std::string m_name;
87 const std::string m_seed_insecure;
88
89 using PoolCursors = std::array<size_t, OUTPUT_TYPES.size()>;
90
95
96 static size_t TypeIndex(OutputType type)
97 {
98 for (size_t i = 0; i < OUTPUT_TYPES.size(); ++i) {
99 if (OUTPUT_TYPES.at(i) == type) return i;
100 }
101 assert(false);
102 }
103
104 std::vector<DescriptorScriptPubKeyMan*> m_spkms;
106
107 void Build()
108 {
109 m_spkms.clear();
110 for (auto& pool : m_dests) pool.clear();
111 for (auto& pool : m_change_dests) pool.clear();
112 m_cursors.fill(0);
113 m_change_cursors.fill(0);
114
115 wallet = std::make_shared<CWallet>(&m_chain, m_name, CreateMockableWalletDatabase());
116 {
117 LOCK(wallet->cs_wallet);
118 wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
119 auto height{*Assert(m_chain.getHeight())};
120 wallet->SetLastBlockProcessed(height, m_chain.getBlockHash(height));
121 }
122 wallet->m_keypool_size = 1; // Avoid timeout in TopUp()
123 assert(wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
126
127 m_iterations = 0;
128 }
129
130 void ImportDescriptors(const std::string& seed_insecure)
131 {
132 const std::vector<std::string> DESCS{
133 "pkh(%s/%s/*)",
134 "sh(wpkh(%s/%s/*))",
135 "tr(%s/%s/*)",
136 "wpkh(%s/%s/*)",
137 };
138
139 for (const std::string& desc_fmt : DESCS) {
140 for (bool internal : {true, false}) {
141 const auto descriptor{strprintf(tfm::RuntimeFormat{desc_fmt}, "[5aa9973a/66h/4h/2h]" + seed_insecure, int{internal})};
142
144 std::string error;
145 auto parsed_desc = std::move(Parse(descriptor, keys, error, /*require_checksum=*/false).at(0));
147 assert(error.empty());
148 assert(parsed_desc->IsRange());
149 assert(parsed_desc->IsSingleType());
150 assert(!keys.keys.empty());
151 WalletDescriptor w_desc{std::move(parsed_desc), /*creation_time=*/0, /*range_start=*/0, /*range_end=*/1, /*next_index=*/0};
152 assert(!wallet->GetDescriptorScriptPubKeyMan(w_desc));
153 LOCK(wallet->cs_wallet);
154 auto& spk_manager = Assert(wallet->AddWalletDescriptor(w_desc, keys, /*label=*/"", internal))->get();
155 wallet->AddActiveScriptPubKeyMan(spk_manager.GetID(), *Assert(w_desc.descriptor->GetOutputType()), internal);
156 m_spkms.push_back(&spk_manager);
157 }
158 }
159 }
160
162 {
163 for (size_t i = 0; i < OUTPUT_TYPES.size(); ++i) {
164 const OutputType type{OUTPUT_TYPES.at(i)};
165 for (size_t j = 0; j < DESTINATION_POOL_SIZE; ++j) {
166 m_dests.at(i).push_back(*Assert(wallet->GetNewDestination(type, "")));
167 m_change_dests.at(i).push_back(*Assert(wallet->GetNewChangeDestination(type)));
168 }
169 }
170 }
171};
172} // namespace wallet
173
174#endif // BITCOIN_TEST_FUZZ_UTIL_WALLET_H
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
#define Assert(val)
Identity function.
Definition check.h:119
Serialized script, used inside transaction inputs and outputs.
Definition script.h:406
T PickValueInArray(const T(&array)[size])
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition chain.h:117
virtual std::optional< int > getHeight()=0
Get current chain height, not including genesis block (returns 0 if chain only contains genesis block...
virtual uint256 getBlockHash(int height)=0
Get block hash. Height must be valid or this function will abort.
Descriptor with some wallet metadata.
Definition walletutil.h:86
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition client.cpp:421
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase()
Definition util.cpp:126
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition walletutil.h:53
OutputType
Definition outputtype.h:18
constexpr auto OUTPUT_TYPES
Definition outputtype.h:26
const char * name
Definition rest.cpp:71
Wraps a descriptor wallet for fuzzing.
Definition wallet.h:33
uint64_t m_iterations
Definition wallet.h:105
interfaces::Chain & m_chain
Definition wallet.h:85
FuzzedWallet(interfaces::Chain &chain, const std::string &name, const std::string &seed_insecure)
Definition wallet.h:39
PoolCursors m_cursors
Definition wallet.h:93
PoolCursors m_change_cursors
Definition wallet.h:94
const std::string m_seed_insecure
Definition wallet.h:87
void PrecomputeDestinations()
Definition wallet.h:161
const std::string m_name
Definition wallet.h:86
std::array< size_t, OUTPUT_TYPES.size()> PoolCursors
Definition wallet.h:89
void ImportDescriptors(const std::string &seed_insecure)
Definition wallet.h:130
CScript GetScriptPubKey(FuzzedDataProvider &fuzzed_data_provider)
Definition wallet.h:73
static constexpr size_t DESTINATION_POOL_SIZE
Definition wallet.h:34
int64_t RangeTotal() const
Definition wallet.h:75
CTxDestination GetDestination(FuzzedDataProvider &fuzzed_data_provider)
Definition wallet.h:61
std::shared_ptr< CWallet > wallet
Definition wallet.h:37
DestinationPool m_change_dests
Definition wallet.h:92
static constexpr uint64_t REBUILD_INTERVAL
Definition wallet.h:35
std::array< std::vector< CTxDestination >, OUTPUT_TYPES.size()> DestinationPool
Definition wallet.h:83
static size_t TypeIndex(OutputType type)
Definition wallet.h:96
DestinationPool m_dests
Definition wallet.h:91
std::vector< DescriptorScriptPubKeyMan * > m_spkms
Definition wallet.h:104
#define LOCK(cs)
Definition sync.h:268
std::vector< uint16_t > keys
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82
assert(!tx.IsCoinBase())
FuzzedDataProvider & fuzzed_data_provider
Definition fees.cpp:46