Skip to content

Commit b9e7f5a

Browse files
committed
test(fuzzing): add persist/load scenario to fuzz target
- update `bdk_wallet_fuzz` to use `rusqlite` feature. - update the created wallet in `bdk_wallet` fuzz target to use an in-memory sqlite database connection, initializing wallet with persistance. - add the `PersistAndLoad` scenario to `bdk_wallet` fuzz target.
1 parent 932b3ee commit b9e7f5a

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

fuzz/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ cargo-fuzz = true
1616

1717
[dependencies]
1818
libfuzzer-sys = "0.4"
19-
bdk_wallet = { path = "../wallet" }
19+
bdk_wallet = { path = "../wallet", features = ["rusqlite"] }
2020

2121
[[bin]]
2222
name = "bdk_wallet"

fuzz/fuzz_targets/bdk_wallet.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use std::{
77
};
88

99
use bdk_wallet::{
10-
bitcoin::{Network, Txid},
10+
bitcoin::{hashes::Hash as _, BlockHash, Network, Txid},
1111
chain::{BlockId, ConfirmationBlockTime, TxUpdate},
12-
descriptor::DescriptorError,
12+
rusqlite::Connection,
1313
KeychainKind, Update, Wallet,
1414
};
1515

@@ -52,10 +52,11 @@ impl WalletAction {
5252

5353
fuzz_target!(|data: &[u8]| {
5454
// creates initial wallet.
55-
let wallet: Result<Wallet, DescriptorError> =
56-
Wallet::create(INTERNAL_DESCRIPTOR, EXTERNAL_DESCRIPTOR)
57-
.network(NETWORK)
58-
.create_wallet_no_persist();
55+
let mut db_conn = Connection::open_in_memory()
56+
.expect("Should start an in-memory database connection successfully!");
57+
let wallet = Wallet::create(EXTERNAL_DESCRIPTOR, INTERNAL_DESCRIPTOR)
58+
.network(NETWORK)
59+
.create_wallet(&mut db_conn);
5960

6061
// asserts that the wallet creation did not fail.
6162
let mut wallet = match wallet {
@@ -117,8 +118,40 @@ fuzz_target!(|data: &[u8]| {
117118
continue;
118119
}
119120
WalletAction::PersistAndLoad => {
120-
// todo!()
121-
continue;
121+
let expected_balance = wallet.balance();
122+
let expected_internal_index = wallet.next_derivation_index(KeychainKind::Internal);
123+
let expected_external_index = wallet.next_derivation_index(KeychainKind::External);
124+
let expected_tip = wallet.latest_checkpoint();
125+
let expected_genesis_hash =
126+
BlockHash::from_byte_array(NETWORK.chain_hash().to_bytes());
127+
128+
// generate fuzzed persist
129+
wallet
130+
.persist(&mut db_conn)
131+
.expect("It should always persist successfully!");
132+
133+
// generate fuzzed load
134+
wallet = Wallet::load()
135+
.descriptor(KeychainKind::External, Some(EXTERNAL_DESCRIPTOR))
136+
.descriptor(KeychainKind::Internal, Some(INTERNAL_DESCRIPTOR))
137+
.check_network(NETWORK)
138+
.check_genesis_hash(expected_genesis_hash)
139+
.load_wallet(&mut db_conn)
140+
.expect("It should always load from persistence successfully!")
141+
.expect("It should load the wallet successfully!");
142+
143+
// verify the persisted data is accurate
144+
assert_eq!(wallet.network(), NETWORK);
145+
assert_eq!(wallet.balance(), expected_balance);
146+
assert_eq!(
147+
wallet.next_derivation_index(KeychainKind::Internal),
148+
expected_internal_index
149+
);
150+
assert_eq!(
151+
wallet.next_derivation_index(KeychainKind::External),
152+
expected_external_index
153+
);
154+
assert_eq!(wallet.latest_checkpoint(), expected_tip);
122155
}
123156
}
124157
}

0 commit comments

Comments
 (0)