Skip to content

Commit 867c696

Browse files
committed
refactor(fuzz): use and improve consume_... fns
1 parent f5d2a68 commit 867c696

File tree

5 files changed

+414
-364
lines changed

5 files changed

+414
-364
lines changed

fuzz/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ description = "A fuzz testing library for the Bitcoin Development Kit Wallet"
77
keywords = ["fuzz", "testing", "fuzzing", "bitcoin", "wallet"]
88
publish = false
99
readme = "README.md"
10+
license = "MIT OR Apache-2.0"
1011
authors = ["Bitcoin Dev Kit Developers"]
1112
edition = "2021"
12-
license = "MIT OR Apache-2.0"
1313

1414
[package.metadata]
1515
cargo-fuzz = true

fuzz/fuzz_targets/wallet.rs

Lines changed: 41 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,54 @@
33
use libfuzzer_sys::fuzz_target;
44
use std::collections::{BTreeMap, VecDeque};
55

6-
use bdk_wallet::{bitcoin::Network, chain::TxUpdate, CreateParams, KeychainKind, Update, Wallet};
7-
use bdk_wallet_fuzz::utils::*;
8-
9-
// testnet descriptors
6+
use bdk_wallet::{
7+
bitcoin::{Network, Txid},
8+
chain::TxUpdate,
9+
descriptor::DescriptorError,
10+
KeychainKind, Update, Wallet,
11+
};
12+
use bdk_wallet_fuzz::fuzz_utils::*;
13+
14+
// descriptors
1015
const INTERNAL_DESCRIPTOR: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
1116
const EXTERNAL_DESCRIPTOR: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
1217

13-
// mainnet descriptors
14-
// const INTERNAL_DESCRIPTOR: &str = "wpkh(xprv9y5m1SxNcjAY8DJPHqXM67ETRFwpjsacG9xGBiTBMj5A2KupsjuNJuFuFJAzoQJb7fjp3jz78TsmDmqpaTtCBzAKEuqE1NMC3Net5Ma2hY6/84'/1'/0'/0/*)";
15-
// const EXTERNAL_DESCRIPTOR: &str = "wpkh(xprv9y5m1SxNcjAY8DJPHqXM67ETRFwpjsacG9xGBiTBMj5A2KupsjuNJuFuFJAzoQJb7fjp3jz78TsmDmqpaTtCBzAKEuqE1NMC3Net5Ma2hY6/84'/1'/0'/1/*)";
16-
17-
// testnet
18+
// network
1819
const NETWORK: Network = Network::Testnet;
1920

20-
// mainnet
21-
// const NETWORK = Network::Testnet;
22-
2321
fuzz_target!(|data: &[u8]| {
24-
// let data_iter = data.iter();
25-
let params = CreateParams::new(INTERNAL_DESCRIPTOR, EXTERNAL_DESCRIPTOR).network(NETWORK);
26-
let mut wallet = match Wallet::create_with_params(params) {
22+
// creates initial wallet.
23+
let wallet: Result<Wallet, DescriptorError> =
24+
Wallet::create(INTERNAL_DESCRIPTOR, EXTERNAL_DESCRIPTOR)
25+
.network(NETWORK)
26+
.create_wallet_no_persist();
27+
28+
// asserts that the wallet creation did not fail.
29+
let mut wallet = match wallet {
2730
Ok(wallet) => wallet,
28-
Err(_) => panic!(),
31+
Err(_) => return,
2932
};
3033

31-
let mut unconfirmed_txids = VecDeque::new();
32-
33-
// fuzzed code goes here
34+
// fuzzed code goes here.
35+
let mut new_data = data;
3436

35-
// fuzz test wallet updates
37+
// generated fuzzed keychain indices.
38+
// let keychain = wallet.keychains().map(|(k, _)| k).collect();
39+
let internal_indices = consume_keychain_indices(&mut new_data, KeychainKind::Internal);
40+
let external_indices = consume_keychain_indices(&mut new_data, KeychainKind::External);
41+
let mut last_active_indices: BTreeMap<KeychainKind, u32> = BTreeMap::new();
42+
last_active_indices.extend(internal_indices);
43+
last_active_indices.extend(external_indices);
3644

37-
// start with active indices.
38-
let mut last_active_indices = BTreeMap::new();
39-
last_active_indices.extend(get_last_active_indices(data, KeychainKind::Internal));
40-
last_active_indices.extend(get_last_active_indices(data, KeychainKind::External));
45+
// generate fuzzed tx update.
46+
let txs = consume_txs(data, &mut wallet);
4147

42-
// generate the txs for the tx graph
43-
let txs = get_txs(data, &mut wallet);
44-
let _ = txs
45-
.iter()
46-
.map(|tx| unconfirmed_txids.push_back(tx.compute_txid()));
48+
let unconfirmed_txids: VecDeque<Txid> = txs.iter().map(|tx| tx.compute_txid()).collect();
4749

48-
let txouts = get_txouts(data);
49-
50-
let anchors = get_anchors(data, unconfirmed_txids.clone());
51-
// if let Some(txid) = unconfirmed_txids.pop_front() {
52-
// anchors.insert((anchor, txid));
53-
// };
54-
55-
let seen_ats = get_seen_ats(data, unconfirmed_txids.clone());
56-
let evicted_ats = get_evicted_ats(data, unconfirmed_txids);
50+
let txouts = consume_txouts(data);
51+
let anchors = consume_anchors(data, unconfirmed_txids.clone());
52+
let seen_ats = consume_seen_ats(data, unconfirmed_txids.clone());
53+
let evicted_ats = consume_evicted_ats(data, unconfirmed_txids.clone());
5754

5855
// build the tx update with fuzzed data
5956
let mut tx_update = TxUpdate::default();
@@ -63,108 +60,15 @@ fuzz_target!(|data: &[u8]| {
6360
tx_update.seen_ats = seen_ats;
6461
tx_update.evicted_ats = evicted_ats;
6562

66-
// generate the chain/checkpoints
67-
68-
let chain = get_checkpoint(data);
63+
// generate fuzzed chain.
64+
let chain = consume_checkpoint(data, &mut wallet);
6965

66+
// apply fuzzed update.
7067
let update = Update {
7168
last_active_indices,
72-
tx_update: tx_update,
73-
chain: chain,
69+
tx_update,
70+
chain: Some(chain),
7471
};
7572

76-
match wallet.apply_update(update.clone()) {
77-
Ok(_result) => {
78-
// println!("{:#?}", update);
79-
// println!("successfully updated wallet")
80-
}
81-
Err(e) => {
82-
// println!("{:#?}", update)
83-
}
84-
};
73+
wallet.apply_update(update).unwrap();
8574
});
86-
87-
// let txouts_count = *next_or_return!(data_iter) as usize;
88-
// let mut txouts = BTreeMap::new();
89-
// for _ in 0..txouts_count {
90-
// let outpoint = bitcoin::OutPoint::new(
91-
// unique_hash.get_txid(),
92-
// *next_or_return!(data_iter) as u32,
93-
// );
94-
// let amount = *next_or_return!(data_iter) as u64 * 1_000;
95-
// let value = bitcoin::Amount::from_sat(amount);
96-
// txouts.insert(
97-
// outpoint,
98-
// bitcoin::TxOut {
99-
// value,
100-
// script_pubkey: Default::default(),
101-
// },
102-
// );
103-
// }
104-
105-
// let mut anchors = BTreeSet::new();
106-
// while next_or_return!(data_iter) & 0x01 == 0x01 {
107-
// let height = scale(*next_or_return!(data_iter));
108-
// let hash = unique_hash.get_block_hash();
109-
// let block_id = BlockId { height, hash };
110-
// let confirmation_time = scale_u64(*next_or_return!(data_iter));
111-
// let anchor = ConfirmationBlockTime {
112-
// block_id,
113-
// confirmation_time,
114-
// };
115-
// // FIXME: inserting anchors for transactions not in the tx graph will fail the
116-
// // SQLite persistence.
117-
// //let txid = unconfirmed_txids
118-
// //.pop_front()
119-
// //.unwrap_or(unique_hash.get_txid());
120-
// if let Some(txid) = unconfirmed_txids.pop_front() {
121-
// anchors.insert((anchor, txid));
122-
// } else {
123-
// break;
124-
// }
125-
// }
126-
127-
// let mut seen_ats = HashMap::new();
128-
// while next_or_return!(data_iter) & 0x01 == 0x01 {
129-
// let time = cmp::min(scale_u64(*next_or_return!(data_iter)), i64::MAX as u64 - 1);
130-
// let txid = unconfirmed_txids
131-
// .pop_front()
132-
// .unwrap_or(unique_hash.get_txid());
133-
// seen_ats.insert(txid, time);
134-
// }
135-
136-
// let tx_update = TxUpdate {
137-
// txs,
138-
// txouts,
139-
// anchors,
140-
// seen_ats,
141-
// };
142-
143-
// // Finally, do the chain update.
144-
// // TODO: sometimes generate invalid updates, reorgs, etc.
145-
// let chain = if next_or_return!(data_iter) & 0x01 == 0x01 {
146-
// let mut tip = wallet.latest_checkpoint();
147-
// let tip_height = tip.height();
148-
// let blocks_count = *next_or_return!(data_iter) as u32;
149-
// for i in 1..blocks_count + 1 {
150-
// tip = tip
151-
// .push(BlockId {
152-
// height: tip_height + i,
153-
// hash: unique_hash.get_block_hash(),
154-
// })
155-
// .unwrap();
156-
// }
157-
// Some(tip)
158-
// } else {
159-
// None
160-
// };
161-
162-
// // The Wallet update should never fail as we only ever create a consistent chain.
163-
// let update = WalletUpdate {
164-
// last_active_indices,
165-
// tx_update,
166-
// chain,
167-
// };
168-
// wallet.apply_update(update).unwrap();
169-
// }
170-
// // Assert the wallet roundtrips to persistence and check some invariants.

0 commit comments

Comments
 (0)