feat(wallet): add back TxBuilder finish() and sort_tx() with thread_rng()
This commit is contained in:
parent
45c0cae0a4
commit
4bddb0de62
@ -1,6 +1,5 @@
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::thread::JoinHandle;
|
use std::thread::JoinHandle;
|
||||||
use std::usize;
|
|
||||||
|
|
||||||
use bdk_chain::collections::BTreeMap;
|
use bdk_chain::collections::BTreeMap;
|
||||||
use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};
|
use bdk_chain::spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult};
|
||||||
|
@ -25,7 +25,7 @@ bip39 = { version = "2.0", optional = true }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["bitcoin/std", "miniscript/std", "bdk_chain/std"]
|
std = ["bitcoin/std", "bitcoin/rand-std", "miniscript/std", "bdk_chain/std"]
|
||||||
compiler = ["miniscript/compiler"]
|
compiler = ["miniscript/compiler"]
|
||||||
all-keys = ["keys-bip39"]
|
all-keys = ["keys-bip39"]
|
||||||
keys-bip39 = ["bip39"]
|
keys-bip39 = ["bip39"]
|
||||||
|
@ -70,30 +70,28 @@ To persist `Wallet` state data use a data store crate that reads and writes [`bd
|
|||||||
```rust,no_run
|
```rust,no_run
|
||||||
use bdk_wallet::{bitcoin::Network, KeychainKind, wallet::{ChangeSet, Wallet}};
|
use bdk_wallet::{bitcoin::Network, KeychainKind, wallet::{ChangeSet, Wallet}};
|
||||||
|
|
||||||
fn main() {
|
// Open or create a new file store for wallet data.
|
||||||
// Open or create a new file store for wallet data.
|
let mut db =
|
||||||
let mut db =
|
|
||||||
bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "/tmp/my_wallet.db")
|
bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "/tmp/my_wallet.db")
|
||||||
.expect("create store");
|
.expect("create store");
|
||||||
|
|
||||||
// Create a wallet with initial wallet data read from the file store.
|
// Create a wallet with initial wallet data read from the file store.
|
||||||
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
|
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
|
||||||
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
|
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
|
||||||
let changeset = db.aggregate_changesets().expect("changeset loaded");
|
let changeset = db.aggregate_changesets().expect("changeset loaded");
|
||||||
let mut wallet =
|
let mut wallet =
|
||||||
Wallet::new_or_load(descriptor, change_descriptor, changeset, Network::Testnet)
|
Wallet::new_or_load(descriptor, change_descriptor, changeset, Network::Testnet)
|
||||||
.expect("create or load wallet");
|
.expect("create or load wallet");
|
||||||
|
|
||||||
// Get a new address to receive bitcoin.
|
// Get a new address to receive bitcoin.
|
||||||
let receive_address = wallet.reveal_next_address(KeychainKind::External);
|
let receive_address = wallet.reveal_next_address(KeychainKind::External);
|
||||||
// Persist staged wallet data changes to the file store.
|
// Persist staged wallet data changes to the file store.
|
||||||
let staged_changeset = wallet.take_staged();
|
let staged_changeset = wallet.take_staged();
|
||||||
if let Some(changeset) = staged_changeset {
|
if let Some(changeset) = staged_changeset {
|
||||||
db.append_changeset(&changeset)
|
db.append_changeset(&changeset)
|
||||||
.expect("must commit changes to database");
|
.expect("must commit changes to database");
|
||||||
}
|
|
||||||
println!("Your new receive address is: {}", receive_address.address);
|
|
||||||
}
|
}
|
||||||
|
println!("Your new receive address is: {}", receive_address.address);
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- ### Sync the balance of a descriptor -->
|
<!-- ### Sync the balance of a descriptor -->
|
||||||
@ -154,7 +152,6 @@ fn main() {
|
|||||||
<!-- use bitcoin::base64; -->
|
<!-- use bitcoin::base64; -->
|
||||||
<!-- use bdk_wallet::bitcoin::consensus::serialize; -->
|
<!-- use bdk_wallet::bitcoin::consensus::serialize; -->
|
||||||
<!-- use bdk_wallet::bitcoin::Network; -->
|
<!-- use bdk_wallet::bitcoin::Network; -->
|
||||||
<!-- use rand::thread_rng(); -->
|
|
||||||
|
|
||||||
<!-- fn main() -> Result<(), bdk_wallet::Error> { -->
|
<!-- fn main() -> Result<(), bdk_wallet::Error> { -->
|
||||||
<!-- let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?); -->
|
<!-- let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?); -->
|
||||||
@ -174,7 +171,7 @@ fn main() {
|
|||||||
<!-- .enable_rbf() -->
|
<!-- .enable_rbf() -->
|
||||||
<!-- .do_not_spend_change() -->
|
<!-- .do_not_spend_change() -->
|
||||||
<!-- .fee_rate(FeeRate::from_sat_per_vb(5.0)); -->
|
<!-- .fee_rate(FeeRate::from_sat_per_vb(5.0)); -->
|
||||||
<!-- builder.finish_with_aux_rand(&mut thread_rng())? -->
|
<!-- builder.finish()? -->
|
||||||
<!-- }; -->
|
<!-- }; -->
|
||||||
|
|
||||||
<!-- println!("Transaction details: {:#?}", details); -->
|
<!-- println!("Transaction details: {:#?}", details); -->
|
||||||
|
@ -15,7 +15,6 @@ use bdk_wallet::descriptor::IntoWalletDescriptor;
|
|||||||
use bdk_wallet::keys::bip39::{Language, Mnemonic, WordCount};
|
use bdk_wallet::keys::bip39::{Language, Mnemonic, WordCount};
|
||||||
use bdk_wallet::keys::{GeneratableKey, GeneratedKey};
|
use bdk_wallet::keys::{GeneratableKey, GeneratedKey};
|
||||||
use bdk_wallet::miniscript::Tap;
|
use bdk_wallet::miniscript::Tap;
|
||||||
use rand::thread_rng;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// This example demonstrates how to generate a mnemonic phrase
|
/// This example demonstrates how to generate a mnemonic phrase
|
||||||
@ -26,9 +25,8 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
// In this example we are generating a 12 words mnemonic phrase
|
// In this example we are generating a 12 words mnemonic phrase
|
||||||
// but it is also possible generate 15, 18, 21 and 24 words
|
// but it is also possible generate 15, 18, 21 and 24 words
|
||||||
// using their respective `WordCount` variant.
|
// using their respective `WordCount` variant.
|
||||||
let mut rng = thread_rng();
|
|
||||||
let mnemonic: GeneratedKey<_, Tap> =
|
let mnemonic: GeneratedKey<_, Tap> =
|
||||||
Mnemonic::generate((WordCount::Words12, Language::English), &mut rng)
|
Mnemonic::generate((WordCount::Words12, Language::English))
|
||||||
.map_err(|_| anyhow!("Mnemonic generation error"))?;
|
.map_err(|_| anyhow!("Mnemonic generation error"))?;
|
||||||
|
|
||||||
println!("Mnemonic phrase: {}", *mnemonic);
|
println!("Mnemonic phrase: {}", *mnemonic);
|
||||||
|
@ -158,8 +158,6 @@ mod test {
|
|||||||
|
|
||||||
use bip39::{Language, Mnemonic};
|
use bip39::{Language, Mnemonic};
|
||||||
|
|
||||||
use rand::thread_rng;
|
|
||||||
|
|
||||||
use crate::keys::{any_network, GeneratableKey, GeneratedKey};
|
use crate::keys::{any_network, GeneratableKey, GeneratedKey};
|
||||||
|
|
||||||
use super::WordCount;
|
use super::WordCount;
|
||||||
@ -218,12 +216,12 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_keys_generate_bip39_random() {
|
fn test_keys_generate_bip39_random() {
|
||||||
let mut rng = thread_rng();
|
|
||||||
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
||||||
Mnemonic::generate((WordCount::Words12, Language::English), &mut rng).unwrap();
|
Mnemonic::generate((WordCount::Words12, Language::English)).unwrap();
|
||||||
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
||||||
|
|
||||||
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
|
||||||
Mnemonic::generate((WordCount::Words24, Language::English), &mut rng).unwrap();
|
Mnemonic::generate((WordCount::Words24, Language::English)).unwrap();
|
||||||
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
assert_eq!(generated_mnemonic.valid_networks, any_network());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,8 +633,18 @@ pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
|
|||||||
entropy: Self::Entropy,
|
entropy: Self::Entropy,
|
||||||
) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
|
) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
|
||||||
|
|
||||||
/// Generate a key given the options with a random entropy
|
/// Generate a key given the options with random entropy.
|
||||||
fn generate(
|
///
|
||||||
|
/// Uses the thread-local random number generator.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn generate(options: Self::Options) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
||||||
|
Self::generate_with_aux_rand(options, &mut bitcoin::key::rand::thread_rng())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a key given the options with random entropy.
|
||||||
|
///
|
||||||
|
/// Uses a provided random number generator (rng).
|
||||||
|
fn generate_with_aux_rand(
|
||||||
options: Self::Options,
|
options: Self::Options,
|
||||||
rng: &mut (impl CryptoRng + RngCore),
|
rng: &mut (impl CryptoRng + RngCore),
|
||||||
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
||||||
@ -660,10 +670,20 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a key with the default options and a random entropy
|
/// Generate a key with the default options and a random entropy
|
||||||
fn generate_default(
|
///
|
||||||
|
/// Uses the thread-local random number generator.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
||||||
|
Self::generate_with_aux_rand(Default::default(), &mut bitcoin::key::rand::thread_rng())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a key with the default options and a random entropy
|
||||||
|
///
|
||||||
|
/// Uses a provided random number generator (rng).
|
||||||
|
fn generate_default_with_aux_rand(
|
||||||
rng: &mut (impl CryptoRng + RngCore),
|
rng: &mut (impl CryptoRng + RngCore),
|
||||||
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
|
||||||
Self::generate(Default::default(), rng)
|
Self::generate_with_aux_rand(Default::default(), rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
//! # use bdk_wallet::*;
|
//! # use bdk_wallet::*;
|
||||||
//! # use bdk_wallet::wallet::coin_selection::decide_change;
|
//! # use bdk_wallet::wallet::coin_selection::decide_change;
|
||||||
//! # use anyhow::Error;
|
//! # use anyhow::Error;
|
||||||
//! # use rand::{thread_rng, RngCore};
|
|
||||||
//!
|
|
||||||
//! #[derive(Debug)]
|
//! #[derive(Debug)]
|
||||||
//! struct AlwaysSpendEverything;
|
//! struct AlwaysSpendEverything;
|
||||||
//!
|
//!
|
||||||
@ -94,7 +92,7 @@
|
|||||||
//! let psbt = {
|
//! let psbt = {
|
||||||
//! let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
|
//! let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
|
||||||
//! builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
|
//! builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
|
||||||
//! builder.finish_with_aux_rand(&mut thread_rng())?
|
//! builder.finish()?
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! // inspect, sign, broadcast, ...
|
//! // inspect, sign, broadcast, ...
|
||||||
|
@ -44,9 +44,9 @@ impl fmt::Display for MiniscriptPsbtError {
|
|||||||
impl std::error::Error for MiniscriptPsbtError {}
|
impl std::error::Error for MiniscriptPsbtError {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Error returned from [`TxBuilder::finish_with_aux_rand`]
|
/// Error returned from [`TxBuilder::finish`]
|
||||||
///
|
///
|
||||||
/// [`TxBuilder::finish_with_aux_rand`]: crate::wallet::tx_builder::TxBuilder::finish_with_aux_rand
|
/// [`TxBuilder::finish`]: crate::wallet::tx_builder::TxBuilder::finish
|
||||||
pub enum CreateTxError {
|
pub enum CreateTxError {
|
||||||
/// There was a problem with the descriptors passed in
|
/// There was a problem with the descriptors passed in
|
||||||
Descriptor(DescriptorError),
|
Descriptor(DescriptorError),
|
||||||
|
@ -1212,7 +1212,6 @@ impl Wallet {
|
|||||||
/// # use bdk_wallet::wallet::ChangeSet;
|
/// # use bdk_wallet::wallet::ChangeSet;
|
||||||
/// # use bdk_wallet::wallet::error::CreateTxError;
|
/// # use bdk_wallet::wallet::error::CreateTxError;
|
||||||
/// # use anyhow::Error;
|
/// # use anyhow::Error;
|
||||||
/// # use rand::thread_rng;
|
|
||||||
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
|
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
|
||||||
/// # let mut wallet = doctest_wallet!();
|
/// # let mut wallet = doctest_wallet!();
|
||||||
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
||||||
@ -1220,7 +1219,7 @@ impl Wallet {
|
|||||||
/// let mut builder = wallet.build_tx();
|
/// let mut builder = wallet.build_tx();
|
||||||
/// builder
|
/// builder
|
||||||
/// .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
|
/// .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
|
||||||
/// builder.finish_with_aux_rand(&mut thread_rng())?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// // sign and broadcast ...
|
/// // sign and broadcast ...
|
||||||
@ -1577,7 +1576,6 @@ impl Wallet {
|
|||||||
/// # use bdk_wallet::wallet::ChangeSet;
|
/// # use bdk_wallet::wallet::ChangeSet;
|
||||||
/// # use bdk_wallet::wallet::error::CreateTxError;
|
/// # use bdk_wallet::wallet::error::CreateTxError;
|
||||||
/// # use anyhow::Error;
|
/// # use anyhow::Error;
|
||||||
/// # use rand::thread_rng;
|
|
||||||
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
|
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
|
||||||
/// # let mut wallet = doctest_wallet!();
|
/// # let mut wallet = doctest_wallet!();
|
||||||
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
||||||
@ -1586,7 +1584,7 @@ impl Wallet {
|
|||||||
/// builder
|
/// builder
|
||||||
/// .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
|
/// .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
|
||||||
/// .enable_rbf();
|
/// .enable_rbf();
|
||||||
/// builder.finish_with_aux_rand(&mut thread_rng())?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
|
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
/// let tx = psbt.clone().extract_tx().expect("tx");
|
/// let tx = psbt.clone().extract_tx().expect("tx");
|
||||||
@ -1595,7 +1593,7 @@ impl Wallet {
|
|||||||
/// let mut builder = wallet.build_fee_bump(tx.compute_txid())?;
|
/// let mut builder = wallet.build_fee_bump(tx.compute_txid())?;
|
||||||
/// builder
|
/// builder
|
||||||
/// .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
|
/// .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
|
||||||
/// builder.finish_with_aux_rand(&mut thread_rng())?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
|
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
@ -1755,14 +1753,13 @@ impl Wallet {
|
|||||||
/// # use bdk_wallet::*;
|
/// # use bdk_wallet::*;
|
||||||
/// # use bdk_wallet::wallet::ChangeSet;
|
/// # use bdk_wallet::wallet::ChangeSet;
|
||||||
/// # use bdk_wallet::wallet::error::CreateTxError;
|
/// # use bdk_wallet::wallet::error::CreateTxError;
|
||||||
/// # use rand::thread_rng;
|
|
||||||
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
|
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
|
||||||
/// # let mut wallet = doctest_wallet!();
|
/// # let mut wallet = doctest_wallet!();
|
||||||
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
||||||
/// let mut psbt = {
|
/// let mut psbt = {
|
||||||
/// let mut builder = wallet.build_tx();
|
/// let mut builder = wallet.build_tx();
|
||||||
/// builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
|
/// builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
|
||||||
/// builder.finish_with_aux_rand(&mut thread_rng())?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
/// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
/// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
/// assert!(finalized, "we should have signed all the inputs");
|
/// assert!(finalized, "we should have signed all the inputs");
|
||||||
@ -1807,6 +1804,7 @@ impl Wallet {
|
|||||||
{
|
{
|
||||||
signer.sign_transaction(psbt, &sign_options, &self.secp)?;
|
signer.sign_transaction(psbt, &sign_options, &self.secp)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// attempt to finalize
|
// attempt to finalize
|
||||||
if sign_options.try_finalize {
|
if sign_options.try_finalize {
|
||||||
self.finalize_psbt(psbt, sign_options)
|
self.finalize_psbt(psbt, sign_options)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
//! # use bdk_wallet::wallet::ChangeSet;
|
//! # use bdk_wallet::wallet::ChangeSet;
|
||||||
//! # use bdk_wallet::wallet::error::CreateTxError;
|
//! # use bdk_wallet::wallet::error::CreateTxError;
|
||||||
//! # use anyhow::Error;
|
//! # use anyhow::Error;
|
||||||
//! # use rand::thread_rng;
|
|
||||||
//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
||||||
//! # let mut wallet = doctest_wallet!();
|
//! # let mut wallet = doctest_wallet!();
|
||||||
//! // create a TxBuilder from a wallet
|
//! // create a TxBuilder from a wallet
|
||||||
@ -35,7 +34,7 @@
|
|||||||
//! .do_not_spend_change()
|
//! .do_not_spend_change()
|
||||||
//! // Turn on RBF signaling
|
//! // Turn on RBF signaling
|
||||||
//! .enable_rbf();
|
//! .enable_rbf();
|
||||||
//! let psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
|
//! let psbt = tx_builder.finish()?;
|
||||||
//! # Ok::<(), anyhow::Error>(())
|
//! # Ok::<(), anyhow::Error>(())
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
|
|||||||
/// A transaction builder
|
/// A transaction builder
|
||||||
///
|
///
|
||||||
/// A `TxBuilder` is created by calling [`build_tx`] or [`build_fee_bump`] on a wallet. After
|
/// A `TxBuilder` is created by calling [`build_tx`] or [`build_fee_bump`] on a wallet. After
|
||||||
/// assigning it, you set options on it until finally calling [`finish_with_aux_rand`] to consume the builder and
|
/// assigning it, you set options on it until finally calling [`finish`] to consume the builder and
|
||||||
/// generate the transaction.
|
/// generate the transaction.
|
||||||
///
|
///
|
||||||
/// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
|
/// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
|
||||||
@ -71,7 +70,6 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
|
|||||||
/// # use bdk_wallet::wallet::ChangeSet;
|
/// # use bdk_wallet::wallet::ChangeSet;
|
||||||
/// # use bdk_wallet::wallet::error::CreateTxError;
|
/// # use bdk_wallet::wallet::error::CreateTxError;
|
||||||
/// # use anyhow::Error;
|
/// # use anyhow::Error;
|
||||||
/// # use rand::thread_rng;
|
|
||||||
/// # let mut wallet = doctest_wallet!();
|
/// # let mut wallet = doctest_wallet!();
|
||||||
/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
|
||||||
/// # let addr2 = addr1.clone();
|
/// # let addr2 = addr1.clone();
|
||||||
@ -82,7 +80,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
|
|||||||
/// .ordering(TxOrdering::Untouched)
|
/// .ordering(TxOrdering::Untouched)
|
||||||
/// .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
|
/// .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
|
||||||
/// .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
|
/// .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
|
||||||
/// builder.finish_with_aux_rand(&mut thread_rng())?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// // non-chaining
|
/// // non-chaining
|
||||||
@ -92,7 +90,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
|
|||||||
/// for addr in &[addr1, addr2] {
|
/// for addr in &[addr1, addr2] {
|
||||||
/// builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
|
/// builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
|
||||||
/// }
|
/// }
|
||||||
/// builder.finish_with_aux_rand(&mut thread_rng())?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
|
/// assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
|
||||||
@ -106,7 +104,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
|
|||||||
///
|
///
|
||||||
/// [`build_tx`]: Wallet::build_tx
|
/// [`build_tx`]: Wallet::build_tx
|
||||||
/// [`build_fee_bump`]: Wallet::build_fee_bump
|
/// [`build_fee_bump`]: Wallet::build_fee_bump
|
||||||
/// [`finish_with_aux_rand`]: Self::finish_with_aux_rand
|
/// [`finish`]: Self::finish
|
||||||
/// [`coin_selection`]: Self::coin_selection
|
/// [`coin_selection`]: Self::coin_selection
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TxBuilder<'a, Cs> {
|
pub struct TxBuilder<'a, Cs> {
|
||||||
@ -358,11 +356,11 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
|
|||||||
/// 2. The data in `non_witness_utxo` does not match what is in `outpoint`.
|
/// 2. The data in `non_witness_utxo` does not match what is in `outpoint`.
|
||||||
///
|
///
|
||||||
/// Note unless you set [`only_witness_utxo`] any non-taproot `psbt_input` you pass to this
|
/// Note unless you set [`only_witness_utxo`] any non-taproot `psbt_input` you pass to this
|
||||||
/// method must have `non_witness_utxo` set otherwise you will get an error when [`finish_with_aux_rand`]
|
/// method must have `non_witness_utxo` set otherwise you will get an error when [`finish`]
|
||||||
/// is called.
|
/// is called.
|
||||||
///
|
///
|
||||||
/// [`only_witness_utxo`]: Self::only_witness_utxo
|
/// [`only_witness_utxo`]: Self::only_witness_utxo
|
||||||
/// [`finish_with_aux_rand`]: Self::finish_with_aux_rand
|
/// [`finish`]: Self::finish
|
||||||
/// [`max_weight_to_satisfy`]: miniscript::Descriptor::max_weight_to_satisfy
|
/// [`max_weight_to_satisfy`]: miniscript::Descriptor::max_weight_to_satisfy
|
||||||
pub fn add_foreign_utxo(
|
pub fn add_foreign_utxo(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -643,7 +641,6 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
|
|||||||
/// # use bdk_wallet::wallet::ChangeSet;
|
/// # use bdk_wallet::wallet::ChangeSet;
|
||||||
/// # use bdk_wallet::wallet::error::CreateTxError;
|
/// # use bdk_wallet::wallet::error::CreateTxError;
|
||||||
/// # use anyhow::Error;
|
/// # use anyhow::Error;
|
||||||
/// # use rand::thread_rng;
|
|
||||||
/// # let to_address =
|
/// # let to_address =
|
||||||
/// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
|
/// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
|
||||||
/// .unwrap()
|
/// .unwrap()
|
||||||
@ -658,7 +655,7 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
|
|||||||
/// .drain_to(to_address.script_pubkey())
|
/// .drain_to(to_address.script_pubkey())
|
||||||
/// .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
|
/// .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
|
||||||
/// .enable_rbf();
|
/// .enable_rbf();
|
||||||
/// let psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
|
/// let psbt = tx_builder.finish()?;
|
||||||
/// # Ok::<(), anyhow::Error>(())
|
/// # Ok::<(), anyhow::Error>(())
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -674,6 +671,23 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
|
|||||||
impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs> {
|
impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs> {
|
||||||
/// Finish building the transaction.
|
/// Finish building the transaction.
|
||||||
///
|
///
|
||||||
|
/// Uses the thread-local random number generator (rng).
|
||||||
|
///
|
||||||
|
/// Returns a new [`Psbt`] per [`BIP174`].
|
||||||
|
///
|
||||||
|
/// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
|
||||||
|
///
|
||||||
|
/// **WARNING**: To avoid change address reuse you must persist the changes resulting from one
|
||||||
|
/// or more calls to this method before closing the wallet. See [`Wallet::reveal_next_address`].
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub fn finish(self) -> Result<Psbt, CreateTxError> {
|
||||||
|
self.finish_with_aux_rand(&mut bitcoin::key::rand::thread_rng())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finish building the transaction.
|
||||||
|
///
|
||||||
|
/// Uses a provided random number generator (rng).
|
||||||
|
///
|
||||||
/// Returns a new [`Psbt`] per [`BIP174`].
|
/// Returns a new [`Psbt`] per [`BIP174`].
|
||||||
///
|
///
|
||||||
/// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
|
/// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
|
||||||
@ -762,7 +776,17 @@ pub enum TxOrdering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TxOrdering {
|
impl TxOrdering {
|
||||||
/// Sort transaction inputs and outputs by [`TxOrdering`] variant
|
/// Sort transaction inputs and outputs by [`TxOrdering`] variant.
|
||||||
|
///
|
||||||
|
/// Uses the thread-local random number generator (rng).
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub fn sort_tx(self, tx: &mut Transaction) {
|
||||||
|
self.sort_tx_with_aux_rand(tx, &mut bitcoin::key::rand::thread_rng())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sort transaction inputs and outputs by [`TxOrdering`] variant.
|
||||||
|
///
|
||||||
|
/// Uses a provided random number generator (rng).
|
||||||
pub fn sort_tx_with_aux_rand(self, tx: &mut Transaction, rng: &mut impl RngCore) {
|
pub fn sort_tx_with_aux_rand(self, tx: &mut Transaction, rng: &mut impl RngCore) {
|
||||||
match self {
|
match self {
|
||||||
TxOrdering::Untouched => {}
|
TxOrdering::Untouched => {}
|
||||||
@ -852,16 +876,14 @@ mod test {
|
|||||||
use bitcoin::consensus::deserialize;
|
use bitcoin::consensus::deserialize;
|
||||||
use bitcoin::hex::FromHex;
|
use bitcoin::hex::FromHex;
|
||||||
use bitcoin::TxOut;
|
use bitcoin::TxOut;
|
||||||
use rand::thread_rng;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_output_ordering_untouched() {
|
fn test_output_ordering_untouched() {
|
||||||
let original_tx = ordering_test_tx!();
|
let original_tx = ordering_test_tx!();
|
||||||
let mut tx = original_tx.clone();
|
let mut tx = original_tx.clone();
|
||||||
let mut rng = thread_rng();
|
|
||||||
|
|
||||||
TxOrdering::Untouched.sort_tx_with_aux_rand(&mut tx, &mut rng);
|
TxOrdering::Untouched.sort_tx(&mut tx);
|
||||||
|
|
||||||
assert_eq!(original_tx, tx);
|
assert_eq!(original_tx, tx);
|
||||||
}
|
}
|
||||||
@ -870,11 +892,10 @@ mod test {
|
|||||||
fn test_output_ordering_shuffle() {
|
fn test_output_ordering_shuffle() {
|
||||||
let original_tx = ordering_test_tx!();
|
let original_tx = ordering_test_tx!();
|
||||||
let mut tx = original_tx.clone();
|
let mut tx = original_tx.clone();
|
||||||
let mut rng = thread_rng();
|
|
||||||
|
|
||||||
(0..40)
|
(0..40)
|
||||||
.find(|_| {
|
.find(|_| {
|
||||||
TxOrdering::Shuffle.sort_tx_with_aux_rand(&mut tx, &mut rng);
|
TxOrdering::Shuffle.sort_tx(&mut tx);
|
||||||
original_tx.input != tx.input
|
original_tx.input != tx.input
|
||||||
})
|
})
|
||||||
.expect("it should have moved the inputs at least once");
|
.expect("it should have moved the inputs at least once");
|
||||||
@ -882,7 +903,7 @@ mod test {
|
|||||||
let mut tx = original_tx.clone();
|
let mut tx = original_tx.clone();
|
||||||
(0..40)
|
(0..40)
|
||||||
.find(|_| {
|
.find(|_| {
|
||||||
TxOrdering::Shuffle.sort_tx_with_aux_rand(&mut tx, &mut rng);
|
TxOrdering::Shuffle.sort_tx(&mut tx);
|
||||||
original_tx.output != tx.output
|
original_tx.output != tx.output
|
||||||
})
|
})
|
||||||
.expect("it should have moved the outputs at least once");
|
.expect("it should have moved the outputs at least once");
|
||||||
@ -894,9 +915,8 @@ mod test {
|
|||||||
|
|
||||||
let original_tx = ordering_test_tx!();
|
let original_tx = ordering_test_tx!();
|
||||||
let mut tx = original_tx;
|
let mut tx = original_tx;
|
||||||
let mut rng = thread_rng();
|
|
||||||
|
|
||||||
TxOrdering::Bip69Lexicographic.sort_tx_with_aux_rand(&mut tx, &mut rng);
|
TxOrdering::Bip69Lexicographic.sort_tx(&mut tx);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tx.input[0].previous_output,
|
tx.input[0].previous_output,
|
||||||
|
@ -201,12 +201,14 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn test_shuffle_slice_empty_vec() {
|
fn test_shuffle_slice_empty_vec() {
|
||||||
let mut test: Vec<u8> = vec![];
|
let mut test: Vec<u8> = vec![];
|
||||||
shuffle_slice(&mut test, &mut thread_rng());
|
shuffle_slice(&mut test, &mut thread_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn test_shuffle_slice_single_vec() {
|
fn test_shuffle_slice_single_vec() {
|
||||||
let mut test: Vec<u8> = vec![0];
|
let mut test: Vec<u8> = vec![0];
|
||||||
shuffle_slice(&mut test, &mut thread_rng());
|
shuffle_slice(&mut test, &mut thread_rng());
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use bdk_wallet::bitcoin::{Amount, FeeRate, Psbt, TxIn};
|
use bdk_wallet::bitcoin::{Amount, FeeRate, Psbt, TxIn};
|
||||||
use bdk_wallet::{psbt, KeychainKind, SignOptions};
|
use bdk_wallet::{psbt, KeychainKind, SignOptions};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use rand::thread_rng;
|
|
||||||
mod common;
|
mod common;
|
||||||
use common::*;
|
use common::*;
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ fn test_psbt_malformed_psbt_input_legacy() {
|
|||||||
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
||||||
let options = SignOptions {
|
let options = SignOptions {
|
||||||
trust_witness_utxo: true,
|
trust_witness_utxo: true,
|
||||||
@ -33,7 +32,7 @@ fn test_psbt_malformed_psbt_input_segwit() {
|
|||||||
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
psbt.inputs.push(psbt_bip.inputs[1].clone());
|
psbt.inputs.push(psbt_bip.inputs[1].clone());
|
||||||
let options = SignOptions {
|
let options = SignOptions {
|
||||||
trust_witness_utxo: true,
|
trust_witness_utxo: true,
|
||||||
@ -49,7 +48,7 @@ fn test_psbt_malformed_tx_input() {
|
|||||||
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
psbt.unsigned_tx.input.push(TxIn::default());
|
psbt.unsigned_tx.input.push(TxIn::default());
|
||||||
let options = SignOptions {
|
let options = SignOptions {
|
||||||
trust_witness_utxo: true,
|
trust_witness_utxo: true,
|
||||||
@ -65,7 +64,7 @@ fn test_psbt_sign_with_finalized() {
|
|||||||
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
|
|
||||||
// add a finalized input
|
// add a finalized input
|
||||||
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
psbt.inputs.push(psbt_bip.inputs[0].clone());
|
||||||
@ -87,7 +86,7 @@ fn test_psbt_fee_rate_with_witness_utxo() {
|
|||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
builder.fee_rate(expected_fee_rate);
|
builder.fee_rate(expected_fee_rate);
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
let fee_amount = psbt.fee_amount();
|
let fee_amount = psbt.fee_amount();
|
||||||
assert!(fee_amount.is_some());
|
assert!(fee_amount.is_some());
|
||||||
|
|
||||||
@ -112,7 +111,7 @@ fn test_psbt_fee_rate_with_nonwitness_utxo() {
|
|||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
builder.fee_rate(expected_fee_rate);
|
builder.fee_rate(expected_fee_rate);
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
let fee_amount = psbt.fee_amount();
|
let fee_amount = psbt.fee_amount();
|
||||||
assert!(fee_amount.is_some());
|
assert!(fee_amount.is_some());
|
||||||
let unfinalized_fee_rate = psbt.fee_rate().unwrap();
|
let unfinalized_fee_rate = psbt.fee_rate().unwrap();
|
||||||
@ -136,7 +135,7 @@ fn test_psbt_fee_rate_with_missing_txout() {
|
|||||||
let mut builder = wpkh_wallet.build_tx();
|
let mut builder = wpkh_wallet.build_tx();
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
builder.fee_rate(expected_fee_rate);
|
builder.fee_rate(expected_fee_rate);
|
||||||
let mut wpkh_psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut wpkh_psbt = builder.finish().unwrap();
|
||||||
|
|
||||||
wpkh_psbt.inputs[0].witness_utxo = None;
|
wpkh_psbt.inputs[0].witness_utxo = None;
|
||||||
wpkh_psbt.inputs[0].non_witness_utxo = None;
|
wpkh_psbt.inputs[0].non_witness_utxo = None;
|
||||||
@ -150,7 +149,7 @@ fn test_psbt_fee_rate_with_missing_txout() {
|
|||||||
let mut builder = pkh_wallet.build_tx();
|
let mut builder = pkh_wallet.build_tx();
|
||||||
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
builder.drain_to(addr.script_pubkey()).drain_wallet();
|
||||||
builder.fee_rate(expected_fee_rate);
|
builder.fee_rate(expected_fee_rate);
|
||||||
let mut pkh_psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut pkh_psbt = builder.finish().unwrap();
|
||||||
|
|
||||||
pkh_psbt.inputs[0].non_witness_utxo = None;
|
pkh_psbt.inputs[0].non_witness_utxo = None;
|
||||||
assert!(pkh_psbt.fee_amount().is_none());
|
assert!(pkh_psbt.fee_amount().is_none());
|
||||||
@ -179,7 +178,7 @@ fn test_psbt_multiple_internalkey_signers() {
|
|||||||
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
let send_to = wallet.peek_address(KeychainKind::External, 0);
|
||||||
let mut builder = wallet.build_tx();
|
let mut builder = wallet.build_tx();
|
||||||
builder.drain_to(send_to.script_pubkey()).drain_wallet();
|
builder.drain_to(send_to.script_pubkey()).drain_wallet();
|
||||||
let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
|
let mut psbt = builder.finish().unwrap();
|
||||||
let unsigned_tx = psbt.unsigned_tx.clone();
|
let unsigned_tx = psbt.unsigned_tx.clone();
|
||||||
|
|
||||||
// Adds a signer for the wrong internal key, bdk should not use this key to sign
|
// Adds a signer for the wrong internal key, bdk should not use this key to sign
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -8,4 +8,3 @@ bdk_wallet = { path = "../../crates/wallet" }
|
|||||||
bdk_electrum = { path = "../../crates/electrum" }
|
bdk_electrum = { path = "../../crates/electrum" }
|
||||||
bdk_file_store = { path = "../../crates/file_store" }
|
bdk_file_store = { path = "../../crates/file_store" }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
rand = "0.8.0"
|
|
||||||
|
@ -14,7 +14,6 @@ use bdk_wallet::bitcoin::{Address, Amount};
|
|||||||
use bdk_wallet::chain::collections::HashSet;
|
use bdk_wallet::chain::collections::HashSet;
|
||||||
use bdk_wallet::{bitcoin::Network, Wallet};
|
use bdk_wallet::{bitcoin::Network, Wallet};
|
||||||
use bdk_wallet::{KeychainKind, SignOptions};
|
use bdk_wallet::{KeychainKind, SignOptions};
|
||||||
use rand::thread_rng;
|
|
||||||
|
|
||||||
fn main() -> Result<(), anyhow::Error> {
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
let db_path = std::env::temp_dir().join("bdk-electrum-example");
|
let db_path = std::env::temp_dir().join("bdk-electrum-example");
|
||||||
@ -97,7 +96,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
||||||
.enable_rbf();
|
.enable_rbf();
|
||||||
|
|
||||||
let mut psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
|
let mut psbt = tx_builder.finish()?;
|
||||||
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
assert!(finalized);
|
assert!(finalized);
|
||||||
|
|
||||||
|
@ -11,4 +11,3 @@ bdk_esplora = { path = "../../crates/esplora", features = ["async-https"] }
|
|||||||
bdk_sqlite = { path = "../../crates/sqlite" }
|
bdk_sqlite = { path = "../../crates/sqlite" }
|
||||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
|
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
rand = "0.8.0"
|
|
||||||
|
@ -5,7 +5,6 @@ use bdk_wallet::{
|
|||||||
bitcoin::{Address, Amount, Network, Script},
|
bitcoin::{Address, Amount, Network, Script},
|
||||||
KeychainKind, SignOptions, Wallet,
|
KeychainKind, SignOptions, Wallet,
|
||||||
};
|
};
|
||||||
use rand::thread_rng;
|
|
||||||
|
|
||||||
use bdk_sqlite::{rusqlite::Connection, Store};
|
use bdk_sqlite::{rusqlite::Connection, Store};
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ async fn main() -> Result<(), anyhow::Error> {
|
|||||||
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
||||||
.enable_rbf();
|
.enable_rbf();
|
||||||
|
|
||||||
let mut psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
|
let mut psbt = tx_builder.finish()?;
|
||||||
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
assert!(finalized);
|
assert!(finalized);
|
||||||
|
|
||||||
|
@ -11,4 +11,3 @@ bdk_wallet = { path = "../../crates/wallet" }
|
|||||||
bdk_esplora = { path = "../../crates/esplora", features = ["blocking"] }
|
bdk_esplora = { path = "../../crates/esplora", features = ["blocking"] }
|
||||||
bdk_file_store = { path = "../../crates/file_store" }
|
bdk_file_store = { path = "../../crates/file_store" }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
rand = "0.8.0"
|
|
||||||
|
@ -11,7 +11,6 @@ use bdk_wallet::{
|
|||||||
bitcoin::{Address, Amount, Network},
|
bitcoin::{Address, Amount, Network},
|
||||||
KeychainKind, SignOptions, Wallet,
|
KeychainKind, SignOptions, Wallet,
|
||||||
};
|
};
|
||||||
use rand::thread_rng;
|
|
||||||
|
|
||||||
fn main() -> Result<(), anyhow::Error> {
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
let db_path = std::env::temp_dir().join("bdk-esplora-example");
|
let db_path = std::env::temp_dir().join("bdk-esplora-example");
|
||||||
@ -81,7 +80,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
||||||
.enable_rbf();
|
.enable_rbf();
|
||||||
|
|
||||||
let mut psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
|
let mut psbt = tx_builder.finish()?;
|
||||||
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
assert!(finalized);
|
assert!(finalized);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user