Skip to content

Commit 6dab68d

Browse files
committed
Merge #1395: Remove rand dependency from bdk
4bddb0d feat(wallet): add back TxBuilder finish() and sort_tx() with thread_rng() (Steve Myers) 45c0cae fix(bdk): remove rand dependency (rustaceanrob) Pull request description: ### Description WIP towards removing `rand` fixes #871 The `rand` dependency was imported explicitly, but `rand` is also implicitly used through the `rand-std` feature flag on `bitcoin`. ### Notes to he reviewers **Updated:** `rand` was used primarily in two parts of `bdk`. Particularly in signing and in building a transaction. Signing: - Used implicitly in [`sign_schnorr`](https://docs.rs/bitcoin/latest/bitcoin/key/struct.Secp256k1.html#method.sign_schnorr), but nowhere else within `signer`. Transaction ordering: - Used to shuffle the inputs and outputs of a transaction, the default - Used in the single random draw __as a fallback__ to branch and bound during coin selection. Branch and bound is the default coin selection option. See conversation for proposed solutions. ### Changelog notice - Remove the `rand` dependency from `bdk` ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature #### Bugfixes: * [x] This pull request breaks the existing API * [x] I've added tests to reproduce the issue which are now passing * [x] I'm linking the issue being fixed by this PR ACKs for top commit: ValuedMammal: ACK 4bddb0d notmandatory: ACK 4bddb0d Tree-SHA512: 662d9bcb1e02f8195d73df16789b8c2aba8ccd7b37ba713ebb0bfd19c66163acbcb6f266b64f88347cbb1f96b88c8a150581012cbf818d1dc8b4437b3e53fc62
2 parents e406675 + 4bddb0d commit 6dab68d

File tree

11 files changed

+270
-152
lines changed

11 files changed

+270
-152
lines changed

.github/workflows/cont_integration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
uses: Swatinem/rust-cache@v2.2.1
9393
- name: Check bdk wallet
9494
working-directory: ./crates/wallet
95-
run: cargo check --target wasm32-unknown-unknown --no-default-features --features miniscript/no-std,bdk_chain/hashbrown,dev-getrandom-wasm
95+
run: cargo check --target wasm32-unknown-unknown --no-default-features --features miniscript/no-std,bdk_chain/hashbrown
9696
- name: Check esplora
9797
working-directory: ./crates/esplora
9898
run: cargo check --target wasm32-unknown-unknown --no-default-features --features miniscript/no-std,bdk_chain/hashbrown,async

crates/esplora/src/blocking_ext.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::collections::BTreeSet;
22
use std::thread::JoinHandle;
3-
use std::usize;
43

54
use bdk_chain::collections::BTreeMap;
65
use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};

crates/wallet/Cargo.toml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,31 @@ edition = "2021"
1313
rust-version = "1.63"
1414

1515
[dependencies]
16-
rand = "^0.8"
16+
rand_core = { version = "0.6.0" }
1717
miniscript = { version = "12.0.0", features = ["serde"], default-features = false }
18-
bitcoin = { version = "0.32.0", features = ["serde", "base64", "rand-std"], default-features = false }
18+
bitcoin = { version = "0.32.0", features = ["serde", "base64"], default-features = false }
1919
serde = { version = "^1.0", features = ["derive"] }
2020
serde_json = { version = "^1.0" }
2121
bdk_chain = { path = "../chain", version = "0.16.0", features = ["miniscript", "serde"], default-features = false }
2222

2323
# Optional dependencies
2424
bip39 = { version = "2.0", optional = true }
2525

26-
[target.'cfg(target_arch = "wasm32")'.dependencies]
27-
getrandom = "0.2"
28-
js-sys = "0.3"
29-
3026
[features]
3127
default = ["std"]
32-
std = ["bitcoin/std", "miniscript/std", "bdk_chain/std"]
28+
std = ["bitcoin/std", "bitcoin/rand-std", "miniscript/std", "bdk_chain/std"]
3329
compiler = ["miniscript/compiler"]
3430
all-keys = ["keys-bip39"]
3531
keys-bip39 = ["bip39"]
3632

37-
# This feature is used to run `cargo check` in our CI targeting wasm. It's not recommended
38-
# for libraries to explicitly include the "getrandom/js" feature, so we only do it when
39-
# necessary for running our CI. See: https://docs.rs/getrandom/0.2.8/getrandom/#webassembly-support
40-
dev-getrandom-wasm = ["getrandom/js"]
41-
4233
[dev-dependencies]
4334
lazy_static = "1.4"
4435
assert_matches = "1.5.0"
4536
tempfile = "3"
4637
bdk_sqlite = { path = "../sqlite" }
4738
bdk_file_store = { path = "../file_store" }
4839
anyhow = "1"
40+
rand = "^0.8"
4941

5042
[package.metadata.docs.rs]
5143
all-features = true

crates/wallet/README.md

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,30 +70,28 @@ To persist `Wallet` state data use a data store crate that reads and writes [`bd
7070
```rust,no_run
7171
use bdk_wallet::{bitcoin::Network, KeychainKind, wallet::{ChangeSet, Wallet}};
7272
73-
fn main() {
74-
// Open or create a new file store for wallet data.
75-
let mut db =
76-
bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "/tmp/my_wallet.db")
77-
.expect("create store");
78-
79-
// Create a wallet with initial wallet data read from the file store.
80-
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
81-
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
82-
let changeset = db.aggregate_changesets().expect("changeset loaded");
83-
let mut wallet =
84-
Wallet::new_or_load(descriptor, change_descriptor, changeset, Network::Testnet)
85-
.expect("create or load wallet");
86-
87-
// Get a new address to receive bitcoin.
88-
let receive_address = wallet.reveal_next_address(KeychainKind::External);
89-
// Persist staged wallet data changes to the file store.
90-
let staged_changeset = wallet.take_staged();
91-
if let Some(changeset) = staged_changeset {
92-
db.append_changeset(&changeset)
93-
.expect("must commit changes to database");
94-
}
95-
println!("Your new receive address is: {}", receive_address.address);
73+
// Open or create a new file store for wallet data.
74+
let mut db =
75+
bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "/tmp/my_wallet.db")
76+
.expect("create store");
77+
78+
// Create a wallet with initial wallet data read from the file store.
79+
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
80+
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
81+
let changeset = db.aggregate_changesets().expect("changeset loaded");
82+
let mut wallet =
83+
Wallet::new_or_load(descriptor, change_descriptor, changeset, Network::Testnet)
84+
.expect("create or load wallet");
85+
86+
// Get a new address to receive bitcoin.
87+
let receive_address = wallet.reveal_next_address(KeychainKind::External);
88+
// Persist staged wallet data changes to the file store.
89+
let staged_changeset = wallet.take_staged();
90+
if let Some(changeset) = staged_changeset {
91+
db.append_changeset(&changeset)
92+
.expect("must commit changes to database");
9693
}
94+
println!("Your new receive address is: {}", receive_address.address);
9795
```
9896

9997
<!-- ### Sync the balance of a descriptor -->

crates/wallet/src/keys/mod.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use core::marker::PhantomData;
2020
use core::ops::Deref;
2121
use core::str::FromStr;
2222

23+
use rand_core::{CryptoRng, RngCore};
24+
2325
use bitcoin::secp256k1::{self, Secp256k1, Signing};
2426

2527
use bitcoin::bip32;
@@ -631,12 +633,23 @@ pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
631633
entropy: Self::Entropy,
632634
) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
633635

634-
/// Generate a key given the options with a random entropy
636+
/// Generate a key given the options with random entropy.
637+
///
638+
/// Uses the thread-local random number generator.
639+
#[cfg(feature = "std")]
635640
fn generate(options: Self::Options) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
636-
use rand::{thread_rng, Rng};
641+
Self::generate_with_aux_rand(options, &mut bitcoin::key::rand::thread_rng())
642+
}
637643

644+
/// Generate a key given the options with random entropy.
645+
///
646+
/// Uses a provided random number generator (rng).
647+
fn generate_with_aux_rand(
648+
options: Self::Options,
649+
rng: &mut (impl CryptoRng + RngCore),
650+
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
638651
let mut entropy = Self::Entropy::default();
639-
thread_rng().fill(entropy.as_mut());
652+
rng.fill_bytes(entropy.as_mut());
640653
Self::generate_with_entropy(options, entropy)
641654
}
642655
}
@@ -657,8 +670,20 @@ where
657670
}
658671

659672
/// Generate a key with the default options and a random entropy
673+
///
674+
/// Uses the thread-local random number generator.
675+
#[cfg(feature = "std")]
660676
fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
661-
Self::generate(Default::default())
677+
Self::generate_with_aux_rand(Default::default(), &mut bitcoin::key::rand::thread_rng())
678+
}
679+
680+
/// Generate a key with the default options and a random entropy
681+
///
682+
/// Uses a provided random number generator (rng).
683+
fn generate_default_with_aux_rand(
684+
rng: &mut (impl CryptoRng + RngCore),
685+
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
686+
Self::generate_with_aux_rand(Default::default(), rng)
662687
}
663688
}
664689

0 commit comments

Comments
 (0)