Upgrade miniscript/bitcoin dependency

Upgrade:

- bitcoin to v0.31.0
- miniscript to v11.0.0

Note: The bitcoin upgrade includes improvements to the
`Transaction::weight()` function, it appears those guys did good, we
no longer need to add the 2 additional weight units "just in case".
This commit is contained in:
Tobin C. Harding 2023-10-16 19:51:53 +11:00
parent 53791eb6c5
commit 984c758f96
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
49 changed files with 556 additions and 519 deletions

View File

@ -14,8 +14,8 @@ rust-version = "1.63"
[dependencies] [dependencies]
rand = "^0.8" rand = "^0.8"
miniscript = { version = "10.0.0", features = ["serde"], default-features = false } miniscript = { version = "11.0.0", features = ["serde"], default-features = false }
bitcoin = { version = "0.30.0", features = ["serde", "base64", "rand-std"], default-features = false } bitcoin = { version = "0.31.0", features = ["serde", "base64", "rand-std"], default-features = false }
serde = { version = "^1.0", features = ["derive"] } serde = { version = "^1.0", features = ["derive"] }
serde_json = { version = "^1.0" } serde_json = { version = "^1.0" }
bdk_chain = { path = "../chain", version = "0.11.0", features = ["miniscript", "serde"], default-features = false } bdk_chain = { path = "../chain", version = "0.11.0", features = ["miniscript", "serde"], default-features = false }

View File

@ -274,14 +274,13 @@ macro_rules! impl_sortedmulti {
#[macro_export] #[macro_export]
macro_rules! parse_tap_tree { macro_rules! parse_tap_tree {
( @merge $tree_a:expr, $tree_b:expr) => {{ ( @merge $tree_a:expr, $tree_b:expr) => {{
use $crate::alloc::sync::Arc;
use $crate::miniscript::descriptor::TapTree; use $crate::miniscript::descriptor::TapTree;
$tree_a $tree_a
.and_then(|tree_a| Ok((tree_a, $tree_b?))) .and_then(|tree_a| Ok((tree_a, $tree_b?)))
.and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| { .and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| {
a_keymap.extend(b_keymap.into_iter()); a_keymap.extend(b_keymap.into_iter());
Ok((TapTree::Tree(Arc::new(a_tree), Arc::new(b_tree)), a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks))) Ok((TapTree::combine(a_tree, b_tree), a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
}) })
}}; }};
@ -806,7 +805,7 @@ mod test {
use crate::descriptor::{DescriptorError, DescriptorMeta}; use crate::descriptor::{DescriptorError, DescriptorMeta};
use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks}; use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
use bitcoin::bip32; use bitcoin::bip32;
use bitcoin::network::constants::Network::{Bitcoin, Regtest, Signet, Testnet}; use bitcoin::Network::{Bitcoin, Regtest, Signet, Testnet};
use bitcoin::PrivateKey; use bitcoin::PrivateKey;
// test the descriptor!() macro // test the descriptor!() macro
@ -936,7 +935,7 @@ mod test {
#[test] #[test]
fn test_bip32_legacy_descriptors() { fn test_bip32_legacy_descriptors() {
let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let path = bip32::DerivationPath::from_str("m/0").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap();
let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap(); let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
@ -981,7 +980,7 @@ mod test {
#[test] #[test]
fn test_bip32_segwitv0_descriptors() { fn test_bip32_segwitv0_descriptors() {
let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let path = bip32::DerivationPath::from_str("m/0").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap();
let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap(); let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
@ -1038,10 +1037,10 @@ mod test {
#[test] #[test]
fn test_dsl_sortedmulti() { fn test_dsl_sortedmulti() {
let key_1 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let key_1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let path_1 = bip32::DerivationPath::from_str("m/0").unwrap(); let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
let key_2 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap(); let key_2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
let path_2 = bip32::DerivationPath::from_str("m/1").unwrap(); let path_2 = bip32::DerivationPath::from_str("m/1").unwrap();
let desc_key1 = (key_1, path_1); let desc_key1 = (key_1, path_1);
@ -1097,7 +1096,7 @@ mod test {
// - verify the valid_networks returned is correctly computed based on the keys present in the descriptor // - verify the valid_networks returned is correctly computed based on the keys present in the descriptor
#[test] #[test]
fn test_valid_networks() { fn test_valid_networks() {
let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let path = bip32::DerivationPath::from_str("m/0").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap();
let desc_key = (xprv, path).into_descriptor_key().unwrap(); let desc_key = (xprv, path).into_descriptor_key().unwrap();
@ -1107,7 +1106,7 @@ mod test {
[Testnet, Regtest, Signet].iter().cloned().collect() [Testnet, Regtest, Signet].iter().cloned().collect()
); );
let xprv = bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap(); let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap();
let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap(); let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
let desc_key = (xprv, path).into_descriptor_key().unwrap(); let desc_key = (xprv, path).into_descriptor_key().unwrap();
@ -1120,15 +1119,15 @@ mod test {
fn test_key_maps_merged() { fn test_key_maps_merged() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let xprv1 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let xprv1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let path1 = bip32::DerivationPath::from_str("m/0").unwrap(); let path1 = bip32::DerivationPath::from_str("m/0").unwrap();
let desc_key1 = (xprv1, path1.clone()).into_descriptor_key().unwrap(); let desc_key1 = (xprv1, path1.clone()).into_descriptor_key().unwrap();
let xprv2 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap(); let xprv2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap(); let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
let desc_key2 = (xprv2, path2.clone()).into_descriptor_key().unwrap(); let desc_key2 = (xprv2, path2.clone()).into_descriptor_key().unwrap();
let xprv3 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap(); let xprv3 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap();
let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap(); let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
let desc_key3 = (xprv3, path3.clone()).into_descriptor_key().unwrap(); let desc_key3 = (xprv3, path3.clone()).into_descriptor_key().unwrap();
@ -1152,7 +1151,7 @@ mod test {
#[test] #[test]
fn test_script_context_validation() { fn test_script_context_validation() {
// this compiles // this compiles
let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let path = bip32::DerivationPath::from_str("m/0").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap();
let desc_key: DescriptorKey<Legacy> = (xprv, path).into_descriptor_key().unwrap(); let desc_key: DescriptorKey<Legacy> = (xprv, path).into_descriptor_key().unwrap();

View File

@ -41,7 +41,7 @@ pub enum Error {
/// Miniscript error /// Miniscript error
Miniscript(miniscript::Error), Miniscript(miniscript::Error),
/// Hex decoding error /// Hex decoding error
Hex(bitcoin::hashes::hex::Error), Hex(bitcoin::hex::HexToBytesError),
} }
impl From<crate::keys::KeyError> for Error { impl From<crate::keys::KeyError> for Error {
@ -110,8 +110,8 @@ impl From<miniscript::Error> for Error {
} }
} }
impl From<bitcoin::hashes::hex::Error> for Error { impl From<bitcoin::hex::HexToBytesError> for Error {
fn from(err: bitcoin::hashes::hex::Error) -> Self { fn from(err: bitcoin::hex::HexToBytesError) -> Self {
Error::Hex(err) Error::Hex(err)
} }
} }

View File

@ -18,7 +18,7 @@ use crate::collections::BTreeMap;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint, KeySource}; use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, KeySource, Xpub};
use bitcoin::{key::XOnlyPublicKey, secp256k1, PublicKey}; use bitcoin::{key::XOnlyPublicKey, secp256k1, PublicKey};
use bitcoin::{psbt, taproot}; use bitcoin::{psbt, taproot};
use bitcoin::{Network, TxOut}; use bitcoin::{Network, TxOut};
@ -377,7 +377,7 @@ where
pub(crate) trait DescriptorMeta { pub(crate) trait DescriptorMeta {
fn is_witness(&self) -> bool; fn is_witness(&self) -> bool;
fn is_taproot(&self) -> bool; fn is_taproot(&self) -> bool;
fn get_extended_keys(&self) -> Vec<DescriptorXKey<ExtendedPubKey>>; fn get_extended_keys(&self) -> Vec<DescriptorXKey<Xpub>>;
fn derive_from_hd_keypaths( fn derive_from_hd_keypaths(
&self, &self,
hd_keypaths: &HdKeyPaths, hd_keypaths: &HdKeyPaths,
@ -418,7 +418,7 @@ impl DescriptorMeta for ExtendedDescriptor {
self.desc_type() == DescriptorType::Tr self.desc_type() == DescriptorType::Tr
} }
fn get_extended_keys(&self) -> Vec<DescriptorXKey<ExtendedPubKey>> { fn get_extended_keys(&self) -> Vec<DescriptorXKey<Xpub>> {
let mut answer = Vec::new(); let mut answer = Vec::new();
self.for_each_key(|pk| { self.for_each_key(|pk| {
@ -438,9 +438,8 @@ impl DescriptorMeta for ExtendedDescriptor {
secp: &SecpCtx, secp: &SecpCtx,
) -> Option<DerivedDescriptor> { ) -> Option<DerivedDescriptor> {
// Ensure that deriving `xpub` with `path` yields `expected` // Ensure that deriving `xpub` with `path` yields `expected`
let verify_key = |xpub: &DescriptorXKey<ExtendedPubKey>, let verify_key =
path: &DerivationPath, |xpub: &DescriptorXKey<Xpub>, path: &DerivationPath, expected: &SinglePubKey| {
expected: &SinglePubKey| {
let derived = xpub let derived = xpub
.xkey .xkey
.derive_pub(secp, path) .derive_pub(secp, path)
@ -605,10 +604,10 @@ mod test {
use core::str::FromStr; use core::str::FromStr;
use assert_matches::assert_matches; use assert_matches::assert_matches;
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::Secp256k1;
use bitcoin::ScriptBuf; use bitcoin::ScriptBuf;
use bitcoin::{bip32, psbt::Psbt}; use bitcoin::{bip32, Psbt};
use super::*; use super::*;
use crate::psbt::PsbtUtils; use crate::psbt::PsbtUtils;
@ -727,7 +726,7 @@ mod test {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let xprv = bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3c3gF1DUWpWNr2SG2XrG8oYPpqYh7hoWsJy9NjabErnzriJPpnGHyKz5NgdXmq1KVbqS1r4NXdCoKitWg5e86zqXHa8kxyB").unwrap(); let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3c3gF1DUWpWNr2SG2XrG8oYPpqYh7hoWsJy9NjabErnzriJPpnGHyKz5NgdXmq1KVbqS1r4NXdCoKitWg5e86zqXHa8kxyB").unwrap();
let path = bip32::DerivationPath::from_str("m/0").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap();
// here `to_descriptor_key` will set the valid networks for the key to only mainnet, since // here `to_descriptor_key` will set the valid networks for the key to only mainnet, since
@ -746,7 +745,7 @@ mod test {
let mut xprv_testnet = xprv; let mut xprv_testnet = xprv;
xprv_testnet.network = Network::Testnet; xprv_testnet.network = Network::Testnet;
let xpub_testnet = bip32::ExtendedPubKey::from_priv(&secp, &xprv_testnet); let xpub_testnet = bip32::Xpub::from_priv(&secp, &xprv_testnet);
let desc_pubkey = DescriptorPublicKey::XPub(DescriptorXKey { let desc_pubkey = DescriptorPublicKey::XPub(DescriptorXKey {
xkey: xpub_testnet, xkey: xpub_testnet,
origin: None, origin: None,
@ -836,7 +835,7 @@ mod test {
fn test_descriptor_from_str_from_output_of_macro() { fn test_descriptor_from_str_from_output_of_macro() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let tpub = bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK").unwrap(); let tpub = bip32::Xpub::from_str("tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK").unwrap();
let path = bip32::DerivationPath::from_str("m/1/2").unwrap(); let path = bip32::DerivationPath::from_str("m/1/2").unwrap();
let key = (tpub, path).into_descriptor_key().unwrap(); let key = (tpub, path).into_descriptor_key().unwrap();
@ -895,7 +894,7 @@ mod test {
.update_with_descriptor_unchecked(&descriptor) .update_with_descriptor_unchecked(&descriptor)
.unwrap(); .unwrap();
assert_eq!(psbt_input.redeem_script, Some(script.to_v0_p2wsh())); assert_eq!(psbt_input.redeem_script, Some(script.to_p2wsh()));
assert_eq!(psbt_input.witness_script, Some(script)); assert_eq!(psbt_input.witness_script, Some(script));
} }
} }

View File

@ -1137,7 +1137,7 @@ impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
let key_spend_sig = let key_spend_sig =
miniscript::Tap::make_signature(tr.internal_key(), signers, build_sat, secp); miniscript::Tap::make_signature(tr.internal_key(), signers, build_sat, secp);
if tr.taptree().is_none() { if tr.tap_tree().is_none() {
Ok(Some(key_spend_sig)) Ok(Some(key_spend_sig))
} else { } else {
let mut items = vec![key_spend_sig]; let mut items = vec![key_spend_sig];
@ -1184,8 +1184,8 @@ mod test {
secp: &SecpCtx, secp: &SecpCtx,
) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) { ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
let path = bip32::DerivationPath::from_str(path).unwrap(); let path = bip32::DerivationPath::from_str(path).unwrap();
let tprv = bip32::ExtendedPrivKey::from_str(tprv).unwrap(); let tprv = bip32::Xpriv::from_str(tprv).unwrap();
let tpub = bip32::ExtendedPubKey::from_priv(secp, &tprv); let tpub = bip32::Xpub::from_priv(secp, &tprv);
let fingerprint = tprv.fingerprint(secp); let fingerprint = tprv.fingerprint(secp);
let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap(); let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
let pubkey = (tpub, path).into_descriptor_key().unwrap(); let pubkey = (tpub, path).into_descriptor_key().unwrap();

View File

@ -195,7 +195,7 @@ impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip44; /// use bdk::template::Bip44;
/// ///
/// let key = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?; /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip44(key.clone(), KeychainKind::External), /// Bip44(key.clone(), KeychainKind::External),
/// Some(Bip44(key, KeychainKind::Internal)), /// Some(Bip44(key, KeychainKind::Internal)),
@ -232,7 +232,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip44Public; /// use bdk::template::Bip44Public;
/// ///
/// let key = bitcoin::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?; /// let key = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?; /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip44Public(key.clone(), fingerprint, KeychainKind::External), /// Bip44Public(key.clone(), fingerprint, KeychainKind::External),
@ -270,7 +270,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip49; /// use bdk::template::Bip49;
/// ///
/// let key = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?; /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip49(key.clone(), KeychainKind::External), /// Bip49(key.clone(), KeychainKind::External),
/// Some(Bip49(key, KeychainKind::Internal)), /// Some(Bip49(key, KeychainKind::Internal)),
@ -307,7 +307,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip49Public; /// use bdk::template::Bip49Public;
/// ///
/// let key = bitcoin::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?; /// let key = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?; /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip49Public(key.clone(), fingerprint, KeychainKind::External), /// Bip49Public(key.clone(), fingerprint, KeychainKind::External),
@ -345,7 +345,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip84; /// use bdk::template::Bip84;
/// ///
/// let key = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?; /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip84(key.clone(), KeychainKind::External), /// Bip84(key.clone(), KeychainKind::External),
/// Some(Bip84(key, KeychainKind::Internal)), /// Some(Bip84(key, KeychainKind::Internal)),
@ -382,7 +382,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip84Public; /// use bdk::template::Bip84Public;
/// ///
/// let key = bitcoin::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?; /// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?; /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip84Public(key.clone(), fingerprint, KeychainKind::External), /// Bip84Public(key.clone(), fingerprint, KeychainKind::External),
@ -420,7 +420,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip86; /// use bdk::template::Bip86;
/// ///
/// let key = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?; /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip86(key.clone(), KeychainKind::External), /// Bip86(key.clone(), KeychainKind::External),
/// Some(Bip86(key, KeychainKind::Internal)), /// Some(Bip86(key, KeychainKind::Internal)),
@ -457,7 +457,7 @@ impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
/// # use bdk::wallet::AddressIndex::New; /// # use bdk::wallet::AddressIndex::New;
/// use bdk::template::Bip86Public; /// use bdk::template::Bip86Public;
/// ///
/// let key = bitcoin::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?; /// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?; /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
/// let mut wallet = Wallet::new_no_persist( /// let mut wallet = Wallet::new_no_persist(
/// Bip86Public(key.clone(), fingerprint, KeychainKind::External), /// Bip86Public(key.clone(), fingerprint, KeychainKind::External),
@ -567,7 +567,7 @@ mod test {
fn test_bip44_template_cointype() { fn test_bip44_template_cointype() {
use bitcoin::bip32::ChildNumber::{self, Hardened}; use bitcoin::bip32::ChildNumber::{self, Hardened};
let xprvkey = bitcoin::bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K2fpbqApQL69a4oKdGVnVN52R82Ft7d1pSqgKmajF62acJo3aMszZb6qQ22QsVECSFxvf9uyxFUvFYQMq3QbtwtRSMjLAhMf").unwrap(); let xprvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K2fpbqApQL69a4oKdGVnVN52R82Ft7d1pSqgKmajF62acJo3aMszZb6qQ22QsVECSFxvf9uyxFUvFYQMq3QbtwtRSMjLAhMf").unwrap();
assert_eq!(Network::Bitcoin, xprvkey.network); assert_eq!(Network::Bitcoin, xprvkey.network);
let xdesc = Bip44(xprvkey, KeychainKind::Internal) let xdesc = Bip44(xprvkey, KeychainKind::Internal)
.build(Network::Bitcoin) .build(Network::Bitcoin)
@ -581,7 +581,7 @@ mod test {
assert_matches!(coin_type, Hardened { index: 0 }); assert_matches!(coin_type, Hardened { index: 0 });
} }
let tprvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let tprvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
assert_eq!(Network::Testnet, tprvkey.network); assert_eq!(Network::Testnet, tprvkey.network);
let tdesc = Bip44(tprvkey, KeychainKind::Internal) let tdesc = Bip44(tprvkey, KeychainKind::Internal)
.build(Network::Testnet) .build(Network::Testnet)
@ -740,7 +740,7 @@ mod test {
// BIP44 `pkh(key/44'/0'/0'/{0,1}/*)` // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
#[test] #[test]
fn test_bip44_template() { fn test_bip44_template() {
let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
check( check(
Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin), Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin),
false, false,
@ -770,7 +770,7 @@ mod test {
// BIP44 public `pkh(key/{0,1}/*)` // BIP44 public `pkh(key/{0,1}/*)`
#[test] #[test]
fn test_bip44_public_template() { fn test_bip44_public_template() {
let pubkey = bitcoin::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap(); let pubkey = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap(); let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
check( check(
Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
@ -801,7 +801,7 @@ mod test {
// BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))` // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
#[test] #[test]
fn test_bip49_template() { fn test_bip49_template() {
let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
check( check(
Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin), Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin),
true, true,
@ -831,7 +831,7 @@ mod test {
// BIP49 public `sh(wpkh(key/{0,1}/*))` // BIP49 public `sh(wpkh(key/{0,1}/*))`
#[test] #[test]
fn test_bip49_public_template() { fn test_bip49_public_template() {
let pubkey = bitcoin::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap(); let pubkey = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap(); let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
check( check(
Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
@ -862,7 +862,7 @@ mod test {
// BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)` // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
#[test] #[test]
fn test_bip84_template() { fn test_bip84_template() {
let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
check( check(
Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin), Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin),
true, true,
@ -892,7 +892,7 @@ mod test {
// BIP84 public `wpkh(key/{0,1}/*)` // BIP84 public `wpkh(key/{0,1}/*)`
#[test] #[test]
fn test_bip84_public_template() { fn test_bip84_public_template() {
let pubkey = bitcoin::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap(); let pubkey = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap(); let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
check( check(
Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
@ -924,7 +924,7 @@ mod test {
// Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
#[test] #[test]
fn test_bip86_template() { fn test_bip86_template() {
let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap(); let prvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap();
check( check(
Bip86(prvkey, KeychainKind::External).build(Network::Bitcoin), Bip86(prvkey, KeychainKind::External).build(Network::Bitcoin),
false, false,
@ -955,7 +955,7 @@ mod test {
// Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
#[test] #[test]
fn test_bip86_public_template() { fn test_bip86_public_template() {
let pubkey = bitcoin::bip32::ExtendedPubKey::from_str("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ").unwrap(); let pubkey = bitcoin::bip32::Xpub::from_str("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ").unwrap();
let fingerprint = bitcoin::bip32::Fingerprint::from_str("73c5da0a").unwrap(); let fingerprint = bitcoin::bip32::Fingerprint::from_str("73c5da0a").unwrap();
check( check(
Bip86Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), Bip86Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),

View File

@ -57,7 +57,7 @@ pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))] #[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed { impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> { fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self[..])?.into()) Ok(bip32::Xpriv::new_master(Network::Bitcoin, &self[..])?.into())
} }
fn into_descriptor_key( fn into_descriptor_key(

View File

@ -110,7 +110,7 @@ impl<Ctx: ScriptContext> DescriptorKey<Ctx> {
Ok((public, KeyMap::default(), valid_networks)) Ok((public, KeyMap::default(), valid_networks))
} }
DescriptorKey::Secret(secret, valid_networks, _) => { DescriptorKey::Secret(secret, valid_networks, _) => {
let mut key_map = KeyMap::with_capacity(1); let mut key_map = KeyMap::new();
let public = secret let public = secret
.to_public(secp) .to_public(secp)
@ -309,15 +309,15 @@ pub trait IntoDescriptorKey<Ctx: ScriptContext>: Sized {
/// Enum for extended keys that can be either `xprv` or `xpub` /// Enum for extended keys that can be either `xprv` or `xpub`
/// ///
/// An instance of [`ExtendedKey`] can be constructed from an [`ExtendedPrivKey`](bip32::ExtendedPrivKey) /// An instance of [`ExtendedKey`] can be constructed from an [`Xpriv`](bip32::Xpriv)
/// or an [`ExtendedPubKey`](bip32::ExtendedPubKey) by using the `From` trait. /// or an [`Xpub`](bip32::Xpub) by using the `From` trait.
/// ///
/// Defaults to the [`Legacy`](miniscript::Legacy) context. /// Defaults to the [`Legacy`](miniscript::Legacy) context.
pub enum ExtendedKey<Ctx: ScriptContext = miniscript::Legacy> { pub enum ExtendedKey<Ctx: ScriptContext = miniscript::Legacy> {
/// A private extended key, aka an `xprv` /// A private extended key, aka an `xprv`
Private((bip32::ExtendedPrivKey, PhantomData<Ctx>)), Private((bip32::Xpriv, PhantomData<Ctx>)),
/// A public extended key, aka an `xpub` /// A public extended key, aka an `xpub`
Public((bip32::ExtendedPubKey, PhantomData<Ctx>)), Public((bip32::Xpub, PhantomData<Ctx>)),
} }
impl<Ctx: ScriptContext> ExtendedKey<Ctx> { impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
@ -329,9 +329,9 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
} }
} }
/// Transform the [`ExtendedKey`] into an [`ExtendedPrivKey`](bip32::ExtendedPrivKey) for the /// Transform the [`ExtendedKey`] into an [`Xpriv`](bip32::Xpriv) for the
/// given [`Network`], if the key contains the private data /// given [`Network`], if the key contains the private data
pub fn into_xprv(self, network: Network) -> Option<bip32::ExtendedPrivKey> { pub fn into_xprv(self, network: Network) -> Option<bip32::Xpriv> {
match self { match self {
ExtendedKey::Private((mut xprv, _)) => { ExtendedKey::Private((mut xprv, _)) => {
xprv.network = network; xprv.network = network;
@ -341,15 +341,15 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
} }
} }
/// Transform the [`ExtendedKey`] into an [`ExtendedPubKey`](bip32::ExtendedPubKey) for the /// Transform the [`ExtendedKey`] into an [`Xpub`](bip32::Xpub) for the
/// given [`Network`] /// given [`Network`]
pub fn into_xpub<C: Signing>( pub fn into_xpub<C: Signing>(
self, self,
network: bitcoin::Network, network: bitcoin::Network,
secp: &Secp256k1<C>, secp: &Secp256k1<C>,
) -> bip32::ExtendedPubKey { ) -> bip32::Xpub {
let mut xpub = match self { let mut xpub = match self {
ExtendedKey::Private((xprv, _)) => bip32::ExtendedPubKey::from_priv(secp, &xprv), ExtendedKey::Private((xprv, _)) => bip32::Xpub::from_priv(secp, &xprv),
ExtendedKey::Public((xpub, _)) => xpub, ExtendedKey::Public((xpub, _)) => xpub,
}; };
@ -358,14 +358,14 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
} }
} }
impl<Ctx: ScriptContext> From<bip32::ExtendedPubKey> for ExtendedKey<Ctx> { impl<Ctx: ScriptContext> From<bip32::Xpub> for ExtendedKey<Ctx> {
fn from(xpub: bip32::ExtendedPubKey) -> Self { fn from(xpub: bip32::Xpub) -> Self {
ExtendedKey::Public((xpub, PhantomData)) ExtendedKey::Public((xpub, PhantomData))
} }
} }
impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> { impl<Ctx: ScriptContext> From<bip32::Xpriv> for ExtendedKey<Ctx> {
fn from(xprv: bip32::ExtendedPrivKey) -> Self { fn from(xprv: bip32::Xpriv) -> Self {
ExtendedKey::Private((xprv, PhantomData)) ExtendedKey::Private((xprv, PhantomData))
} }
} }
@ -383,8 +383,8 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
/// ///
/// ## Examples /// ## Examples
/// ///
/// Key types that can be directly converted into an [`ExtendedPrivKey`] or /// Key types that can be directly converted into an [`Xpriv`] or
/// an [`ExtendedPubKey`] can implement only the required `into_extended_key()` method. /// an [`Xpub`] can implement only the required `into_extended_key()` method.
/// ///
/// ``` /// ```
/// use bdk::bitcoin; /// use bdk::bitcoin;
@ -399,7 +399,7 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
/// ///
/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType { /// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
/// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> { /// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
/// let xprv = bip32::ExtendedPrivKey { /// let xprv = bip32::Xpriv {
/// network: self.network, /// network: self.network,
/// depth: 0, /// depth: 0,
/// parent_fingerprint: bip32::Fingerprint::default(), /// parent_fingerprint: bip32::Fingerprint::default(),
@ -415,7 +415,7 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
/// ///
/// Types that don't internally encode the [`Network`] in which they are valid need some extra /// Types that don't internally encode the [`Network`] in which they are valid need some extra
/// steps to override the set of valid networks, otherwise only the network specified in the /// steps to override the set of valid networks, otherwise only the network specified in the
/// [`ExtendedPrivKey`] or [`ExtendedPubKey`] will be considered valid. /// [`Xpriv`] or [`Xpub`] will be considered valid.
/// ///
/// ``` /// ```
/// use bdk::bitcoin; /// use bdk::bitcoin;
@ -431,7 +431,7 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
/// ///
/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType { /// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
/// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> { /// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
/// let xprv = bip32::ExtendedPrivKey { /// let xprv = bip32::Xpriv {
/// network: bitcoin::Network::Bitcoin, // pick an arbitrary network here /// network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
/// depth: 0, /// depth: 0,
/// parent_fingerprint: bip32::Fingerprint::default(), /// parent_fingerprint: bip32::Fingerprint::default(),
@ -459,8 +459,8 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
/// ``` /// ```
/// ///
/// [`DerivationPath`]: (bip32::DerivationPath) /// [`DerivationPath`]: (bip32::DerivationPath)
/// [`ExtendedPrivKey`]: (bip32::ExtendedPrivKey) /// [`Xpriv`]: (bip32::Xpriv)
/// [`ExtendedPubKey`]: (bip32::ExtendedPubKey) /// [`Xpub`]: (bip32::Xpub)
pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized { pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
/// Consume `self` and turn it into an [`ExtendedKey`] /// Consume `self` and turn it into an [`ExtendedKey`]
#[cfg_attr( #[cfg_attr(
@ -520,13 +520,13 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedKey<Ctx> {
} }
} }
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey { impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpub {
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> { fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
Ok(self.into()) Ok(self.into())
} }
} }
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey { impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpriv {
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> { fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
Ok(self.into()) Ok(self.into())
} }
@ -670,7 +670,7 @@ where
{ {
} }
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::ExtendedPrivKey { impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
type Entropy = [u8; 32]; type Entropy = [u8; 32];
type Options = (); type Options = ();
@ -681,7 +681,7 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::ExtendedPrivKey {
entropy: Self::Entropy, entropy: Self::Entropy,
) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
// pick a arbitrary network here, but say that we support all of them // pick a arbitrary network here, but say that we support all of them
let xprv = bip32::ExtendedPrivKey::new_master(Network::Bitcoin, entropy.as_ref())?; let xprv = bip32::Xpriv::new_master(Network::Bitcoin, entropy.as_ref())?;
Ok(GeneratedKey::new(xprv, any_network())) Ok(GeneratedKey::new(xprv, any_network()))
} }
} }
@ -971,7 +971,7 @@ pub mod test {
#[test] #[test]
fn test_keys_generate_xprv() { fn test_keys_generate_xprv() {
let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> = let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
bip32::ExtendedPrivKey::generate_with_entropy_default(TEST_ENTROPY).unwrap(); bip32::Xpriv::generate_with_entropy_default(TEST_ENTROPY).unwrap();
assert_eq!(generated_xprv.valid_networks, any_network()); assert_eq!(generated_xprv.valid_networks, any_network());
assert_eq!(generated_xprv.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q"); assert_eq!(generated_xprv.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q");

View File

@ -9,12 +9,12 @@
// You may not use this file except in accordance with one or both of these // You may not use this file except in accordance with one or both of these
// licenses. // licenses.
//! Additional functions on the `rust-bitcoin` `PartiallySignedTransaction` structure. //! Additional functions on the `rust-bitcoin` `Psbt` structure.
use alloc::vec::Vec; use alloc::vec::Vec;
use bitcoin::psbt::PartiallySignedTransaction as Psbt;
use bitcoin::Amount; use bitcoin::Amount;
use bitcoin::FeeRate; use bitcoin::FeeRate;
use bitcoin::Psbt;
use bitcoin::TxOut; use bitcoin::TxOut;
// TODO upstream the functions here to `rust-bitcoin`? // TODO upstream the functions here to `rust-bitcoin`?
@ -29,7 +29,7 @@ pub trait PsbtUtils {
fn fee_amount(&self) -> Option<u64>; fn fee_amount(&self) -> Option<u64>;
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the /// The transaction's fee rate. This value will only be accurate if calculated AFTER the
/// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the /// `Psbt` is finalized and all witness/signature data is added to the
/// transaction. /// transaction.
/// If the PSBT is missing a TxOut for an input returns None. /// If the PSBT is missing a TxOut for an input returns None.
fn fee_rate(&self) -> Option<FeeRate>; fn fee_rate(&self) -> Option<FeeRate>;
@ -54,8 +54,13 @@ impl PsbtUtils for Psbt {
let utxos: Option<Vec<TxOut>> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect(); let utxos: Option<Vec<TxOut>> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect();
utxos.map(|inputs| { utxos.map(|inputs| {
let input_amount: u64 = inputs.iter().map(|i| i.value).sum(); let input_amount: u64 = inputs.iter().map(|i| i.value.to_sat()).sum();
let output_amount: u64 = self.unsigned_tx.output.iter().map(|o| o.value).sum(); let output_amount: u64 = self
.unsigned_tx
.output
.iter()
.map(|o| o.value.to_sat())
.sum();
input_amount input_amount
.checked_sub(output_amount) .checked_sub(output_amount)
.expect("input amount must be greater than output amount") .expect("input amount must be greater than output amount")
@ -64,9 +69,7 @@ impl PsbtUtils for Psbt {
fn fee_rate(&self) -> Option<FeeRate> { fn fee_rate(&self) -> Option<FeeRate> {
let fee_amount = self.fee_amount(); let fee_amount = self.fee_amount();
fee_amount.map(|fee| { let weight = self.clone().extract_tx().ok()?.weight();
let weight = self.clone().extract_tx().weight(); fee_amount.map(|fee| Amount::from_sat(fee) / weight)
Amount::from_sat(fee) / weight
})
} }
} }

View File

@ -52,9 +52,10 @@
//! .scan( //! .scan(
//! (&mut selected_amount, &mut additional_weight), //! (&mut selected_amount, &mut additional_weight),
//! |(selected_amount, additional_weight), weighted_utxo| { //! |(selected_amount, additional_weight), weighted_utxo| {
//! **selected_amount += weighted_utxo.utxo.txout().value; //! **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
//! **additional_weight += Weight::from_wu( //! **additional_weight += Weight::from_wu(
//! (TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight) //! (TxIn::default().segwit_weight().to_wu()
//! + weighted_utxo.satisfaction_weight as u64)
//! as u64, //! as u64,
//! ); //! );
//! Some(weighted_utxo.utxo) //! Some(weighted_utxo.utxo)
@ -192,7 +193,7 @@ pub struct CoinSelectionResult {
impl CoinSelectionResult { impl CoinSelectionResult {
/// The total value of the inputs selected. /// The total value of the inputs selected.
pub fn selected_amount(&self) -> u64 { pub fn selected_amount(&self) -> u64 {
self.selected.iter().map(|u| u.txout().value).sum() self.selected.iter().map(|u| u.txout().value.to_sat()).sum()
} }
/// The total value of the inputs selected from the local wallet. /// The total value of the inputs selected from the local wallet.
@ -200,7 +201,7 @@ impl CoinSelectionResult {
self.selected self.selected
.iter() .iter()
.filter_map(|u| match u { .filter_map(|u| match u {
Utxo::Local(_) => Some(u.txout().value), Utxo::Local(_) => Some(u.txout().value.to_sat()),
_ => None, _ => None,
}) })
.sum() .sum()
@ -344,11 +345,11 @@ fn select_sorted_utxos(
if must_use || **selected_amount < target_amount + **fee_amount { if must_use || **selected_amount < target_amount + **fee_amount {
**fee_amount += (fee_rate **fee_amount += (fee_rate
* Weight::from_wu( * Weight::from_wu(
(TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight) TxIn::default().segwit_weight().to_wu()
as u64, + weighted_utxo.satisfaction_weight as u64,
)) ))
.to_sat(); .to_sat();
**selected_amount += weighted_utxo.utxo.txout().value; **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
Some(weighted_utxo.utxo) Some(weighted_utxo.utxo)
} else { } else {
None None
@ -390,10 +391,10 @@ impl OutputGroup {
fn new(weighted_utxo: WeightedUtxo, fee_rate: FeeRate) -> Self { fn new(weighted_utxo: WeightedUtxo, fee_rate: FeeRate) -> Self {
let fee = (fee_rate let fee = (fee_rate
* Weight::from_wu( * Weight::from_wu(
(TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight) as u64, TxIn::default().segwit_weight().to_wu() + weighted_utxo.satisfaction_weight as u64,
)) ))
.to_sat(); .to_sat();
let effective_value = weighted_utxo.utxo.txout().value as i64 - fee as i64; let effective_value = weighted_utxo.utxo.txout().value.to_sat() as i64 - fee as i64;
OutputGroup { OutputGroup {
weighted_utxo, weighted_utxo,
fee, fee,
@ -484,7 +485,7 @@ impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection {
.chain(optional_utxos.iter()) .chain(optional_utxos.iter())
.fold((0, 0), |(mut fees, mut value), utxo| { .fold((0, 0), |(mut fees, mut value), utxo| {
fees += utxo.fee; fees += utxo.fee;
value += utxo.weighted_utxo.utxo.txout().value; value += utxo.weighted_utxo.utxo.txout().value.to_sat();
(fees, value) (fees, value)
}); });
@ -588,7 +589,7 @@ impl BranchAndBoundCoinSelection {
// If we found a solution better than the previous one, or if there wasn't previous // If we found a solution better than the previous one, or if there wasn't previous
// solution, update the best solution // solution, update the best solution
if best_selection_value.is_none() || curr_value < best_selection_value.unwrap() { if best_selection_value.is_none() || curr_value < best_selection_value.unwrap() {
best_selection = current_selection.clone(); best_selection.clone_from(&current_selection);
best_selection_value = Some(curr_value); best_selection_value = Some(curr_value);
} }
@ -742,7 +743,7 @@ mod test {
use core::str::FromStr; use core::str::FromStr;
use bdk_chain::ConfirmationTime; use bdk_chain::ConfirmationTime;
use bitcoin::{Amount, OutPoint, ScriptBuf, TxIn, TxOut}; use bitcoin::{Amount, ScriptBuf, TxIn, TxOut};
use super::*; use super::*;
use crate::types::*; use crate::types::*;
@ -770,7 +771,7 @@ mod test {
utxo: Utxo::Local(LocalOutput { utxo: Utxo::Local(LocalOutput {
outpoint, outpoint,
txout: TxOut { txout: TxOut {
value, value: Amount::from_sat(value),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
keychain: KeychainKind::External, keychain: KeychainKind::External,
@ -834,7 +835,7 @@ mod test {
)) ))
.unwrap(), .unwrap(),
txout: TxOut { txout: TxOut {
value: rng.gen_range(0..200000000), value: Amount::from_sat(rng.gen_range(0..200000000)),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
keychain: KeychainKind::External, keychain: KeychainKind::External,
@ -865,7 +866,7 @@ mod test {
)) ))
.unwrap(), .unwrap(),
txout: TxOut { txout: TxOut {
value: utxos_value, value: Amount::from_sat(utxos_value),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
keychain: KeychainKind::External, keychain: KeychainKind::External,
@ -882,7 +883,7 @@ mod test {
utxos.shuffle(&mut rng); utxos.shuffle(&mut rng);
utxos[..utxos_picked_len] utxos[..utxos_picked_len]
.iter() .iter()
.map(|u| u.utxo.txout().value) .map(|u| u.utxo.txout().value.to_sat())
.sum() .sum()
} }
@ -1071,7 +1072,11 @@ mod test {
fn test_oldest_first_coin_selection_insufficient_funds_high_fees() { fn test_oldest_first_coin_selection_insufficient_funds_high_fees() {
let utxos = get_oldest_first_test_utxos(); let utxos = get_oldest_first_test_utxos();
let target_amount: u64 = utxos.iter().map(|wu| wu.utxo.txout().value).sum::<u64>() - 50; let target_amount: u64 = utxos
.iter()
.map(|wu| wu.utxo.txout().value.to_sat())
.sum::<u64>()
- 50;
let drain_script = ScriptBuf::default(); let drain_script = ScriptBuf::default();
OldestFirstCoinSelection OldestFirstCoinSelection
@ -1166,9 +1171,9 @@ mod test {
)); ));
// Defensive assertions, for sanity and in case someone changes the test utxos vector. // Defensive assertions, for sanity and in case someone changes the test utxos vector.
let amount: u64 = required.iter().map(|u| u.utxo.txout().value).sum(); let amount: u64 = required.iter().map(|u| u.utxo.txout().value.to_sat()).sum();
assert_eq!(amount, 100_000); assert_eq!(amount, 100_000);
let amount: u64 = optional.iter().map(|u| u.utxo.txout().value).sum(); let amount: u64 = optional.iter().map(|u| u.utxo.txout().value.to_sat()).sum();
assert!(amount > 150_000); assert!(amount > 150_000);
let drain_script = ScriptBuf::default(); let drain_script = ScriptBuf::default();
@ -1238,7 +1243,8 @@ mod test {
assert_eq!(result.selected.len(), 1); assert_eq!(result.selected.len(), 1);
assert_eq!(result.selected_amount(), 100_000); assert_eq!(result.selected_amount(), 100_000);
let input_weight = (TxIn::default().segwit_weight() + P2WPKH_SATISFACTION_SIZE) as u64; let input_weight =
TxIn::default().segwit_weight().to_wu() + P2WPKH_SATISFACTION_SIZE as u64;
// the final fee rate should be exactly the same as the fee rate given // the final fee rate should be exactly the same as the fee rate given
let result_feerate = Amount::from_sat(result.fee_amount) / Weight::from_wu(input_weight); let result_feerate = Amount::from_sat(result.fee_amount) / Weight::from_wu(input_weight);
assert_eq!(result_feerate, feerate); assert_eq!(result_feerate, feerate);
@ -1460,9 +1466,9 @@ mod test {
let utxos = get_test_utxos(); let utxos = get_test_utxos();
let drain_script = ScriptBuf::default(); let drain_script = ScriptBuf::default();
let (required, optional) = utxos let (required, optional) = utxos.into_iter().partition(
.into_iter() |u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value.to_sat() < 1000),
.partition(|u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value < 1000)); );
let selection = BranchAndBoundCoinSelection::default().coin_select( let selection = BranchAndBoundCoinSelection::default().coin_select(
required, required,
@ -1511,7 +1517,7 @@ mod test {
utxo: Utxo::Local(LocalOutput { utxo: Utxo::Local(LocalOutput {
outpoint: OutPoint::new(bitcoin::hashes::Hash::hash(txid.as_bytes()), 0), outpoint: OutPoint::new(bitcoin::hashes::Hash::hash(txid.as_bytes()), 0),
txout: TxOut { txout: TxOut {
value, value: Amount::from_sat(value),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
keychain: KeychainKind::External, keychain: KeychainKind::External,

View File

@ -216,7 +216,7 @@ mod test {
use bdk_chain::{BlockId, ConfirmationTime}; use bdk_chain::{BlockId, ConfirmationTime};
use bitcoin::hashes::Hash; use bitcoin::hashes::Hash;
use bitcoin::{BlockHash, Network, Transaction}; use bitcoin::{transaction, BlockHash, Network, Transaction};
use super::*; use super::*;
use crate::wallet::Wallet; use crate::wallet::Wallet;
@ -230,7 +230,7 @@ mod test {
let transaction = Transaction { let transaction = Transaction {
input: vec![], input: vec![],
output: vec![], output: vec![],
version: 0, version: transaction::Version::non_standard(0),
lock_time: bitcoin::absolute::LockTime::ZERO, lock_time: bitcoin::absolute::LockTime::ZERO,
}; };
wallet wallet

View File

@ -48,8 +48,8 @@
//! ``` //! ```
use bitcoin::bip32::Fingerprint; use bitcoin::bip32::Fingerprint;
use bitcoin::psbt::PartiallySignedTransaction;
use bitcoin::secp256k1::{All, Secp256k1}; use bitcoin::secp256k1::{All, Secp256k1};
use bitcoin::Psbt;
use hwi::error::Error; use hwi::error::Error;
use hwi::types::{HWIChain, HWIDevice}; use hwi::types::{HWIChain, HWIDevice};
@ -87,7 +87,7 @@ impl SignerCommon for HWISigner {
impl TransactionSigner for HWISigner { impl TransactionSigner for HWISigner {
fn sign_transaction( fn sign_transaction(
&self, &self,
psbt: &mut PartiallySignedTransaction, psbt: &mut Psbt,
_sign_options: &crate::SignOptions, _sign_options: &crate::SignOptions,
_secp: &crate::wallet::utils::SecpCtx, _secp: &crate::wallet::utils::SecpCtx,
) -> Result<(), SignerError> { ) -> Result<(), SignerError> {

View File

@ -30,14 +30,14 @@ use bdk_chain::{
Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut,
IndexedTxGraph, Persist, PersistBackend, IndexedTxGraph, Persist, PersistBackend,
}; };
use bitcoin::constants::genesis_block;
use bitcoin::secp256k1::{All, Secp256k1}; use bitcoin::secp256k1::{All, Secp256k1};
use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
use bitcoin::{ use bitcoin::{
absolute, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence, Transaction, absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
TxOut, Txid, Weight, Witness, Transaction, TxOut, Txid, Witness,
}; };
use bitcoin::{consensus::encode::serialize, BlockHash}; use bitcoin::{consensus::encode::serialize, transaction, Amount, BlockHash, Psbt};
use bitcoin::{constants::genesis_block, psbt};
use core::fmt; use core::fmt;
use core::ops::Deref; use core::ops::Deref;
use descriptor::error::Error as DescriptorError; use descriptor::error::Error as DescriptorError;
@ -945,11 +945,11 @@ impl<D> Wallet<D> {
/// ``` /// ```
/// ///
/// ```rust, no_run /// ```rust, no_run
/// # use bitcoin::psbt::PartiallySignedTransaction; /// # use bitcoin::Psbt;
/// # use bdk::Wallet; /// # use bdk::Wallet;
/// # let mut wallet: Wallet<()> = todo!(); /// # let mut wallet: Wallet<()> = todo!();
/// # let mut psbt: PartiallySignedTransaction = todo!(); /// # let mut psbt: Psbt = todo!();
/// let tx = &psbt.clone().extract_tx(); /// let tx = &psbt.clone().extract_tx().expect("tx");
/// let fee = wallet.calculate_fee(tx).expect("fee"); /// let fee = wallet.calculate_fee(tx).expect("fee");
/// ``` /// ```
/// [`insert_txout`]: Self::insert_txout /// [`insert_txout`]: Self::insert_txout
@ -976,12 +976,12 @@ impl<D> Wallet<D> {
/// ``` /// ```
/// ///
/// ```rust, no_run /// ```rust, no_run
/// # use bitcoin::psbt::PartiallySignedTransaction; /// # use bitcoin::Psbt;
/// # use bdk::Wallet; /// # use bdk::Wallet;
/// # let mut wallet: Wallet<()> = todo!(); /// # let mut wallet: Wallet<()> = todo!();
/// # let mut psbt: PartiallySignedTransaction = todo!(); /// # let mut psbt: Psbt = todo!();
/// let tx = psbt.clone().extract_tx(); /// let tx = &psbt.clone().extract_tx().expect("tx");
/// let fee_rate = wallet.calculate_fee_rate(&tx).expect("fee rate"); /// let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate");
/// ``` /// ```
/// [`insert_txout`]: Self::insert_txout /// [`insert_txout`]: Self::insert_txout
pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> { pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> {
@ -1007,11 +1007,11 @@ impl<D> Wallet<D> {
/// ``` /// ```
/// ///
/// ```rust, no_run /// ```rust, no_run
/// # use bitcoin::psbt::PartiallySignedTransaction; /// # use bitcoin::Psbt;
/// # use bdk::Wallet; /// # use bdk::Wallet;
/// # let mut wallet: Wallet<()> = todo!(); /// # let mut wallet: Wallet<()> = todo!();
/// # let mut psbt: PartiallySignedTransaction = todo!(); /// # let mut psbt: Psbt = todo!();
/// let tx = &psbt.clone().extract_tx(); /// let tx = &psbt.clone().extract_tx().expect("tx");
/// let (sent, received) = wallet.sent_and_received(tx); /// let (sent, received) = wallet.sent_and_received(tx);
/// ``` /// ```
pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) { pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) {
@ -1261,7 +1261,7 @@ impl<D> Wallet<D> {
&mut self, &mut self,
coin_selection: Cs, coin_selection: Cs,
params: TxParams, params: TxParams,
) -> Result<psbt::PartiallySignedTransaction, CreateTxError<D::WriteError>> ) -> Result<Psbt, CreateTxError<D::WriteError>>
where where
D: PersistBackend<ChangeSet>, D: PersistBackend<ChangeSet>,
{ {
@ -1455,7 +1455,7 @@ impl<D> Wallet<D> {
}; };
let mut tx = Transaction { let mut tx = Transaction {
version, version: transaction::Version::non_standard(version),
lock_time, lock_time,
input: vec![], input: vec![],
output: vec![], output: vec![],
@ -1485,7 +1485,7 @@ impl<D> Wallet<D> {
let new_out = TxOut { let new_out = TxOut {
script_pubkey: script_pubkey.clone(), script_pubkey: script_pubkey.clone(),
value, value: Amount::from_sat(value),
}; };
tx.output.push(new_out); tx.output.push(new_out);
@ -1495,17 +1495,6 @@ impl<D> Wallet<D> {
fee_amount += (fee_rate * tx.weight()).to_sat(); fee_amount += (fee_rate * tx.weight()).to_sat();
// Segwit transactions' header is 2WU larger than legacy txs' header,
// as they contain a witness marker (1WU) and a witness flag (1WU) (see BIP144).
// At this point we really don't know if the resulting transaction will be segwit
// or legacy, so we just add this 2WU to the fee_amount - overshooting the fee amount
// is better than undershooting it.
// If we pass a fee_amount that is slightly higher than the final fee_amount, we
// end up with a transaction with a slightly higher fee rate than the requested one.
// If, instead, we undershoot, we may end up with a feerate lower than the requested one
// - we might come up with non broadcastable txs!
fee_amount += (fee_rate * Weight::from_wu(2)).to_sat();
if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
&& internal_descriptor.is_none() && internal_descriptor.is_none()
{ {
@ -1594,7 +1583,7 @@ impl<D> Wallet<D> {
// create drain output // create drain output
let drain_output = TxOut { let drain_output = TxOut {
value: *amount, value: Amount::from_sat(*amount),
script_pubkey: drain_script, script_pubkey: drain_script,
}; };
@ -1640,7 +1629,7 @@ impl<D> Wallet<D> {
/// builder.finish()? /// builder.finish()?
/// }; /// };
/// let _ = wallet.sign(&mut psbt, SignOptions::default())?; /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
/// let tx = psbt.extract_tx(); /// let tx = psbt.clone().extract_tx().expect("tx");
/// // broadcast tx but it's taking too long to confirm so we want to bump the fee /// // broadcast tx but it's taking too long to confirm so we want to bump the fee
/// let mut psbt = { /// let mut psbt = {
/// let mut builder = wallet.build_fee_bump(tx.txid())?; /// let mut builder = wallet.build_fee_bump(tx.txid())?;
@ -1764,11 +1753,11 @@ impl<D> Wallet<D> {
let params = TxParams { let params = TxParams {
// TODO: figure out what rbf option should be? // TODO: figure out what rbf option should be?
version: Some(tx_builder::Version(tx.version)), version: Some(tx_builder::Version(tx.version.0)),
recipients: tx recipients: tx
.output .output
.into_iter() .into_iter()
.map(|txout| (txout.script_pubkey, txout.value)) .map(|txout| (txout.script_pubkey, txout.value.to_sat()))
.collect(), .collect(),
utxos: original_utxos, utxos: original_utxos,
bumping_fee: Some(tx_builder::PreviousFee { bumping_fee: Some(tx_builder::PreviousFee {
@ -1814,11 +1803,7 @@ impl<D> Wallet<D> {
/// 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");
/// # Ok::<(),anyhow::Error>(()) /// # Ok::<(),anyhow::Error>(())
pub fn sign( pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result<bool, SignerError> {
&self,
psbt: &mut psbt::PartiallySignedTransaction,
sign_options: SignOptions,
) -> Result<bool, SignerError> {
// This adds all the PSBT metadata for the inputs, which will help us later figure out how // This adds all the PSBT metadata for the inputs, which will help us later figure out how
// to derive our keys // to derive our keys
self.update_psbt_with_descriptor(psbt) self.update_psbt_with_descriptor(psbt)
@ -1898,7 +1883,7 @@ impl<D> Wallet<D> {
/// The [`SignOptions`] can be used to tweak the behavior of the finalizer. /// The [`SignOptions`] can be used to tweak the behavior of the finalizer.
pub fn finalize_psbt( pub fn finalize_psbt(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
sign_options: SignOptions, sign_options: SignOptions,
) -> Result<bool, SignerError> { ) -> Result<bool, SignerError> {
let chain_tip = self.chain.tip().block_id(); let chain_tip = self.chain.tip().block_id();
@ -2124,7 +2109,7 @@ impl<D> Wallet<D> {
if must_only_use_confirmed_tx && !confirmation_time.is_confirmed() { if must_only_use_confirmed_tx && !confirmation_time.is_confirmed() {
return false; return false;
} }
if tx.is_coin_base() { if tx.is_coinbase() {
debug_assert!( debug_assert!(
confirmation_time.is_confirmed(), confirmation_time.is_confirmed(),
"coinbase must always be confirmed" "coinbase must always be confirmed"
@ -2173,11 +2158,11 @@ impl<D> Wallet<D> {
tx: Transaction, tx: Transaction,
selected: Vec<Utxo>, selected: Vec<Utxo>,
params: TxParams, params: TxParams,
) -> Result<psbt::PartiallySignedTransaction, CreateTxError<D::WriteError>> ) -> Result<Psbt, CreateTxError<D::WriteError>>
where where
D: PersistBackend<ChangeSet>, D: PersistBackend<ChangeSet>,
{ {
let mut psbt = psbt::PartiallySignedTransaction::from_unsigned_tx(tx)?; let mut psbt = Psbt::from_unsigned_tx(tx)?;
if params.add_global_xpubs { if params.add_global_xpubs {
let all_xpubs = self let all_xpubs = self
@ -2233,7 +2218,7 @@ impl<D> Wallet<D> {
let is_taproot = foreign_psbt_input let is_taproot = foreign_psbt_input
.witness_utxo .witness_utxo
.as_ref() .as_ref()
.map(|txout| txout.script_pubkey.is_v1_p2tr()) .map(|txout| txout.script_pubkey.is_p2tr())
.unwrap_or(false); .unwrap_or(false);
if !is_taproot if !is_taproot
&& !params.only_witness_utxo && !params.only_witness_utxo
@ -2295,10 +2280,7 @@ impl<D> Wallet<D> {
Ok(psbt_input) Ok(psbt_input)
} }
fn update_psbt_with_descriptor( fn update_psbt_with_descriptor(&self, psbt: &mut Psbt) -> Result<(), MiniscriptPsbtError> {
&self,
psbt: &mut psbt::PartiallySignedTransaction,
) -> Result<(), MiniscriptPsbtError> {
// We need to borrow `psbt` mutably within the loops, so we have to allocate a vec for all // We need to borrow `psbt` mutably within the loops, so we have to allocate a vec for all
// the input utxos and outputs // the input utxos and outputs
let utxos = (0..psbt.inputs.len()) let utxos = (0..psbt.inputs.len())
@ -2602,11 +2584,11 @@ macro_rules! doctest_wallet {
.unwrap(); .unwrap();
let address = wallet.get_address(AddressIndex::New).address; let address = wallet.get_address(AddressIndex::New).address;
let tx = Transaction { let tx = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 500_000, value: Amount::from_sat(500_000),
script_pubkey: address.script_pubkey(), script_pubkey: address.script_pubkey(),
}], }],
}; };

View File

@ -19,13 +19,12 @@
//! # use core::str::FromStr; //! # use core::str::FromStr;
//! # use bitcoin::secp256k1::{Secp256k1, All}; //! # use bitcoin::secp256k1::{Secp256k1, All};
//! # use bitcoin::*; //! # use bitcoin::*;
//! # use bitcoin::psbt;
//! # use bdk::signer::*; //! # use bdk::signer::*;
//! # use bdk::*; //! # use bdk::*;
//! # #[derive(Debug)] //! # #[derive(Debug)]
//! # struct CustomHSM; //! # struct CustomHSM;
//! # impl CustomHSM { //! # impl CustomHSM {
//! # fn hsm_sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> { //! # fn hsm_sign_input(&self, _psbt: &mut Psbt, _input: usize) -> Result<(), SignerError> {
//! # Ok(()) //! # Ok(())
//! # } //! # }
//! # fn connect() -> Self { //! # fn connect() -> Self {
@ -55,7 +54,7 @@
//! impl InputSigner for CustomSigner { //! impl InputSigner for CustomSigner {
//! fn sign_input( //! fn sign_input(
//! &self, //! &self,
//! psbt: &mut psbt::PartiallySignedTransaction, //! psbt: &mut Psbt,
//! input_index: usize, //! input_index: usize,
//! _sign_options: &SignOptions, //! _sign_options: &SignOptions,
//! _secp: &Secp256k1<All>, //! _secp: &Secp256k1<All>,
@ -87,13 +86,13 @@ use core::cmp::Ordering;
use core::fmt; use core::fmt;
use core::ops::{Bound::Included, Deref}; use core::ops::{Bound::Included, Deref};
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, Fingerprint}; use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpriv};
use bitcoin::hashes::hash160; use bitcoin::hashes::hash160;
use bitcoin::secp256k1::Message; use bitcoin::secp256k1::Message;
use bitcoin::sighash::{EcdsaSighashType, TapSighash, TapSighashType}; use bitcoin::sighash::{EcdsaSighashType, TapSighash, TapSighashType};
use bitcoin::{ecdsa, psbt, sighash, taproot}; use bitcoin::{ecdsa, psbt, sighash, taproot};
use bitcoin::{key::TapTweak, key::XOnlyPublicKey, secp256k1}; use bitcoin::{key::TapTweak, key::XOnlyPublicKey, secp256k1};
use bitcoin::{PrivateKey, PublicKey}; use bitcoin::{PrivateKey, Psbt, PublicKey};
use miniscript::descriptor::{ use miniscript::descriptor::{
Descriptor, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, Descriptor, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey,
@ -264,7 +263,7 @@ pub trait InputSigner: SignerCommon {
/// Sign a single psbt input /// Sign a single psbt input
fn sign_input( fn sign_input(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
input_index: usize, input_index: usize,
sign_options: &SignOptions, sign_options: &SignOptions,
secp: &SecpCtx, secp: &SecpCtx,
@ -279,7 +278,7 @@ pub trait TransactionSigner: SignerCommon {
/// Sign all the inputs of the psbt /// Sign all the inputs of the psbt
fn sign_transaction( fn sign_transaction(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
sign_options: &SignOptions, sign_options: &SignOptions,
secp: &SecpCtx, secp: &SecpCtx,
) -> Result<(), SignerError>; ) -> Result<(), SignerError>;
@ -288,7 +287,7 @@ pub trait TransactionSigner: SignerCommon {
impl<T: InputSigner> TransactionSigner for T { impl<T: InputSigner> TransactionSigner for T {
fn sign_transaction( fn sign_transaction(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
sign_options: &SignOptions, sign_options: &SignOptions,
secp: &SecpCtx, secp: &SecpCtx,
) -> Result<(), SignerError> { ) -> Result<(), SignerError> {
@ -300,7 +299,7 @@ impl<T: InputSigner> TransactionSigner for T {
} }
} }
impl SignerCommon for SignerWrapper<DescriptorXKey<ExtendedPrivKey>> { impl SignerCommon for SignerWrapper<DescriptorXKey<Xpriv>> {
fn id(&self, secp: &SecpCtx) -> SignerId { fn id(&self, secp: &SecpCtx) -> SignerId {
SignerId::from(self.root_fingerprint(secp)) SignerId::from(self.root_fingerprint(secp))
} }
@ -310,10 +309,10 @@ impl SignerCommon for SignerWrapper<DescriptorXKey<ExtendedPrivKey>> {
} }
} }
impl InputSigner for SignerWrapper<DescriptorXKey<ExtendedPrivKey>> { impl InputSigner for SignerWrapper<DescriptorXKey<Xpriv>> {
fn sign_input( fn sign_input(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
input_index: usize, input_index: usize,
sign_options: &SignOptions, sign_options: &SignOptions,
secp: &SecpCtx, secp: &SecpCtx,
@ -396,7 +395,7 @@ fn multikey_to_xkeys<K: InnerXKey + Clone>(
.collect() .collect()
} }
impl SignerCommon for SignerWrapper<DescriptorMultiXKey<ExtendedPrivKey>> { impl SignerCommon for SignerWrapper<DescriptorMultiXKey<Xpriv>> {
fn id(&self, secp: &SecpCtx) -> SignerId { fn id(&self, secp: &SecpCtx) -> SignerId {
SignerId::from(self.root_fingerprint(secp)) SignerId::from(self.root_fingerprint(secp))
} }
@ -406,10 +405,10 @@ impl SignerCommon for SignerWrapper<DescriptorMultiXKey<ExtendedPrivKey>> {
} }
} }
impl InputSigner for SignerWrapper<DescriptorMultiXKey<ExtendedPrivKey>> { impl InputSigner for SignerWrapper<DescriptorMultiXKey<Xpriv>> {
fn sign_input( fn sign_input(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
input_index: usize, input_index: usize,
sign_options: &SignOptions, sign_options: &SignOptions,
secp: &SecpCtx, secp: &SecpCtx,
@ -438,7 +437,7 @@ impl SignerCommon for SignerWrapper<PrivateKey> {
impl InputSigner for SignerWrapper<PrivateKey> { impl InputSigner for SignerWrapper<PrivateKey> {
fn sign_input( fn sign_input(
&self, &self,
psbt: &mut psbt::PartiallySignedTransaction, psbt: &mut Psbt,
input_index: usize, input_index: usize,
sign_options: &SignOptions, sign_options: &SignOptions,
secp: &SecpCtx, secp: &SecpCtx,
@ -577,7 +576,7 @@ fn sign_psbt_schnorr(
hash_ty: TapSighashType, hash_ty: TapSighashType,
secp: &SecpCtx, secp: &SecpCtx,
) { ) {
let keypair = secp256k1::KeyPair::from_seckey_slice(secp, secret_key.as_ref()).unwrap(); let keypair = secp256k1::Keypair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
let keypair = match leaf_hash { let keypair = match leaf_hash {
None => keypair None => keypair
.tap_tweak(secp, psbt_input.tap_merkle_root) .tap_tweak(secp, psbt_input.tap_merkle_root)
@ -852,7 +851,7 @@ pub(crate) trait ComputeSighash {
type SighashType; type SighashType;
fn sighash( fn sighash(
psbt: &psbt::PartiallySignedTransaction, psbt: &Psbt,
input_index: usize, input_index: usize,
extra: Self::Extra, extra: Self::Extra,
) -> Result<(Self::Sighash, Self::SighashType), SignerError>; ) -> Result<(Self::Sighash, Self::SighashType), SignerError>;
@ -864,7 +863,7 @@ impl ComputeSighash for Legacy {
type SighashType = EcdsaSighashType; type SighashType = EcdsaSighashType;
fn sighash( fn sighash(
psbt: &psbt::PartiallySignedTransaction, psbt: &Psbt,
input_index: usize, input_index: usize,
_extra: (), _extra: (),
) -> Result<(Self::Sighash, Self::SighashType), SignerError> { ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
@ -913,7 +912,7 @@ impl ComputeSighash for Segwitv0 {
type SighashType = EcdsaSighashType; type SighashType = EcdsaSighashType;
fn sighash( fn sighash(
psbt: &psbt::PartiallySignedTransaction, psbt: &Psbt,
input_index: usize, input_index: usize,
_extra: (), _extra: (),
) -> Result<(Self::Sighash, Self::SighashType), SignerError> { ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
@ -924,7 +923,7 @@ impl ComputeSighash for Segwitv0 {
let psbt_input = &psbt.inputs[input_index]; let psbt_input = &psbt.inputs[input_index];
let tx_input = &psbt.unsigned_tx.input[input_index]; let tx_input = &psbt.unsigned_tx.input[input_index];
let sighash = psbt_input let sighash_type = psbt_input
.sighash_type .sighash_type
.unwrap_or_else(|| EcdsaSighashType::All.into()) .unwrap_or_else(|| EcdsaSighashType::All.into())
.ecdsa_hash_ty() .ecdsa_hash_ty()
@ -952,40 +951,39 @@ impl ComputeSighash for Segwitv0 {
}; };
let value = utxo.value; let value = utxo.value;
let script = match psbt_input.witness_script { let mut sighasher = sighash::SighashCache::new(&psbt.unsigned_tx);
Some(ref witness_script) => witness_script.clone(),
let sighash = match psbt_input.witness_script {
Some(ref witness_script) => {
sighasher.p2wsh_signature_hash(input_index, witness_script, value, sighash_type)?
}
None => { None => {
if utxo.script_pubkey.is_v0_p2wpkh() { if utxo.script_pubkey.is_p2wpkh() {
utxo.script_pubkey sighasher.p2wpkh_signature_hash(
.p2wpkh_script_code() input_index,
.expect("We check above that the spk is a p2wpkh") &utxo.script_pubkey,
value,
sighash_type,
)?
} else if psbt_input } else if psbt_input
.redeem_script .redeem_script
.as_ref() .as_ref()
.map(|s| s.is_v0_p2wpkh()) .map(|s| s.is_p2wpkh())
.unwrap_or(false) .unwrap_or(false)
{ {
psbt_input let script_pubkey = psbt_input.redeem_script.as_ref().unwrap();
.redeem_script sighasher.p2wpkh_signature_hash(
.as_ref() input_index,
.unwrap() script_pubkey,
.p2wpkh_script_code() value,
.expect("We check above that the spk is a p2wpkh") sighash_type,
)?
} else { } else {
return Err(SignerError::MissingWitnessScript); return Err(SignerError::MissingWitnessScript);
} }
} }
}; };
Ok((sighash, sighash_type))
Ok((
sighash::SighashCache::new(&psbt.unsigned_tx).segwit_signature_hash(
input_index,
&script,
value,
sighash,
)?,
sighash,
))
} }
} }
@ -995,7 +993,7 @@ impl ComputeSighash for Tap {
type SighashType = TapSighashType; type SighashType = TapSighashType;
fn sighash( fn sighash(
psbt: &psbt::PartiallySignedTransaction, psbt: &Psbt,
input_index: usize, input_index: usize,
extra: Self::Extra, extra: Self::Extra,
) -> Result<(Self::Sighash, TapSighashType), SignerError> { ) -> Result<(Self::Sighash, TapSighashType), SignerError> {
@ -1166,7 +1164,7 @@ mod signers_container_tests {
impl TransactionSigner for DummySigner { impl TransactionSigner for DummySigner {
fn sign_transaction( fn sign_transaction(
&self, &self,
_psbt: &mut psbt::PartiallySignedTransaction, _psbt: &mut Psbt,
_sign_options: &SignOptions, _sign_options: &SignOptions,
_secp: &SecpCtx, _secp: &SecpCtx,
) -> Result<(), SignerError> { ) -> Result<(), SignerError> {
@ -1184,8 +1182,8 @@ mod signers_container_tests {
) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) { ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
let secp: Secp256k1<All> = Secp256k1::new(); let secp: Secp256k1<All> = Secp256k1::new();
let path = bip32::DerivationPath::from_str(PATH).unwrap(); let path = bip32::DerivationPath::from_str(PATH).unwrap();
let tprv = bip32::ExtendedPrivKey::from_str(tprv).unwrap(); let tprv = bip32::Xpriv::from_str(tprv).unwrap();
let tpub = bip32::ExtendedPubKey::from_priv(&secp, &tprv); let tpub = bip32::Xpub::from_priv(&secp, &tprv);
let fingerprint = tprv.fingerprint(&secp); let fingerprint = tprv.fingerprint(&secp);
let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap(); let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
let pubkey = (tpub, path).into_descriptor_key().unwrap(); let pubkey = (tpub, path).into_descriptor_key().unwrap();

View File

@ -46,7 +46,7 @@ use core::fmt;
use core::marker::PhantomData; use core::marker::PhantomData;
use bdk_chain::PersistBackend; use bdk_chain::PersistBackend;
use bitcoin::psbt::{self, PartiallySignedTransaction as Psbt}; use bitcoin::psbt::{self, Psbt};
use bitcoin::script::PushBytes; use bitcoin::script::PushBytes;
use bitcoin::{absolute, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid}; use bitcoin::{absolute, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid};
@ -927,7 +927,8 @@ mod test {
use bdk_chain::ConfirmationTime; use bdk_chain::ConfirmationTime;
use bitcoin::consensus::deserialize; use bitcoin::consensus::deserialize;
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
use bitcoin::TxOut;
use super::*; use super::*;
@ -998,7 +999,7 @@ mod test {
.unwrap() .unwrap()
); );
assert_eq!(tx.output[0].value, 800); assert_eq!(tx.output[0].value.to_sat(), 800);
assert_eq!(tx.output[1].script_pubkey, ScriptBuf::from(vec![0xAA])); assert_eq!(tx.output[1].script_pubkey, ScriptBuf::from(vec![0xAA]));
assert_eq!( assert_eq!(
tx.output[2].script_pubkey, tx.output[2].script_pubkey,
@ -1015,7 +1016,7 @@ mod test {
txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
vout: 0, vout: 0,
}, },
txout: Default::default(), txout: TxOut::NULL,
keychain: KeychainKind::External, keychain: KeychainKind::External,
is_spent: false, is_spent: false,
confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 },
@ -1026,7 +1027,7 @@ mod test {
txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
vout: 1, vout: 1,
}, },
txout: Default::default(), txout: TxOut::NULL,
keychain: KeychainKind::Internal, keychain: KeychainKind::Internal,
is_spent: false, is_spent: false,
confirmation_time: ConfirmationTime::Confirmed { confirmation_time: ConfirmationTime::Confirmed {

View File

@ -138,7 +138,7 @@ mod test {
.require_network(Network::Bitcoin) .require_network(Network::Bitcoin)
.unwrap() .unwrap()
.script_pubkey(); .script_pubkey();
assert!(script_p2wpkh.is_v0_p2wpkh()); assert!(script_p2wpkh.is_p2wpkh());
assert!(293.is_dust(&script_p2wpkh)); assert!(293.is_dust(&script_p2wpkh));
assert!(!294.is_dust(&script_p2wpkh)); assert!(!294.is_dust(&script_p2wpkh));
} }

View File

@ -4,7 +4,10 @@ use bdk::{wallet::AddressIndex, KeychainKind, LocalOutput, Wallet};
use bdk_chain::indexed_tx_graph::Indexer; use bdk_chain::indexed_tx_graph::Indexer;
use bdk_chain::{BlockId, ConfirmationTime}; use bdk_chain::{BlockId, ConfirmationTime};
use bitcoin::hashes::Hash; use bitcoin::hashes::Hash;
use bitcoin::{Address, BlockHash, FeeRate, Network, OutPoint, Transaction, TxIn, TxOut, Txid}; use bitcoin::{
transaction, Address, Amount, BlockHash, FeeRate, Network, OutPoint, Transaction, TxIn, TxOut,
Txid,
};
use std::str::FromStr; use std::str::FromStr;
// Return a fake wallet that appears to be funded for testing. // Return a fake wallet that appears to be funded for testing.
@ -24,7 +27,7 @@ pub fn get_funded_wallet_with_change(
.unwrap(); .unwrap();
let tx0 = Transaction { let tx0 = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: bitcoin::absolute::LockTime::ZERO, lock_time: bitcoin::absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { previous_output: OutPoint {
@ -36,13 +39,13 @@ pub fn get_funded_wallet_with_change(
witness: Default::default(), witness: Default::default(),
}], }],
output: vec![TxOut { output: vec![TxOut {
value: 76_000, value: Amount::from_sat(76_000),
script_pubkey: change_address.script_pubkey(), script_pubkey: change_address.script_pubkey(),
}], }],
}; };
let tx1 = Transaction { let tx1 = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: bitcoin::absolute::LockTime::ZERO, lock_time: bitcoin::absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { previous_output: OutPoint {
@ -55,11 +58,11 @@ pub fn get_funded_wallet_with_change(
}], }],
output: vec![ output: vec![
TxOut { TxOut {
value: 50_000, value: Amount::from_sat(50_000),
script_pubkey: change_address.script_pubkey(), script_pubkey: change_address.script_pubkey(),
}, },
TxOut { TxOut {
value: 25_000, value: Amount::from_sat(25_000),
script_pubkey: sendto_address.script_pubkey(), script_pubkey: sendto_address.script_pubkey(),
}, },
], ],

View File

@ -1,9 +1,7 @@
use bdk::bitcoin::FeeRate; use bdk::bitcoin::{Amount, FeeRate, Psbt, TxIn};
use bdk::bitcoin::TxIn;
use bdk::wallet::AddressIndex; use bdk::wallet::AddressIndex;
use bdk::wallet::AddressIndex::New; use bdk::wallet::AddressIndex::New;
use bdk::{psbt, SignOptions}; use bdk::{psbt, SignOptions};
use bitcoin::psbt::PartiallySignedTransaction as Psbt;
use core::str::FromStr; use core::str::FromStr;
mod common; mod common;
use common::*; use common::*;
@ -163,7 +161,7 @@ fn test_psbt_multiple_internalkey_signers() {
use bdk::signer::{SignerContext, SignerOrdering, SignerWrapper}; use bdk::signer::{SignerContext, SignerOrdering, SignerWrapper};
use bdk::KeychainKind; use bdk::KeychainKind;
use bitcoin::key::TapTweak; use bitcoin::key::TapTweak;
use bitcoin::secp256k1::{schnorr, KeyPair, Message, Secp256k1, XOnlyPublicKey}; use bitcoin::secp256k1::{schnorr, Keypair, Message, Secp256k1, XOnlyPublicKey};
use bitcoin::sighash::{Prevouts, SighashCache, TapSighashType}; use bitcoin::sighash::{Prevouts, SighashCache, TapSighashType};
use bitcoin::{PrivateKey, TxOut}; use bitcoin::{PrivateKey, TxOut};
use std::sync::Arc; use std::sync::Arc;
@ -172,7 +170,7 @@ fn test_psbt_multiple_internalkey_signers() {
let wif = "cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG"; let wif = "cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG";
let desc = format!("tr({})", wif); let desc = format!("tr({})", wif);
let prv = PrivateKey::from_wif(wif).unwrap(); let prv = PrivateKey::from_wif(wif).unwrap();
let keypair = KeyPair::from_secret_key(&secp, &prv.inner); let keypair = Keypair::from_secret_key(&secp, &prv.inner);
let (mut wallet, _) = get_funded_wallet(&desc); let (mut wallet, _) = get_funded_wallet(&desc);
let to_spend = wallet.get_balance().total(); let to_spend = wallet.get_balance().total();
@ -205,7 +203,7 @@ fn test_psbt_multiple_internalkey_signers() {
// the prevout we're spending // the prevout we're spending
let prevouts = &[TxOut { let prevouts = &[TxOut {
script_pubkey: send_to.script_pubkey(), script_pubkey: send_to.script_pubkey(),
value: to_spend, value: Amount::from_sat(to_spend),
}]; }];
let prevouts = Prevouts::All(prevouts); let prevouts = Prevouts::All(prevouts);
let input_index = 0; let input_index = 0;

View File

@ -18,8 +18,8 @@ use bitcoin::script::PushBytesBuf;
use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
use bitcoin::taproot::TapNodeHash; use bitcoin::taproot::TapNodeHash;
use bitcoin::{ use bitcoin::{
absolute, Address, Amount, BlockHash, FeeRate, Network, OutPoint, ScriptBuf, Sequence, absolute, transaction, Address, Amount, BlockHash, FeeRate, Network, OutPoint, ScriptBuf,
Transaction, TxIn, TxOut, Txid, Weight, Sequence, Transaction, TxIn, TxOut, Txid, Weight,
}; };
mod common; mod common;
@ -27,12 +27,12 @@ use common::*;
fn receive_output(wallet: &mut Wallet, value: u64, height: ConfirmationTime) -> OutPoint { fn receive_output(wallet: &mut Wallet, value: u64, height: ConfirmationTime) -> OutPoint {
let tx = Transaction { let tx = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
script_pubkey: wallet.get_address(LastUnused).script_pubkey(), script_pubkey: wallet.get_address(LastUnused).script_pubkey(),
value, value: Amount::from_sat(value),
}], }],
}; };
@ -265,10 +265,10 @@ fn test_list_output() {
assert_eq!(txos.len(), 2); assert_eq!(txos.len(), 2);
for (op, txo) in txos { for (op, txo) in txos {
if op.txid == txid { if op.txid == txid {
assert_eq!(txo.txout.value, 50_000); assert_eq!(txo.txout.value.to_sat(), 50_000);
assert!(!txo.is_spent); assert!(!txo.is_spent);
} else { } else {
assert_eq!(txo.txout.value, 76_000); assert_eq!(txo.txout.value.to_sat(), 76_000);
assert!(txo.is_spent); assert!(txo.is_spent);
} }
} }
@ -278,7 +278,7 @@ macro_rules! assert_fee_rate {
($psbt:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({ ($psbt:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
let psbt = $psbt.clone(); let psbt = $psbt.clone();
#[allow(unused_mut)] #[allow(unused_mut)]
let mut tx = $psbt.clone().extract_tx(); let mut tx = $psbt.clone().extract_tx().expect("failed to extract tx");
$( $(
$( $add_signature )* $( $add_signature )*
for txin in &mut tx.input { for txin in &mut tx.input {
@ -297,12 +297,12 @@ macro_rules! assert_fee_rate {
let fee_amount = psbt let fee_amount = psbt
.inputs .inputs
.iter() .iter()
.fold(0, |acc, i| acc + i.witness_utxo.as_ref().unwrap().value) .fold(0, |acc, i| acc + i.witness_utxo.as_ref().unwrap().value.to_sat())
- psbt - psbt
.unsigned_tx .unsigned_tx
.output .output
.iter() .iter()
.fold(0, |acc, o| acc + o.value); .fold(0, |acc, o| acc + o.value.to_sat());
assert_eq!(fee_amount, $fees); assert_eq!(fee_amount, $fees);
@ -383,7 +383,7 @@ fn test_create_tx_custom_version() {
.version(42); .version(42);
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
assert_eq!(psbt.unsigned_tx.version, 42); assert_eq!(psbt.unsigned_tx.version.0, 42);
} }
#[test] #[test]
@ -570,7 +570,7 @@ fn test_create_tx_change_policy_no_internal() {
macro_rules! check_fee { macro_rules! check_fee {
($wallet:expr, $psbt: expr) => {{ ($wallet:expr, $psbt: expr) => {{
let tx = $psbt.clone().extract_tx(); let tx = $psbt.clone().extract_tx().expect("failed to extract tx");
let tx_fee = $wallet.calculate_fee(&tx).ok(); let tx_fee = $wallet.calculate_fee(&tx).ok();
assert_eq!(tx_fee, $psbt.fee_amount()); assert_eq!(tx_fee, $psbt.fee_amount());
tx_fee tx_fee
@ -587,7 +587,10 @@ fn test_create_tx_drain_wallet_and_drain_to() {
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!(psbt.unsigned_tx.output.len(), 1);
assert_eq!(psbt.unsigned_tx.output[0].value, 50_000 - fee.unwrap_or(0)); assert_eq!(
psbt.unsigned_tx.output[0].value.to_sat(),
50_000 - fee.unwrap_or(0)
);
} }
#[test] #[test]
@ -615,8 +618,8 @@ fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() {
.iter() .iter()
.find(|x| x.script_pubkey == drain_addr.script_pubkey()) .find(|x| x.script_pubkey == drain_addr.script_pubkey())
.unwrap(); .unwrap();
assert_eq!(main_output.value, 20_000,); assert_eq!(main_output.value.to_sat(), 20_000,);
assert_eq!(drain_output.value, 30_000 - fee.unwrap_or(0)); assert_eq!(drain_output.value.to_sat(), 30_000 - fee.unwrap_or(0));
} }
#[test] #[test]
@ -633,7 +636,10 @@ fn test_create_tx_drain_to_and_utxos() {
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!(psbt.unsigned_tx.output.len(), 1);
assert_eq!(psbt.unsigned_tx.output[0].value, 50_000 - fee.unwrap_or(0)); assert_eq!(
psbt.unsigned_tx.output[0].value.to_sat(),
50_000 - fee.unwrap_or(0)
);
} }
#[test] #[test]
@ -686,7 +692,10 @@ fn test_create_tx_absolute_fee() {
assert_eq!(fee.unwrap_or(0), 100); assert_eq!(fee.unwrap_or(0), 100);
assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!(psbt.unsigned_tx.output.len(), 1);
assert_eq!(psbt.unsigned_tx.output[0].value, 50_000 - fee.unwrap_or(0)); assert_eq!(
psbt.unsigned_tx.output[0].value.to_sat(),
50_000 - fee.unwrap_or(0)
);
} }
#[test] #[test]
@ -703,7 +712,10 @@ fn test_create_tx_absolute_zero_fee() {
assert_eq!(fee.unwrap_or(0), 0); assert_eq!(fee.unwrap_or(0), 0);
assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!(psbt.unsigned_tx.output.len(), 1);
assert_eq!(psbt.unsigned_tx.output[0].value, 50_000 - fee.unwrap_or(0)); assert_eq!(
psbt.unsigned_tx.output[0].value.to_sat(),
50_000 - fee.unwrap_or(0)
);
} }
#[test] #[test]
@ -733,8 +745,11 @@ fn test_create_tx_add_change() {
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(psbt.unsigned_tx.output.len(), 2); assert_eq!(psbt.unsigned_tx.output.len(), 2);
assert_eq!(psbt.unsigned_tx.output[0].value, 25_000); assert_eq!(psbt.unsigned_tx.output[0].value.to_sat(), 25_000);
assert_eq!(psbt.unsigned_tx.output[1].value, 25_000 - fee.unwrap_or(0)); assert_eq!(
psbt.unsigned_tx.output[1].value.to_sat(),
25_000 - fee.unwrap_or(0)
);
} }
#[test] #[test]
@ -747,7 +762,7 @@ fn test_create_tx_skip_change_dust() {
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!(psbt.unsigned_tx.output.len(), 1);
assert_eq!(psbt.unsigned_tx.output[0].value, 49_800); assert_eq!(psbt.unsigned_tx.output[0].value.to_sat(), 49_800);
assert_eq!(fee.unwrap_or(0), 200); assert_eq!(fee.unwrap_or(0), 200);
} }
@ -778,9 +793,12 @@ fn test_create_tx_ordering_respected() {
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(psbt.unsigned_tx.output.len(), 3); assert_eq!(psbt.unsigned_tx.output.len(), 3);
assert_eq!(psbt.unsigned_tx.output[0].value, 10_000 - fee.unwrap_or(0)); assert_eq!(
assert_eq!(psbt.unsigned_tx.output[1].value, 10_000); psbt.unsigned_tx.output[0].value.to_sat(),
assert_eq!(psbt.unsigned_tx.output[2].value, 30_000); 10_000 - fee.unwrap_or(0)
);
assert_eq!(psbt.unsigned_tx.output[1].value.to_sat(), 10_000);
assert_eq!(psbt.unsigned_tx.output[2].value.to_sat(), 30_000);
} }
#[test] #[test]
@ -856,7 +874,7 @@ fn test_create_tx_output_hd_keypaths() {
#[test] #[test]
fn test_create_tx_set_redeem_script_p2sh() { fn test_create_tx_set_redeem_script_p2sh() {
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
let (mut wallet, _) = let (mut wallet, _) =
get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))"); get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
@ -879,7 +897,7 @@ fn test_create_tx_set_redeem_script_p2sh() {
#[test] #[test]
fn test_create_tx_set_witness_script_p2wsh() { fn test_create_tx_set_witness_script_p2wsh() {
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
let (mut wallet, _) = let (mut wallet, _) =
get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))"); get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
@ -914,7 +932,7 @@ fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
) )
.unwrap(); .unwrap();
assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh())); assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_p2wsh()));
assert_eq!(psbt.inputs[0].witness_script, Some(script)); assert_eq!(psbt.inputs[0].witness_script, Some(script));
} }
@ -978,10 +996,10 @@ fn test_create_tx_add_utxo() {
let small_output_tx = Transaction { let small_output_tx = Transaction {
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 25_000, value: Amount::from_sat(25_000),
script_pubkey: wallet.get_address(New).address.script_pubkey(), script_pubkey: wallet.get_address(New).address.script_pubkey(),
}], }],
version: 0, version: transaction::Version::non_standard(0),
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
}; };
wallet wallet
@ -1003,7 +1021,8 @@ fn test_create_tx_add_utxo() {
}) })
.unwrap(); .unwrap();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
assert_eq!( assert_eq!(
psbt.unsigned_tx.input.len(), psbt.unsigned_tx.input.len(),
@ -1023,10 +1042,10 @@ fn test_create_tx_manually_selected_insufficient() {
let small_output_tx = Transaction { let small_output_tx = Transaction {
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 25_000, value: Amount::from_sat(25_000),
script_pubkey: wallet.get_address(New).address.script_pubkey(), script_pubkey: wallet.get_address(New).address.script_pubkey(),
}], }],
version: 0, version: transaction::Version::non_standard(0),
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
}; };
@ -1071,11 +1090,11 @@ fn test_create_tx_policy_path_no_csv() {
let mut wallet = Wallet::new_no_persist(descriptors, None, Network::Regtest).unwrap(); let mut wallet = Wallet::new_no_persist(descriptors, None, Network::Regtest).unwrap();
let tx = Transaction { let tx = Transaction {
version: 0, version: transaction::Version::non_standard(0),
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 50_000, value: Amount::from_sat(50_000),
script_pubkey: wallet.get_address(New).script_pubkey(), script_pubkey: wallet.get_address(New).script_pubkey(),
}], }],
}; };
@ -1145,7 +1164,7 @@ fn test_create_tx_policy_path_ignored_subtree_with_csv() {
#[test] #[test]
fn test_create_tx_global_xpubs_with_origin() { fn test_create_tx_global_xpubs_with_origin() {
use bitcoin::bip32; use bitcoin::bip32;
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
let (mut wallet, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)"); let (mut wallet, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
let addr = wallet.get_address(New); let addr = wallet.get_address(New);
@ -1155,7 +1174,7 @@ fn test_create_tx_global_xpubs_with_origin() {
.add_global_xpubs(); .add_global_xpubs();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let key = bip32::ExtendedPubKey::from_str("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap(); let key = bip32::Xpub::from_str("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
let fingerprint = bip32::Fingerprint::from_hex("73756c7f").unwrap(); let fingerprint = bip32::Fingerprint::from_hex("73756c7f").unwrap();
let path = bip32::DerivationPath::from_str("m/48'/0'/0'/2'").unwrap(); let path = bip32::DerivationPath::from_str("m/48'/0'/0'/2'").unwrap();
@ -1192,7 +1211,8 @@ fn test_add_foreign_utxo() {
let mut psbt = builder.finish().unwrap(); let mut psbt = builder.finish().unwrap();
wallet1.insert_txout(utxo.outpoint, utxo.txout); wallet1.insert_txout(utxo.outpoint, utxo.txout);
let fee = check_fee!(wallet1, psbt); let fee = check_fee!(wallet1, psbt);
let sent_received = wallet1.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet1.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
assert_eq!( assert_eq!(
sent_received.0 - sent_received.1, sent_received.0 - sent_received.1,
@ -1265,7 +1285,7 @@ fn test_calculate_fee_with_missing_foreign_utxo() {
.add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
.unwrap(); .unwrap();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
wallet1.calculate_fee(&tx).unwrap(); wallet1.calculate_fee(&tx).unwrap();
} }
@ -1421,7 +1441,7 @@ fn test_create_tx_global_xpubs_origin_missing() {
#[test] #[test]
fn test_create_tx_global_xpubs_master_without_origin() { fn test_create_tx_global_xpubs_master_without_origin() {
use bitcoin::bip32; use bitcoin::bip32;
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
let (mut wallet, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)"); let (mut wallet, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
let addr = wallet.get_address(New); let addr = wallet.get_address(New);
@ -1431,7 +1451,7 @@ fn test_create_tx_global_xpubs_master_without_origin() {
.add_global_xpubs(); .add_global_xpubs();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let key = bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap(); let key = bip32::Xpub::from_str("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
let fingerprint = bip32::Fingerprint::from_hex("997a323b").unwrap(); let fingerprint = bip32::Fingerprint::from_hex("997a323b").unwrap();
assert_eq!(psbt.xpub.len(), 1); assert_eq!(psbt.xpub.len(), 1);
@ -1450,7 +1470,7 @@ fn test_bump_fee_irreplaceable_tx() {
builder.add_recipient(addr.script_pubkey(), 25_000); builder.add_recipient(addr.script_pubkey(), 25_000);
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
@ -1467,7 +1487,7 @@ fn test_bump_fee_confirmed_tx() {
builder.add_recipient(addr.script_pubkey(), 25_000); builder.add_recipient(addr.script_pubkey(), 25_000);
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1494,7 +1514,7 @@ fn test_bump_fee_low_fee_rate() {
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let feerate = psbt.fee_rate().unwrap(); let feerate = psbt.fee_rate().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1527,7 +1547,7 @@ fn test_bump_fee_low_abs() {
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1550,7 +1570,7 @@ fn test_bump_fee_zero_abs() {
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
@ -1572,10 +1592,11 @@ fn test_bump_fee_reduce_change() {
.add_recipient(addr.script_pubkey(), 25_000) .add_recipient(addr.script_pubkey(), 25_000)
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let original_sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let original_sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let original_fee = check_fee!(wallet, psbt); let original_fee = check_fee!(wallet, psbt);
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
@ -1585,7 +1606,8 @@ fn test_bump_fee_reduce_change() {
let mut builder = wallet.build_fee_bump(txid).unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.fee_rate(feerate).enable_rbf(); builder.fee_rate(feerate).enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_sent_received.0); assert_eq!(sent_received.0, original_sent_received.0);
@ -1603,14 +1625,15 @@ fn test_bump_fee_reduce_change() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
25_000 Amount::from_sat(25_000)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
sent_received.1 sent_received.1
); );
@ -1620,7 +1643,8 @@ fn test_bump_fee_reduce_change() {
builder.fee_absolute(200); builder.fee_absolute(200);
builder.enable_rbf(); builder.enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_sent_received.0); assert_eq!(sent_received.0, original_sent_received.0);
@ -1643,14 +1667,15 @@ fn test_bump_fee_reduce_change() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
25_000 Amount::from_sat(25_000)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
sent_received.1 sent_received.1
); );
@ -1669,7 +1694,7 @@ fn test_bump_fee_reduce_single_recipient() {
.drain_wallet() .drain_wallet()
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.clone().extract_tx(); let tx = psbt.clone().extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let original_fee = check_fee!(wallet, psbt); let original_fee = check_fee!(wallet, psbt);
let txid = tx.txid(); let txid = tx.txid();
@ -1684,7 +1709,8 @@ fn test_bump_fee_reduce_single_recipient() {
.allow_shrinking(addr.script_pubkey()) .allow_shrinking(addr.script_pubkey())
.unwrap(); .unwrap();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_sent_received.0); assert_eq!(sent_received.0, original_sent_received.0);
@ -1692,7 +1718,10 @@ fn test_bump_fee_reduce_single_recipient() {
let tx = &psbt.unsigned_tx; let tx = &psbt.unsigned_tx;
assert_eq!(tx.output.len(), 1); assert_eq!(tx.output.len(), 1);
assert_eq!(tx.output[0].value + fee.unwrap_or(0), sent_received.0); assert_eq!(
tx.output[0].value.to_sat() + fee.unwrap_or(0),
sent_received.0
);
assert_fee_rate!(psbt, fee.unwrap_or(0), feerate, @add_signature); assert_fee_rate!(psbt, fee.unwrap_or(0), feerate, @add_signature);
} }
@ -1710,7 +1739,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() {
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let original_fee = check_fee!(wallet, psbt); let original_fee = check_fee!(wallet, psbt);
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1731,7 +1760,10 @@ fn test_bump_fee_absolute_reduce_single_recipient() {
assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0));
assert_eq!(tx.output.len(), 1); assert_eq!(tx.output.len(), 1);
assert_eq!(tx.output[0].value + fee.unwrap_or(0), sent_received.0); assert_eq!(
tx.output[0].value.to_sat() + fee.unwrap_or(0),
sent_received.0
);
assert_eq!(fee.unwrap_or(0), 300); assert_eq!(fee.unwrap_or(0), 300);
} }
@ -1741,11 +1773,11 @@ fn test_bump_fee_drain_wallet() {
let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
// receive an extra tx so that our wallet has two utxos. // receive an extra tx so that our wallet has two utxos.
let tx = Transaction { let tx = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 25_000, value: Amount::from_sat(25_000),
script_pubkey: wallet.get_address(New).script_pubkey(), script_pubkey: wallet.get_address(New).script_pubkey(),
}], }],
}; };
@ -1773,7 +1805,7 @@ fn test_bump_fee_drain_wallet() {
.manually_selected_only() .manually_selected_only()
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
@ -1791,7 +1823,7 @@ fn test_bump_fee_drain_wallet() {
.unwrap() .unwrap()
.fee_rate(FeeRate::from_sat_per_vb_unchecked(5)); .fee_rate(FeeRate::from_sat_per_vb_unchecked(5));
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.extract_tx()); let sent_received = wallet.sent_and_received(&psbt.extract_tx().expect("failed to extract tx"));
assert_eq!(sent_received.0, 75_000); assert_eq!(sent_received.0, 75_000);
} }
@ -1806,12 +1838,12 @@ fn test_bump_fee_remove_output_manually_selected_only() {
// existing output. In other words, bump_fee + manually_selected_only is always an error // existing output. In other words, bump_fee + manually_selected_only is always an error
// unless you've also set "allow_shrinking" OR there is a change output. // unless you've also set "allow_shrinking" OR there is a change output.
let init_tx = Transaction { let init_tx = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
script_pubkey: wallet.get_address(New).script_pubkey(), script_pubkey: wallet.get_address(New).script_pubkey(),
value: 25_000, value: Amount::from_sat(25_000),
}], }],
}; };
wallet wallet
@ -1841,7 +1873,7 @@ fn test_bump_fee_remove_output_manually_selected_only() {
.manually_selected_only() .manually_selected_only()
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1860,12 +1892,12 @@ fn test_bump_fee_remove_output_manually_selected_only() {
fn test_bump_fee_add_input() { fn test_bump_fee_add_input() {
let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); let (mut wallet, _) = get_funded_wallet(get_test_wpkh());
let init_tx = Transaction { let init_tx = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
script_pubkey: wallet.get_address(New).script_pubkey(), script_pubkey: wallet.get_address(New).script_pubkey(),
value: 25_000, value: Amount::from_sat(25_000),
}], }],
}; };
let pos = wallet let pos = wallet
@ -1885,7 +1917,7 @@ fn test_bump_fee_add_input() {
.add_recipient(addr.script_pubkey(), 45_000) .add_recipient(addr.script_pubkey(), 45_000)
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let original_details = wallet.sent_and_received(&tx); let original_details = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1895,7 +1927,8 @@ fn test_bump_fee_add_input() {
let mut builder = wallet.build_fee_bump(txid).unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50)); builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50));
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_details.0 + 25_000); assert_eq!(sent_received.0, original_details.0 + 25_000);
assert_eq!(fee.unwrap_or(0) + sent_received.1, 30_000); assert_eq!(fee.unwrap_or(0) + sent_received.1, 30_000);
@ -1909,14 +1942,15 @@ fn test_bump_fee_add_input() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
45_000 Amount::from_sat(45_000)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
sent_received.1 sent_received.1
); );
@ -1935,7 +1969,7 @@ fn test_bump_fee_absolute_add_input() {
.add_recipient(addr.script_pubkey(), 45_000) .add_recipient(addr.script_pubkey(), 45_000)
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
@ -1945,7 +1979,8 @@ fn test_bump_fee_absolute_add_input() {
let mut builder = wallet.build_fee_bump(txid).unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.fee_absolute(6_000); builder.fee_absolute(6_000);
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_sent_received.0 + 25_000); assert_eq!(sent_received.0, original_sent_received.0 + 25_000);
@ -1960,14 +1995,15 @@ fn test_bump_fee_absolute_add_input() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
45_000 Amount::from_sat(45_000)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
sent_received.1 sent_received.1
); );
@ -1991,10 +2027,11 @@ fn test_bump_fee_no_change_add_input_and_change() {
.manually_selected_only() .manually_selected_only()
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let original_sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let original_sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let original_fee = check_fee!(wallet, psbt); let original_fee = check_fee!(wallet, psbt);
let tx = psbt.extract_tx(); let tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
wallet wallet
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
@ -2005,7 +2042,8 @@ fn test_bump_fee_no_change_add_input_and_change() {
let mut builder = wallet.build_fee_bump(txid).unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50)); builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50));
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
let original_send_all_amount = original_sent_received.0 - original_fee.unwrap_or(0); let original_send_all_amount = original_sent_received.0 - original_fee.unwrap_or(0);
@ -2024,14 +2062,15 @@ fn test_bump_fee_no_change_add_input_and_change() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
original_send_all_amount Amount::from_sat(original_send_all_amount)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
75_000 - original_send_all_amount - fee.unwrap_or(0) 75_000 - original_send_all_amount - fee.unwrap_or(0)
); );
@ -2050,10 +2089,11 @@ fn test_bump_fee_add_input_change_dust() {
.add_recipient(addr.script_pubkey(), 45_000) .add_recipient(addr.script_pubkey(), 45_000)
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let original_sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let original_sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let original_fee = check_fee!(wallet, psbt); let original_fee = check_fee!(wallet, psbt);
let mut tx = psbt.extract_tx(); let mut tx = psbt.extract_tx().expect("failed to extract tx");
for txin in &mut tx.input { for txin in &mut tx.input {
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // to get realistic weight txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // to get realistic weight
} }
@ -2082,7 +2122,8 @@ fn test_bump_fee_add_input_change_dust() {
let fee_abs = 50_000 + 25_000 - 45_000 - 10; let fee_abs = 50_000 + 25_000 - 45_000 - 10;
builder.fee_rate(Amount::from_sat(fee_abs) / new_tx_weight); builder.fee_rate(Amount::from_sat(fee_abs) / new_tx_weight);
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(original_sent_received.1, 5_000 - original_fee.unwrap_or(0)); assert_eq!(original_sent_received.1, 5_000 - original_fee.unwrap_or(0));
@ -2100,7 +2141,7 @@ fn test_bump_fee_add_input_change_dust() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
45_000 Amount::from_sat(45_000)
); );
assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(140), @dust_change, @add_signature); assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(140), @dust_change, @add_signature);
@ -2119,7 +2160,7 @@ fn test_bump_fee_force_add_input() {
.add_recipient(addr.script_pubkey(), 45_000) .add_recipient(addr.script_pubkey(), 45_000)
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let mut tx = psbt.extract_tx(); let mut tx = psbt.extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
for txin in &mut tx.input { for txin in &mut tx.input {
@ -2136,7 +2177,8 @@ fn test_bump_fee_force_add_input() {
.unwrap() .unwrap()
.fee_rate(FeeRate::from_sat_per_vb_unchecked(5)); .fee_rate(FeeRate::from_sat_per_vb_unchecked(5));
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_sent_received.0 + 25_000); assert_eq!(sent_received.0, original_sent_received.0 + 25_000);
@ -2151,14 +2193,15 @@ fn test_bump_fee_force_add_input() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
45_000 Amount::from_sat(45_000)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
sent_received.1 sent_received.1
); );
@ -2178,7 +2221,7 @@ fn test_bump_fee_absolute_force_add_input() {
.add_recipient(addr.script_pubkey(), 45_000) .add_recipient(addr.script_pubkey(), 45_000)
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let mut tx = psbt.extract_tx(); let mut tx = psbt.extract_tx().expect("failed to extract tx");
let original_sent_received = wallet.sent_and_received(&tx); let original_sent_received = wallet.sent_and_received(&tx);
let txid = tx.txid(); let txid = tx.txid();
// skip saving the new utxos, we know they can't be used anyways // skip saving the new utxos, we know they can't be used anyways
@ -2194,7 +2237,8 @@ fn test_bump_fee_absolute_force_add_input() {
let mut builder = wallet.build_fee_bump(txid).unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.add_utxo(incoming_op).unwrap().fee_absolute(250); builder.add_utxo(incoming_op).unwrap().fee_absolute(250);
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
let fee = check_fee!(wallet, psbt); let fee = check_fee!(wallet, psbt);
assert_eq!(sent_received.0, original_sent_received.0 + 25_000); assert_eq!(sent_received.0, original_sent_received.0 + 25_000);
@ -2209,14 +2253,15 @@ fn test_bump_fee_absolute_force_add_input() {
.find(|txout| txout.script_pubkey == addr.script_pubkey()) .find(|txout| txout.script_pubkey == addr.script_pubkey())
.unwrap() .unwrap()
.value, .value,
45_000 Amount::from_sat(45_000)
); );
assert_eq!( assert_eq!(
tx.output tx.output
.iter() .iter()
.find(|txout| txout.script_pubkey != addr.script_pubkey()) .find(|txout| txout.script_pubkey != addr.script_pubkey())
.unwrap() .unwrap()
.value, .value
.to_sat(),
sent_received.1 sent_received.1
); );
@ -2249,7 +2294,7 @@ fn test_bump_fee_unconfirmed_inputs_only() {
25_000, 25_000,
ConfirmationTime::Unconfirmed { last_seen: 0 }, ConfirmationTime::Unconfirmed { last_seen: 0 },
); );
let mut tx = psbt.extract_tx(); let mut tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
for txin in &mut tx.input { for txin in &mut tx.input {
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
@ -2282,7 +2327,7 @@ fn test_bump_fee_unconfirmed_input() {
.drain_to(addr.script_pubkey()) .drain_to(addr.script_pubkey())
.enable_rbf(); .enable_rbf();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let mut tx = psbt.extract_tx(); let mut tx = psbt.extract_tx().expect("failed to extract tx");
let txid = tx.txid(); let txid = tx.txid();
for txin in &mut tx.input { for txin in &mut tx.input {
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
@ -2341,7 +2386,7 @@ fn test_sign_single_xprv() {
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
assert!(finalized); assert!(finalized);
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!(extracted.input[0].witness.len(), 2); assert_eq!(extracted.input[0].witness.len(), 2);
} }
@ -2356,7 +2401,7 @@ fn test_sign_single_xprv_with_master_fingerprint_and_path() {
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
assert!(finalized); assert!(finalized);
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!(extracted.input[0].witness.len(), 2); assert_eq!(extracted.input[0].witness.len(), 2);
} }
@ -2371,7 +2416,7 @@ fn test_sign_single_xprv_bip44_path() {
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
assert!(finalized); assert!(finalized);
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!(extracted.input[0].witness.len(), 2); assert_eq!(extracted.input[0].witness.len(), 2);
} }
@ -2386,7 +2431,7 @@ fn test_sign_single_xprv_sh_wpkh() {
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
assert!(finalized); assert!(finalized);
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!(extracted.input[0].witness.len(), 2); assert_eq!(extracted.input[0].witness.len(), 2);
} }
@ -2402,7 +2447,7 @@ fn test_sign_single_wif() {
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
assert!(finalized); assert!(finalized);
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!(extracted.input[0].witness.len(), 2); assert_eq!(extracted.input[0].witness.len(), 2);
} }
@ -2420,7 +2465,7 @@ fn test_sign_single_xprv_no_hd_keypaths() {
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
assert!(finalized); assert!(finalized);
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!(extracted.input[0].witness.len(), 2); assert_eq!(extracted.input[0].witness.len(), 2);
} }
@ -2458,7 +2503,7 @@ fn test_signing_only_one_of_multiple_inputs() {
// add another input to the psbt that is at least passable. // add another input to the psbt that is at least passable.
let dud_input = bitcoin::psbt::Input { let dud_input = bitcoin::psbt::Input {
witness_utxo: Some(TxOut { witness_utxo: Some(TxOut {
value: 100_000, value: Amount::from_sat(100_000),
script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str( script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str(
"wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)", "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
) )
@ -2591,7 +2636,7 @@ fn test_sign_nonstandard_sighash() {
"Should finalize the input since we can produce signatures" "Should finalize the input since we can produce signatures"
); );
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!( assert_eq!(
*extracted.input[0].witness.to_vec()[0].last().unwrap(), *extracted.input[0].witness.to_vec()[0].last().unwrap(),
sighash.to_u32() as u8, sighash.to_u32() as u8,
@ -2762,7 +2807,7 @@ fn test_sending_to_bip350_bech32m_address() {
#[test] #[test]
fn test_get_address() { fn test_get_address() {
use bdk::descriptor::template::Bip84; use bdk::descriptor::template::Bip84;
let key = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let mut wallet = Wallet::new_no_persist( let mut wallet = Wallet::new_no_persist(
Bip84(key, KeychainKind::External), Bip84(key, KeychainKind::External),
Some(Bip84(key, KeychainKind::Internal)), Some(Bip84(key, KeychainKind::Internal)),
@ -2813,7 +2858,7 @@ fn test_get_address_no_reuse_single_descriptor() {
use bdk::descriptor::template::Bip84; use bdk::descriptor::template::Bip84;
use std::collections::HashSet; use std::collections::HashSet;
let key = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
let mut wallet = let mut wallet =
Wallet::new_no_persist(Bip84(key, KeychainKind::External), None, Network::Regtest).unwrap(); Wallet::new_no_persist(Bip84(key, KeychainKind::External), None, Network::Regtest).unwrap();
@ -2954,7 +2999,7 @@ fn test_taproot_psbt_populate_tap_key_origins_repeated_key() {
#[test] #[test]
fn test_taproot_psbt_input_tap_tree() { fn test_taproot_psbt_input_tap_tree() {
use bitcoin::hashes::hex::FromHex; use bitcoin::hex::FromHex;
use bitcoin::taproot; use bitcoin::taproot;
let (mut wallet, _) = get_funded_wallet(get_test_tr_with_taptree()); let (mut wallet, _) = get_funded_wallet(get_test_tr_with_taptree());
@ -3088,7 +3133,8 @@ fn test_taproot_foreign_utxo() {
.add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction) .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
.unwrap(); .unwrap();
let psbt = builder.finish().unwrap(); let psbt = builder.finish().unwrap();
let sent_received = wallet1.sent_and_received(&psbt.clone().extract_tx()); let sent_received =
wallet1.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
wallet1.insert_txout(utxo.outpoint, utxo.txout); wallet1.insert_txout(utxo.outpoint, utxo.txout);
let fee = check_fee!(wallet1, psbt); let fee = check_fee!(wallet1, psbt);
@ -3396,7 +3442,7 @@ fn test_taproot_sign_non_default_sighash() {
"Should finalize the input since we can produce signatures" "Should finalize the input since we can produce signatures"
); );
let extracted = psbt.extract_tx(); let extracted = psbt.extract_tx().expect("failed to extract tx");
assert_eq!( assert_eq!(
*extracted.input[0].witness.to_vec()[0].last().unwrap(), *extracted.input[0].witness.to_vec()[0].last().unwrap(),
sighash as u8, sighash as u8,
@ -3417,14 +3463,14 @@ fn test_spend_coinbase() {
}) })
.unwrap(); .unwrap();
let coinbase_tx = Transaction { let coinbase_tx = Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint::null(), previous_output: OutPoint::null(),
..Default::default() ..Default::default()
}], }],
output: vec![TxOut { output: vec![TxOut {
value: 25_000, value: Amount::from_sat(25_000),
script_pubkey: wallet.get_address(New).address.script_pubkey(), script_pubkey: wallet.get_address(New).address.script_pubkey(),
}], }],
}; };
@ -3686,7 +3732,7 @@ fn test_tx_cancellation() {
.unwrap(); .unwrap();
assert_eq!(change_derivation_2, (KeychainKind::Internal, 1)); assert_eq!(change_derivation_2, (KeychainKind::Internal, 1));
wallet.cancel_tx(&psbt1.extract_tx()); wallet.cancel_tx(&psbt1.extract_tx().expect("failed to extract tx"));
let psbt3 = new_tx!(wallet); let psbt3 = new_tx!(wallet);
let change_derivation_3 = psbt3 let change_derivation_3 = psbt3
@ -3706,7 +3752,7 @@ fn test_tx_cancellation() {
.unwrap(); .unwrap();
assert_eq!(change_derivation_3, (KeychainKind::Internal, 2)); assert_eq!(change_derivation_3, (KeychainKind::Internal, 2));
wallet.cancel_tx(&psbt3.extract_tx()); wallet.cancel_tx(&psbt3.extract_tx().expect("failed to extract tx"));
let psbt3 = new_tx!(wallet); let psbt3 = new_tx!(wallet);
let change_derivation_4 = psbt3 let change_derivation_4 = psbt3

View File

@ -14,8 +14,8 @@ readme = "README.md"
[dependencies] [dependencies]
# For no-std, remember to enable the bitcoin/no-std feature # For no-std, remember to enable the bitcoin/no-std feature
bitcoin = { version = "0.30", default-features = false } bitcoin = { version = "0.31", default-features = false }
bitcoincore-rpc = { version = "0.17" } bitcoincore-rpc = { version = "0.18" }
bdk_chain = { path = "../chain", version = "0.11", default-features = false } bdk_chain = { path = "../chain", version = "0.11", default-features = false }
[dev-dependencies] [dev-dependencies]

View File

@ -350,7 +350,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
.rpc_client() .rpc_client()
.get_new_address(None, None)? .get_new_address(None, None)?
.assume_checked(); .assume_checked();
let spk_to_track = ScriptBuf::new_v0_p2wsh(&WScriptHash::all_zeros()); let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
let addr_to_track = Address::from_script(&spk_to_track, bitcoin::Network::Regtest)?; let addr_to_track = Address::from_script(&spk_to_track, bitcoin::Network::Regtest)?;
// setup receiver // setup receiver

View File

@ -14,12 +14,12 @@ readme = "README.md"
[dependencies] [dependencies]
# For no-std, remember to enable the bitcoin/no-std feature # For no-std, remember to enable the bitcoin/no-std feature
bitcoin = { version = "0.30.0", default-features = false } bitcoin = { version = "0.31.0", default-features = false }
serde_crate = { package = "serde", version = "1", optional = true, features = ["derive", "rc"] } serde_crate = { package = "serde", version = "1", optional = true, features = ["derive", "rc"] }
# Use hashbrown as a feature flag to have HashSet and HashMap from it. # Use hashbrown as a feature flag to have HashSet and HashMap from it.
hashbrown = { version = "0.9.1", optional = true, features = ["serde"] } hashbrown = { version = "0.9.1", optional = true, features = ["serde"] }
miniscript = { version = "10.0.0", optional = true, default-features = false } miniscript = { version = "11.0.0", optional = true, default-features = false }
[dev-dependencies] [dev-dependencies]
rand = "0.8" rand = "0.8"

View File

@ -4,7 +4,7 @@ use crate::{
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap}, collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap},
indexed_tx_graph::Indexer, indexed_tx_graph::Indexer,
}; };
use bitcoin::{self, OutPoint, Script, ScriptBuf, Transaction, TxOut, Txid}; use bitcoin::{OutPoint, Script, ScriptBuf, Transaction, TxOut, Txid};
/// An index storing [`TxOut`]s that have a script pubkey that matches those in a list. /// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
/// ///
@ -281,12 +281,12 @@ impl<I: Clone + Ord> SpkTxOutIndex<I> {
for txin in &tx.input { for txin in &tx.input {
if let Some((_, txout)) = self.txout(txin.previous_output) { if let Some((_, txout)) = self.txout(txin.previous_output) {
sent += txout.value; sent += txout.value.to_sat();
} }
} }
for txout in &tx.output { for txout in &tx.output {
if self.index_of_spk(&txout.script_pubkey).is_some() { if self.index_of_spk(&txout.script_pubkey).is_some() {
received += txout.value; received += txout.value.to_sat();
} }
} }

View File

@ -319,7 +319,7 @@ impl<A> TxGraph<A> {
/// ///
/// [`insert_txout`]: Self::insert_txout /// [`insert_txout`]: Self::insert_txout
pub fn calculate_fee(&self, tx: &Transaction) -> Result<u64, CalculateFeeError> { pub fn calculate_fee(&self, tx: &Transaction) -> Result<u64, CalculateFeeError> {
if tx.is_coin_base() { if tx.is_coinbase() {
return Ok(0); return Ok(0);
} }
@ -331,7 +331,7 @@ impl<A> TxGraph<A> {
(sum, missing_outpoints) (sum, missing_outpoints)
} }
Some(txout) => { Some(txout) => {
sum += txout.value as i64; sum += txout.value.to_sat() as i64;
(sum, missing_outpoints) (sum, missing_outpoints)
} }
}, },
@ -343,7 +343,7 @@ impl<A> TxGraph<A> {
let outputs_sum = tx let outputs_sum = tx
.output .output
.iter() .iter()
.map(|txout| txout.value as i64) .map(|txout| txout.value.to_sat() as i64)
.sum::<i64>(); .sum::<i64>();
let fee = inputs_sum - outputs_sum; let fee = inputs_sum - outputs_sum;
@ -807,7 +807,7 @@ impl<A: Anchor> TxGraph<A> {
TxNodeInternal::Whole(tx) => { TxNodeInternal::Whole(tx) => {
// A coinbase tx that is not anchored in the best chain cannot be unconfirmed and // A coinbase tx that is not anchored in the best chain cannot be unconfirmed and
// should always be filtered out. // should always be filtered out.
if tx.as_ref().is_coin_base() { if tx.is_coinbase() {
return Ok(None); return Ok(None);
} }
tx.clone() tx.clone()
@ -1063,7 +1063,7 @@ impl<A: Anchor> TxGraph<A> {
txout, txout,
chain_position, chain_position,
spent_by, spent_by,
is_on_coinbase: tx_node.tx.as_ref().is_coin_base(), is_on_coinbase: tx_node.tx.is_coinbase(),
}, },
))) )))
}, },
@ -1166,16 +1166,16 @@ impl<A: Anchor> TxGraph<A> {
match &txout.chain_position { match &txout.chain_position {
ChainPosition::Confirmed(_) => { ChainPosition::Confirmed(_) => {
if txout.is_confirmed_and_spendable(chain_tip.height) { if txout.is_confirmed_and_spendable(chain_tip.height) {
confirmed += txout.txout.value; confirmed += txout.txout.value.to_sat();
} else if !txout.is_mature(chain_tip.height) { } else if !txout.is_mature(chain_tip.height) {
immature += txout.txout.value; immature += txout.txout.value.to_sat();
} }
} }
ChainPosition::Unconfirmed(_) => { ChainPosition::Unconfirmed(_) => {
if trust_predicate(&spk_i, &txout.txout.script_pubkey) { if trust_predicate(&spk_i, &txout.txout.script_pubkey) {
trusted_pending += txout.txout.value; trusted_pending += txout.txout.value.to_sat();
} else { } else {
untrusted_pending += txout.txout.value; untrusted_pending += txout.txout.value.to_sat();
} }
} }
} }

View File

@ -70,7 +70,7 @@ macro_rules! changeset {
#[allow(unused)] #[allow(unused)]
pub fn new_tx(lt: u32) -> bitcoin::Transaction { pub fn new_tx(lt: u32) -> bitcoin::Transaction {
bitcoin::Transaction { bitcoin::Transaction {
version: 0x00, version: bitcoin::transaction::Version::non_standard(0x00),
lock_time: bitcoin::absolute::LockTime::from_consensus(lt), lock_time: bitcoin::absolute::LockTime::from_consensus(lt),
input: vec![], input: vec![],
output: vec![], output: vec![],

View File

@ -3,8 +3,8 @@ use std::collections::HashMap;
use bdk_chain::{tx_graph::TxGraph, Anchor, SpkTxOutIndex}; use bdk_chain::{tx_graph::TxGraph, Anchor, SpkTxOutIndex};
use bitcoin::{ use bitcoin::{
locktime::absolute::LockTime, secp256k1::Secp256k1, OutPoint, ScriptBuf, Sequence, Transaction, locktime::absolute::LockTime, secp256k1::Secp256k1, transaction, Amount, OutPoint, ScriptBuf,
TxIn, TxOut, Txid, Witness, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
}; };
use miniscript::Descriptor; use miniscript::Descriptor;
@ -68,7 +68,7 @@ pub fn init_graph<'a, A: Anchor + Clone + 'a>(
for (bogus_txin_vout, tx_tmp) in tx_templates.into_iter().enumerate() { for (bogus_txin_vout, tx_tmp) in tx_templates.into_iter().enumerate() {
let tx = Transaction { let tx = Transaction {
version: 0, version: transaction::Version::non_standard(0),
lock_time: LockTime::ZERO, lock_time: LockTime::ZERO,
input: tx_tmp input: tx_tmp
.inputs .inputs
@ -111,11 +111,11 @@ pub fn init_graph<'a, A: Anchor + Clone + 'a>(
.iter() .iter()
.map(|output| match &output.spk_index { .map(|output| match &output.spk_index {
None => TxOut { None => TxOut {
value: output.value, value: Amount::from_sat(output.value),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
Some(index) => TxOut { Some(index) => TxOut {
value: output.value, value: Amount::from_sat(output.value),
script_pubkey: spk_index.spk_at_index(index).unwrap().to_owned(), script_pubkey: spk_index.spk_at_index(index).unwrap().to_owned(),
}, },
}) })

View File

@ -9,7 +9,9 @@ use bdk_chain::{
local_chain::LocalChain, local_chain::LocalChain,
tx_graph, ChainPosition, ConfirmationHeightAnchor, tx_graph, ChainPosition, ConfirmationHeightAnchor,
}; };
use bitcoin::{secp256k1::Secp256k1, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut}; use bitcoin::{
secp256k1::Secp256k1, Amount, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut,
};
use miniscript::Descriptor; use miniscript::Descriptor;
/// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented /// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented
@ -35,11 +37,11 @@ fn insert_relevant_txs() {
let tx_a = Transaction { let tx_a = Transaction {
output: vec![ output: vec![
TxOut { TxOut {
value: 10_000, value: Amount::from_sat(10_000),
script_pubkey: spk_0, script_pubkey: spk_0,
}, },
TxOut { TxOut {
value: 20_000, value: Amount::from_sat(20_000),
script_pubkey: spk_1, script_pubkey: spk_1,
}, },
], ],
@ -154,7 +156,7 @@ fn test_list_owned_txouts() {
..Default::default() ..Default::default()
}], }],
output: vec![TxOut { output: vec![TxOut {
value: 70000, value: Amount::from_sat(70000),
script_pubkey: trusted_spks[0].to_owned(), script_pubkey: trusted_spks[0].to_owned(),
}], }],
..common::new_tx(0) ..common::new_tx(0)
@ -163,7 +165,7 @@ fn test_list_owned_txouts() {
// tx2 is an incoming transaction received at untrusted keychain at block 1. // tx2 is an incoming transaction received at untrusted keychain at block 1.
let tx2 = Transaction { let tx2 = Transaction {
output: vec![TxOut { output: vec![TxOut {
value: 30000, value: Amount::from_sat(30000),
script_pubkey: untrusted_spks[0].to_owned(), script_pubkey: untrusted_spks[0].to_owned(),
}], }],
..common::new_tx(0) ..common::new_tx(0)
@ -176,7 +178,7 @@ fn test_list_owned_txouts() {
..Default::default() ..Default::default()
}], }],
output: vec![TxOut { output: vec![TxOut {
value: 10000, value: Amount::from_sat(10000),
script_pubkey: trusted_spks[1].to_owned(), script_pubkey: trusted_spks[1].to_owned(),
}], }],
..common::new_tx(0) ..common::new_tx(0)
@ -185,7 +187,7 @@ fn test_list_owned_txouts() {
// tx4 is an external transaction receiving at untrusted keychain, unconfirmed. // tx4 is an external transaction receiving at untrusted keychain, unconfirmed.
let tx4 = Transaction { let tx4 = Transaction {
output: vec![TxOut { output: vec![TxOut {
value: 20000, value: Amount::from_sat(20000),
script_pubkey: untrusted_spks[1].to_owned(), script_pubkey: untrusted_spks[1].to_owned(),
}], }],
..common::new_tx(0) ..common::new_tx(0)
@ -194,7 +196,7 @@ fn test_list_owned_txouts() {
// tx5 is spending tx3 and receiving change at trusted keychain, unconfirmed. // tx5 is spending tx3 and receiving change at trusted keychain, unconfirmed.
let tx5 = Transaction { let tx5 = Transaction {
output: vec![TxOut { output: vec![TxOut {
value: 15000, value: Amount::from_sat(15000),
script_pubkey: trusted_spks[2].to_owned(), script_pubkey: trusted_spks[2].to_owned(),
}], }],
..common::new_tx(0) ..common::new_tx(0)

View File

@ -9,7 +9,7 @@ use bdk_chain::{
Append, Append,
}; };
use bitcoin::{secp256k1::Secp256k1, OutPoint, ScriptBuf, Transaction, TxOut}; use bitcoin::{secp256k1::Secp256k1, Amount, OutPoint, ScriptBuf, Transaction, TxOut};
use miniscript::{Descriptor, DescriptorPublicKey}; use miniscript::{Descriptor, DescriptorPublicKey};
#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] #[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
@ -176,14 +176,14 @@ fn test_lookahead() {
.at_derivation_index(external_index) .at_derivation_index(external_index)
.unwrap() .unwrap()
.script_pubkey(), .script_pubkey(),
value: 10_000, value: Amount::from_sat(10_000),
}, },
TxOut { TxOut {
script_pubkey: internal_desc script_pubkey: internal_desc
.at_derivation_index(internal_index) .at_derivation_index(internal_index)
.unwrap() .unwrap()
.script_pubkey(), .script_pubkey(),
value: 10_000, value: Amount::from_sat(10_000),
}, },
], ],
..common::new_tx(external_index) ..common::new_tx(external_index)
@ -238,7 +238,7 @@ fn test_scan_with_lookahead() {
let op = OutPoint::new(h!("fake tx"), spk_i); let op = OutPoint::new(h!("fake tx"), spk_i);
let txout = TxOut { let txout = TxOut {
script_pubkey: spk.clone(), script_pubkey: spk.clone(),
value: 0, value: Amount::ZERO,
}; };
let changeset = txout_index.index_txout(op, &txout); let changeset = txout_index.index_txout(op, &txout);
@ -264,7 +264,7 @@ fn test_scan_with_lookahead() {
let op = OutPoint::new(h!("fake tx"), 41); let op = OutPoint::new(h!("fake tx"), 41);
let txout = TxOut { let txout = TxOut {
script_pubkey: spk_41, script_pubkey: spk_41,
value: 0, value: Amount::ZERO,
}; };
let changeset = txout_index.index_txout(op, &txout); let changeset = txout_index.index_txout(op, &txout);
assert!(changeset.is_empty()); assert!(changeset.is_empty());

View File

@ -1,5 +1,5 @@
use bdk_chain::{indexed_tx_graph::Indexer, SpkTxOutIndex}; use bdk_chain::{indexed_tx_graph::Indexer, SpkTxOutIndex};
use bitcoin::{absolute, OutPoint, ScriptBuf, Transaction, TxIn, TxOut}; use bitcoin::{absolute, transaction, Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut};
#[test] #[test]
fn spk_txout_sent_and_received() { fn spk_txout_sent_and_received() {
@ -11,11 +11,11 @@ fn spk_txout_sent_and_received() {
index.insert_spk(1, spk2.clone()); index.insert_spk(1, spk2.clone());
let tx1 = Transaction { let tx1 = Transaction {
version: 0x02, version: transaction::Version::TWO,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 42_000, value: Amount::from_sat(42_000),
script_pubkey: spk1.clone(), script_pubkey: spk1.clone(),
}], }],
}; };
@ -30,7 +30,7 @@ fn spk_txout_sent_and_received() {
); );
let tx2 = Transaction { let tx2 = Transaction {
version: 0x1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint { previous_output: OutPoint {
@ -41,12 +41,12 @@ fn spk_txout_sent_and_received() {
}], }],
output: vec![ output: vec![
TxOut { TxOut {
value: 20_000, value: Amount::from_sat(20_000),
script_pubkey: spk2, script_pubkey: spk2,
}, },
TxOut { TxOut {
script_pubkey: spk1, script_pubkey: spk1,
value: 30_000, value: Amount::from_sat(30_000),
}, },
], ],
}; };
@ -73,11 +73,11 @@ fn mark_used() {
assert!(spk_index.is_used(&1)); assert!(spk_index.is_used(&1));
let tx1 = Transaction { let tx1 = Transaction {
version: 0x02, version: transaction::Version::TWO,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 42_000, value: Amount::from_sat(42_000),
script_pubkey: spk1, script_pubkey: spk1,
}], }],
}; };

View File

@ -8,7 +8,8 @@ use bdk_chain::{
Anchor, Append, BlockId, ChainOracle, ChainPosition, ConfirmationHeightAnchor, Anchor, Append, BlockId, ChainOracle, ChainPosition, ConfirmationHeightAnchor,
}; };
use bitcoin::{ use bitcoin::{
absolute, hashes::Hash, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Txid, absolute, hashes::Hash, transaction, Amount, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn,
TxOut, Txid,
}; };
use common::*; use common::*;
use core::iter; use core::iter;
@ -23,14 +24,14 @@ fn insert_txouts() {
( (
OutPoint::new(h!("tx1"), 1), OutPoint::new(h!("tx1"), 1),
TxOut { TxOut {
value: 10_000, value: Amount::from_sat(10_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
), ),
( (
OutPoint::new(h!("tx1"), 2), OutPoint::new(h!("tx1"), 2),
TxOut { TxOut {
value: 20_000, value: Amount::from_sat(20_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
), ),
@ -40,21 +41,21 @@ fn insert_txouts() {
let update_ops = [( let update_ops = [(
OutPoint::new(h!("tx2"), 0), OutPoint::new(h!("tx2"), 0),
TxOut { TxOut {
value: 20_000, value: Amount::from_sat(20_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
)]; )];
// One full transaction to be included in the update // One full transaction to be included in the update
let update_txs = Transaction { let update_txs = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint::null(), previous_output: OutPoint::null(),
..Default::default() ..Default::default()
}], }],
output: vec![TxOut { output: vec![TxOut {
value: 30_000, value: Amount::from_sat(30_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}], }],
}; };
@ -164,14 +165,14 @@ fn insert_txouts() {
( (
1u32, 1u32,
&TxOut { &TxOut {
value: 10_000, value: Amount::from_sat(10_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
} }
), ),
( (
2u32, 2u32,
&TxOut { &TxOut {
value: 20_000, value: Amount::from_sat(20_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
} }
) )
@ -184,7 +185,7 @@ fn insert_txouts() {
[( [(
0u32, 0u32,
&TxOut { &TxOut {
value: 30_000, value: Amount::from_sat(30_000),
script_pubkey: ScriptBuf::new() script_pubkey: ScriptBuf::new()
} }
)] )]
@ -206,7 +207,7 @@ fn insert_txouts() {
#[test] #[test]
fn insert_tx_graph_doesnt_count_coinbase_as_spent() { fn insert_tx_graph_doesnt_count_coinbase_as_spent() {
let tx = Transaction { let tx = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint::null(), previous_output: OutPoint::null(),
@ -225,10 +226,10 @@ fn insert_tx_graph_doesnt_count_coinbase_as_spent() {
#[test] #[test]
fn insert_tx_graph_keeps_track_of_spend() { fn insert_tx_graph_keeps_track_of_spend() {
let tx1 = Transaction { let tx1 = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
}; };
let op = OutPoint { let op = OutPoint {
@ -237,7 +238,7 @@ fn insert_tx_graph_keeps_track_of_spend() {
}; };
let tx2 = Transaction { let tx2 = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: op, previous_output: op,
@ -266,13 +267,13 @@ fn insert_tx_graph_keeps_track_of_spend() {
#[test] #[test]
fn insert_tx_can_retrieve_full_tx_from_graph() { fn insert_tx_can_retrieve_full_tx_from_graph() {
let tx = Transaction { let tx = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint::null(), previous_output: OutPoint::null(),
..Default::default() ..Default::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
}; };
let mut graph = TxGraph::<()>::default(); let mut graph = TxGraph::<()>::default();
@ -287,12 +288,12 @@ fn insert_tx_can_retrieve_full_tx_from_graph() {
fn insert_tx_displaces_txouts() { fn insert_tx_displaces_txouts() {
let mut tx_graph = TxGraph::<()>::default(); let mut tx_graph = TxGraph::<()>::default();
let tx = Transaction { let tx = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 42_000, value: Amount::from_sat(42_000),
script_pubkey: ScriptBuf::default(), script_pubkey: ScriptBuf::new(),
}], }],
}; };
@ -302,7 +303,7 @@ fn insert_tx_displaces_txouts() {
vout: 0, vout: 0,
}, },
TxOut { TxOut {
value: 1_337_000, value: Amount::from_sat(1_337_000),
script_pubkey: ScriptBuf::default(), script_pubkey: ScriptBuf::default(),
}, },
); );
@ -315,8 +316,8 @@ fn insert_tx_displaces_txouts() {
vout: 0, vout: 0,
}, },
TxOut { TxOut {
value: 1_000_000_000, value: Amount::from_sat(1_000_000_000),
script_pubkey: ScriptBuf::default(), script_pubkey: ScriptBuf::new(),
}, },
); );
@ -330,7 +331,7 @@ fn insert_tx_displaces_txouts() {
}) })
.unwrap() .unwrap()
.value, .value,
42_000 Amount::from_sat(42_000)
); );
assert_eq!( assert_eq!(
tx_graph.get_txout(OutPoint { tx_graph.get_txout(OutPoint {
@ -345,12 +346,12 @@ fn insert_tx_displaces_txouts() {
fn insert_txout_does_not_displace_tx() { fn insert_txout_does_not_displace_tx() {
let mut tx_graph = TxGraph::<()>::default(); let mut tx_graph = TxGraph::<()>::default();
let tx = Transaction { let tx = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 42_000, value: Amount::from_sat(42_000),
script_pubkey: ScriptBuf::default(), script_pubkey: ScriptBuf::new(),
}], }],
}; };
@ -362,8 +363,8 @@ fn insert_txout_does_not_displace_tx() {
vout: 0, vout: 0,
}, },
TxOut { TxOut {
value: 1_337_000, value: Amount::from_sat(1_337_000),
script_pubkey: ScriptBuf::default(), script_pubkey: ScriptBuf::new(),
}, },
); );
@ -373,8 +374,8 @@ fn insert_txout_does_not_displace_tx() {
vout: 0, vout: 0,
}, },
TxOut { TxOut {
value: 1_000_000_000, value: Amount::from_sat(1_000_000_000),
script_pubkey: ScriptBuf::default(), script_pubkey: ScriptBuf::new(),
}, },
); );
@ -386,7 +387,7 @@ fn insert_txout_does_not_displace_tx() {
}) })
.unwrap() .unwrap()
.value, .value,
42_000 Amount::from_sat(42_000)
); );
assert_eq!( assert_eq!(
tx_graph.get_txout(OutPoint { tx_graph.get_txout(OutPoint {
@ -401,21 +402,21 @@ fn insert_txout_does_not_displace_tx() {
fn test_calculate_fee() { fn test_calculate_fee() {
let mut graph = TxGraph::<()>::default(); let mut graph = TxGraph::<()>::default();
let intx1 = Transaction { let intx1 = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 100, value: Amount::from_sat(100),
..Default::default() script_pubkey: ScriptBuf::new(),
}], }],
}; };
let intx2 = Transaction { let intx2 = Transaction {
version: 0x02, version: transaction::Version::TWO,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![], input: vec![],
output: vec![TxOut { output: vec![TxOut {
value: 200, value: Amount::from_sat(200),
..Default::default() script_pubkey: ScriptBuf::new(),
}], }],
}; };
@ -425,8 +426,8 @@ fn test_calculate_fee() {
vout: 0, vout: 0,
}, },
TxOut { TxOut {
value: 300, value: Amount::from_sat(300),
..Default::default() script_pubkey: ScriptBuf::new(),
}, },
); );
@ -435,7 +436,7 @@ fn test_calculate_fee() {
let _ = graph.insert_txout(intxout1.0, intxout1.1); let _ = graph.insert_txout(intxout1.0, intxout1.1);
let mut tx = Transaction { let mut tx = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![ input: vec![
TxIn { TxIn {
@ -458,8 +459,8 @@ fn test_calculate_fee() {
}, },
], ],
output: vec![TxOut { output: vec![TxOut {
value: 500, value: Amount::from_sat(500),
..Default::default() script_pubkey: ScriptBuf::new(),
}], }],
}; };
@ -491,13 +492,13 @@ fn test_calculate_fee() {
#[test] #[test]
fn test_calculate_fee_on_coinbase() { fn test_calculate_fee_on_coinbase() {
let tx = Transaction { let tx = Transaction {
version: 0x01, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
input: vec![TxIn { input: vec![TxIn {
previous_output: OutPoint::null(), previous_output: OutPoint::null(),
..Default::default() ..Default::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
}; };
let graph = TxGraph::<()>::default(); let graph = TxGraph::<()>::default();
@ -533,7 +534,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(h!("op0"), 0), previous_output: OutPoint::new(h!("op0"), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default(), TxOut::default()], output: vec![TxOut::NULL, TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -543,7 +544,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(tx_a0.txid(), 0), previous_output: OutPoint::new(tx_a0.txid(), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default(), TxOut::default()], output: vec![TxOut::NULL, TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -553,7 +554,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(tx_a0.txid(), 1), previous_output: OutPoint::new(tx_a0.txid(), 1),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -562,7 +563,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(h!("op1"), 0), previous_output: OutPoint::new(h!("op1"), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -572,7 +573,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(tx_b0.txid(), 0), previous_output: OutPoint::new(tx_b0.txid(), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -582,7 +583,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(tx_b0.txid(), 1), previous_output: OutPoint::new(tx_b0.txid(), 1),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -598,7 +599,7 @@ fn test_walk_ancestors() {
..TxIn::default() ..TxIn::default()
}, },
], ],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -607,7 +608,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(h!("op2"), 0), previous_output: OutPoint::new(h!("op2"), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -617,7 +618,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(tx_c1.txid(), 0), previous_output: OutPoint::new(tx_c1.txid(), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -633,7 +634,7 @@ fn test_walk_ancestors() {
..TxIn::default() ..TxIn::default()
}, },
], ],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -643,7 +644,7 @@ fn test_walk_ancestors() {
previous_output: OutPoint::new(tx_d1.txid(), 0), previous_output: OutPoint::new(tx_d1.txid(), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -726,7 +727,7 @@ fn test_conflicting_descendants() {
previous_output, previous_output,
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -736,7 +737,7 @@ fn test_conflicting_descendants() {
previous_output, previous_output,
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default(), TxOut::default()], output: vec![TxOut::NULL, TxOut::NULL],
..common::new_tx(1) ..common::new_tx(1)
}; };
@ -746,7 +747,7 @@ fn test_conflicting_descendants() {
previous_output: OutPoint::new(tx_a.txid(), 0), previous_output: OutPoint::new(tx_a.txid(), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(2) ..common::new_tx(2)
}; };
@ -768,7 +769,7 @@ fn test_conflicting_descendants() {
#[test] #[test]
fn test_descendants_no_repeat() { fn test_descendants_no_repeat() {
let tx_a = Transaction { let tx_a = Transaction {
output: vec![TxOut::default(), TxOut::default(), TxOut::default()], output: vec![TxOut::NULL, TxOut::NULL, TxOut::NULL],
..common::new_tx(0) ..common::new_tx(0)
}; };
@ -778,7 +779,7 @@ fn test_descendants_no_repeat() {
previous_output: OutPoint::new(tx_a.txid(), vout), previous_output: OutPoint::new(tx_a.txid(), vout),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(1) ..common::new_tx(1)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -789,7 +790,7 @@ fn test_descendants_no_repeat() {
previous_output: OutPoint::new(txs_b[vout as usize].txid(), vout), previous_output: OutPoint::new(txs_b[vout as usize].txid(), vout),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(2) ..common::new_tx(2)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -805,7 +806,7 @@ fn test_descendants_no_repeat() {
..TxIn::default() ..TxIn::default()
}, },
], ],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(3) ..common::new_tx(3)
}; };
@ -814,7 +815,7 @@ fn test_descendants_no_repeat() {
previous_output: OutPoint::new(tx_d.txid(), 0), previous_output: OutPoint::new(tx_d.txid(), 0),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(4) ..common::new_tx(4)
}; };
@ -824,7 +825,7 @@ fn test_descendants_no_repeat() {
previous_output: OutPoint::new(h!("tx_does_not_exist"), v), previous_output: OutPoint::new(h!("tx_does_not_exist"), v),
..TxIn::default() ..TxIn::default()
}], }],
output: vec![TxOut::default()], output: vec![TxOut::NULL],
..common::new_tx(v) ..common::new_tx(v)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -871,11 +872,11 @@ fn test_chain_spends() {
input: vec![], input: vec![],
output: vec![ output: vec![
TxOut { TxOut {
value: 10_000, value: Amount::from_sat(10_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
TxOut { TxOut {
value: 20_000, value: Amount::from_sat(20_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
], ],
@ -890,11 +891,11 @@ fn test_chain_spends() {
}], }],
output: vec![ output: vec![
TxOut { TxOut {
value: 5_000, value: Amount::from_sat(5_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
TxOut { TxOut {
value: 5_000, value: Amount::from_sat(5_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
], ],
@ -909,11 +910,11 @@ fn test_chain_spends() {
}], }],
output: vec![ output: vec![
TxOut { TxOut {
value: 10_000, value: Amount::from_sat(10_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
TxOut { TxOut {
value: 10_000, value: Amount::from_sat(10_000),
script_pubkey: ScriptBuf::new(), script_pubkey: ScriptBuf::new(),
}, },
], ],

View File

@ -13,10 +13,10 @@ readme = "README.md"
[dependencies] [dependencies]
bdk_chain = { path = "../chain", version = "0.11.0", default-features = false } bdk_chain = { path = "../chain", version = "0.11.0", default-features = false }
electrum-client = { version = "0.18" } electrum-client = { version = "0.19" }
#rustls = { version = "=0.21.1", optional = true, features = ["dangerous_configuration"] } #rustls = { version = "=0.21.1", optional = true, features = ["dangerous_configuration"] }
[dev-dependencies] [dev-dependencies]
bdk_testenv = { path = "../testenv", version = "0.1.0", default-features = false } bdk_testenv = { path = "../testenv", default-features = false }
electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } electrsd = { version= "0.27.1", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] }
anyhow = "1" anyhow = "1"

View File

@ -40,7 +40,7 @@ fn scan_detects_confirmed_tx() -> Result<()> {
.client .client
.get_new_address(None, None)? .get_new_address(None, None)?
.assume_checked(); .assume_checked();
let spk_to_track = ScriptBuf::new_v0_p2wsh(&WScriptHash::all_zeros()); let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?; let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?;
// Setup receiver. // Setup receiver.
@ -106,7 +106,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> Result<()> {
.client .client
.get_new_address(None, None)? .get_new_address(None, None)?
.assume_checked(); .assume_checked();
let spk_to_track = ScriptBuf::new_v0_p2wsh(&WScriptHash::all_zeros()); let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?; let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?;
// Setup receiver. // Setup receiver.

View File

@ -13,17 +13,17 @@ readme = "README.md"
[dependencies] [dependencies]
bdk_chain = { path = "../chain", version = "0.11.0", default-features = false } bdk_chain = { path = "../chain", version = "0.11.0", default-features = false }
esplora-client = { version = "0.6.0", default-features = false } esplora-client = { version = "0.7.0", default-features = false }
async-trait = { version = "0.1.66", optional = true } async-trait = { version = "0.1.66", optional = true }
futures = { version = "0.3.26", optional = true } futures = { version = "0.3.26", optional = true }
# use these dependencies if you need to enable their /no-std features # use these dependencies if you need to enable their /no-std features
bitcoin = { version = "0.30.0", optional = true, default-features = false } bitcoin = { version = "0.31.0", optional = true, default-features = false }
miniscript = { version = "10.0.0", optional = true, default-features = false } miniscript = { version = "11.0.0", optional = true, default-features = false }
[dev-dependencies] [dev-dependencies]
bdk_testenv = { path = "../testenv", version = "0.1.0", default_features = false } bdk_testenv = { path = "../testenv", default_features = false }
electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } electrsd = { version= "0.27.1", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
[features] [features]

View File

@ -1,7 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use bdk_chain::collections::btree_map; use bdk_chain::collections::btree_map;
use bdk_chain::{ use bdk_chain::{
bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
collections::BTreeMap, collections::BTreeMap,
local_chain::{self, CheckPoint}, local_chain::{self, CheckPoint},
BlockId, ConfirmationTimeHeightAnchor, TxGraph, BlockId, ConfirmationTimeHeightAnchor, TxGraph,
@ -228,7 +228,7 @@ impl EsploraAsyncExt for esplora_client::AsyncClient {
}, },
TxOut { TxOut {
script_pubkey: prevout.scriptpubkey.clone(), script_pubkey: prevout.scriptpubkey.clone(),
value: prevout.value, value: Amount::from_sat(prevout.value),
}, },
)) ))
}); });

View File

@ -3,7 +3,7 @@ use std::thread::JoinHandle;
use bdk_chain::collections::btree_map; use bdk_chain::collections::btree_map;
use bdk_chain::collections::BTreeMap; use bdk_chain::collections::BTreeMap;
use bdk_chain::{ use bdk_chain::{
bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
local_chain::{self, CheckPoint}, local_chain::{self, CheckPoint},
BlockId, ConfirmationTimeHeightAnchor, TxGraph, BlockId, ConfirmationTimeHeightAnchor, TxGraph,
}; };
@ -218,7 +218,7 @@ impl EsploraExt for esplora_client::BlockingClient {
}, },
TxOut { TxOut {
script_pubkey: prevout.scriptpubkey.clone(), script_pubkey: prevout.scriptpubkey.clone(),
value: prevout.value, value: Amount::from_sat(prevout.value),
}, },
)) ))
}); });

View File

@ -30,7 +30,7 @@ macro_rules! local_chain {
pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> {
let env = TestEnv::new()?; let env = TestEnv::new()?;
let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap()); let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap());
let client = Builder::new(base_url.as_str()).build_blocking()?; let client = Builder::new(base_url.as_str()).build_blocking();
let receive_address0 = let receive_address0 =
Address::from_str("bcrt1qc6fweuf4xjvz4x3gx3t9e0fh4hvqyu2qw4wvxm")?.assume_checked(); Address::from_str("bcrt1qc6fweuf4xjvz4x3gx3t9e0fh4hvqyu2qw4wvxm")?.assume_checked();
@ -111,7 +111,7 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> {
pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> { pub fn test_update_tx_graph_stop_gap() -> anyhow::Result<()> {
let env = TestEnv::new()?; let env = TestEnv::new()?;
let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap()); let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap());
let client = Builder::new(base_url.as_str()).build_blocking()?; let client = Builder::new(base_url.as_str()).build_blocking();
let _block_hashes = env.mine_blocks(101, None)?; let _block_hashes = env.mine_blocks(101, None)?;
// Now let's test the gap limit. First of all get a chain of 10 addresses. // Now let's test the gap limit. First of all get a chain of 10 addresses.
@ -215,7 +215,7 @@ fn update_local_chain() -> anyhow::Result<()> {
// so new blocks can be seen by Electrs // so new blocks can be seen by Electrs
let env = env.reset_electrsd()?; let env = env.reset_electrsd()?;
let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap()); let base_url = format!("http://{}", &env.electrsd.esplora_url.clone().unwrap());
let client = Builder::new(base_url.as_str()).build_blocking()?; let client = Builder::new(base_url.as_str()).build_blocking();
struct TestCase { struct TestCase {
name: &'static str, name: &'static str,

View File

@ -10,4 +10,4 @@ readme = "README.md"
[dependencies] [dependencies]
bdk = { path = "../bdk" } bdk = { path = "../bdk" }
hwi = { version = "0.7.0", features = [ "miniscript"] } hwi = { version = "0.8.0", features = [ "miniscript"] }

View File

@ -1,6 +1,6 @@
use bdk::bitcoin::bip32::Fingerprint; use bdk::bitcoin::bip32::Fingerprint;
use bdk::bitcoin::psbt::PartiallySignedTransaction;
use bdk::bitcoin::secp256k1::{All, Secp256k1}; use bdk::bitcoin::secp256k1::{All, Secp256k1};
use bdk::bitcoin::Psbt;
use hwi::error::Error; use hwi::error::Error;
use hwi::types::{HWIChain, HWIDevice}; use hwi::types::{HWIChain, HWIDevice};
@ -37,7 +37,7 @@ impl SignerCommon for HWISigner {
impl TransactionSigner for HWISigner { impl TransactionSigner for HWISigner {
fn sign_transaction( fn sign_transaction(
&self, &self,
psbt: &mut PartiallySignedTransaction, psbt: &mut Psbt,
_sign_options: &bdk::SignOptions, _sign_options: &bdk::SignOptions,
_secp: &Secp256k1<All>, _secp: &Secp256k1<All>,
) -> Result<(), SignerError> { ) -> Result<(), SignerError> {

View File

@ -13,9 +13,9 @@ readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bitcoincore-rpc = { version = "0.17" } bitcoincore-rpc = { version = "0.18" }
bdk_chain = { path = "../chain", version = "0.11", default-features = false } bdk_chain = { path = "../chain", version = "0.11", default-features = false }
electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } electrsd = { version= "0.27.1", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] }
anyhow = { version = "1" } anyhow = { version = "1" }
[features] [features]

View File

@ -1,7 +1,7 @@
use bdk_chain::bitcoin::{ use bdk_chain::bitcoin::{
address::NetworkChecked, block::Header, hash_types::TxMerkleNode, hashes::Hash, address::NetworkChecked, block::Header, hash_types::TxMerkleNode, hashes::Hash,
secp256k1::rand::random, Address, Amount, Block, BlockHash, CompactTarget, ScriptBuf, secp256k1::rand::random, transaction, Address, Amount, Block, BlockHash, CompactTarget,
ScriptHash, Transaction, TxIn, TxOut, Txid, ScriptBuf, ScriptHash, Transaction, TxIn, TxOut, Txid,
}; };
use bitcoincore_rpc::{ use bitcoincore_rpc::{
bitcoincore_rpc_json::{GetBlockTemplateModes, GetBlockTemplateRules}, bitcoincore_rpc_json::{GetBlockTemplateModes, GetBlockTemplateRules},
@ -109,7 +109,7 @@ impl TestEnv {
)?; )?;
let txdata = vec![Transaction { let txdata = vec![Transaction {
version: 1, version: transaction::Version::ONE,
lock_time: bdk_chain::bitcoin::absolute::LockTime::from_height(0)?, lock_time: bdk_chain::bitcoin::absolute::LockTime::from_height(0)?,
input: vec![TxIn { input: vec![TxIn {
previous_output: bdk_chain::bitcoin::OutPoint::default(), previous_output: bdk_chain::bitcoin::OutPoint::default(),
@ -122,7 +122,7 @@ impl TestEnv {
witness: bdk_chain::bitcoin::Witness::new(), witness: bdk_chain::bitcoin::Witness::new(),
}], }],
output: vec![TxOut { output: vec![TxOut {
value: 0, value: Amount::ZERO,
script_pubkey: ScriptBuf::new_p2sh(&ScriptHash::all_zeros()), script_pubkey: ScriptBuf::new_p2sh(&ScriptHash::all_zeros()),
}], }],
}]; }];

View File

@ -3,12 +3,14 @@ use anyhow::Context;
use bdk_coin_select::{coin_select_bnb, CoinSelector, CoinSelectorOpt, WeightedValue}; use bdk_coin_select::{coin_select_bnb, CoinSelector, CoinSelectorOpt, WeightedValue};
use bdk_file_store::Store; use bdk_file_store::Store;
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use std::{cmp::Reverse, collections::HashMap, path::PathBuf, sync::Mutex, time::Duration}; use std::{cmp::Reverse, collections::BTreeMap, path::PathBuf, sync::Mutex, time::Duration};
use bdk_chain::{ use bdk_chain::{
bitcoin::{ bitcoin::{
absolute, address, psbt::Prevouts, secp256k1::Secp256k1, sighash::SighashCache, Address, absolute, address,
Network, Sequence, Transaction, TxIn, TxOut, secp256k1::Secp256k1,
sighash::{Prevouts, SighashCache},
transaction, Address, Amount, Network, Sequence, Transaction, TxIn, TxOut,
}, },
indexed_tx_graph::{self, IndexedTxGraph}, indexed_tx_graph::{self, IndexedTxGraph},
keychain::{self, KeychainTxOutIndex}, keychain::{self, KeychainTxOutIndex},
@ -197,7 +199,7 @@ pub struct CreateTxChange {
pub fn create_tx<A: Anchor, O: ChainOracle>( pub fn create_tx<A: Anchor, O: ChainOracle>(
graph: &mut KeychainTxGraph<A>, graph: &mut KeychainTxGraph<A>,
chain: &O, chain: &O,
keymap: &HashMap<DescriptorPublicKey, DescriptorSecretKey>, keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
cs_algorithm: CoinSelectionAlgo, cs_algorithm: CoinSelectionAlgo,
address: Address, address: Address,
value: u64, value: u64,
@ -235,7 +237,7 @@ where
.iter() .iter()
.map(|(plan, utxo)| { .map(|(plan, utxo)| {
WeightedValue::new( WeightedValue::new(
utxo.txout.value, utxo.txout.value.to_sat(),
plan.expected_weight() as _, plan.expected_weight() as _,
plan.witness_version().is_some(), plan.witness_version().is_some(),
) )
@ -243,7 +245,7 @@ where
.collect(); .collect();
let mut outputs = vec![TxOut { let mut outputs = vec![TxOut {
value, value: Amount::from_sat(value),
script_pubkey: address.script_pubkey(), script_pubkey: address.script_pubkey(),
}]; }];
@ -273,7 +275,7 @@ where
.expect("failed to obtain change plan"); .expect("failed to obtain change plan");
let mut change_output = TxOut { let mut change_output = TxOut {
value: 0, value: Amount::ZERO,
script_pubkey: change_script, script_pubkey: change_script,
}; };
@ -311,13 +313,13 @@ where
let selected_txos = selection.apply_selection(&candidates).collect::<Vec<_>>(); let selected_txos = selection.apply_selection(&candidates).collect::<Vec<_>>();
if let Some(drain_value) = selection_meta.drain_value { if let Some(drain_value) = selection_meta.drain_value {
change_output.value = drain_value; change_output.value = Amount::from_sat(drain_value);
// if the selection tells us to use change and the change value is sufficient, we add it as an output // if the selection tells us to use change and the change value is sufficient, we add it as an output
outputs.push(change_output) outputs.push(change_output)
} }
let mut transaction = Transaction { let mut transaction = Transaction {
version: 0x02, version: transaction::Version::TWO,
// because the temporary planning module does not support timelocks, we can use the chain // because the temporary planning module does not support timelocks, we can use the chain
// tip as the `lock_time` for anti-fee-sniping purposes // tip as the `lock_time` for anti-fee-sniping purposes
lock_time: absolute::LockTime::from_height(chain.get_chain_tip()?.height) lock_time: absolute::LockTime::from_height(chain.get_chain_tip()?.height)
@ -440,7 +442,7 @@ pub fn handle_commands<CS: clap::Subcommand, S: clap::Args, A: Anchor, O: ChainO
graph: &Mutex<KeychainTxGraph<A>>, graph: &Mutex<KeychainTxGraph<A>>,
db: &Mutex<Database<C>>, db: &Mutex<Database<C>>,
chain: &Mutex<O>, chain: &Mutex<O>,
keymap: &HashMap<DescriptorPublicKey, DescriptorSecretKey>, keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
network: Network, network: Network,
broadcast: impl FnOnce(S, &Transaction) -> anyhow::Result<()>, broadcast: impl FnOnce(S, &Transaction) -> anyhow::Result<()>,
cmd: Commands<CS, S>, cmd: Commands<CS, S>,

View File

@ -86,7 +86,7 @@ impl EsploraArgs {
_ => panic!("unsupported network"), _ => panic!("unsupported network"),
}); });
let client = esplora_client::Builder::new(esplora_url).build_blocking()?; let client = esplora_client::Builder::new(esplora_url).build_blocking();
Ok(client) Ok(client)
} }
} }

View File

@ -99,7 +99,7 @@ fn main() -> Result<(), anyhow::Error> {
let finalized = wallet.sign(&mut psbt, SignOptions::default())?; let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
assert!(finalized); assert!(finalized);
let tx = psbt.extract_tx(); let tx = psbt.extract_tx()?;
client.transaction_broadcast(&tx)?; client.transaction_broadcast(&tx)?;
println!("Tx broadcasted! Txid: {}", tx.txid()); println!("Tx broadcasted! Txid: {}", tx.txid());

View File

@ -90,7 +90,7 @@ async fn main() -> Result<(), anyhow::Error> {
let finalized = wallet.sign(&mut psbt, SignOptions::default())?; let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
assert!(finalized); assert!(finalized);
let tx = psbt.extract_tx(); let tx = psbt.extract_tx()?;
client.broadcast(&tx).await?; client.broadcast(&tx).await?;
println!("Tx broadcasted! Txid: {}", tx.txid()); println!("Tx broadcasted! Txid: {}", tx.txid());

View File

@ -34,7 +34,7 @@ fn main() -> Result<(), anyhow::Error> {
print!("Syncing..."); print!("Syncing...");
let client = let client =
esplora_client::Builder::new("https://blockstream.info/testnet/api").build_blocking()?; esplora_client::Builder::new("https://blockstream.info/testnet/api").build_blocking();
let prev_tip = wallet.latest_checkpoint(); let prev_tip = wallet.latest_checkpoint();
let keychain_spks = wallet let keychain_spks = wallet
@ -90,7 +90,7 @@ fn main() -> Result<(), anyhow::Error> {
let finalized = wallet.sign(&mut psbt, SignOptions::default())?; let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
assert!(finalized); assert!(finalized);
let tx = psbt.extract_tx(); let tx = psbt.extract_tx()?;
client.broadcast(&tx)?; client.broadcast(&tx)?;
println!("Tx broadcasted! Txid: {}", tx.txid()); println!("Tx broadcasted! Txid: {}", tx.txid());

View File

@ -96,7 +96,7 @@ impl CoinSelectorOpt {
) -> Self { ) -> Self {
let mut tx = Transaction { let mut tx = Transaction {
input: vec![], input: vec![],
version: 1, version: transaction::Version::ONE,
lock_time: absolute::LockTime::ZERO, lock_time: absolute::LockTime::ZERO,
output: txouts.to_vec(), output: txouts.to_vec(),
}; };
@ -112,7 +112,7 @@ impl CoinSelectorOpt {
target_value: if txouts.is_empty() { target_value: if txouts.is_empty() {
None None
} else { } else {
Some(txouts.iter().map(|txout| txout.value).sum()) Some(txouts.iter().map(|txout| txout.value.to_sat()).sum())
}, },
..Self::from_weights( ..Self::from_weights(
base_weight.to_wu() as u32, base_weight.to_wu() as u32,

View File

@ -12,7 +12,7 @@ use bdk_chain::{
bitcoin, bitcoin,
collections::{BTreeSet, HashMap}, collections::{BTreeSet, HashMap},
}; };
use bitcoin::{absolute, Transaction, TxOut}; use bitcoin::{absolute, transaction, Transaction, TxOut};
use core::fmt::{Debug, Display}; use core::fmt::{Debug, Display};
mod coin_selector; mod coin_selector;
@ -29,5 +29,5 @@ pub const TXIN_BASE_WEIGHT: u32 = (32 + 4 + 4) * 4;
// Shamelessly copied from // Shamelessly copied from
// https://github.com/rust-bitcoin/rust-miniscript/blob/d5615acda1a7fdc4041a11c1736af139b8c7ebe8/src/util.rs#L8 // https://github.com/rust-bitcoin/rust-miniscript/blob/d5615acda1a7fdc4041a11c1736af139b8c7ebe8/src/util.rs#L8
pub(crate) fn varint_size(v: usize) -> u32 { pub(crate) fn varint_size(v: usize) -> u32 {
bitcoin::VarInt(v as u64).len() as u32 bitcoin::VarInt(v as u64).size() as u32
} }

View File

@ -17,14 +17,13 @@
use bdk_chain::{bitcoin, collections::*, miniscript}; use bdk_chain::{bitcoin, collections::*, miniscript};
use bitcoin::{ use bitcoin::{
absolute, absolute,
address::WitnessVersion,
bip32::{DerivationPath, Fingerprint, KeySource}, bip32::{DerivationPath, Fingerprint, KeySource},
blockdata::transaction::Sequence, blockdata::transaction::Sequence,
ecdsa, ecdsa,
hashes::{hash160, ripemd160, sha256}, hashes::{hash160, ripemd160, sha256},
secp256k1::Secp256k1, secp256k1::Secp256k1,
taproot::{self, LeafVersion, TapLeafHash}, taproot::{self, LeafVersion, TapLeafHash},
ScriptBuf, TxIn, Witness, ScriptBuf, TxIn, Witness, WitnessVersion,
}; };
use miniscript::{ use miniscript::{
descriptor::{InnerXKey, Tr}, descriptor::{InnerXKey, Tr},
@ -32,7 +31,7 @@ use miniscript::{
}; };
pub(crate) fn varint_len(v: usize) -> usize { pub(crate) fn varint_len(v: usize) -> usize {
bitcoin::VarInt(v as u64).len() as usize bitcoin::VarInt(v as u64).size() as usize
} }
mod plan_impls; mod plan_impls;

View File

@ -3,12 +3,11 @@ use core::ops::Deref;
use bitcoin::{ use bitcoin::{
bip32, bip32,
hashes::{hash160, ripemd160, sha256}, hashes::{hash160, ripemd160, sha256, Hash},
key::XOnlyPublicKey, key::XOnlyPublicKey,
psbt::Prevouts, secp256k1::{Keypair, Message, PublicKey, Signing, Verification},
secp256k1::{KeyPair, Message, PublicKey, Signing, Verification},
sighash, sighash,
sighash::{EcdsaSighashType, SighashCache, TapSighashType}, sighash::{EcdsaSighashType, Prevouts, SighashCache, TapSighashType},
taproot, Transaction, TxOut, taproot, Transaction, TxOut,
}; };
@ -163,11 +162,11 @@ impl RequiredSignatures<DescriptorPublicKey> {
let tweak = let tweak =
taproot::TapTweakHash::from_key_and_tweak(x_only_pubkey, merkle_root.clone()); taproot::TapTweakHash::from_key_and_tweak(x_only_pubkey, merkle_root.clone());
let keypair = KeyPair::from_secret_key(&secp, &secret_key.clone()) let keypair = Keypair::from_secret_key(&secp, &secret_key.clone())
.add_xonly_tweak(&secp, &tweak.to_scalar()) .add_xonly_tweak(&secp, &tweak.to_scalar())
.unwrap(); .unwrap();
let msg = Message::from_slice(sighash.as_ref()).expect("Sighashes are 32 bytes"); let msg = Message::from_digest(sighash.to_byte_array());
let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair); let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair);
let bitcoin_sig = taproot::Signature { let bitcoin_sig = taproot::Signature {
@ -209,9 +208,8 @@ impl RequiredSignatures<DescriptorPublicKey> {
todo!(); todo!();
} }
}; };
let keypair = KeyPair::from_secret_key(&secp, &secret_key.clone()); let keypair = Keypair::from_secret_key(&secp, &secret_key.clone());
let msg = let msg = Message::from_digest(sighash.to_byte_array());
Message::from_slice(sighash.as_ref()).expect("Sighashes are 32 bytes");
let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair); let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair);
let bitcoin_sig = taproot::Signature { let bitcoin_sig = taproot::Signature {
sig, sig,