diff --git a/crates/bdk/Cargo.toml b/crates/bdk/Cargo.toml index 396e5675d..2cfa8c951 100644 --- a/crates/bdk/Cargo.toml +++ b/crates/bdk/Cargo.toml @@ -14,8 +14,8 @@ rust-version = "1.63" [dependencies] rand = "^0.8" -miniscript = { version = "10.0.0", features = ["serde"], default-features = false } -bitcoin = { version = "0.30.0", features = ["serde", "base64", "rand-std"], default-features = false } +miniscript = { version = "11.0.0", features = ["serde"], default-features = false } +bitcoin = { version = "0.31.0", features = ["serde", "base64", "rand-std"], default-features = false } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1.0" } bdk_chain = { path = "../chain", version = "0.11.0", features = ["miniscript", "serde"], default-features = false } diff --git a/crates/bdk/src/descriptor/dsl.rs b/crates/bdk/src/descriptor/dsl.rs index 50cd978f7..aa52ff279 100644 --- a/crates/bdk/src/descriptor/dsl.rs +++ b/crates/bdk/src/descriptor/dsl.rs @@ -274,14 +274,13 @@ macro_rules! impl_sortedmulti { #[macro_export] macro_rules! parse_tap_tree { ( @merge $tree_a:expr, $tree_b:expr) => {{ - use $crate::alloc::sync::Arc; use $crate::miniscript::descriptor::TapTree; $tree_a .and_then(|tree_a| Ok((tree_a, $tree_b?))) .and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| { 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::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks}; use bitcoin::bip32; - use bitcoin::network::constants::Network::{Bitcoin, Regtest, Signet, Testnet}; + use bitcoin::Network::{Bitcoin, Regtest, Signet, Testnet}; use bitcoin::PrivateKey; // test the descriptor!() macro @@ -936,7 +935,7 @@ mod test { #[test] 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 desc_key = (xprv, path.clone()).into_descriptor_key().unwrap(); @@ -981,7 +980,7 @@ mod test { #[test] 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 desc_key = (xprv, path.clone()).into_descriptor_key().unwrap(); @@ -1038,10 +1037,10 @@ mod test { #[test] 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 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 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 #[test] 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 desc_key = (xprv, path).into_descriptor_key().unwrap(); @@ -1107,7 +1106,7 @@ mod test { [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 desc_key = (xprv, path).into_descriptor_key().unwrap(); @@ -1120,15 +1119,15 @@ mod test { fn test_key_maps_merged() { 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 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 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 desc_key3 = (xprv3, path3.clone()).into_descriptor_key().unwrap(); @@ -1152,7 +1151,7 @@ mod test { #[test] fn test_script_context_validation() { // 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 desc_key: DescriptorKey = (xprv, path).into_descriptor_key().unwrap(); diff --git a/crates/bdk/src/descriptor/error.rs b/crates/bdk/src/descriptor/error.rs index b36e69e63..b2809f210 100644 --- a/crates/bdk/src/descriptor/error.rs +++ b/crates/bdk/src/descriptor/error.rs @@ -41,7 +41,7 @@ pub enum Error { /// Miniscript error Miniscript(miniscript::Error), /// Hex decoding error - Hex(bitcoin::hashes::hex::Error), + Hex(bitcoin::hex::HexToBytesError), } impl From for Error { @@ -110,8 +110,8 @@ impl From for Error { } } -impl From for Error { - fn from(err: bitcoin::hashes::hex::Error) -> Self { +impl From for Error { + fn from(err: bitcoin::hex::HexToBytesError) -> Self { Error::Hex(err) } } diff --git a/crates/bdk/src/descriptor/mod.rs b/crates/bdk/src/descriptor/mod.rs index 153ade254..4b1135feb 100644 --- a/crates/bdk/src/descriptor/mod.rs +++ b/crates/bdk/src/descriptor/mod.rs @@ -18,7 +18,7 @@ use crate::collections::BTreeMap; use alloc::string::String; 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::{psbt, taproot}; use bitcoin::{Network, TxOut}; @@ -377,7 +377,7 @@ where pub(crate) trait DescriptorMeta { fn is_witness(&self) -> bool; fn is_taproot(&self) -> bool; - fn get_extended_keys(&self) -> Vec>; + fn get_extended_keys(&self) -> Vec>; fn derive_from_hd_keypaths( &self, hd_keypaths: &HdKeyPaths, @@ -418,7 +418,7 @@ impl DescriptorMeta for ExtendedDescriptor { self.desc_type() == DescriptorType::Tr } - fn get_extended_keys(&self) -> Vec> { + fn get_extended_keys(&self) -> Vec> { let mut answer = Vec::new(); self.for_each_key(|pk| { @@ -438,21 +438,20 @@ impl DescriptorMeta for ExtendedDescriptor { secp: &SecpCtx, ) -> Option { // Ensure that deriving `xpub` with `path` yields `expected` - let verify_key = |xpub: &DescriptorXKey, - path: &DerivationPath, - expected: &SinglePubKey| { - let derived = xpub - .xkey - .derive_pub(secp, path) - .expect("The path should never contain hardened derivation steps") - .public_key; - - match expected { - SinglePubKey::FullKey(pk) if &PublicKey::new(derived) == pk => true, - SinglePubKey::XOnly(pk) if &XOnlyPublicKey::from(derived) == pk => true, - _ => false, - } - }; + let verify_key = + |xpub: &DescriptorXKey, path: &DerivationPath, expected: &SinglePubKey| { + let derived = xpub + .xkey + .derive_pub(secp, path) + .expect("The path should never contain hardened derivation steps") + .public_key; + + match expected { + SinglePubKey::FullKey(pk) if &PublicKey::new(derived) == pk => true, + SinglePubKey::XOnly(pk) if &XOnlyPublicKey::from(derived) == pk => true, + _ => false, + } + }; let mut path_found = None; @@ -605,10 +604,10 @@ mod test { use core::str::FromStr; use assert_matches::assert_matches; - use bitcoin::hashes::hex::FromHex; + use bitcoin::hex::FromHex; use bitcoin::secp256k1::Secp256k1; use bitcoin::ScriptBuf; - use bitcoin::{bip32, psbt::Psbt}; + use bitcoin::{bip32, Psbt}; use super::*; use crate::psbt::PsbtUtils; @@ -727,7 +726,7 @@ mod test { 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(); // 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; 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 { xkey: xpub_testnet, origin: None, @@ -836,7 +835,7 @@ mod test { fn test_descriptor_from_str_from_output_of_macro() { 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 key = (tpub, path).into_descriptor_key().unwrap(); @@ -895,7 +894,7 @@ mod test { .update_with_descriptor_unchecked(&descriptor) .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)); } } diff --git a/crates/bdk/src/descriptor/policy.rs b/crates/bdk/src/descriptor/policy.rs index 523e94b40..820bf2d2d 100644 --- a/crates/bdk/src/descriptor/policy.rs +++ b/crates/bdk/src/descriptor/policy.rs @@ -1137,7 +1137,7 @@ impl ExtractPolicy for Descriptor { let key_spend_sig = 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)) } else { let mut items = vec![key_spend_sig]; @@ -1184,8 +1184,8 @@ mod test { secp: &SecpCtx, ) -> (DescriptorKey, DescriptorKey, Fingerprint) { let path = bip32::DerivationPath::from_str(path).unwrap(); - let tprv = bip32::ExtendedPrivKey::from_str(tprv).unwrap(); - let tpub = bip32::ExtendedPubKey::from_priv(secp, &tprv); + let tprv = bip32::Xpriv::from_str(tprv).unwrap(); + let tpub = bip32::Xpub::from_priv(secp, &tprv); let fingerprint = tprv.fingerprint(secp); let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap(); let pubkey = (tpub, path).into_descriptor_key().unwrap(); diff --git a/crates/bdk/src/descriptor/template.rs b/crates/bdk/src/descriptor/template.rs index 2773795a8..6f51139ac 100644 --- a/crates/bdk/src/descriptor/template.rs +++ b/crates/bdk/src/descriptor/template.rs @@ -195,7 +195,7 @@ impl> DescriptorTemplate for P2TR { /// # use bdk::wallet::AddressIndex::New; /// 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( /// Bip44(key.clone(), KeychainKind::External), /// Some(Bip44(key, KeychainKind::Internal)), @@ -232,7 +232,7 @@ impl> DescriptorTemplate for Bip44 { /// # use bdk::wallet::AddressIndex::New; /// 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 mut wallet = Wallet::new_no_persist( /// Bip44Public(key.clone(), fingerprint, KeychainKind::External), @@ -270,7 +270,7 @@ impl> DescriptorTemplate for Bip44Public { /// # use bdk::wallet::AddressIndex::New; /// 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( /// Bip49(key.clone(), KeychainKind::External), /// Some(Bip49(key, KeychainKind::Internal)), @@ -307,7 +307,7 @@ impl> DescriptorTemplate for Bip49 { /// # use bdk::wallet::AddressIndex::New; /// 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 mut wallet = Wallet::new_no_persist( /// Bip49Public(key.clone(), fingerprint, KeychainKind::External), @@ -345,7 +345,7 @@ impl> DescriptorTemplate for Bip49Public { /// # use bdk::wallet::AddressIndex::New; /// 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( /// Bip84(key.clone(), KeychainKind::External), /// Some(Bip84(key, KeychainKind::Internal)), @@ -382,7 +382,7 @@ impl> DescriptorTemplate for Bip84 { /// # use bdk::wallet::AddressIndex::New; /// 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 mut wallet = Wallet::new_no_persist( /// Bip84Public(key.clone(), fingerprint, KeychainKind::External), @@ -420,7 +420,7 @@ impl> DescriptorTemplate for Bip84Public { /// # use bdk::wallet::AddressIndex::New; /// 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( /// Bip86(key.clone(), KeychainKind::External), /// Some(Bip86(key, KeychainKind::Internal)), @@ -457,7 +457,7 @@ impl> DescriptorTemplate for Bip86 { /// # use bdk::wallet::AddressIndex::New; /// 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 mut wallet = Wallet::new_no_persist( /// Bip86Public(key.clone(), fingerprint, KeychainKind::External), @@ -567,7 +567,7 @@ mod test { fn test_bip44_template_cointype() { 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); let xdesc = Bip44(xprvkey, KeychainKind::Internal) .build(Network::Bitcoin) @@ -581,7 +581,7 @@ mod test { 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); let tdesc = Bip44(tprvkey, KeychainKind::Internal) .build(Network::Testnet) @@ -740,7 +740,7 @@ mod test { // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)` #[test] fn test_bip44_template() { - let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); + let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); check( Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin), false, @@ -770,7 +770,7 @@ mod test { // BIP44 public `pkh(key/{0,1}/*)` #[test] 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(); check( Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), @@ -801,7 +801,7 @@ mod test { // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))` #[test] fn test_bip49_template() { - let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); + let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); check( Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin), true, @@ -831,7 +831,7 @@ mod test { // BIP49 public `sh(wpkh(key/{0,1}/*))` #[test] 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(); check( Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), @@ -862,7 +862,7 @@ mod test { // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)` #[test] fn test_bip84_template() { - let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); + let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); check( Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin), true, @@ -892,7 +892,7 @@ mod test { // BIP84 public `wpkh(key/{0,1}/*)` #[test] 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(); check( 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 #[test] fn test_bip86_template() { - let prvkey = bitcoin::bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap(); + let prvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap(); check( Bip86(prvkey, KeychainKind::External).build(Network::Bitcoin), false, @@ -955,7 +955,7 @@ mod test { // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki #[test] 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(); check( Bip86Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin), diff --git a/crates/bdk/src/keys/bip39.rs b/crates/bdk/src/keys/bip39.rs index 8b09ac287..7158505f3 100644 --- a/crates/bdk/src/keys/bip39.rs +++ b/crates/bdk/src/keys/bip39.rs @@ -57,7 +57,7 @@ pub type MnemonicWithPassphrase = (Mnemonic, Option); #[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))] impl DerivableKey for Seed { fn into_extended_key(self) -> Result, KeyError> { - Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self[..])?.into()) + Ok(bip32::Xpriv::new_master(Network::Bitcoin, &self[..])?.into()) } fn into_descriptor_key( diff --git a/crates/bdk/src/keys/mod.rs b/crates/bdk/src/keys/mod.rs index 541d439a6..75abb3aa6 100644 --- a/crates/bdk/src/keys/mod.rs +++ b/crates/bdk/src/keys/mod.rs @@ -110,7 +110,7 @@ impl DescriptorKey { Ok((public, KeyMap::default(), valid_networks)) } DescriptorKey::Secret(secret, valid_networks, _) => { - let mut key_map = KeyMap::with_capacity(1); + let mut key_map = KeyMap::new(); let public = secret .to_public(secp) @@ -309,15 +309,15 @@ pub trait IntoDescriptorKey: Sized { /// Enum for extended keys that can be either `xprv` or `xpub` /// -/// An instance of [`ExtendedKey`] can be constructed from an [`ExtendedPrivKey`](bip32::ExtendedPrivKey) -/// or an [`ExtendedPubKey`](bip32::ExtendedPubKey) by using the `From` trait. +/// An instance of [`ExtendedKey`] can be constructed from an [`Xpriv`](bip32::Xpriv) +/// or an [`Xpub`](bip32::Xpub) by using the `From` trait. /// /// Defaults to the [`Legacy`](miniscript::Legacy) context. pub enum ExtendedKey { /// A private extended key, aka an `xprv` - Private((bip32::ExtendedPrivKey, PhantomData)), + Private((bip32::Xpriv, PhantomData)), /// A public extended key, aka an `xpub` - Public((bip32::ExtendedPubKey, PhantomData)), + Public((bip32::Xpub, PhantomData)), } impl ExtendedKey { @@ -329,9 +329,9 @@ impl ExtendedKey { } } - /// 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 - pub fn into_xprv(self, network: Network) -> Option { + pub fn into_xprv(self, network: Network) -> Option { match self { ExtendedKey::Private((mut xprv, _)) => { xprv.network = network; @@ -341,15 +341,15 @@ impl ExtendedKey { } } - /// Transform the [`ExtendedKey`] into an [`ExtendedPubKey`](bip32::ExtendedPubKey) for the + /// Transform the [`ExtendedKey`] into an [`Xpub`](bip32::Xpub) for the /// given [`Network`] pub fn into_xpub( self, network: bitcoin::Network, secp: &Secp256k1, - ) -> bip32::ExtendedPubKey { + ) -> bip32::Xpub { 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, }; @@ -358,14 +358,14 @@ impl ExtendedKey { } } -impl From for ExtendedKey { - fn from(xpub: bip32::ExtendedPubKey) -> Self { +impl From for ExtendedKey { + fn from(xpub: bip32::Xpub) -> Self { ExtendedKey::Public((xpub, PhantomData)) } } -impl From for ExtendedKey { - fn from(xprv: bip32::ExtendedPrivKey) -> Self { +impl From for ExtendedKey { + fn from(xprv: bip32::Xpriv) -> Self { ExtendedKey::Private((xprv, PhantomData)) } } @@ -383,8 +383,8 @@ impl From for ExtendedKey { /// /// ## Examples /// -/// Key types that can be directly converted into an [`ExtendedPrivKey`] or -/// an [`ExtendedPubKey`] can implement only the required `into_extended_key()` method. +/// Key types that can be directly converted into an [`Xpriv`] or +/// an [`Xpub`] can implement only the required `into_extended_key()` method. /// /// ``` /// use bdk::bitcoin; @@ -399,7 +399,7 @@ impl From for ExtendedKey { /// /// impl DerivableKey for MyCustomKeyType { /// fn into_extended_key(self) -> Result, KeyError> { -/// let xprv = bip32::ExtendedPrivKey { +/// let xprv = bip32::Xpriv { /// network: self.network, /// depth: 0, /// parent_fingerprint: bip32::Fingerprint::default(), @@ -415,7 +415,7 @@ impl From for ExtendedKey { /// /// 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 -/// [`ExtendedPrivKey`] or [`ExtendedPubKey`] will be considered valid. +/// [`Xpriv`] or [`Xpub`] will be considered valid. /// /// ``` /// use bdk::bitcoin; @@ -431,7 +431,7 @@ impl From for ExtendedKey { /// /// impl DerivableKey for MyCustomKeyType { /// fn into_extended_key(self) -> Result, KeyError> { -/// let xprv = bip32::ExtendedPrivKey { +/// let xprv = bip32::Xpriv { /// network: bitcoin::Network::Bitcoin, // pick an arbitrary network here /// depth: 0, /// parent_fingerprint: bip32::Fingerprint::default(), @@ -459,8 +459,8 @@ impl From for ExtendedKey { /// ``` /// /// [`DerivationPath`]: (bip32::DerivationPath) -/// [`ExtendedPrivKey`]: (bip32::ExtendedPrivKey) -/// [`ExtendedPubKey`]: (bip32::ExtendedPubKey) +/// [`Xpriv`]: (bip32::Xpriv) +/// [`Xpub`]: (bip32::Xpub) pub trait DerivableKey: Sized { /// Consume `self` and turn it into an [`ExtendedKey`] #[cfg_attr( @@ -520,13 +520,13 @@ impl DerivableKey for ExtendedKey { } } -impl DerivableKey for bip32::ExtendedPubKey { +impl DerivableKey for bip32::Xpub { fn into_extended_key(self) -> Result, KeyError> { Ok(self.into()) } } -impl DerivableKey for bip32::ExtendedPrivKey { +impl DerivableKey for bip32::Xpriv { fn into_extended_key(self) -> Result, KeyError> { Ok(self.into()) } @@ -670,7 +670,7 @@ where { } -impl GeneratableKey for bip32::ExtendedPrivKey { +impl GeneratableKey for bip32::Xpriv { type Entropy = [u8; 32]; type Options = (); @@ -681,7 +681,7 @@ impl GeneratableKey for bip32::ExtendedPrivKey { entropy: Self::Entropy, ) -> Result, Self::Error> { // 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())) } } @@ -971,7 +971,7 @@ pub mod test { #[test] fn test_keys_generate_xprv() { 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.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q"); diff --git a/crates/bdk/src/psbt/mod.rs b/crates/bdk/src/psbt/mod.rs index 260669175..7a66989e9 100644 --- a/crates/bdk/src/psbt/mod.rs +++ b/crates/bdk/src/psbt/mod.rs @@ -9,12 +9,12 @@ // You may not use this file except in accordance with one or both of these // licenses. -//! Additional functions on the `rust-bitcoin` `PartiallySignedTransaction` structure. +//! Additional functions on the `rust-bitcoin` `Psbt` structure. use alloc::vec::Vec; -use bitcoin::psbt::PartiallySignedTransaction as Psbt; use bitcoin::Amount; use bitcoin::FeeRate; +use bitcoin::Psbt; use bitcoin::TxOut; // TODO upstream the functions here to `rust-bitcoin`? @@ -29,7 +29,7 @@ pub trait PsbtUtils { fn fee_amount(&self) -> Option; /// 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. /// If the PSBT is missing a TxOut for an input returns None. fn fee_rate(&self) -> Option; @@ -54,8 +54,13 @@ impl PsbtUtils for Psbt { let utxos: Option> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect(); utxos.map(|inputs| { - let input_amount: u64 = inputs.iter().map(|i| i.value).sum(); - let output_amount: u64 = self.unsigned_tx.output.iter().map(|o| o.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.to_sat()) + .sum(); input_amount .checked_sub(output_amount) .expect("input amount must be greater than output amount") @@ -64,9 +69,7 @@ impl PsbtUtils for Psbt { fn fee_rate(&self) -> Option { let fee_amount = self.fee_amount(); - fee_amount.map(|fee| { - let weight = self.clone().extract_tx().weight(); - Amount::from_sat(fee) / weight - }) + let weight = self.clone().extract_tx().ok()?.weight(); + fee_amount.map(|fee| Amount::from_sat(fee) / weight) } } diff --git a/crates/bdk/src/wallet/coin_selection.rs b/crates/bdk/src/wallet/coin_selection.rs index b5bcecabb..49cb56c0c 100644 --- a/crates/bdk/src/wallet/coin_selection.rs +++ b/crates/bdk/src/wallet/coin_selection.rs @@ -52,9 +52,10 @@ //! .scan( //! (&mut selected_amount, &mut additional_weight), //! |(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( -//! (TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight) +//! (TxIn::default().segwit_weight().to_wu() +//! + weighted_utxo.satisfaction_weight as u64) //! as u64, //! ); //! Some(weighted_utxo.utxo) @@ -192,7 +193,7 @@ pub struct CoinSelectionResult { impl CoinSelectionResult { /// The total value of the inputs selected. 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. @@ -200,7 +201,7 @@ impl CoinSelectionResult { self.selected .iter() .filter_map(|u| match u { - Utxo::Local(_) => Some(u.txout().value), + Utxo::Local(_) => Some(u.txout().value.to_sat()), _ => None, }) .sum() @@ -344,11 +345,11 @@ fn select_sorted_utxos( if must_use || **selected_amount < target_amount + **fee_amount { **fee_amount += (fee_rate * 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(); - **selected_amount += weighted_utxo.utxo.txout().value; + **selected_amount += weighted_utxo.utxo.txout().value.to_sat(); Some(weighted_utxo.utxo) } else { None @@ -390,10 +391,10 @@ impl OutputGroup { fn new(weighted_utxo: WeightedUtxo, fee_rate: FeeRate) -> Self { let fee = (fee_rate * 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(); - 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 { weighted_utxo, fee, @@ -484,7 +485,7 @@ impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection { .chain(optional_utxos.iter()) .fold((0, 0), |(mut fees, mut value), utxo| { fees += utxo.fee; - value += utxo.weighted_utxo.utxo.txout().value; + value += utxo.weighted_utxo.utxo.txout().value.to_sat(); (fees, value) }); @@ -588,7 +589,7 @@ impl BranchAndBoundCoinSelection { // If we found a solution better than the previous one, or if there wasn't previous // solution, update the best solution if best_selection_value.is_none() || curr_value < best_selection_value.unwrap() { - best_selection = current_selection.clone(); + best_selection.clone_from(¤t_selection); best_selection_value = Some(curr_value); } @@ -742,7 +743,7 @@ mod test { use core::str::FromStr; use bdk_chain::ConfirmationTime; - use bitcoin::{Amount, OutPoint, ScriptBuf, TxIn, TxOut}; + use bitcoin::{Amount, ScriptBuf, TxIn, TxOut}; use super::*; use crate::types::*; @@ -770,7 +771,7 @@ mod test { utxo: Utxo::Local(LocalOutput { outpoint, txout: TxOut { - value, + value: Amount::from_sat(value), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, @@ -834,7 +835,7 @@ mod test { )) .unwrap(), txout: TxOut { - value: rng.gen_range(0..200000000), + value: Amount::from_sat(rng.gen_range(0..200000000)), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, @@ -865,7 +866,7 @@ mod test { )) .unwrap(), txout: TxOut { - value: utxos_value, + value: Amount::from_sat(utxos_value), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, @@ -882,7 +883,7 @@ mod test { utxos.shuffle(&mut rng); utxos[..utxos_picked_len] .iter() - .map(|u| u.utxo.txout().value) + .map(|u| u.utxo.txout().value.to_sat()) .sum() } @@ -1071,7 +1072,11 @@ mod test { fn test_oldest_first_coin_selection_insufficient_funds_high_fees() { let utxos = get_oldest_first_test_utxos(); - let target_amount: u64 = utxos.iter().map(|wu| wu.utxo.txout().value).sum::() - 50; + let target_amount: u64 = utxos + .iter() + .map(|wu| wu.utxo.txout().value.to_sat()) + .sum::() + - 50; let drain_script = ScriptBuf::default(); OldestFirstCoinSelection @@ -1166,9 +1171,9 @@ mod test { )); // 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); - 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); let drain_script = ScriptBuf::default(); @@ -1238,7 +1243,8 @@ mod test { assert_eq!(result.selected.len(), 1); 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 let result_feerate = Amount::from_sat(result.fee_amount) / Weight::from_wu(input_weight); assert_eq!(result_feerate, feerate); @@ -1460,9 +1466,9 @@ mod test { let utxos = get_test_utxos(); let drain_script = ScriptBuf::default(); - let (required, optional) = utxos - .into_iter() - .partition(|u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value < 1000)); + let (required, optional) = utxos.into_iter().partition( + |u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value.to_sat() < 1000), + ); let selection = BranchAndBoundCoinSelection::default().coin_select( required, @@ -1511,7 +1517,7 @@ mod test { utxo: Utxo::Local(LocalOutput { outpoint: OutPoint::new(bitcoin::hashes::Hash::hash(txid.as_bytes()), 0), txout: TxOut { - value, + value: Amount::from_sat(value), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, diff --git a/crates/bdk/src/wallet/export.rs b/crates/bdk/src/wallet/export.rs index f2d656891..50c91eb66 100644 --- a/crates/bdk/src/wallet/export.rs +++ b/crates/bdk/src/wallet/export.rs @@ -216,7 +216,7 @@ mod test { use bdk_chain::{BlockId, ConfirmationTime}; use bitcoin::hashes::Hash; - use bitcoin::{BlockHash, Network, Transaction}; + use bitcoin::{transaction, BlockHash, Network, Transaction}; use super::*; use crate::wallet::Wallet; @@ -230,7 +230,7 @@ mod test { let transaction = Transaction { input: vec![], output: vec![], - version: 0, + version: transaction::Version::non_standard(0), lock_time: bitcoin::absolute::LockTime::ZERO, }; wallet diff --git a/crates/bdk/src/wallet/hardwaresigner.rs b/crates/bdk/src/wallet/hardwaresigner.rs index 8b11e784a..5a210f64c 100644 --- a/crates/bdk/src/wallet/hardwaresigner.rs +++ b/crates/bdk/src/wallet/hardwaresigner.rs @@ -48,8 +48,8 @@ //! ``` use bitcoin::bip32::Fingerprint; -use bitcoin::psbt::PartiallySignedTransaction; use bitcoin::secp256k1::{All, Secp256k1}; +use bitcoin::Psbt; use hwi::error::Error; use hwi::types::{HWIChain, HWIDevice}; @@ -87,7 +87,7 @@ impl SignerCommon for HWISigner { impl TransactionSigner for HWISigner { fn sign_transaction( &self, - psbt: &mut PartiallySignedTransaction, + psbt: &mut Psbt, _sign_options: &crate::SignOptions, _secp: &crate::wallet::utils::SecpCtx, ) -> Result<(), SignerError> { diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index db252d3ae..846878823 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -30,14 +30,14 @@ use bdk_chain::{ Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut, IndexedTxGraph, Persist, PersistBackend, }; +use bitcoin::constants::genesis_block; use bitcoin::secp256k1::{All, Secp256k1}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::{ - absolute, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence, Transaction, - TxOut, Txid, Weight, Witness, + absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence, + Transaction, TxOut, Txid, Witness, }; -use bitcoin::{consensus::encode::serialize, BlockHash}; -use bitcoin::{constants::genesis_block, psbt}; +use bitcoin::{consensus::encode::serialize, transaction, Amount, BlockHash, Psbt}; use core::fmt; use core::ops::Deref; use descriptor::error::Error as DescriptorError; @@ -945,11 +945,11 @@ impl Wallet { /// ``` /// /// ```rust, no_run - /// # use bitcoin::psbt::PartiallySignedTransaction; + /// # use bitcoin::Psbt; /// # use bdk::Wallet; /// # let mut wallet: Wallet<()> = todo!(); - /// # let mut psbt: PartiallySignedTransaction = todo!(); - /// let tx = &psbt.clone().extract_tx(); + /// # let mut psbt: Psbt = todo!(); + /// let tx = &psbt.clone().extract_tx().expect("tx"); /// let fee = wallet.calculate_fee(tx).expect("fee"); /// ``` /// [`insert_txout`]: Self::insert_txout @@ -976,12 +976,12 @@ impl Wallet { /// ``` /// /// ```rust, no_run - /// # use bitcoin::psbt::PartiallySignedTransaction; + /// # use bitcoin::Psbt; /// # use bdk::Wallet; /// # let mut wallet: Wallet<()> = todo!(); - /// # let mut psbt: PartiallySignedTransaction = todo!(); - /// let tx = psbt.clone().extract_tx(); - /// let fee_rate = wallet.calculate_fee_rate(&tx).expect("fee rate"); + /// # let mut psbt: Psbt = todo!(); + /// let tx = &psbt.clone().extract_tx().expect("tx"); + /// let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate"); /// ``` /// [`insert_txout`]: Self::insert_txout pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result { @@ -1007,11 +1007,11 @@ impl Wallet { /// ``` /// /// ```rust, no_run - /// # use bitcoin::psbt::PartiallySignedTransaction; + /// # use bitcoin::Psbt; /// # use bdk::Wallet; /// # let mut wallet: Wallet<()> = todo!(); - /// # let mut psbt: PartiallySignedTransaction = todo!(); - /// let tx = &psbt.clone().extract_tx(); + /// # let mut psbt: Psbt = todo!(); + /// let tx = &psbt.clone().extract_tx().expect("tx"); /// let (sent, received) = wallet.sent_and_received(tx); /// ``` pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) { @@ -1261,7 +1261,7 @@ impl Wallet { &mut self, coin_selection: Cs, params: TxParams, - ) -> Result> + ) -> Result> where D: PersistBackend, { @@ -1455,7 +1455,7 @@ impl Wallet { }; let mut tx = Transaction { - version, + version: transaction::Version::non_standard(version), lock_time, input: vec![], output: vec![], @@ -1485,7 +1485,7 @@ impl Wallet { let new_out = TxOut { script_pubkey: script_pubkey.clone(), - value, + value: Amount::from_sat(value), }; tx.output.push(new_out); @@ -1495,17 +1495,6 @@ impl Wallet { 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 && internal_descriptor.is_none() { @@ -1594,7 +1583,7 @@ impl Wallet { // create drain output let drain_output = TxOut { - value: *amount, + value: Amount::from_sat(*amount), script_pubkey: drain_script, }; @@ -1640,7 +1629,7 @@ impl Wallet { /// builder.finish()? /// }; /// 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 /// let mut psbt = { /// let mut builder = wallet.build_fee_bump(tx.txid())?; @@ -1764,11 +1753,11 @@ impl Wallet { let params = TxParams { // 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 .output .into_iter() - .map(|txout| (txout.script_pubkey, txout.value)) + .map(|txout| (txout.script_pubkey, txout.value.to_sat())) .collect(), utxos: original_utxos, bumping_fee: Some(tx_builder::PreviousFee { @@ -1814,11 +1803,7 @@ impl Wallet { /// let finalized = wallet.sign(&mut psbt, SignOptions::default())?; /// assert!(finalized, "we should have signed all the inputs"); /// # Ok::<(),anyhow::Error>(()) - pub fn sign( - &self, - psbt: &mut psbt::PartiallySignedTransaction, - sign_options: SignOptions, - ) -> Result { + pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result { // This adds all the PSBT metadata for the inputs, which will help us later figure out how // to derive our keys self.update_psbt_with_descriptor(psbt) @@ -1898,7 +1883,7 @@ impl Wallet { /// The [`SignOptions`] can be used to tweak the behavior of the finalizer. pub fn finalize_psbt( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, sign_options: SignOptions, ) -> Result { let chain_tip = self.chain.tip().block_id(); @@ -2124,7 +2109,7 @@ impl Wallet { if must_only_use_confirmed_tx && !confirmation_time.is_confirmed() { return false; } - if tx.is_coin_base() { + if tx.is_coinbase() { debug_assert!( confirmation_time.is_confirmed(), "coinbase must always be confirmed" @@ -2173,11 +2158,11 @@ impl Wallet { tx: Transaction, selected: Vec, params: TxParams, - ) -> Result> + ) -> Result> where D: PersistBackend, { - let mut psbt = psbt::PartiallySignedTransaction::from_unsigned_tx(tx)?; + let mut psbt = Psbt::from_unsigned_tx(tx)?; if params.add_global_xpubs { let all_xpubs = self @@ -2233,7 +2218,7 @@ impl Wallet { let is_taproot = foreign_psbt_input .witness_utxo .as_ref() - .map(|txout| txout.script_pubkey.is_v1_p2tr()) + .map(|txout| txout.script_pubkey.is_p2tr()) .unwrap_or(false); if !is_taproot && !params.only_witness_utxo @@ -2295,10 +2280,7 @@ impl Wallet { Ok(psbt_input) } - fn update_psbt_with_descriptor( - &self, - psbt: &mut psbt::PartiallySignedTransaction, - ) -> Result<(), MiniscriptPsbtError> { + fn update_psbt_with_descriptor(&self, psbt: &mut Psbt) -> Result<(), MiniscriptPsbtError> { // We need to borrow `psbt` mutably within the loops, so we have to allocate a vec for all // the input utxos and outputs let utxos = (0..psbt.inputs.len()) @@ -2602,11 +2584,11 @@ macro_rules! doctest_wallet { .unwrap(); let address = wallet.get_address(AddressIndex::New).address; let tx = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 500_000, + value: Amount::from_sat(500_000), script_pubkey: address.script_pubkey(), }], }; diff --git a/crates/bdk/src/wallet/signer.rs b/crates/bdk/src/wallet/signer.rs index 38e51dfb2..4610657e2 100644 --- a/crates/bdk/src/wallet/signer.rs +++ b/crates/bdk/src/wallet/signer.rs @@ -19,13 +19,12 @@ //! # use core::str::FromStr; //! # use bitcoin::secp256k1::{Secp256k1, All}; //! # use bitcoin::*; -//! # use bitcoin::psbt; //! # use bdk::signer::*; //! # use bdk::*; //! # #[derive(Debug)] //! # struct 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(()) //! # } //! # fn connect() -> Self { @@ -55,7 +54,7 @@ //! impl InputSigner for CustomSigner { //! fn sign_input( //! &self, -//! psbt: &mut psbt::PartiallySignedTransaction, +//! psbt: &mut Psbt, //! input_index: usize, //! _sign_options: &SignOptions, //! _secp: &Secp256k1, @@ -87,13 +86,13 @@ use core::cmp::Ordering; use core::fmt; 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::secp256k1::Message; use bitcoin::sighash::{EcdsaSighashType, TapSighash, TapSighashType}; use bitcoin::{ecdsa, psbt, sighash, taproot}; use bitcoin::{key::TapTweak, key::XOnlyPublicKey, secp256k1}; -use bitcoin::{PrivateKey, PublicKey}; +use bitcoin::{PrivateKey, Psbt, PublicKey}; use miniscript::descriptor::{ Descriptor, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, @@ -264,7 +263,7 @@ pub trait InputSigner: SignerCommon { /// Sign a single psbt input fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -279,7 +278,7 @@ pub trait TransactionSigner: SignerCommon { /// Sign all the inputs of the psbt fn sign_transaction( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, sign_options: &SignOptions, secp: &SecpCtx, ) -> Result<(), SignerError>; @@ -288,7 +287,7 @@ pub trait TransactionSigner: SignerCommon { impl TransactionSigner for T { fn sign_transaction( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, sign_options: &SignOptions, secp: &SecpCtx, ) -> Result<(), SignerError> { @@ -300,7 +299,7 @@ impl TransactionSigner for T { } } -impl SignerCommon for SignerWrapper> { +impl SignerCommon for SignerWrapper> { fn id(&self, secp: &SecpCtx) -> SignerId { SignerId::from(self.root_fingerprint(secp)) } @@ -310,10 +309,10 @@ impl SignerCommon for SignerWrapper> { } } -impl InputSigner for SignerWrapper> { +impl InputSigner for SignerWrapper> { fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -396,7 +395,7 @@ fn multikey_to_xkeys( .collect() } -impl SignerCommon for SignerWrapper> { +impl SignerCommon for SignerWrapper> { fn id(&self, secp: &SecpCtx) -> SignerId { SignerId::from(self.root_fingerprint(secp)) } @@ -406,10 +405,10 @@ impl SignerCommon for SignerWrapper> { } } -impl InputSigner for SignerWrapper> { +impl InputSigner for SignerWrapper> { fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -438,7 +437,7 @@ impl SignerCommon for SignerWrapper { impl InputSigner for SignerWrapper { fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -577,7 +576,7 @@ fn sign_psbt_schnorr( hash_ty: TapSighashType, 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 { None => keypair .tap_tweak(secp, psbt_input.tap_merkle_root) @@ -852,7 +851,7 @@ pub(crate) trait ComputeSighash { type SighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &Psbt, input_index: usize, extra: Self::Extra, ) -> Result<(Self::Sighash, Self::SighashType), SignerError>; @@ -864,7 +863,7 @@ impl ComputeSighash for Legacy { type SighashType = EcdsaSighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &Psbt, input_index: usize, _extra: (), ) -> Result<(Self::Sighash, Self::SighashType), SignerError> { @@ -913,7 +912,7 @@ impl ComputeSighash for Segwitv0 { type SighashType = EcdsaSighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &Psbt, input_index: usize, _extra: (), ) -> Result<(Self::Sighash, Self::SighashType), SignerError> { @@ -924,7 +923,7 @@ impl ComputeSighash for Segwitv0 { let psbt_input = &psbt.inputs[input_index]; let tx_input = &psbt.unsigned_tx.input[input_index]; - let sighash = psbt_input + let sighash_type = psbt_input .sighash_type .unwrap_or_else(|| EcdsaSighashType::All.into()) .ecdsa_hash_ty() @@ -952,40 +951,39 @@ impl ComputeSighash for Segwitv0 { }; let value = utxo.value; - let script = match psbt_input.witness_script { - Some(ref witness_script) => witness_script.clone(), + let mut sighasher = sighash::SighashCache::new(&psbt.unsigned_tx); + + let sighash = match psbt_input.witness_script { + Some(ref witness_script) => { + sighasher.p2wsh_signature_hash(input_index, witness_script, value, sighash_type)? + } None => { - if utxo.script_pubkey.is_v0_p2wpkh() { - utxo.script_pubkey - .p2wpkh_script_code() - .expect("We check above that the spk is a p2wpkh") + if utxo.script_pubkey.is_p2wpkh() { + sighasher.p2wpkh_signature_hash( + input_index, + &utxo.script_pubkey, + value, + sighash_type, + )? } else if psbt_input .redeem_script .as_ref() - .map(|s| s.is_v0_p2wpkh()) + .map(|s| s.is_p2wpkh()) .unwrap_or(false) { - psbt_input - .redeem_script - .as_ref() - .unwrap() - .p2wpkh_script_code() - .expect("We check above that the spk is a p2wpkh") + let script_pubkey = psbt_input.redeem_script.as_ref().unwrap(); + sighasher.p2wpkh_signature_hash( + input_index, + script_pubkey, + value, + sighash_type, + )? } else { return Err(SignerError::MissingWitnessScript); } } }; - - Ok(( - sighash::SighashCache::new(&psbt.unsigned_tx).segwit_signature_hash( - input_index, - &script, - value, - sighash, - )?, - sighash, - )) + Ok((sighash, sighash_type)) } } @@ -995,7 +993,7 @@ impl ComputeSighash for Tap { type SighashType = TapSighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &Psbt, input_index: usize, extra: Self::Extra, ) -> Result<(Self::Sighash, TapSighashType), SignerError> { @@ -1166,7 +1164,7 @@ mod signers_container_tests { impl TransactionSigner for DummySigner { fn sign_transaction( &self, - _psbt: &mut psbt::PartiallySignedTransaction, + _psbt: &mut Psbt, _sign_options: &SignOptions, _secp: &SecpCtx, ) -> Result<(), SignerError> { @@ -1184,8 +1182,8 @@ mod signers_container_tests { ) -> (DescriptorKey, DescriptorKey, Fingerprint) { let secp: Secp256k1 = Secp256k1::new(); let path = bip32::DerivationPath::from_str(PATH).unwrap(); - let tprv = bip32::ExtendedPrivKey::from_str(tprv).unwrap(); - let tpub = bip32::ExtendedPubKey::from_priv(&secp, &tprv); + let tprv = bip32::Xpriv::from_str(tprv).unwrap(); + let tpub = bip32::Xpub::from_priv(&secp, &tprv); let fingerprint = tprv.fingerprint(&secp); let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap(); let pubkey = (tpub, path).into_descriptor_key().unwrap(); diff --git a/crates/bdk/src/wallet/tx_builder.rs b/crates/bdk/src/wallet/tx_builder.rs index 74bc081c5..4009dab1a 100644 --- a/crates/bdk/src/wallet/tx_builder.rs +++ b/crates/bdk/src/wallet/tx_builder.rs @@ -46,7 +46,7 @@ use core::fmt; use core::marker::PhantomData; use bdk_chain::PersistBackend; -use bitcoin::psbt::{self, PartiallySignedTransaction as Psbt}; +use bitcoin::psbt::{self, Psbt}; use bitcoin::script::PushBytes; use bitcoin::{absolute, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid}; @@ -927,7 +927,8 @@ mod test { use bdk_chain::ConfirmationTime; use bitcoin::consensus::deserialize; - use bitcoin::hashes::hex::FromHex; + use bitcoin::hex::FromHex; + use bitcoin::TxOut; use super::*; @@ -998,7 +999,7 @@ mod test { .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[2].script_pubkey, @@ -1015,7 +1016,7 @@ mod test { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), vout: 0, }, - txout: Default::default(), + txout: TxOut::NULL, keychain: KeychainKind::External, is_spent: false, confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, @@ -1026,7 +1027,7 @@ mod test { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), vout: 1, }, - txout: Default::default(), + txout: TxOut::NULL, keychain: KeychainKind::Internal, is_spent: false, confirmation_time: ConfirmationTime::Confirmed { diff --git a/crates/bdk/src/wallet/utils.rs b/crates/bdk/src/wallet/utils.rs index 71e24950b..208a88dfe 100644 --- a/crates/bdk/src/wallet/utils.rs +++ b/crates/bdk/src/wallet/utils.rs @@ -138,7 +138,7 @@ mod test { .require_network(Network::Bitcoin) .unwrap() .script_pubkey(); - assert!(script_p2wpkh.is_v0_p2wpkh()); + assert!(script_p2wpkh.is_p2wpkh()); assert!(293.is_dust(&script_p2wpkh)); assert!(!294.is_dust(&script_p2wpkh)); } diff --git a/crates/bdk/tests/common.rs b/crates/bdk/tests/common.rs index b4012286b..0598e9f1a 100644 --- a/crates/bdk/tests/common.rs +++ b/crates/bdk/tests/common.rs @@ -4,7 +4,10 @@ use bdk::{wallet::AddressIndex, KeychainKind, LocalOutput, Wallet}; use bdk_chain::indexed_tx_graph::Indexer; use bdk_chain::{BlockId, ConfirmationTime}; 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; // Return a fake wallet that appears to be funded for testing. @@ -24,7 +27,7 @@ pub fn get_funded_wallet_with_change( .unwrap(); let tx0 = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: bitcoin::absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { @@ -36,13 +39,13 @@ pub fn get_funded_wallet_with_change( witness: Default::default(), }], output: vec![TxOut { - value: 76_000, + value: Amount::from_sat(76_000), script_pubkey: change_address.script_pubkey(), }], }; let tx1 = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: bitcoin::absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { @@ -55,11 +58,11 @@ pub fn get_funded_wallet_with_change( }], output: vec![ TxOut { - value: 50_000, + value: Amount::from_sat(50_000), script_pubkey: change_address.script_pubkey(), }, TxOut { - value: 25_000, + value: Amount::from_sat(25_000), script_pubkey: sendto_address.script_pubkey(), }, ], diff --git a/crates/bdk/tests/psbt.rs b/crates/bdk/tests/psbt.rs index e7dd64426..24dc38c1f 100644 --- a/crates/bdk/tests/psbt.rs +++ b/crates/bdk/tests/psbt.rs @@ -1,9 +1,7 @@ -use bdk::bitcoin::FeeRate; -use bdk::bitcoin::TxIn; +use bdk::bitcoin::{Amount, FeeRate, Psbt, TxIn}; use bdk::wallet::AddressIndex; use bdk::wallet::AddressIndex::New; use bdk::{psbt, SignOptions}; -use bitcoin::psbt::PartiallySignedTransaction as Psbt; use core::str::FromStr; mod common; use common::*; @@ -163,7 +161,7 @@ fn test_psbt_multiple_internalkey_signers() { use bdk::signer::{SignerContext, SignerOrdering, SignerWrapper}; use bdk::KeychainKind; 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::{PrivateKey, TxOut}; use std::sync::Arc; @@ -172,7 +170,7 @@ fn test_psbt_multiple_internalkey_signers() { let wif = "cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG"; let desc = format!("tr({})", wif); 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 to_spend = wallet.get_balance().total(); @@ -205,7 +203,7 @@ fn test_psbt_multiple_internalkey_signers() { // the prevout we're spending let prevouts = &[TxOut { script_pubkey: send_to.script_pubkey(), - value: to_spend, + value: Amount::from_sat(to_spend), }]; let prevouts = Prevouts::All(prevouts); let input_index = 0; diff --git a/crates/bdk/tests/wallet.rs b/crates/bdk/tests/wallet.rs index 49c1bc9c3..68ef541b9 100644 --- a/crates/bdk/tests/wallet.rs +++ b/crates/bdk/tests/wallet.rs @@ -18,8 +18,8 @@ use bitcoin::script::PushBytesBuf; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::taproot::TapNodeHash; use bitcoin::{ - absolute, Address, Amount, BlockHash, FeeRate, Network, OutPoint, ScriptBuf, Sequence, - Transaction, TxIn, TxOut, Txid, Weight, + absolute, transaction, Address, Amount, BlockHash, FeeRate, Network, OutPoint, ScriptBuf, + Sequence, Transaction, TxIn, TxOut, Txid, Weight, }; mod common; @@ -27,12 +27,12 @@ use common::*; fn receive_output(wallet: &mut Wallet, value: u64, height: ConfirmationTime) -> OutPoint { let tx = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { 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); for (op, txo) in txos { if op.txid == txid { - assert_eq!(txo.txout.value, 50_000); + assert_eq!(txo.txout.value.to_sat(), 50_000); assert!(!txo.is_spent); } else { - assert_eq!(txo.txout.value, 76_000); + assert_eq!(txo.txout.value.to_sat(), 76_000); 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 )* )* ) => ({ let psbt = $psbt.clone(); #[allow(unused_mut)] - let mut tx = $psbt.clone().extract_tx(); + let mut tx = $psbt.clone().extract_tx().expect("failed to extract tx"); $( $( $add_signature )* for txin in &mut tx.input { @@ -297,12 +297,12 @@ macro_rules! assert_fee_rate { let fee_amount = psbt .inputs .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 .unsigned_tx .output .iter() - .fold(0, |acc, o| acc + o.value); + .fold(0, |acc, o| acc + o.value.to_sat()); assert_eq!(fee_amount, $fees); @@ -383,7 +383,7 @@ fn test_create_tx_custom_version() { .version(42); let psbt = builder.finish().unwrap(); - assert_eq!(psbt.unsigned_tx.version, 42); + assert_eq!(psbt.unsigned_tx.version.0, 42); } #[test] @@ -570,7 +570,7 @@ fn test_create_tx_change_policy_no_internal() { macro_rules! check_fee { ($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(); assert_eq!(tx_fee, $psbt.fee_amount()); tx_fee @@ -587,7 +587,10 @@ fn test_create_tx_drain_wallet_and_drain_to() { let fee = check_fee!(wallet, psbt); 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] @@ -615,8 +618,8 @@ fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() { .iter() .find(|x| x.script_pubkey == drain_addr.script_pubkey()) .unwrap(); - assert_eq!(main_output.value, 20_000,); - assert_eq!(drain_output.value, 30_000 - fee.unwrap_or(0)); + assert_eq!(main_output.value.to_sat(), 20_000,); + assert_eq!(drain_output.value.to_sat(), 30_000 - fee.unwrap_or(0)); } #[test] @@ -633,7 +636,10 @@ fn test_create_tx_drain_to_and_utxos() { let fee = check_fee!(wallet, psbt); 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] @@ -686,7 +692,10 @@ fn test_create_tx_absolute_fee() { assert_eq!(fee.unwrap_or(0), 100); 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] @@ -703,7 +712,10 @@ fn test_create_tx_absolute_zero_fee() { assert_eq!(fee.unwrap_or(0), 0); 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] @@ -733,8 +745,11 @@ fn test_create_tx_add_change() { let fee = check_fee!(wallet, psbt); assert_eq!(psbt.unsigned_tx.output.len(), 2); - assert_eq!(psbt.unsigned_tx.output[0].value, 25_000); - assert_eq!(psbt.unsigned_tx.output[1].value, 25_000 - fee.unwrap_or(0)); + assert_eq!(psbt.unsigned_tx.output[0].value.to_sat(), 25_000); + assert_eq!( + psbt.unsigned_tx.output[1].value.to_sat(), + 25_000 - fee.unwrap_or(0) + ); } #[test] @@ -747,7 +762,7 @@ fn test_create_tx_skip_change_dust() { let fee = check_fee!(wallet, psbt); 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); } @@ -778,9 +793,12 @@ fn test_create_tx_ordering_respected() { let fee = check_fee!(wallet, psbt); assert_eq!(psbt.unsigned_tx.output.len(), 3); - assert_eq!(psbt.unsigned_tx.output[0].value, 10_000 - fee.unwrap_or(0)); - assert_eq!(psbt.unsigned_tx.output[1].value, 10_000); - assert_eq!(psbt.unsigned_tx.output[2].value, 30_000); + assert_eq!( + psbt.unsigned_tx.output[0].value.to_sat(), + 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] @@ -856,7 +874,7 @@ fn test_create_tx_output_hd_keypaths() { #[test] fn test_create_tx_set_redeem_script_p2sh() { - use bitcoin::hashes::hex::FromHex; + use bitcoin::hex::FromHex; let (mut wallet, _) = get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))"); @@ -879,7 +897,7 @@ fn test_create_tx_set_redeem_script_p2sh() { #[test] fn test_create_tx_set_witness_script_p2wsh() { - use bitcoin::hashes::hex::FromHex; + use bitcoin::hex::FromHex; let (mut wallet, _) = get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))"); @@ -914,7 +932,7 @@ fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() { ) .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)); } @@ -978,10 +996,10 @@ fn test_create_tx_add_utxo() { let small_output_tx = Transaction { input: vec![], output: vec![TxOut { - value: 25_000, + value: Amount::from_sat(25_000), script_pubkey: wallet.get_address(New).address.script_pubkey(), }], - version: 0, + version: transaction::Version::non_standard(0), lock_time: absolute::LockTime::ZERO, }; wallet @@ -1003,7 +1021,8 @@ fn test_create_tx_add_utxo() { }) .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!( psbt.unsigned_tx.input.len(), @@ -1023,10 +1042,10 @@ fn test_create_tx_manually_selected_insufficient() { let small_output_tx = Transaction { input: vec![], output: vec![TxOut { - value: 25_000, + value: Amount::from_sat(25_000), script_pubkey: wallet.get_address(New).address.script_pubkey(), }], - version: 0, + version: transaction::Version::non_standard(0), 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 tx = Transaction { - version: 0, + version: transaction::Version::non_standard(0), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 50_000, + value: Amount::from_sat(50_000), script_pubkey: wallet.get_address(New).script_pubkey(), }], }; @@ -1145,7 +1164,7 @@ fn test_create_tx_policy_path_ignored_subtree_with_csv() { #[test] fn test_create_tx_global_xpubs_with_origin() { 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 addr = wallet.get_address(New); @@ -1155,7 +1174,7 @@ fn test_create_tx_global_xpubs_with_origin() { .add_global_xpubs(); 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 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(); wallet1.insert_txout(utxo.outpoint, utxo.txout); 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!( 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) .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(); } @@ -1421,7 +1441,7 @@ fn test_create_tx_global_xpubs_origin_missing() { #[test] fn test_create_tx_global_xpubs_master_without_origin() { use bitcoin::bip32; - use bitcoin::hashes::hex::FromHex; + use bitcoin::hex::FromHex; let (mut wallet, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)"); let addr = wallet.get_address(New); @@ -1431,7 +1451,7 @@ fn test_create_tx_global_xpubs_master_without_origin() { .add_global_xpubs(); 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(); assert_eq!(psbt.xpub.len(), 1); @@ -1450,7 +1470,7 @@ fn test_bump_fee_irreplaceable_tx() { builder.add_recipient(addr.script_pubkey(), 25_000); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx().expect("failed to extract tx"); let txid = tx.txid(); wallet .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); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx().expect("failed to extract tx"); let txid = tx.txid(); wallet @@ -1494,7 +1514,7 @@ fn test_bump_fee_low_fee_rate() { let psbt = builder.finish().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(); wallet @@ -1527,7 +1547,7 @@ fn test_bump_fee_low_abs() { .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx().expect("failed to extract tx"); let txid = tx.txid(); wallet @@ -1550,7 +1570,7 @@ fn test_bump_fee_zero_abs() { .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx().expect("failed to extract tx"); let txid = tx.txid(); wallet .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) .enable_rbf(); 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 tx = psbt.extract_tx(); + let tx = psbt.extract_tx().expect("failed to extract tx"); let txid = tx.txid(); wallet .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(); builder.fee_rate(feerate).enable_rbf(); 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); 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()) .unwrap() .value, - 25_000 + Amount::from_sat(25_000) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), sent_received.1 ); @@ -1620,7 +1643,8 @@ fn test_bump_fee_reduce_change() { builder.fee_absolute(200); builder.enable_rbf(); 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); 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()) .unwrap() .value, - 25_000 + Amount::from_sat(25_000) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), sent_received.1 ); @@ -1669,7 +1694,7 @@ fn test_bump_fee_reduce_single_recipient() { .drain_wallet() .enable_rbf(); 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_fee = check_fee!(wallet, psbt); let txid = tx.txid(); @@ -1684,7 +1709,8 @@ fn test_bump_fee_reduce_single_recipient() { .allow_shrinking(addr.script_pubkey()) .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); 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; 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); } @@ -1710,7 +1739,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() { .enable_rbf(); let psbt = builder.finish().unwrap(); 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 txid = tx.txid(); wallet @@ -1731,7 +1760,10 @@ fn test_bump_fee_absolute_reduce_single_recipient() { assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); 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); } @@ -1741,11 +1773,11 @@ fn test_bump_fee_drain_wallet() { let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); // receive an extra tx so that our wallet has two utxos. let tx = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 25_000, + value: Amount::from_sat(25_000), script_pubkey: wallet.get_address(New).script_pubkey(), }], }; @@ -1773,7 +1805,7 @@ fn test_bump_fee_drain_wallet() { .manually_selected_only() .enable_rbf(); 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 txid = tx.txid(); @@ -1791,7 +1823,7 @@ fn test_bump_fee_drain_wallet() { .unwrap() .fee_rate(FeeRate::from_sat_per_vb_unchecked(5)); 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); } @@ -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 // unless you've also set "allow_shrinking" OR there is a change output. let init_tx = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { script_pubkey: wallet.get_address(New).script_pubkey(), - value: 25_000, + value: Amount::from_sat(25_000), }], }; wallet @@ -1841,7 +1873,7 @@ fn test_bump_fee_remove_output_manually_selected_only() { .manually_selected_only() .enable_rbf(); 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 txid = tx.txid(); wallet @@ -1860,12 +1892,12 @@ fn test_bump_fee_remove_output_manually_selected_only() { fn test_bump_fee_add_input() { let (mut wallet, _) = get_funded_wallet(get_test_wpkh()); let init_tx = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { script_pubkey: wallet.get_address(New).script_pubkey(), - value: 25_000, + value: Amount::from_sat(25_000), }], }; let pos = wallet @@ -1885,7 +1917,7 @@ fn test_bump_fee_add_input() { .add_recipient(addr.script_pubkey(), 45_000) .enable_rbf(); 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 txid = tx.txid(); wallet @@ -1895,7 +1927,8 @@ fn test_bump_fee_add_input() { let mut builder = wallet.build_fee_bump(txid).unwrap(); builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50)); 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); assert_eq!(sent_received.0, original_details.0 + 25_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()) .unwrap() .value, - 45_000 + Amount::from_sat(45_000) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), sent_received.1 ); @@ -1935,7 +1969,7 @@ fn test_bump_fee_absolute_add_input() { .add_recipient(addr.script_pubkey(), 45_000) .enable_rbf(); 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 txid = tx.txid(); wallet @@ -1945,7 +1979,8 @@ fn test_bump_fee_absolute_add_input() { let mut builder = wallet.build_fee_bump(txid).unwrap(); builder.fee_absolute(6_000); 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); 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()) .unwrap() .value, - 45_000 + Amount::from_sat(45_000) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), sent_received.1 ); @@ -1991,10 +2027,11 @@ fn test_bump_fee_no_change_add_input_and_change() { .manually_selected_only() .enable_rbf(); 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 tx = psbt.extract_tx(); + let tx = psbt.extract_tx().expect("failed to extract tx"); let txid = tx.txid(); wallet .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(); builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50)); 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 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()) .unwrap() .value, - original_send_all_amount + Amount::from_sat(original_send_all_amount) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), 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) .enable_rbf(); 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 mut tx = psbt.extract_tx(); + let mut tx = psbt.extract_tx().expect("failed to extract tx"); for txin in &mut tx.input { 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; builder.fee_rate(Amount::from_sat(fee_abs) / new_tx_weight); 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); 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()) .unwrap() .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); @@ -2119,7 +2160,7 @@ fn test_bump_fee_force_add_input() { .add_recipient(addr.script_pubkey(), 45_000) .enable_rbf(); 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 txid = tx.txid(); for txin in &mut tx.input { @@ -2136,7 +2177,8 @@ fn test_bump_fee_force_add_input() { .unwrap() .fee_rate(FeeRate::from_sat_per_vb_unchecked(5)); 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); 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()) .unwrap() .value, - 45_000 + Amount::from_sat(45_000) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), sent_received.1 ); @@ -2178,7 +2221,7 @@ fn test_bump_fee_absolute_force_add_input() { .add_recipient(addr.script_pubkey(), 45_000) .enable_rbf(); 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 txid = tx.txid(); // 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(); builder.add_utxo(incoming_op).unwrap().fee_absolute(250); 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); 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()) .unwrap() .value, - 45_000 + Amount::from_sat(45_000) ); assert_eq!( tx.output .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_sat(), sent_received.1 ); @@ -2249,7 +2294,7 @@ fn test_bump_fee_unconfirmed_inputs_only() { 25_000, 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(); for txin in &mut tx.input { 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()) .enable_rbf(); 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(); for txin in &mut tx.input { 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(); 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); } @@ -2356,7 +2401,7 @@ fn test_sign_single_xprv_with_master_fingerprint_and_path() { let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); 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); } @@ -2371,7 +2416,7 @@ fn test_sign_single_xprv_bip44_path() { let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); 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); } @@ -2386,7 +2431,7 @@ fn test_sign_single_xprv_sh_wpkh() { let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); 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); } @@ -2402,7 +2447,7 @@ fn test_sign_single_wif() { let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); 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); } @@ -2420,7 +2465,7 @@ fn test_sign_single_xprv_no_hd_keypaths() { let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); 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); } @@ -2458,7 +2503,7 @@ fn test_signing_only_one_of_multiple_inputs() { // add another input to the psbt that is at least passable. let dud_input = bitcoin::psbt::Input { witness_utxo: Some(TxOut { - value: 100_000, + value: Amount::from_sat(100_000), script_pubkey: miniscript::Descriptor::::from_str( "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)", ) @@ -2591,7 +2636,7 @@ fn test_sign_nonstandard_sighash() { "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!( *extracted.input[0].witness.to_vec()[0].last().unwrap(), sighash.to_u32() as u8, @@ -2762,7 +2807,7 @@ fn test_sending_to_bip350_bech32m_address() { #[test] fn test_get_address() { 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( Bip84(key, KeychainKind::External), Some(Bip84(key, KeychainKind::Internal)), @@ -2813,7 +2858,7 @@ fn test_get_address_no_reuse_single_descriptor() { use bdk::descriptor::template::Bip84; 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 = 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] fn test_taproot_psbt_input_tap_tree() { - use bitcoin::hashes::hex::FromHex; + use bitcoin::hex::FromHex; use bitcoin::taproot; 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) .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); 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" ); - let extracted = psbt.extract_tx(); + let extracted = psbt.extract_tx().expect("failed to extract tx"); assert_eq!( *extracted.input[0].witness.to_vec()[0].last().unwrap(), sighash as u8, @@ -3417,14 +3463,14 @@ fn test_spend_coinbase() { }) .unwrap(); let coinbase_tx = Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], output: vec![TxOut { - value: 25_000, + value: Amount::from_sat(25_000), script_pubkey: wallet.get_address(New).address.script_pubkey(), }], }; @@ -3686,7 +3732,7 @@ fn test_tx_cancellation() { .unwrap(); 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 change_derivation_3 = psbt3 @@ -3706,7 +3752,7 @@ fn test_tx_cancellation() { .unwrap(); 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 change_derivation_4 = psbt3 diff --git a/crates/bitcoind_rpc/Cargo.toml b/crates/bitcoind_rpc/Cargo.toml index cc1acadc6..387c01af7 100644 --- a/crates/bitcoind_rpc/Cargo.toml +++ b/crates/bitcoind_rpc/Cargo.toml @@ -14,8 +14,8 @@ readme = "README.md" [dependencies] # For no-std, remember to enable the bitcoin/no-std feature -bitcoin = { version = "0.30", default-features = false } -bitcoincore-rpc = { version = "0.17" } +bitcoin = { version = "0.31", default-features = false } +bitcoincore-rpc = { version = "0.18" } bdk_chain = { path = "../chain", version = "0.11", default-features = false } [dev-dependencies] diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index 97946da99..f2e2a5d59 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -350,7 +350,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { .rpc_client() .get_new_address(None, None)? .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)?; // setup receiver diff --git a/crates/chain/Cargo.toml b/crates/chain/Cargo.toml index 6c5a59915..8328d6174 100644 --- a/crates/chain/Cargo.toml +++ b/crates/chain/Cargo.toml @@ -14,12 +14,12 @@ readme = "README.md" [dependencies] # 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"] } # Use hashbrown as a feature flag to have HashSet and HashMap from it. 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] rand = "0.8" diff --git a/crates/chain/src/spk_txout_index.rs b/crates/chain/src/spk_txout_index.rs index 90ee7dcab..24d06d123 100644 --- a/crates/chain/src/spk_txout_index.rs +++ b/crates/chain/src/spk_txout_index.rs @@ -4,7 +4,7 @@ use crate::{ collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap}, 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. /// @@ -281,12 +281,12 @@ impl SpkTxOutIndex { for txin in &tx.input { if let Some((_, txout)) = self.txout(txin.previous_output) { - sent += txout.value; + sent += txout.value.to_sat(); } } for txout in &tx.output { if self.index_of_spk(&txout.script_pubkey).is_some() { - received += txout.value; + received += txout.value.to_sat(); } } diff --git a/crates/chain/src/tx_graph.rs b/crates/chain/src/tx_graph.rs index d951d2d31..b0759adbf 100644 --- a/crates/chain/src/tx_graph.rs +++ b/crates/chain/src/tx_graph.rs @@ -319,7 +319,7 @@ impl TxGraph { /// /// [`insert_txout`]: Self::insert_txout pub fn calculate_fee(&self, tx: &Transaction) -> Result { - if tx.is_coin_base() { + if tx.is_coinbase() { return Ok(0); } @@ -331,7 +331,7 @@ impl TxGraph { (sum, missing_outpoints) } Some(txout) => { - sum += txout.value as i64; + sum += txout.value.to_sat() as i64; (sum, missing_outpoints) } }, @@ -343,7 +343,7 @@ impl TxGraph { let outputs_sum = tx .output .iter() - .map(|txout| txout.value as i64) + .map(|txout| txout.value.to_sat() as i64) .sum::(); let fee = inputs_sum - outputs_sum; @@ -807,7 +807,7 @@ impl TxGraph { TxNodeInternal::Whole(tx) => { // A coinbase tx that is not anchored in the best chain cannot be unconfirmed and // should always be filtered out. - if tx.as_ref().is_coin_base() { + if tx.is_coinbase() { return Ok(None); } tx.clone() @@ -1063,7 +1063,7 @@ impl TxGraph { txout, chain_position, 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 TxGraph { match &txout.chain_position { ChainPosition::Confirmed(_) => { 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) { - immature += txout.txout.value; + immature += txout.txout.value.to_sat(); } } ChainPosition::Unconfirmed(_) => { if trust_predicate(&spk_i, &txout.txout.script_pubkey) { - trusted_pending += txout.txout.value; + trusted_pending += txout.txout.value.to_sat(); } else { - untrusted_pending += txout.txout.value; + untrusted_pending += txout.txout.value.to_sat(); } } } diff --git a/crates/chain/tests/common/mod.rs b/crates/chain/tests/common/mod.rs index 7cc3f57a9..6116484ce 100644 --- a/crates/chain/tests/common/mod.rs +++ b/crates/chain/tests/common/mod.rs @@ -70,7 +70,7 @@ macro_rules! changeset { #[allow(unused)] pub fn new_tx(lt: u32) -> bitcoin::Transaction { bitcoin::Transaction { - version: 0x00, + version: bitcoin::transaction::Version::non_standard(0x00), lock_time: bitcoin::absolute::LockTime::from_consensus(lt), input: vec![], output: vec![], diff --git a/crates/chain/tests/common/tx_template.rs b/crates/chain/tests/common/tx_template.rs index ec2eb1159..fab12c1c2 100644 --- a/crates/chain/tests/common/tx_template.rs +++ b/crates/chain/tests/common/tx_template.rs @@ -3,8 +3,8 @@ use std::collections::HashMap; use bdk_chain::{tx_graph::TxGraph, Anchor, SpkTxOutIndex}; use bitcoin::{ - locktime::absolute::LockTime, secp256k1::Secp256k1, OutPoint, ScriptBuf, Sequence, Transaction, - TxIn, TxOut, Txid, Witness, + locktime::absolute::LockTime, secp256k1::Secp256k1, transaction, Amount, OutPoint, ScriptBuf, + Sequence, Transaction, TxIn, TxOut, Txid, Witness, }; 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() { let tx = Transaction { - version: 0, + version: transaction::Version::non_standard(0), lock_time: LockTime::ZERO, input: tx_tmp .inputs @@ -111,11 +111,11 @@ pub fn init_graph<'a, A: Anchor + Clone + 'a>( .iter() .map(|output| match &output.spk_index { None => TxOut { - value: output.value, + value: Amount::from_sat(output.value), script_pubkey: ScriptBuf::new(), }, Some(index) => TxOut { - value: output.value, + value: Amount::from_sat(output.value), script_pubkey: spk_index.spk_at_index(index).unwrap().to_owned(), }, }) diff --git a/crates/chain/tests/test_indexed_tx_graph.rs b/crates/chain/tests/test_indexed_tx_graph.rs index 8a56db175..1c8bf398b 100644 --- a/crates/chain/tests/test_indexed_tx_graph.rs +++ b/crates/chain/tests/test_indexed_tx_graph.rs @@ -9,7 +9,9 @@ use bdk_chain::{ local_chain::LocalChain, 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; /// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented @@ -35,11 +37,11 @@ fn insert_relevant_txs() { let tx_a = Transaction { output: vec![ TxOut { - value: 10_000, + value: Amount::from_sat(10_000), script_pubkey: spk_0, }, TxOut { - value: 20_000, + value: Amount::from_sat(20_000), script_pubkey: spk_1, }, ], @@ -154,7 +156,7 @@ fn test_list_owned_txouts() { ..Default::default() }], output: vec![TxOut { - value: 70000, + value: Amount::from_sat(70000), script_pubkey: trusted_spks[0].to_owned(), }], ..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. let tx2 = Transaction { output: vec![TxOut { - value: 30000, + value: Amount::from_sat(30000), script_pubkey: untrusted_spks[0].to_owned(), }], ..common::new_tx(0) @@ -176,7 +178,7 @@ fn test_list_owned_txouts() { ..Default::default() }], output: vec![TxOut { - value: 10000, + value: Amount::from_sat(10000), script_pubkey: trusted_spks[1].to_owned(), }], ..common::new_tx(0) @@ -185,7 +187,7 @@ fn test_list_owned_txouts() { // tx4 is an external transaction receiving at untrusted keychain, unconfirmed. let tx4 = Transaction { output: vec![TxOut { - value: 20000, + value: Amount::from_sat(20000), script_pubkey: untrusted_spks[1].to_owned(), }], ..common::new_tx(0) @@ -194,7 +196,7 @@ fn test_list_owned_txouts() { // tx5 is spending tx3 and receiving change at trusted keychain, unconfirmed. let tx5 = Transaction { output: vec![TxOut { - value: 15000, + value: Amount::from_sat(15000), script_pubkey: trusted_spks[2].to_owned(), }], ..common::new_tx(0) diff --git a/crates/chain/tests/test_keychain_txout_index.rs b/crates/chain/tests/test_keychain_txout_index.rs index 0f71b08da..6e67a0f29 100644 --- a/crates/chain/tests/test_keychain_txout_index.rs +++ b/crates/chain/tests/test_keychain_txout_index.rs @@ -9,7 +9,7 @@ use bdk_chain::{ Append, }; -use bitcoin::{secp256k1::Secp256k1, OutPoint, ScriptBuf, Transaction, TxOut}; +use bitcoin::{secp256k1::Secp256k1, Amount, OutPoint, ScriptBuf, Transaction, TxOut}; use miniscript::{Descriptor, DescriptorPublicKey}; #[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] @@ -176,14 +176,14 @@ fn test_lookahead() { .at_derivation_index(external_index) .unwrap() .script_pubkey(), - value: 10_000, + value: Amount::from_sat(10_000), }, TxOut { script_pubkey: internal_desc .at_derivation_index(internal_index) .unwrap() .script_pubkey(), - value: 10_000, + value: Amount::from_sat(10_000), }, ], ..common::new_tx(external_index) @@ -238,7 +238,7 @@ fn test_scan_with_lookahead() { let op = OutPoint::new(h!("fake tx"), spk_i); let txout = TxOut { script_pubkey: spk.clone(), - value: 0, + value: Amount::ZERO, }; 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 txout = TxOut { script_pubkey: spk_41, - value: 0, + value: Amount::ZERO, }; let changeset = txout_index.index_txout(op, &txout); assert!(changeset.is_empty()); diff --git a/crates/chain/tests/test_spk_txout_index.rs b/crates/chain/tests/test_spk_txout_index.rs index e8b752146..c84bd7194 100644 --- a/crates/chain/tests/test_spk_txout_index.rs +++ b/crates/chain/tests/test_spk_txout_index.rs @@ -1,5 +1,5 @@ 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] fn spk_txout_sent_and_received() { @@ -11,11 +11,11 @@ fn spk_txout_sent_and_received() { index.insert_spk(1, spk2.clone()); let tx1 = Transaction { - version: 0x02, + version: transaction::Version::TWO, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, + value: Amount::from_sat(42_000), script_pubkey: spk1.clone(), }], }; @@ -30,7 +30,7 @@ fn spk_txout_sent_and_received() { ); let tx2 = Transaction { - version: 0x1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { @@ -41,12 +41,12 @@ fn spk_txout_sent_and_received() { }], output: vec![ TxOut { - value: 20_000, + value: Amount::from_sat(20_000), script_pubkey: spk2, }, TxOut { 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)); let tx1 = Transaction { - version: 0x02, + version: transaction::Version::TWO, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, + value: Amount::from_sat(42_000), script_pubkey: spk1, }], }; diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index 8b4674485..74dd271dc 100644 --- a/crates/chain/tests/test_tx_graph.rs +++ b/crates/chain/tests/test_tx_graph.rs @@ -8,7 +8,8 @@ use bdk_chain::{ Anchor, Append, BlockId, ChainOracle, ChainPosition, ConfirmationHeightAnchor, }; 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 core::iter; @@ -23,14 +24,14 @@ fn insert_txouts() { ( OutPoint::new(h!("tx1"), 1), TxOut { - value: 10_000, + value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new(), }, ), ( OutPoint::new(h!("tx1"), 2), TxOut { - value: 20_000, + value: Amount::from_sat(20_000), script_pubkey: ScriptBuf::new(), }, ), @@ -40,21 +41,21 @@ fn insert_txouts() { let update_ops = [( OutPoint::new(h!("tx2"), 0), TxOut { - value: 20_000, + value: Amount::from_sat(20_000), script_pubkey: ScriptBuf::new(), }, )]; // One full transaction to be included in the update let update_txs = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], output: vec![TxOut { - value: 30_000, + value: Amount::from_sat(30_000), script_pubkey: ScriptBuf::new(), }], }; @@ -164,14 +165,14 @@ fn insert_txouts() { ( 1u32, &TxOut { - value: 10_000, + value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new(), } ), ( 2u32, &TxOut { - value: 20_000, + value: Amount::from_sat(20_000), script_pubkey: ScriptBuf::new(), } ) @@ -184,7 +185,7 @@ fn insert_txouts() { [( 0u32, &TxOut { - value: 30_000, + value: Amount::from_sat(30_000), script_pubkey: ScriptBuf::new() } )] @@ -206,7 +207,7 @@ fn insert_txouts() { #[test] fn insert_tx_graph_doesnt_count_coinbase_as_spent() { let tx = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), @@ -225,10 +226,10 @@ fn insert_tx_graph_doesnt_count_coinbase_as_spent() { #[test] fn insert_tx_graph_keeps_track_of_spend() { let tx1 = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], }; let op = OutPoint { @@ -237,7 +238,7 @@ fn insert_tx_graph_keeps_track_of_spend() { }; let tx2 = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: op, @@ -266,13 +267,13 @@ fn insert_tx_graph_keeps_track_of_spend() { #[test] fn insert_tx_can_retrieve_full_tx_from_graph() { let tx = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], }; let mut graph = TxGraph::<()>::default(); @@ -287,12 +288,12 @@ fn insert_tx_can_retrieve_full_tx_from_graph() { fn insert_tx_displaces_txouts() { let mut tx_graph = TxGraph::<()>::default(); let tx = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, - script_pubkey: ScriptBuf::default(), + value: Amount::from_sat(42_000), + script_pubkey: ScriptBuf::new(), }], }; @@ -302,7 +303,7 @@ fn insert_tx_displaces_txouts() { vout: 0, }, TxOut { - value: 1_337_000, + value: Amount::from_sat(1_337_000), script_pubkey: ScriptBuf::default(), }, ); @@ -315,8 +316,8 @@ fn insert_tx_displaces_txouts() { vout: 0, }, TxOut { - value: 1_000_000_000, - script_pubkey: ScriptBuf::default(), + value: Amount::from_sat(1_000_000_000), + script_pubkey: ScriptBuf::new(), }, ); @@ -330,7 +331,7 @@ fn insert_tx_displaces_txouts() { }) .unwrap() .value, - 42_000 + Amount::from_sat(42_000) ); assert_eq!( tx_graph.get_txout(OutPoint { @@ -345,12 +346,12 @@ fn insert_tx_displaces_txouts() { fn insert_txout_does_not_displace_tx() { let mut tx_graph = TxGraph::<()>::default(); let tx = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, - script_pubkey: ScriptBuf::default(), + value: Amount::from_sat(42_000), + script_pubkey: ScriptBuf::new(), }], }; @@ -362,8 +363,8 @@ fn insert_txout_does_not_displace_tx() { vout: 0, }, TxOut { - value: 1_337_000, - script_pubkey: ScriptBuf::default(), + value: Amount::from_sat(1_337_000), + script_pubkey: ScriptBuf::new(), }, ); @@ -373,8 +374,8 @@ fn insert_txout_does_not_displace_tx() { vout: 0, }, TxOut { - value: 1_000_000_000, - script_pubkey: ScriptBuf::default(), + value: Amount::from_sat(1_000_000_000), + script_pubkey: ScriptBuf::new(), }, ); @@ -386,7 +387,7 @@ fn insert_txout_does_not_displace_tx() { }) .unwrap() .value, - 42_000 + Amount::from_sat(42_000) ); assert_eq!( tx_graph.get_txout(OutPoint { @@ -401,21 +402,21 @@ fn insert_txout_does_not_displace_tx() { fn test_calculate_fee() { let mut graph = TxGraph::<()>::default(); let intx1 = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 100, - ..Default::default() + value: Amount::from_sat(100), + script_pubkey: ScriptBuf::new(), }], }; let intx2 = Transaction { - version: 0x02, + version: transaction::Version::TWO, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 200, - ..Default::default() + value: Amount::from_sat(200), + script_pubkey: ScriptBuf::new(), }], }; @@ -425,8 +426,8 @@ fn test_calculate_fee() { vout: 0, }, TxOut { - value: 300, - ..Default::default() + value: Amount::from_sat(300), + script_pubkey: ScriptBuf::new(), }, ); @@ -435,7 +436,7 @@ fn test_calculate_fee() { let _ = graph.insert_txout(intxout1.0, intxout1.1); let mut tx = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![ TxIn { @@ -458,8 +459,8 @@ fn test_calculate_fee() { }, ], output: vec![TxOut { - value: 500, - ..Default::default() + value: Amount::from_sat(500), + script_pubkey: ScriptBuf::new(), }], }; @@ -491,13 +492,13 @@ fn test_calculate_fee() { #[test] fn test_calculate_fee_on_coinbase() { let tx = Transaction { - version: 0x01, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], }; let graph = TxGraph::<()>::default(); @@ -533,7 +534,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(h!("op0"), 0), ..TxIn::default() }], - output: vec![TxOut::default(), TxOut::default()], + output: vec![TxOut::NULL, TxOut::NULL], ..common::new_tx(0) }; @@ -543,7 +544,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_a0.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default(), TxOut::default()], + output: vec![TxOut::NULL, TxOut::NULL], ..common::new_tx(0) }; @@ -553,7 +554,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_a0.txid(), 1), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -562,7 +563,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(h!("op1"), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -572,7 +573,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_b0.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -582,7 +583,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_b0.txid(), 1), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -598,7 +599,7 @@ fn test_walk_ancestors() { ..TxIn::default() }, ], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -607,7 +608,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(h!("op2"), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -617,7 +618,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_c1.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -633,7 +634,7 @@ fn test_walk_ancestors() { ..TxIn::default() }, ], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -643,7 +644,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_d1.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -726,7 +727,7 @@ fn test_conflicting_descendants() { previous_output, ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(0) }; @@ -736,7 +737,7 @@ fn test_conflicting_descendants() { previous_output, ..TxIn::default() }], - output: vec![TxOut::default(), TxOut::default()], + output: vec![TxOut::NULL, TxOut::NULL], ..common::new_tx(1) }; @@ -746,7 +747,7 @@ fn test_conflicting_descendants() { previous_output: OutPoint::new(tx_a.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(2) }; @@ -768,7 +769,7 @@ fn test_conflicting_descendants() { #[test] fn test_descendants_no_repeat() { let tx_a = Transaction { - output: vec![TxOut::default(), TxOut::default(), TxOut::default()], + output: vec![TxOut::NULL, TxOut::NULL, TxOut::NULL], ..common::new_tx(0) }; @@ -778,7 +779,7 @@ fn test_descendants_no_repeat() { previous_output: OutPoint::new(tx_a.txid(), vout), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(1) }) .collect::>(); @@ -789,7 +790,7 @@ fn test_descendants_no_repeat() { previous_output: OutPoint::new(txs_b[vout as usize].txid(), vout), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(2) }) .collect::>(); @@ -805,7 +806,7 @@ fn test_descendants_no_repeat() { ..TxIn::default() }, ], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(3) }; @@ -814,7 +815,7 @@ fn test_descendants_no_repeat() { previous_output: OutPoint::new(tx_d.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(4) }; @@ -824,7 +825,7 @@ fn test_descendants_no_repeat() { previous_output: OutPoint::new(h!("tx_does_not_exist"), v), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::NULL], ..common::new_tx(v) }) .collect::>(); @@ -871,11 +872,11 @@ fn test_chain_spends() { input: vec![], output: vec![ TxOut { - value: 10_000, + value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new(), }, TxOut { - value: 20_000, + value: Amount::from_sat(20_000), script_pubkey: ScriptBuf::new(), }, ], @@ -890,11 +891,11 @@ fn test_chain_spends() { }], output: vec![ TxOut { - value: 5_000, + value: Amount::from_sat(5_000), script_pubkey: ScriptBuf::new(), }, TxOut { - value: 5_000, + value: Amount::from_sat(5_000), script_pubkey: ScriptBuf::new(), }, ], @@ -909,11 +910,11 @@ fn test_chain_spends() { }], output: vec![ TxOut { - value: 10_000, + value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new(), }, TxOut { - value: 10_000, + value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new(), }, ], diff --git a/crates/electrum/Cargo.toml b/crates/electrum/Cargo.toml index 18064183d..c424a0d7f 100644 --- a/crates/electrum/Cargo.toml +++ b/crates/electrum/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" [dependencies] 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"] } [dev-dependencies] -bdk_testenv = { path = "../testenv", version = "0.1.0", default-features = false } -electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } +bdk_testenv = { path = "../testenv", default-features = false } +electrsd = { version= "0.27.1", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } anyhow = "1" \ No newline at end of file diff --git a/crates/electrum/tests/test_electrum.rs b/crates/electrum/tests/test_electrum.rs index 0dc80ac61..68afb3bea 100644 --- a/crates/electrum/tests/test_electrum.rs +++ b/crates/electrum/tests/test_electrum.rs @@ -40,7 +40,7 @@ fn scan_detects_confirmed_tx() -> Result<()> { .client .get_new_address(None, None)? .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)?; // Setup receiver. @@ -106,7 +106,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> Result<()> { .client .get_new_address(None, None)? .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)?; // Setup receiver. diff --git a/crates/esplora/Cargo.toml b/crates/esplora/Cargo.toml index c1cecac4f..d2d890746 100644 --- a/crates/esplora/Cargo.toml +++ b/crates/esplora/Cargo.toml @@ -13,17 +13,17 @@ readme = "README.md" [dependencies] 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 } futures = { version = "0.3.26", optional = true } # use these dependencies if you need to enable their /no-std features -bitcoin = { version = "0.30.0", optional = true, default-features = false } -miniscript = { version = "10.0.0", optional = true, default-features = false } +bitcoin = { version = "0.31.0", optional = true, default-features = false } +miniscript = { version = "11.0.0", optional = true, default-features = false } [dev-dependencies] -bdk_testenv = { path = "../testenv", version = "0.1.0", default_features = false } -electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } +bdk_testenv = { path = "../testenv", default_features = false } +electrsd = { version= "0.27.1", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [features] diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index 9e25eedfb..bd7a2c850 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use bdk_chain::collections::btree_map; use bdk_chain::{ - bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, + bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, collections::BTreeMap, local_chain::{self, CheckPoint}, BlockId, ConfirmationTimeHeightAnchor, TxGraph, @@ -228,7 +228,7 @@ impl EsploraAsyncExt for esplora_client::AsyncClient { }, TxOut { script_pubkey: prevout.scriptpubkey.clone(), - value: prevout.value, + value: Amount::from_sat(prevout.value), }, )) }); diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index 9cd11e819..52aefedcb 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -3,7 +3,7 @@ use std::thread::JoinHandle; use bdk_chain::collections::btree_map; use bdk_chain::collections::BTreeMap; use bdk_chain::{ - bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, + bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, local_chain::{self, CheckPoint}, BlockId, ConfirmationTimeHeightAnchor, TxGraph, }; @@ -218,7 +218,7 @@ impl EsploraExt for esplora_client::BlockingClient { }, TxOut { script_pubkey: prevout.scriptpubkey.clone(), - value: prevout.value, + value: Amount::from_sat(prevout.value), }, )) }); diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index de0594eec..35e38a778 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -30,7 +30,7 @@ macro_rules! local_chain { pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let env = TestEnv::new()?; 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 = 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<()> { let env = TestEnv::new()?; 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)?; // 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 let env = env.reset_electrsd()?; 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 { name: &'static str, diff --git a/crates/hwi/Cargo.toml b/crates/hwi/Cargo.toml index de7272432..711a2f948 100644 --- a/crates/hwi/Cargo.toml +++ b/crates/hwi/Cargo.toml @@ -10,4 +10,4 @@ readme = "README.md" [dependencies] bdk = { path = "../bdk" } -hwi = { version = "0.7.0", features = [ "miniscript"] } +hwi = { version = "0.8.0", features = [ "miniscript"] } diff --git a/crates/hwi/src/signer.rs b/crates/hwi/src/signer.rs index b16b60c54..a297291ce 100644 --- a/crates/hwi/src/signer.rs +++ b/crates/hwi/src/signer.rs @@ -1,6 +1,6 @@ use bdk::bitcoin::bip32::Fingerprint; -use bdk::bitcoin::psbt::PartiallySignedTransaction; use bdk::bitcoin::secp256k1::{All, Secp256k1}; +use bdk::bitcoin::Psbt; use hwi::error::Error; use hwi::types::{HWIChain, HWIDevice}; @@ -37,7 +37,7 @@ impl SignerCommon for HWISigner { impl TransactionSigner for HWISigner { fn sign_transaction( &self, - psbt: &mut PartiallySignedTransaction, + psbt: &mut Psbt, _sign_options: &bdk::SignOptions, _secp: &Secp256k1, ) -> Result<(), SignerError> { diff --git a/crates/testenv/Cargo.toml b/crates/testenv/Cargo.toml index 46d4e177b..e52d2a3bc 100644 --- a/crates/testenv/Cargo.toml +++ b/crates/testenv/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bitcoincore-rpc = { version = "0.17" } +bitcoincore-rpc = { version = "0.18" } 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" } [features] diff --git a/crates/testenv/src/lib.rs b/crates/testenv/src/lib.rs index b836387c1..8cba86261 100644 --- a/crates/testenv/src/lib.rs +++ b/crates/testenv/src/lib.rs @@ -1,7 +1,7 @@ use bdk_chain::bitcoin::{ address::NetworkChecked, block::Header, hash_types::TxMerkleNode, hashes::Hash, - secp256k1::rand::random, Address, Amount, Block, BlockHash, CompactTarget, ScriptBuf, - ScriptHash, Transaction, TxIn, TxOut, Txid, + secp256k1::rand::random, transaction, Address, Amount, Block, BlockHash, CompactTarget, + ScriptBuf, ScriptHash, Transaction, TxIn, TxOut, Txid, }; use bitcoincore_rpc::{ bitcoincore_rpc_json::{GetBlockTemplateModes, GetBlockTemplateRules}, @@ -109,7 +109,7 @@ impl TestEnv { )?; let txdata = vec![Transaction { - version: 1, + version: transaction::Version::ONE, lock_time: bdk_chain::bitcoin::absolute::LockTime::from_height(0)?, input: vec![TxIn { previous_output: bdk_chain::bitcoin::OutPoint::default(), @@ -122,7 +122,7 @@ impl TestEnv { witness: bdk_chain::bitcoin::Witness::new(), }], output: vec![TxOut { - value: 0, + value: Amount::ZERO, script_pubkey: ScriptBuf::new_p2sh(&ScriptHash::all_zeros()), }], }]; diff --git a/example-crates/example_cli/src/lib.rs b/example-crates/example_cli/src/lib.rs index 4989c08c6..cac9f8667 100644 --- a/example-crates/example_cli/src/lib.rs +++ b/example-crates/example_cli/src/lib.rs @@ -3,12 +3,14 @@ use anyhow::Context; use bdk_coin_select::{coin_select_bnb, CoinSelector, CoinSelectorOpt, WeightedValue}; use bdk_file_store::Store; 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::{ bitcoin::{ - absolute, address, psbt::Prevouts, secp256k1::Secp256k1, sighash::SighashCache, Address, - Network, Sequence, Transaction, TxIn, TxOut, + absolute, address, + secp256k1::Secp256k1, + sighash::{Prevouts, SighashCache}, + transaction, Address, Amount, Network, Sequence, Transaction, TxIn, TxOut, }, indexed_tx_graph::{self, IndexedTxGraph}, keychain::{self, KeychainTxOutIndex}, @@ -197,7 +199,7 @@ pub struct CreateTxChange { pub fn create_tx( graph: &mut KeychainTxGraph, chain: &O, - keymap: &HashMap, + keymap: &BTreeMap, cs_algorithm: CoinSelectionAlgo, address: Address, value: u64, @@ -235,7 +237,7 @@ where .iter() .map(|(plan, utxo)| { WeightedValue::new( - utxo.txout.value, + utxo.txout.value.to_sat(), plan.expected_weight() as _, plan.witness_version().is_some(), ) @@ -243,7 +245,7 @@ where .collect(); let mut outputs = vec![TxOut { - value, + value: Amount::from_sat(value), script_pubkey: address.script_pubkey(), }]; @@ -273,7 +275,7 @@ where .expect("failed to obtain change plan"); let mut change_output = TxOut { - value: 0, + value: Amount::ZERO, script_pubkey: change_script, }; @@ -311,13 +313,13 @@ where let selected_txos = selection.apply_selection(&candidates).collect::>(); 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 outputs.push(change_output) } let mut transaction = Transaction { - version: 0x02, + version: transaction::Version::TWO, // because the temporary planning module does not support timelocks, we can use the chain // tip as the `lock_time` for anti-fee-sniping purposes lock_time: absolute::LockTime::from_height(chain.get_chain_tip()?.height) @@ -440,7 +442,7 @@ pub fn handle_commands>, db: &Mutex>, chain: &Mutex, - keymap: &HashMap, + keymap: &BTreeMap, network: Network, broadcast: impl FnOnce(S, &Transaction) -> anyhow::Result<()>, cmd: Commands, diff --git a/example-crates/example_esplora/src/main.rs b/example-crates/example_esplora/src/main.rs index e92205706..0772539f0 100644 --- a/example-crates/example_esplora/src/main.rs +++ b/example-crates/example_esplora/src/main.rs @@ -86,7 +86,7 @@ impl EsploraArgs { _ => 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) } } diff --git a/example-crates/wallet_electrum/src/main.rs b/example-crates/wallet_electrum/src/main.rs index 4f8aba9fd..5a76e60f3 100644 --- a/example-crates/wallet_electrum/src/main.rs +++ b/example-crates/wallet_electrum/src/main.rs @@ -99,7 +99,7 @@ fn main() -> Result<(), anyhow::Error> { let finalized = wallet.sign(&mut psbt, SignOptions::default())?; assert!(finalized); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx()?; client.transaction_broadcast(&tx)?; println!("Tx broadcasted! Txid: {}", tx.txid()); diff --git a/example-crates/wallet_esplora_async/src/main.rs b/example-crates/wallet_esplora_async/src/main.rs index 690cd87e2..657479b67 100644 --- a/example-crates/wallet_esplora_async/src/main.rs +++ b/example-crates/wallet_esplora_async/src/main.rs @@ -90,7 +90,7 @@ async fn main() -> Result<(), anyhow::Error> { let finalized = wallet.sign(&mut psbt, SignOptions::default())?; assert!(finalized); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx()?; client.broadcast(&tx).await?; println!("Tx broadcasted! Txid: {}", tx.txid()); diff --git a/example-crates/wallet_esplora_blocking/src/main.rs b/example-crates/wallet_esplora_blocking/src/main.rs index 73bfdd559..307792856 100644 --- a/example-crates/wallet_esplora_blocking/src/main.rs +++ b/example-crates/wallet_esplora_blocking/src/main.rs @@ -34,7 +34,7 @@ fn main() -> Result<(), anyhow::Error> { print!("Syncing..."); 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 keychain_spks = wallet @@ -90,7 +90,7 @@ fn main() -> Result<(), anyhow::Error> { let finalized = wallet.sign(&mut psbt, SignOptions::default())?; assert!(finalized); - let tx = psbt.extract_tx(); + let tx = psbt.extract_tx()?; client.broadcast(&tx)?; println!("Tx broadcasted! Txid: {}", tx.txid()); diff --git a/nursery/coin_select/src/coin_selector.rs b/nursery/coin_select/src/coin_selector.rs index 281992a96..729f9b23b 100644 --- a/nursery/coin_select/src/coin_selector.rs +++ b/nursery/coin_select/src/coin_selector.rs @@ -96,7 +96,7 @@ impl CoinSelectorOpt { ) -> Self { let mut tx = Transaction { input: vec![], - version: 1, + version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, output: txouts.to_vec(), }; @@ -112,7 +112,7 @@ impl CoinSelectorOpt { target_value: if txouts.is_empty() { None } else { - Some(txouts.iter().map(|txout| txout.value).sum()) + Some(txouts.iter().map(|txout| txout.value.to_sat()).sum()) }, ..Self::from_weights( base_weight.to_wu() as u32, diff --git a/nursery/coin_select/src/lib.rs b/nursery/coin_select/src/lib.rs index dc38c676d..3b8ae12f9 100644 --- a/nursery/coin_select/src/lib.rs +++ b/nursery/coin_select/src/lib.rs @@ -12,7 +12,7 @@ use bdk_chain::{ bitcoin, collections::{BTreeSet, HashMap}, }; -use bitcoin::{absolute, Transaction, TxOut}; +use bitcoin::{absolute, transaction, Transaction, TxOut}; use core::fmt::{Debug, Display}; mod coin_selector; @@ -29,5 +29,5 @@ pub const TXIN_BASE_WEIGHT: u32 = (32 + 4 + 4) * 4; // Shamelessly copied from // https://github.com/rust-bitcoin/rust-miniscript/blob/d5615acda1a7fdc4041a11c1736af139b8c7ebe8/src/util.rs#L8 pub(crate) fn varint_size(v: usize) -> u32 { - bitcoin::VarInt(v as u64).len() as u32 + bitcoin::VarInt(v as u64).size() as u32 } diff --git a/nursery/tmp_plan/src/lib.rs b/nursery/tmp_plan/src/lib.rs index 226ce8b59..d39a7fe6c 100644 --- a/nursery/tmp_plan/src/lib.rs +++ b/nursery/tmp_plan/src/lib.rs @@ -17,14 +17,13 @@ use bdk_chain::{bitcoin, collections::*, miniscript}; use bitcoin::{ absolute, - address::WitnessVersion, bip32::{DerivationPath, Fingerprint, KeySource}, blockdata::transaction::Sequence, ecdsa, hashes::{hash160, ripemd160, sha256}, secp256k1::Secp256k1, taproot::{self, LeafVersion, TapLeafHash}, - ScriptBuf, TxIn, Witness, + ScriptBuf, TxIn, Witness, WitnessVersion, }; use miniscript::{ descriptor::{InnerXKey, Tr}, @@ -32,7 +31,7 @@ use miniscript::{ }; 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; diff --git a/nursery/tmp_plan/src/requirements.rs b/nursery/tmp_plan/src/requirements.rs index 08e1ef822..520290c0e 100644 --- a/nursery/tmp_plan/src/requirements.rs +++ b/nursery/tmp_plan/src/requirements.rs @@ -3,12 +3,11 @@ use core::ops::Deref; use bitcoin::{ bip32, - hashes::{hash160, ripemd160, sha256}, + hashes::{hash160, ripemd160, sha256, Hash}, key::XOnlyPublicKey, - psbt::Prevouts, - secp256k1::{KeyPair, Message, PublicKey, Signing, Verification}, + secp256k1::{Keypair, Message, PublicKey, Signing, Verification}, sighash, - sighash::{EcdsaSighashType, SighashCache, TapSighashType}, + sighash::{EcdsaSighashType, Prevouts, SighashCache, TapSighashType}, taproot, Transaction, TxOut, }; @@ -163,11 +162,11 @@ impl RequiredSignatures { let tweak = 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()) .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 bitcoin_sig = taproot::Signature { @@ -209,9 +208,8 @@ impl RequiredSignatures { todo!(); } }; - let keypair = KeyPair::from_secret_key(&secp, &secret_key.clone()); - let msg = - Message::from_slice(sighash.as_ref()).expect("Sighashes are 32 bytes"); + let keypair = Keypair::from_secret_key(&secp, &secret_key.clone()); + let msg = Message::from_digest(sighash.to_byte_array()); let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair); let bitcoin_sig = taproot::Signature { sig,