Bitcoin Core  24.1.0
P2P Digital Currency
deserialize.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2021 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 <addrdb.h>
6 #include <addrman.h>
7 #include <addrman_impl.h>
8 #include <blockencodings.h>
9 #include <blockfilter.h>
10 #include <chain.h>
11 #include <coins.h>
12 #include <compressor.h>
13 #include <consensus/merkle.h>
14 #include <key.h>
15 #include <merkleblock.h>
16 #include <net.h>
17 #include <netbase.h>
18 #include <netgroup.h>
19 #include <node/utxo_snapshot.h>
20 #include <primitives/block.h>
21 #include <protocol.h>
22 #include <psbt.h>
23 #include <pubkey.h>
24 #include <script/keyorigin.h>
25 #include <streams.h>
26 #include <test/util/setup_common.h>
27 #include <undo.h>
28 #include <util/system.h>
29 #include <version.h>
30 
31 #include <exception>
32 #include <optional>
33 #include <stdexcept>
34 #include <stdint.h>
35 #include <unistd.h>
36 
37 #include <test/fuzz/fuzz.h>
38 
40 
41 namespace {
42 const BasicTestingSetup* g_setup;
43 } // namespace
44 
46 {
47  static const auto testing_setup = MakeNoLogFileContext<>();
48  g_setup = testing_setup.get();
49 
50  // Fuzzers using pubkey must hold an ECCVerifyHandle.
51  static const ECCVerifyHandle verify_handle;
52 }
53 
54 #define FUZZ_TARGET_DESERIALIZE(name, code) \
55  FUZZ_TARGET_INIT(name, initialize_deserialize) \
56  { \
57  try { \
58  code \
59  } catch (const invalid_fuzzing_input_exception&) { \
60  } \
61  }
62 
63 namespace {
64 
65 struct invalid_fuzzing_input_exception : public std::exception {
66 };
67 
68 template <typename T>
69 CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION, const int ser_type = SER_NETWORK)
70 {
71  CDataStream ds(ser_type, version);
72  ds << obj;
73  return ds;
74 }
75 
76 template <typename T>
77 T Deserialize(CDataStream ds)
78 {
79  T obj;
80  ds >> obj;
81  return obj;
82 }
83 
84 template <typename T>
85 void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optional<int> protocol_version = std::nullopt, const int ser_type = SER_NETWORK)
86 {
87  CDataStream ds(buffer, ser_type, INIT_PROTO_VERSION);
88  if (protocol_version) {
89  ds.SetVersion(*protocol_version);
90  } else {
91  try {
92  int version;
93  ds >> version;
94  ds.SetVersion(version);
95  } catch (const std::ios_base::failure&) {
96  throw invalid_fuzzing_input_exception();
97  }
98  }
99  try {
100  ds >> obj;
101  } catch (const std::ios_base::failure&) {
102  throw invalid_fuzzing_input_exception();
103  }
104  assert(buffer.empty() || !Serialize(obj).empty());
105 }
106 
107 template <typename T>
108 void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION, const int ser_type = SER_NETWORK)
109 {
110  assert(Deserialize<T>(Serialize(obj, version, ser_type)) == obj);
111 }
112 
113 } // namespace
114 
115 FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
116  BlockFilter block_filter;
117  DeserializeFromFuzzingInput(buffer, block_filter);
118 })
119 FUZZ_TARGET_DESERIALIZE(addr_info_deserialize, {
120  AddrInfo addr_info;
121  DeserializeFromFuzzingInput(buffer, addr_info);
122 })
123 FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
124  CBlockFileInfo block_file_info;
125  DeserializeFromFuzzingInput(buffer, block_file_info);
126 })
127 FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
128  CBlockHeaderAndShortTxIDs block_header_and_short_txids;
129  DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
130 })
131 FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
132  CFeeRate fee_rate;
133  DeserializeFromFuzzingInput(buffer, fee_rate);
135 })
136 FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
137  CMerkleBlock merkle_block;
138  DeserializeFromFuzzingInput(buffer, merkle_block);
139 })
140 FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
141  COutPoint out_point;
142  DeserializeFromFuzzingInput(buffer, out_point);
144 })
145 FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
146  CPartialMerkleTree partial_merkle_tree;
147  DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
148 })
149 FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
150  CPubKey pub_key;
151  DeserializeFromFuzzingInput(buffer, pub_key);
153 })
154 FUZZ_TARGET_DESERIALIZE(script_deserialize, {
155  CScript script;
156  DeserializeFromFuzzingInput(buffer, script);
157 })
158 FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
159  CTxIn tx_in;
160  DeserializeFromFuzzingInput(buffer, tx_in);
162 })
163 FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
164  FlatFilePos flat_file_pos;
165  DeserializeFromFuzzingInput(buffer, flat_file_pos);
167 })
168 FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
169  KeyOriginInfo key_origin_info;
170  DeserializeFromFuzzingInput(buffer, key_origin_info);
171  AssertEqualAfterSerializeDeserialize(key_origin_info);
172 })
173 FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
174  PartiallySignedTransaction partially_signed_transaction;
175  DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
176 })
177 FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
178  PrefilledTransaction prefilled_transaction;
179  DeserializeFromFuzzingInput(buffer, prefilled_transaction);
180 })
181 FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
182  PSBTInput psbt_input;
183  DeserializeFromFuzzingInput(buffer, psbt_input);
184 })
185 FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
186  PSBTOutput psbt_output;
187  DeserializeFromFuzzingInput(buffer, psbt_output);
188 })
189 FUZZ_TARGET_DESERIALIZE(block_deserialize, {
190  CBlock block;
191  DeserializeFromFuzzingInput(buffer, block);
192 })
193 FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
194  CBlockLocator bl;
195  DeserializeFromFuzzingInput(buffer, bl);
196 })
197 FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
198  CBlock block;
199  DeserializeFromFuzzingInput(buffer, block);
200  bool mutated;
201  BlockMerkleRoot(block, &mutated);
202 })
203 FUZZ_TARGET_DESERIALIZE(addrman_deserialize, {
204  NetGroupManager netgroupman{std::vector<bool>()};
205  AddrMan am(netgroupman,
206  /*deterministic=*/false,
207  g_setup->m_node.args->GetIntArg("-checkaddrman", 0));
208  DeserializeFromFuzzingInput(buffer, am);
209 })
210 FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
211  CBlockHeader bh;
212  DeserializeFromFuzzingInput(buffer, bh);
213 })
214 FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
215  CTxUndo tu;
216  DeserializeFromFuzzingInput(buffer, tu);
217 })
218 FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
219  CBlockUndo bu;
220  DeserializeFromFuzzingInput(buffer, bu);
221 })
222 FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
223  Coin coin;
224  DeserializeFromFuzzingInput(buffer, coin);
225 })
226 FUZZ_TARGET_DESERIALIZE(netaddr_deserialize, {
227  CNetAddr na;
228  DeserializeFromFuzzingInput(buffer, na);
229  if (na.IsAddrV1Compatible()) {
231  }
233 })
234 FUZZ_TARGET_DESERIALIZE(service_deserialize, {
235  CService s;
236  DeserializeFromFuzzingInput(buffer, s);
237  if (s.IsAddrV1Compatible()) {
239  }
241  CService s1;
245  CService s2;
248 })
249 FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
250  CMessageHeader mh;
251  DeserializeFromFuzzingInput(buffer, mh);
252  (void)mh.IsCommandValid();
253 })
254 FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_notime, {
255  CAddress a;
257  // A CAddress without nTime (as is expected under INIT_PROTO_VERSION) will roundtrip
258  // in all 5 formats (with/without nTime, v1/v2, network/disk)
264 })
265 FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_withtime, {
266  CAddress a;
268  // A CAddress in V1 mode will roundtrip in all 4 formats that have nTime.
273 })
274 FUZZ_TARGET_DESERIALIZE(address_deserialize_v2, {
275  CAddress a;
277  // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
278  // with time if it's V1 compatible.
279  if (a.IsAddrV1Compatible()) {
282  }
285 })
286 FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
287  CInv i;
288  DeserializeFromFuzzingInput(buffer, i);
289 })
290 FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
291  CBloomFilter bf;
292  DeserializeFromFuzzingInput(buffer, bf);
293 })
294 FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
295  CDiskBlockIndex dbi;
296  DeserializeFromFuzzingInput(buffer, dbi);
297 })
298 FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
299  CTxOut to;
300  auto toc = Using<TxOutCompression>(to);
301  DeserializeFromFuzzingInput(buffer, toc);
302 })
303 FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
305  DeserializeFromFuzzingInput(buffer, bt);
306 })
307 FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
309  DeserializeFromFuzzingInput(buffer, btr);
310 })
311 FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
312  SnapshotMetadata snapshot_metadata;
313  DeserializeFromFuzzingInput(buffer, snapshot_metadata);
314 })
315 FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
316  uint160 u160;
317  DeserializeFromFuzzingInput(buffer, u160);
319 })
320 FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
321  uint256 u256;
322  DeserializeFromFuzzingInput(buffer, u256);
324 })
325 // Classes intentionally not covered in this file since their deserialization code is
326 // fuzzed elsewhere:
327 // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
328 // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
assert(!tx.IsCoinBase())
Describes a place in the block chain to another node such that if the other node doesn&#39;t have the sam...
Definition: block.h:120
A UTXO entry.
Definition: coins.h:30
Definition: block.h:68
inv message data
Definition: protocol.h:471
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
Definition: bloom.h:44
A version of CTransaction with the PSBT format.
Definition: psbt.h:946
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:185
Data structure that represents a partial merkle tree.
Definition: merkleblock.h:54
bool mutated
Netgroup manager.
Definition: netgroup.h:16
bool IsCommandValid() const
Definition: protocol.cpp:107
Stochastic address manager.
Definition: addrman.h:86
Basic testing setup.
Definition: setup_common.h:83
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
Definition: netaddress.h:33
A structure for PSBTs which contains per output information.
Definition: psbt.h:710
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:335
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
Definition: merkleblock.h:124
An input of a transaction.
Definition: transaction.h:73
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
Definition: version.h:15
Complete block filter struct as defined in BIP 157.
Definition: blockfilter.h:111
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:520
Extended statistics about a CAddress.
Definition: addrman_impl.h:39
An encapsulated public key.
Definition: pubkey.h:33
void Serialize(Stream &, char)=delete
A CService with information about it as peer.
Definition: protocol.h:354
A structure for PSBTs which contain per-input information.
Definition: psbt.h:191
BlockMerkleRoot(block, &mutated)
An output of a transaction.
Definition: transaction.h:156
Used to marshal pointers into hashes for db storage.
Definition: chain.h:368
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:34
Network address.
Definition: netaddress.h:117
256-bit opaque blob.
Definition: uint256.h:119
Undo information for a CBlock.
Definition: undo.h:63
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:410
Undo information for a CTransaction.
Definition: undo.h:53
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12
#define FUZZ_TARGET_DESERIALIZE(name, code)
Definition: deserialize.cpp:54
constexpr bool empty() const noexcept
Definition: span.h:188
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition: feerate.h:32
160-bit opaque blob.
Definition: uint256.h:108
AssertEqualAfterSerializeDeserialize(flat_file_pos)
DeserializeFromFuzzingInput(buffer, addr_info)
void initialize_deserialize()
Definition: deserialize.cpp:45
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:96
void SetVersion(int n)
Definition: streams.h:277
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Definition: netaddress.cpp:499
#define T(expected, seed, data)
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:21
Metadata describing a serialized version of a UTXO set from which an assumeutxo Chainstate can be con...
Definition: utxo_snapshot.h:15
Message header.
Definition: protocol.h:26