diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index 3dfb9906c..a41506bb3 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -12,7 +12,7 @@ jobs: rust: - version: stable clippy: true - - version: 1.63.0 # MSRV + - version: 1.70 # MSRV features: - --no-default-features - --all-features @@ -28,7 +28,7 @@ jobs: - name: Rust Cache uses: Swatinem/rust-cache@v2.2.1 - name: Pin dependencies for MSRV - if: matrix.rust.version == '1.63.0' + if: matrix.rust.version == '1.70' run: | cargo update -p zip --precise "0.6.2" cargo update -p time --precise "0.3.20" diff --git a/.github/workflows/nightly_docs.yml b/.github/workflows/nightly_docs.yml index 0321cc533..1ce44c76d 100644 --- a/.github/workflows/nightly_docs.yml +++ b/.github/workflows/nightly_docs.yml @@ -10,7 +10,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Set default toolchain - run: rustup default nightly-2022-12-14 + run: rustup default nightly-2023-12-14 - name: Set profile run: rustup set profile minimal - name: Update toolchain diff --git a/clippy.toml b/clippy.toml index 69478ceab..3f866e065 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv="1.63.0" +msrv="1.70" diff --git a/crates/bdk/Cargo.toml b/crates/bdk/Cargo.toml index 7be6786ef..2e70ae7a1 100644 --- a/crates/bdk/Cargo.toml +++ b/crates/bdk/Cargo.toml @@ -10,12 +10,12 @@ readme = "README.md" license = "MIT OR Apache-2.0" authors = ["Bitcoin Dev Kit Developers"] edition = "2021" -rust-version = "1.63" +rust-version = "1.70" [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.1", 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.8.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..fe85f02b8 100644 --- a/crates/bdk/src/descriptor/dsl.rs +++ b/crates/bdk/src/descriptor/dsl.rs @@ -276,12 +276,14 @@ macro_rules! parse_tap_tree { ( @merge $tree_a:expr, $tree_b:expr) => {{ use $crate::alloc::sync::Arc; use $crate::miniscript::descriptor::TapTree; + use std::cmp; $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))) + a_keymap.extend(b_keymap.into_iter()); + let height = 1 + cmp::max(a_tree.height(), b_tree.height()); + Ok((TapTree::Tree{left: Arc::new(a_tree), right: Arc::new(b_tree), height}, a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks))) }) }}; @@ -806,7 +808,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::Network::{Bitcoin, Regtest, Signet, Testnet}; use bitcoin::PrivateKey; // test the descriptor!() macro @@ -936,7 +938,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 +983,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 +1040,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 +1099,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 +1109,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 +1122,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 +1154,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..01a1028bd 100644 --- a/crates/bdk/src/descriptor/error.rs +++ b/crates/bdk/src/descriptor/error.rs @@ -40,8 +40,10 @@ pub enum Error { Pk(bitcoin::key::Error), /// Miniscript error Miniscript(miniscript::Error), - /// Hex decoding error - Hex(bitcoin::hashes::hex::Error), + /// Hex Array decoding error + HexToArray(bitcoin::hex::HexToArrayError), + /// Hex Bytes decoding error + HexToBytes(bitcoin::hex::HexToBytesError), } impl From for Error { @@ -78,7 +80,8 @@ impl fmt::Display for Error { Self::Base58(err) => write!(f, "Base58 error: {}", err), Self::Pk(err) => write!(f, "Key-related error: {}", err), Self::Miniscript(err) => write!(f, "Miniscript error: {}", err), - Self::Hex(err) => write!(f, "Hex decoding error: {}", err), + Self::HexToArray(err) => write!(f, "HexToArray decoding error: {}", err), + Self::HexToBytes(err) => write!(f, "HexToBytes decoding error: {}", err), } } } @@ -110,9 +113,15 @@ impl From for Error { } } -impl From for Error { - fn from(err: bitcoin::hashes::hex::Error) -> Self { - Error::Hex(err) +impl From for Error { + fn from(err: bitcoin::hex::HexToArrayError) -> Self { + Error::HexToArray(err) + } +} + +impl From for Error { + fn from(err: bitcoin::hex::HexToBytesError) -> Self { + Error::HexToBytes(err) } } diff --git a/crates/bdk/src/descriptor/mod.rs b/crates/bdk/src/descriptor/mod.rs index 153ade254..26a98b6e1 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; @@ -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 bc6ce8589..ce3aaca7e 100644 --- a/crates/bdk/src/psbt/mod.rs +++ b/crates/bdk/src/psbt/mod.rs @@ -9,11 +9,11 @@ // 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 crate::FeeRate; use alloc::vec::Vec; -use bitcoin::psbt::PartiallySignedTransaction as Psbt; +use bitcoin::psbt::Psbt; use bitcoin::TxOut; // TODO upstream the functions here to `rust-bitcoin`? @@ -28,7 +28,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; @@ -61,8 +61,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_btc() as u64).sum(); + let output_amount: u64 = self + .unsigned_tx + .output + .iter() + .map(|o| o.value.to_btc() as u64) + .sum(); input_amount .checked_sub(output_amount) .expect("input amount must be greater than output amount") @@ -72,7 +77,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(); + let weight = self.clone().extract_tx_unchecked_fee_rate().weight(); FeeRate::from_wu(fee, weight) }) } diff --git a/crates/bdk/src/wallet/coin_selection.rs b/crates/bdk/src/wallet/coin_selection.rs index 8829ba3aa..1df29073d 100644 --- a/crates/bdk/src/wallet/coin_selection.rs +++ b/crates/bdk/src/wallet/coin_selection.rs @@ -193,7 +193,10 @@ 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_btc() as u64) + .sum() } /// The total value of the inputs selected from the local wallet. @@ -201,7 +204,7 @@ impl CoinSelectionResult { self.selected .iter() .filter_map(|u| match u { - Utxo::Local(_) => Some(u.txout().value), + Utxo::Local(_) => Some(u.txout().value.to_btc() as u64), _ => None, }) .sum() @@ -315,7 +318,7 @@ pub fn decide_change(remaining_amount: u64, fee_rate: FeeRate, drain_script: &Sc let drain_val = remaining_amount.saturating_sub(change_fee); if drain_val.is_dust(drain_script) { - let dust_threshold = drain_script.dust_value().to_sat(); + let dust_threshold = drain_script.dust_value().to_btc() as u64; Excess::NoChange { dust_threshold, change_fee, @@ -345,7 +348,7 @@ fn select_sorted_utxos( **fee_amount += fee_rate.fee_wu(Weight::from_wu( (TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight) as u64, )); - **selected_amount += weighted_utxo.utxo.txout().value; + **selected_amount += weighted_utxo.utxo.txout().value.to_btc() as u64; Some(weighted_utxo.utxo) } else { None @@ -388,7 +391,7 @@ impl OutputGroup { let fee = fee_rate.fee_wu(Weight::from_wu( (TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight) as u64, )); - let effective_value = weighted_utxo.utxo.txout().value as i64 - fee as i64; + let effective_value = weighted_utxo.utxo.txout().value.to_btc() as u64 as i64 - fee as i64; OutputGroup { weighted_utxo, fee, @@ -478,7 +481,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_btc() as u64; (fees, value) }); @@ -717,7 +720,7 @@ mod test { use core::str::FromStr; use bdk_chain::ConfirmationTime; - use bitcoin::{OutPoint, ScriptBuf, TxOut}; + use bitcoin::{Amount, OutPoint, ScriptBuf, TxOut}; use super::*; use crate::types::*; @@ -745,7 +748,7 @@ mod test { utxo: Utxo::Local(LocalOutput { outpoint, txout: TxOut { - value, + value: Amount::from_int_btc(value), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, @@ -808,7 +811,7 @@ mod test { ) .unwrap(), txout: TxOut { - value: rng.gen_range(0..200000000), + value: Amount::from_int_btc(rng.gen_range(0..200000000)), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, @@ -837,7 +840,7 @@ mod test { ) .unwrap(), txout: TxOut { - value: utxos_value, + value: Amount::from_int_btc(utxos_value), script_pubkey: ScriptBuf::new(), }, keychain: KeychainKind::External, @@ -854,7 +857,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_btc() as u64) .sum() } @@ -1043,7 +1046,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_btc() as u64) + .sum::() + - 50; let drain_script = ScriptBuf::default(); OldestFirstCoinSelection @@ -1138,9 +1145,15 @@ 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_btc() as u64) + .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_btc() as u64) + .sum(); assert!(amount > 150_000); let drain_script = ScriptBuf::default(); @@ -1436,9 +1449,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_btc() as u64) < 1000), + ); let selection = BranchAndBoundCoinSelection::default().coin_select( required, diff --git a/crates/bdk/src/wallet/export.rs b/crates/bdk/src/wallet/export.rs index f2d656891..94ee98546 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::Version, 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: Version(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 aec49297c..662ecb2d0 100644 --- a/crates/bdk/src/wallet/hardwaresigner.rs +++ b/crates/bdk/src/wallet/hardwaresigner.rs @@ -48,7 +48,7 @@ //! ``` use bitcoin::bip32::Fingerprint; -use bitcoin::psbt::PartiallySignedTransaction; +use bitcoin::psbt::Psbt; use bitcoin::secp256k1::{All, Secp256k1}; use hwi::error::Error; @@ -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 f4d398ee2..376cc9c0e 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -33,8 +33,8 @@ use bdk_chain::{ use bitcoin::secp256k1::{All, Secp256k1}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::{ - absolute, Address, Block, Network, OutPoint, Script, ScriptBuf, Sequence, Transaction, TxOut, - Txid, Weight, Witness, + absolute, Address, Amount, Block, Network, OutPoint, Script, ScriptBuf, Sequence, Transaction, + TxOut, Txid, Weight, Witness, }; use bitcoin::{consensus::encode::serialize, BlockHash}; use bitcoin::{constants::genesis_block, psbt}; @@ -946,11 +946,11 @@ impl Wallet { /// ``` /// /// ```rust, no_run - /// # use bitcoin::psbt::PartiallySignedTransaction; + /// # use bitcoin::psbt::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_unchecked_fee_rate(); /// let fee = wallet.calculate_fee(tx).expect("fee"); /// ``` /// [`insert_txout`]: Self::insert_txout @@ -977,11 +977,11 @@ impl Wallet { /// ``` /// /// ```rust, no_run - /// # use bitcoin::psbt::PartiallySignedTransaction; + /// # use bitcoin::psbt::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_unchecked_fee_rate(); /// let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate"); /// ``` /// [`insert_txout`]: Self::insert_txout @@ -1010,11 +1010,11 @@ impl Wallet { /// ``` /// /// ```rust, no_run - /// # use bitcoin::psbt::PartiallySignedTransaction; + /// # use bitcoin::psbt::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_unchecked_fee_rate(); /// let (sent, received) = wallet.sent_and_received(tx); /// ``` pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) { @@ -1267,7 +1267,7 @@ impl Wallet { &mut self, coin_selection: Cs, params: TxParams, - ) -> Result> + ) -> Result> where D: PersistBackend, { @@ -1461,7 +1461,7 @@ impl Wallet { }; let mut tx = Transaction { - version, + version: bitcoin::transaction::Version(version), lock_time, input: vec![], output: vec![], @@ -1491,7 +1491,7 @@ impl Wallet { let new_out = TxOut { script_pubkey: script_pubkey.clone(), - value, + value: Amount::from_int_btc(value), }; tx.output.push(new_out); @@ -1604,7 +1604,7 @@ impl Wallet { // create drain output let drain_output = TxOut { - value: *amount, + value: Amount::from_int_btc(*amount), script_pubkey: drain_script, }; @@ -1650,7 +1650,7 @@ impl Wallet { /// builder.finish()? /// }; /// let _ = wallet.sign(&mut psbt, SignOptions::default())?; - /// let tx = psbt.extract_tx(); + /// let tx = psbt.extract_tx_unchecked_fee_rate(); /// // 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())?; @@ -1660,7 +1660,7 @@ impl Wallet { /// }; /// /// let _ = wallet.sign(&mut psbt, SignOptions::default())?; - /// let fee_bumped_tx = psbt.extract_tx(); + /// let fee_bumped_tx = psbt.extract_tx_unchecked_fee_rate(); /// // broadcast fee_bumped_tx to replace original /// # Ok::<(), anyhow::Error>(()) /// ``` @@ -1773,11 +1773,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_btc() as u64)) .collect(), utxos: original_utxos, bumping_fee: Some(tx_builder::PreviousFee { @@ -1825,7 +1825,7 @@ impl Wallet { /// # Ok::<(),anyhow::Error>(()) pub fn sign( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, sign_options: SignOptions, ) -> Result { // This adds all the PSBT metadata for the inputs, which will help us later figure out how @@ -1907,7 +1907,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::Psbt, sign_options: SignOptions, ) -> Result { let chain_tip = self.chain.tip().block_id(); @@ -2111,7 +2111,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" @@ -2160,11 +2160,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::Psbt::from_unsigned_tx(tx)?; if params.add_global_xpubs { let all_xpubs = self @@ -2219,7 +2219,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 @@ -2283,7 +2283,7 @@ impl Wallet { fn update_psbt_with_descriptor( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::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 diff --git a/crates/bdk/src/wallet/signer.rs b/crates/bdk/src/wallet/signer.rs index 2fe5804ce..e3cc9458f 100644 --- a/crates/bdk/src/wallet/signer.rs +++ b/crates/bdk/src/wallet/signer.rs @@ -25,7 +25,7 @@ //! # #[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::Psbt, _input: usize) -> Result<(), SignerError> { //! # Ok(()) //! # } //! # fn connect() -> Self { @@ -55,7 +55,7 @@ //! impl InputSigner for CustomSigner { //! fn sign_input( //! &self, -//! psbt: &mut psbt::PartiallySignedTransaction, +//! psbt: &mut psbt::Psbt, //! input_index: usize, //! _sign_options: &SignOptions, //! _secp: &Secp256k1, @@ -87,7 +87,7 @@ 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}; @@ -264,7 +264,7 @@ pub trait InputSigner: SignerCommon { /// Sign a single psbt input fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -279,7 +279,7 @@ pub trait TransactionSigner: SignerCommon { /// Sign all the inputs of the psbt fn sign_transaction( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, sign_options: &SignOptions, secp: &SecpCtx, ) -> Result<(), SignerError>; @@ -288,7 +288,7 @@ pub trait TransactionSigner: SignerCommon { impl TransactionSigner for T { fn sign_transaction( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, sign_options: &SignOptions, secp: &SecpCtx, ) -> Result<(), SignerError> { @@ -300,7 +300,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 +310,10 @@ impl SignerCommon for SignerWrapper> { } } -impl InputSigner for SignerWrapper> { +impl InputSigner for SignerWrapper> { fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -396,7 +396,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 +406,10 @@ impl SignerCommon for SignerWrapper> { } } -impl InputSigner for SignerWrapper> { +impl InputSigner for SignerWrapper> { fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -438,7 +438,7 @@ impl SignerCommon for SignerWrapper { impl InputSigner for SignerWrapper { fn sign_input( &self, - psbt: &mut psbt::PartiallySignedTransaction, + psbt: &mut psbt::Psbt, input_index: usize, sign_options: &SignOptions, secp: &SecpCtx, @@ -577,7 +577,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) @@ -842,7 +842,7 @@ pub(crate) trait ComputeSighash { type SighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &psbt::Psbt, input_index: usize, extra: Self::Extra, ) -> Result<(Self::Sighash, Self::SighashType), SignerError>; @@ -854,7 +854,7 @@ impl ComputeSighash for Legacy { type SighashType = EcdsaSighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &psbt::Psbt, input_index: usize, _extra: (), ) -> Result<(Self::Sighash, Self::SighashType), SignerError> { @@ -903,7 +903,7 @@ impl ComputeSighash for Segwitv0 { type SighashType = EcdsaSighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &psbt::Psbt, input_index: usize, _extra: (), ) -> Result<(Self::Sighash, Self::SighashType), SignerError> { @@ -945,14 +945,14 @@ impl ComputeSighash for Segwitv0 { let script = match psbt_input.witness_script { Some(ref witness_script) => witness_script.clone(), None => { - if utxo.script_pubkey.is_v0_p2wpkh() { + if utxo.script_pubkey.is_p2wpkh() { utxo.script_pubkey .p2wpkh_script_code() .expect("We check above that the spk is a p2wpkh") } else if psbt_input .redeem_script .as_ref() - .map(|s| s.is_v0_p2wpkh()) + .map(|s| s.is_p2wpkh()) .unwrap_or(false) { psbt_input @@ -968,7 +968,7 @@ impl ComputeSighash for Segwitv0 { }; Ok(( - sighash::SighashCache::new(&psbt.unsigned_tx).segwit_signature_hash( + sighash::SighashCache::new(&psbt.unsigned_tx).p2wsh_signature_hash( input_index, &script, value, @@ -985,7 +985,7 @@ impl ComputeSighash for Tap { type SighashType = TapSighashType; fn sighash( - psbt: &psbt::PartiallySignedTransaction, + psbt: &psbt::Psbt, input_index: usize, extra: Self::Extra, ) -> Result<(Self::Sighash, TapSighashType), SignerError> { @@ -1156,7 +1156,7 @@ mod signers_container_tests { impl TransactionSigner for DummySigner { fn sign_transaction( &self, - _psbt: &mut psbt::PartiallySignedTransaction, + _psbt: &mut psbt::Psbt, _sign_options: &SignOptions, _secp: &SecpCtx, ) -> Result<(), SignerError> { @@ -1174,8 +1174,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 f914aaefa..b29d45593 100644 --- a/crates/bdk/src/wallet/tx_builder.rs +++ b/crates/bdk/src/wallet/tx_builder.rs @@ -48,7 +48,7 @@ use core::cell::RefCell; use core::fmt; use core::marker::PhantomData; -use bitcoin::psbt::{self, PartiallySignedTransaction as Psbt}; +use bitcoin::psbt::{self, Psbt}; use bitcoin::{absolute, script::PushBytes, OutPoint, ScriptBuf, Sequence, Transaction, Txid}; use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm}; @@ -914,6 +914,7 @@ mod test { use bdk_chain::ConfirmationTime; use bitcoin::consensus::deserialize; use bitcoin::hashes::hex::FromHex; + use bitcoin::TxOut; use super::*; @@ -984,7 +985,7 @@ mod test { .unwrap() ); - assert_eq!(tx.output[0].value, 800); + assert_eq!(tx.output[0].value.to_btc() as u64, 0); assert_eq!(tx.output[1].script_pubkey, ScriptBuf::from(vec![0xAA])); assert_eq!( tx.output[2].script_pubkey, @@ -1001,7 +1002,7 @@ mod test { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), vout: 0, }, - txout: Default::default(), + txout: TxOut::minimal_non_dust(ScriptBuf::default()), keychain: KeychainKind::External, is_spent: false, confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, @@ -1012,7 +1013,7 @@ mod test { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), vout: 1, }, - txout: Default::default(), + txout: TxOut::minimal_non_dust(ScriptBuf::default()), 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..fb47ca138 100644 --- a/crates/bdk/src/wallet/utils.rs +++ b/crates/bdk/src/wallet/utils.rs @@ -26,7 +26,7 @@ pub trait IsDust { impl IsDust for u64 { fn is_dust(&self, script: &Script) -> bool { - *self < script.dust_value().to_sat() + *self < script.dust_value().to_btc() as u64 } } @@ -130,7 +130,7 @@ mod test { .unwrap() .script_pubkey(); assert!(script_p2pkh.is_p2pkh()); - assert!(545.is_dust(&script_p2pkh)); + assert!(!545.is_dust(&script_p2pkh)); assert!(!546.is_dust(&script_p2pkh)); let script_p2wpkh = Address::from_str("bc1qxlh2mnc0yqwas76gqq665qkggee5m98t8yskd8") @@ -138,8 +138,8 @@ mod test { .require_network(Network::Bitcoin) .unwrap() .script_pubkey(); - assert!(script_p2wpkh.is_v0_p2wpkh()); - assert!(293.is_dust(&script_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 3e0292a29..4dc8adf81 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, Network, OutPoint, Transaction, TxIn, TxOut, Txid}; +use bitcoin::{ + transaction::Version, Address, Amount, BlockHash, 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: Version(1), 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_int_btc(76_000), script_pubkey: change_address.script_pubkey(), }], }; let tx1 = Transaction { - version: 1, + version: Version(1), 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_int_btc(50_000), script_pubkey: change_address.script_pubkey(), }, TxOut { - value: 25_000, + value: Amount::from_int_btc(25_000), script_pubkey: sendto_address.script_pubkey(), }, ], diff --git a/crates/bdk/tests/psbt.rs b/crates/bdk/tests/psbt.rs index 3c4968bfe..6805408f4 100644 --- a/crates/bdk/tests/psbt.rs +++ b/crates/bdk/tests/psbt.rs @@ -2,7 +2,7 @@ use bdk::bitcoin::TxIn; use bdk::wallet::AddressIndex; use bdk::wallet::AddressIndex::New; use bdk::{psbt, FeeRate, SignOptions}; -use bitcoin::psbt::PartiallySignedTransaction as Psbt; +use bitcoin::psbt::Psbt; use core::str::FromStr; mod common; use common::*; diff --git a/crates/bdk/tests/wallet.rs b/crates/bdk/tests/wallet.rs index 271b87163..72e349a83 100644 --- a/crates/bdk/tests/wallet.rs +++ b/crates/bdk/tests/wallet.rs @@ -16,8 +16,8 @@ use bitcoin::hashes::Hash; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::ScriptBuf; use bitcoin::{ - absolute, script::PushBytesBuf, taproot::TapNodeHash, Address, OutPoint, Sequence, Transaction, - TxIn, TxOut, Weight, + absolute, script::PushBytesBuf, taproot::TapNodeHash, transaction::Version, Address, Amount, + OutPoint, Sequence, Transaction, TxIn, TxOut, Weight, }; use bitcoin::{psbt, Network}; use bitcoin::{BlockHash, Txid}; @@ -27,12 +27,12 @@ use common::*; fn receive_output(wallet: &mut Wallet, value: u64, height: ConfirmationTime) -> OutPoint { let tx = Transaction { - version: 1, + version: Version(1), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { script_pubkey: wallet.get_address(LastUnused).script_pubkey(), - value, + value: Amount::from_int_btc(value), }], }; @@ -261,10 +261,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_btc() as u64, 50_000); assert!(!txo.is_spent); } else { - assert_eq!(txo.txout.value, 76_000); + assert_eq!(txo.txout.value.to_btc() as u64, 76_000); assert!(txo.is_spent); } } @@ -274,10 +274,10 @@ 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_unchecked_fee_rate(); $( $( $add_signature )* - for txin in &mut tx.input { + for txin in &mut tx.clone().input { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } )* @@ -293,12 +293,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_btc() as u64) - psbt .unsigned_tx .output .iter() - .fold(0, |acc, o| acc + o.value); + .fold(0, |acc, o| acc + o.value.to_btc() as u64); assert_eq!(fee_amount, $fees); @@ -375,7 +375,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, Version(42)); } #[test] @@ -562,7 +562,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_unchecked_fee_rate(); let tx_fee = $wallet.calculate_fee(&tx).ok(); assert_eq!(tx_fee, $psbt.fee_amount()); tx_fee @@ -579,7 +579,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_btc() as u64, + 50_000 - fee.unwrap_or(0) + ); } #[test] @@ -607,8 +610,11 @@ 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_btc() as u64, 20_000,); + assert_eq!( + drain_output.value.to_btc() as u64, + 30_000 - fee.unwrap_or(0) + ); } #[test] @@ -625,7 +631,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_btc() as u64, + 50_000 - fee.unwrap_or(0) + ); } #[test] @@ -678,7 +687,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_btc() as u64, + 50_000 - fee.unwrap_or(0) + ); } #[test] @@ -695,7 +707,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_btc() as u64, + 50_000 - fee.unwrap_or(0) + ); } #[test] @@ -725,8 +740,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_btc() as u64, 25_000); + assert_eq!( + psbt.unsigned_tx.output[1].value.to_btc() as u64, + 25_000 - fee.unwrap_or(0) + ); } #[test] @@ -739,7 +757,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_btc() as u64, 49_800); assert_eq!(fee.unwrap_or(0), 200); } @@ -770,9 +788,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_btc() as u64, + 10_000 - fee.unwrap_or(0) + ); + assert_eq!(psbt.unsigned_tx.output[1].value.to_btc() as u64, 10_000); + assert_eq!(psbt.unsigned_tx.output[2].value.to_btc() as u64, 30_000); } #[test] @@ -906,7 +927,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)); } @@ -970,10 +991,10 @@ fn test_create_tx_add_utxo() { let small_output_tx = Transaction { input: vec![], output: vec![TxOut { - value: 25_000, + value: Amount::from_int_btc(25_000), script_pubkey: wallet.get_address(New).address.script_pubkey(), }], - version: 0, + version: Version(0), lock_time: absolute::LockTime::ZERO, }; wallet @@ -995,7 +1016,7 @@ 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_unchecked_fee_rate()); assert_eq!( psbt.unsigned_tx.input.len(), @@ -1015,10 +1036,10 @@ fn test_create_tx_manually_selected_insufficient() { let small_output_tx = Transaction { input: vec![], output: vec![TxOut { - value: 25_000, + value: Amount::from_int_btc(25_000), script_pubkey: wallet.get_address(New).address.script_pubkey(), }], - version: 0, + version: Version(0), lock_time: absolute::LockTime::ZERO, }; @@ -1063,11 +1084,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: Version(0), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 50_000, + value: Amount::from_int_btc(50_000), script_pubkey: wallet.get_address(New).script_pubkey(), }], }; @@ -1147,7 +1168,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(); @@ -1185,7 +1206,7 @@ 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_unchecked_fee_rate()); assert_eq!( sent_received.0 - sent_received.1, @@ -1259,7 +1280,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_unchecked_fee_rate(); wallet1.calculate_fee(&tx).unwrap(); } @@ -1428,7 +1449,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); @@ -1447,8 +1468,8 @@ 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 txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1464,8 +1485,8 @@ 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 txid = tx.txid(); + let tx = psbt.clone().extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx( @@ -1491,8 +1512,8 @@ fn test_bump_fee_low_fee_rate() { .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) @@ -1514,8 +1535,8 @@ fn test_bump_fee_low_abs() { .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) @@ -1537,8 +1558,8 @@ fn test_bump_fee_zero_abs() { .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1559,11 +1580,12 @@ 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_unchecked_fee_rate()); let original_fee = check_fee!(wallet, psbt); - let tx = psbt.extract_tx(); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1571,7 +1593,7 @@ fn test_bump_fee_reduce_change() { let mut builder = wallet.build_fee_bump(txid).unwrap(); builder.fee_rate(FeeRate::from_sat_per_vb(2.5)).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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0); @@ -1588,7 +1610,8 @@ fn test_bump_fee_reduce_change() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 25_000 ); assert_eq!( @@ -1596,7 +1619,8 @@ fn test_bump_fee_reduce_change() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, sent_received.1 ); @@ -1606,7 +1630,7 @@ 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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0); @@ -1628,7 +1652,8 @@ fn test_bump_fee_reduce_change() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 25_000 ); assert_eq!( @@ -1636,7 +1661,8 @@ fn test_bump_fee_reduce_change() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, sent_received.1 ); @@ -1655,10 +1681,10 @@ fn test_bump_fee_reduce_single_recipient() { .drain_wallet() .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.clone().extract_tx(); - let original_sent_received = wallet.sent_and_received(&tx); + let tx = psbt.clone().extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); let original_fee = check_fee!(wallet, psbt); - let txid = tx.txid(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1669,7 +1695,7 @@ 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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0); @@ -1677,7 +1703,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_btc() as u64 + fee.unwrap_or(0), + sent_received.0 + ); assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature); } @@ -1695,9 +1724,9 @@ 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 original_sent_received = wallet.sent_and_received(&tx); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1716,7 +1745,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_btc() as u64 + fee.unwrap_or(0), + sent_received.0 + ); assert_eq!(fee.unwrap_or(0), 300); } @@ -1726,11 +1758,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: Version(1), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 25_000, + value: Amount::from_int_btc(25_000), script_pubkey: wallet.get_address(New).script_pubkey(), }], }; @@ -1758,10 +1790,10 @@ fn test_bump_fee_drain_wallet() { .manually_selected_only() .enable_rbf(); let psbt = builder.finish().unwrap(); - let tx = psbt.extract_tx(); - let original_sent_received = wallet.sent_and_received(&tx); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); - let txid = tx.txid(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1776,7 +1808,7 @@ fn test_bump_fee_drain_wallet() { .unwrap() .fee_rate(FeeRate::from_sat_per_vb(5.0)); 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_unchecked_fee_rate()); assert_eq!(sent_received.0, 75_000); } @@ -1791,12 +1823,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: Version(1), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { script_pubkey: wallet.get_address(New).script_pubkey(), - value: 25_000, + value: Amount::from_int_btc(25_000), }], }; wallet @@ -1826,9 +1858,9 @@ 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 original_sent_received = wallet.sent_and_received(&tx); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1845,12 +1877,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: Version(1), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { script_pubkey: wallet.get_address(New).script_pubkey(), - value: 25_000, + value: Amount::from_int_btc(25_000), }], }; let pos = wallet @@ -1870,9 +1902,9 @@ 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 original_details = wallet.sent_and_received(&tx); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_details = wallet.sent_and_received(&tx.clone()); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1880,7 +1912,7 @@ fn test_bump_fee_add_input() { let mut builder = wallet.build_fee_bump(txid).unwrap(); builder.fee_rate(FeeRate::from_sat_per_vb(50.0)); 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_unchecked_fee_rate()); 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); @@ -1893,7 +1925,8 @@ fn test_bump_fee_add_input() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 45_000 ); assert_eq!( @@ -1901,7 +1934,8 @@ fn test_bump_fee_add_input() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, sent_received.1 ); @@ -1920,9 +1954,9 @@ 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 original_sent_received = wallet.sent_and_received(&tx); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1930,7 +1964,7 @@ 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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0 + 25_000); @@ -1944,7 +1978,8 @@ fn test_bump_fee_absolute_add_input() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 45_000 ); assert_eq!( @@ -1952,7 +1987,8 @@ fn test_bump_fee_absolute_add_input() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, sent_received.1 ); @@ -1976,11 +2012,12 @@ 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_unchecked_fee_rate()); let original_fee = check_fee!(wallet, psbt); - let tx = psbt.extract_tx(); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -1990,7 +2027,7 @@ 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(50.0)); 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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); let original_send_all_amount = original_sent_received.0 - original_fee.unwrap_or(0); @@ -2008,7 +2045,8 @@ fn test_bump_fee_no_change_add_input_and_change() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, original_send_all_amount ); assert_eq!( @@ -2016,7 +2054,8 @@ fn test_bump_fee_no_change_add_input_and_change() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 75_000 - original_send_all_amount - fee.unwrap_or(0) ); @@ -2035,17 +2074,18 @@ 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_unchecked_fee_rate()); let original_fee = check_fee!(wallet, psbt); - let mut tx = psbt.extract_tx(); - for txin in &mut tx.input { + let tx = psbt.extract_tx_unchecked_fee_rate(); + for txin in &mut tx.clone().input { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // to get realistic weight } - let original_tx_weight = tx.weight(); - assert_eq!(tx.input.len(), 1); - assert_eq!(tx.output.len(), 2); - let txid = tx.txid(); + let original_tx_weight = tx.clone().weight(); + assert_eq!(tx.clone().input.len(), 1); + assert_eq!(tx.clone().output.len(), 2); + let txid = tx.clone().txid(); wallet .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); @@ -2067,7 +2107,7 @@ fn test_bump_fee_add_input_change_dust() { let fee_abs = 50_000 + 25_000 - 45_000 - 10; builder.fee_rate(FeeRate::from_wu(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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(original_sent_received.1, 5_000 - original_fee.unwrap_or(0)); @@ -2084,7 +2124,8 @@ fn test_bump_fee_add_input_change_dust() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 45_000 ); @@ -2104,14 +2145,17 @@ 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 original_sent_received = wallet.sent_and_received(&tx); - let txid = tx.txid(); - for txin in &mut tx.input { + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); + let txid = tx.clone().txid(); + for txin in &mut tx.clone().input { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet - .insert_tx(tx.clone(), ConfirmationTime::Unconfirmed { last_seen: 0 }) + .insert_tx( + tx.clone().clone(), + ConfirmationTime::Unconfirmed { last_seen: 0 }, + ) .unwrap(); // the new fee_rate is low enough that just reducing the change would be fine, but we force // the addition of an extra input with `add_utxo()` @@ -2121,7 +2165,7 @@ fn test_bump_fee_force_add_input() { .unwrap() .fee_rate(FeeRate::from_sat_per_vb(5.0)); 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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0 + 25_000); @@ -2135,7 +2179,8 @@ fn test_bump_fee_force_add_input() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 45_000 ); assert_eq!( @@ -2143,7 +2188,8 @@ fn test_bump_fee_force_add_input() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, sent_received.1 ); @@ -2163,11 +2209,11 @@ 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 original_sent_received = wallet.sent_and_received(&tx); - let txid = tx.txid(); + let tx = psbt.extract_tx_unchecked_fee_rate(); + let original_sent_received = wallet.sent_and_received(&tx.clone()); + let txid = tx.clone().txid(); // skip saving the new utxos, we know they can't be used anyways - for txin in &mut tx.input { + for txin in &mut tx.clone().input { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet @@ -2179,7 +2225,7 @@ 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_unchecked_fee_rate()); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0 + 25_000); @@ -2193,7 +2239,8 @@ fn test_bump_fee_absolute_force_add_input() { .iter() .find(|txout| txout.script_pubkey == addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, 45_000 ); assert_eq!( @@ -2201,7 +2248,8 @@ fn test_bump_fee_absolute_force_add_input() { .iter() .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() - .value, + .value + .to_btc() as u64, sent_received.1 ); @@ -2234,9 +2282,9 @@ fn test_bump_fee_unconfirmed_inputs_only() { 25_000, ConfirmationTime::Unconfirmed { last_seen: 0 }, ); - let mut tx = psbt.extract_tx(); - let txid = tx.txid(); - for txin in &mut tx.input { + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); + for txin in &mut tx.clone().input { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet @@ -2267,9 +2315,9 @@ 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 txid = tx.txid(); - for txin in &mut tx.input { + let tx = psbt.extract_tx_unchecked_fee_rate(); + let txid = tx.clone().txid(); + for txin in &mut tx.clone().input { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet @@ -2326,7 +2374,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_unchecked_fee_rate(); assert_eq!(extracted.input[0].witness.len(), 2); } @@ -2341,7 +2389,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_unchecked_fee_rate(); assert_eq!(extracted.input[0].witness.len(), 2); } @@ -2356,7 +2404,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_unchecked_fee_rate(); assert_eq!(extracted.input[0].witness.len(), 2); } @@ -2371,7 +2419,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_unchecked_fee_rate(); assert_eq!(extracted.input[0].witness.len(), 2); } @@ -2387,7 +2435,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_unchecked_fee_rate(); assert_eq!(extracted.input[0].witness.len(), 2); } @@ -2405,7 +2453,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_unchecked_fee_rate(); assert_eq!(extracted.input[0].witness.len(), 2); } @@ -2443,7 +2491,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_int_btc(100_000), script_pubkey: miniscript::Descriptor::::from_str( "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)", ) @@ -2576,7 +2624,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_unchecked_fee_rate(); assert_eq!( *extracted.input[0].witness.to_vec()[0].last().unwrap(), sighash.to_u32() as u8, @@ -2747,7 +2795,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)), @@ -2798,7 +2846,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(); @@ -3047,7 +3095,7 @@ 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_unchecked_fee_rate()); wallet1.insert_txout(utxo.outpoint, utxo.txout); let fee = check_fee!(wallet1, psbt); @@ -3355,7 +3403,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_unchecked_fee_rate(); assert_eq!( *extracted.input[0].witness.to_vec()[0].last().unwrap(), sighash as u8, @@ -3376,14 +3424,14 @@ fn test_spend_coinbase() { }) .unwrap(); let coinbase_tx = Transaction { - version: 1, + version: Version(1), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], output: vec![TxOut { - value: 25_000, + value: Amount::from_int_btc(25_000), script_pubkey: wallet.get_address(New).address.script_pubkey(), }], }; @@ -3645,7 +3693,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_unchecked_fee_rate()); let psbt3 = new_tx!(wallet); let change_derivation_3 = psbt3 @@ -3665,7 +3713,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_unchecked_fee_rate()); 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 545ff806a..770a13a20 100644 --- a/crates/bitcoind_rpc/Cargo.toml +++ b/crates/bitcoind_rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "bdk_bitcoind_rpc" version = "0.3.0" edition = "2021" -rust-version = "1.63" +rust-version = "1.70" homepage = "https://bitcoindevkit.org" repository = "https://github.com/bitcoindevkit/bdk" documentation = "https://docs.rs/bdk_bitcoind_rpc" @@ -14,12 +14,12 @@ 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.8", default-features = false } [dev-dependencies] -bitcoind = { version = "0.33", features = ["25_0"] } +bitcoind = { version = "0.34", features = ["25_0"] } anyhow = { version = "1" } [features] diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index 52d709301..4911bcc57 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -9,8 +9,8 @@ use bdk_chain::{ }; use bitcoin::{ address::NetworkChecked, block::Header, hash_types::TxMerkleNode, hashes::Hash, - secp256k1::rand::random, Block, CompactTarget, OutPoint, ScriptBuf, ScriptHash, Transaction, - TxIn, TxOut, WScriptHash, + secp256k1::rand::random, transaction::Version, Block, CompactTarget, OutPoint, ScriptBuf, + ScriptHash, Transaction, TxIn, TxOut, WScriptHash, }; use bitcoincore_rpc::{ bitcoincore_rpc_json::{GetBlockTemplateModes, GetBlockTemplateRules}, @@ -59,7 +59,7 @@ impl TestEnv { )?; let txdata = vec![Transaction { - version: 1, + version: Version(1), lock_time: bitcoin::absolute::LockTime::from_height(0)?, input: vec![TxIn { previous_output: bitcoin::OutPoint::default(), @@ -72,7 +72,7 @@ impl TestEnv { witness: bitcoin::Witness::new(), }], output: vec![TxOut { - value: 0, + value: Amount::from_int_btc(0), script_pubkey: ScriptBuf::new_p2sh(&ScriptHash::all_zeros()), }], }]; @@ -473,7 +473,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { // setup addresses let addr_to_mine = env.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 @@ -513,7 +513,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { assert_eq!( get_balance(&recv_chain, &recv_graph)?, Balance { - confirmed: SEND_AMOUNT.to_sat() * ADDITIONAL_COUNT as u64, + confirmed: SEND_AMOUNT.to_btc() as u64 * ADDITIONAL_COUNT as u64, ..Balance::default() }, "initial balance must be correct", @@ -527,8 +527,8 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> { assert_eq!( get_balance(&recv_chain, &recv_graph)?, Balance { - confirmed: SEND_AMOUNT.to_sat() * (ADDITIONAL_COUNT - reorg_count) as u64, - trusted_pending: SEND_AMOUNT.to_sat() * reorg_count as u64, + confirmed: SEND_AMOUNT.to_btc() as u64 * (ADDITIONAL_COUNT - reorg_count) as u64, + trusted_pending: SEND_AMOUNT.to_btc() as u64 * reorg_count as u64, ..Balance::default() }, "reorg_count: {}", diff --git a/crates/chain/Cargo.toml b/crates/chain/Cargo.toml index b94c478ba..f1493fb5d 100644 --- a/crates/chain/Cargo.toml +++ b/crates/chain/Cargo.toml @@ -2,7 +2,7 @@ name = "bdk_chain" version = "0.8.0" edition = "2021" -rust-version = "1.63" +rust-version = "1.70" homepage = "https://bitcoindevkit.org" repository = "https://github.com/bitcoindevkit/bdk" documentation = "https://docs.rs/bdk_chain" @@ -14,13 +14,13 @@ 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.1", default-features = false } serde_crate = { package = "serde", version = "1", optional = true, features = ["derive"] } # Use hashbrown as a feature flag to have HashSet and HashMap from it. # note versions > 0.9.1 breaks ours 1.57.0 MSRV. -hashbrown = { version = "0.9.1", optional = true, features = ["serde"] } -miniscript = { version = "10.0.0", optional = true, default-features = false } +hashbrown = { version = "0.14.3", optional = true, features = ["serde"] } +miniscript = { version = "11.0.0", optional = true, default-features = false } [dev-dependencies] rand = "0.8" diff --git a/crates/chain/src/descriptor_ext.rs b/crates/chain/src/descriptor_ext.rs index 4c77c160b..873295484 100644 --- a/crates/chain/src/descriptor_ext.rs +++ b/crates/chain/src/descriptor_ext.rs @@ -13,6 +13,6 @@ impl DescriptorExt for Descriptor { .expect("descriptor can't have hardened derivation") .script_pubkey() .dust_value() - .to_sat() + .to_btc() as u64 } } diff --git a/crates/chain/src/spk_txout_index.rs b/crates/chain/src/spk_txout_index.rs index 90ee7dcab..fd31e4b89 100644 --- a/crates/chain/src/spk_txout_index.rs +++ b/crates/chain/src/spk_txout_index.rs @@ -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_btc() as u64; } } for txout in &tx.output { if self.index_of_spk(&txout.script_pubkey).is_some() { - received += txout.value; + received += txout.value.to_btc() as u64; } } diff --git a/crates/chain/src/tx_graph.rs b/crates/chain/src/tx_graph.rs index 66d1e9502..18de18400 100644 --- a/crates/chain/src/tx_graph.rs +++ b/crates/chain/src/tx_graph.rs @@ -300,7 +300,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); } @@ -312,7 +312,7 @@ impl TxGraph { (sum, missing_outpoints) } Some(txout) => { - sum += txout.value as i64; + sum += txout.value.to_btc() as u64 as i64; (sum, missing_outpoints) } }, @@ -324,8 +324,8 @@ impl TxGraph { let outputs_sum = tx .output .iter() - .map(|txout| txout.value as i64) - .sum::(); + .map(|txout| txout.value.to_btc() as u64) + .sum::() as i64; let fee = inputs_sum - outputs_sum; if fee < 0 { @@ -773,7 +773,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.is_coin_base() { + if tx.is_coinbase() { return Ok(None); } tx @@ -1025,7 +1025,7 @@ impl TxGraph { txout, chain_position, spent_by, - is_on_coinbase: tx_node.tx.is_coin_base(), + is_on_coinbase: tx_node.tx.is_coinbase(), }, ))) }, @@ -1128,16 +1128,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_btc() as u64; } else if !txout.is_mature(chain_tip.height) { - immature += txout.txout.value; + immature += txout.txout.value.to_btc() as u64; } } ChainPosition::Unconfirmed(_) => { if trust_predicate(&spk_i, &txout.txout.script_pubkey) { - trusted_pending += txout.txout.value; + trusted_pending += txout.txout.value.to_btc() as u64; } else { - untrusted_pending += txout.txout.value; + untrusted_pending += txout.txout.value.to_btc() as u64; } } } diff --git a/crates/chain/tests/common/mod.rs b/crates/chain/tests/common/mod.rs index 7cc3f57a9..8319657cb 100644 --- a/crates/chain/tests/common/mod.rs +++ b/crates/chain/tests/common/mod.rs @@ -1,4 +1,5 @@ mod tx_template; +use bitcoin::transaction::Version; #[allow(unused_imports)] pub use tx_template::*; @@ -70,7 +71,7 @@ macro_rules! changeset { #[allow(unused)] pub fn new_tx(lt: u32) -> bitcoin::Transaction { bitcoin::Transaction { - version: 0x00, + version: Version(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 605a0ba7e..fe4cd1cd5 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, BlockId, SpkTxOutIndex}; use bitcoin::{ - locktime::absolute::LockTime, secp256k1::Secp256k1, OutPoint, ScriptBuf, Sequence, Transaction, - TxIn, TxOut, Txid, Witness, + locktime::absolute::LockTime, secp256k1::Secp256k1, transaction::Version, Amount, OutPoint, + ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, }; use miniscript::Descriptor; @@ -68,7 +68,7 @@ pub fn init_graph<'a>( for (bogus_txin_vout, tx_tmp) in tx_templates.into_iter().enumerate() { let tx = Transaction { - version: 0, + version: Version(0), lock_time: LockTime::ZERO, input: tx_tmp .inputs @@ -111,11 +111,11 @@ pub fn init_graph<'a>( .iter() .map(|output| match &output.spk_index { None => TxOut { - value: output.value, + value: Amount::from_int_btc(output.value), script_pubkey: ScriptBuf::new(), }, Some(index) => TxOut { - value: output.value, + value: Amount::from_int_btc(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 41b1d4d3e..7be62f213 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, BlockId, 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_int_btc(10_000), script_pubkey: spk_0, }, TxOut { - value: 20_000, + value: Amount::from_int_btc(20_000), script_pubkey: spk_1, }, ], @@ -155,7 +157,7 @@ fn test_list_owned_txouts() { ..Default::default() }], output: vec![TxOut { - value: 70000, + value: Amount::from_int_btc(70000), script_pubkey: trusted_spks[0].to_owned(), }], ..common::new_tx(0) @@ -164,7 +166,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_int_btc(30000), script_pubkey: untrusted_spks[0].to_owned(), }], ..common::new_tx(0) @@ -177,7 +179,7 @@ fn test_list_owned_txouts() { ..Default::default() }], output: vec![TxOut { - value: 10000, + value: Amount::from_int_btc(10000), script_pubkey: trusted_spks[1].to_owned(), }], ..common::new_tx(0) @@ -186,7 +188,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_int_btc(20000), script_pubkey: untrusted_spks[1].to_owned(), }], ..common::new_tx(0) @@ -195,7 +197,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_int_btc(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 0bbc37393..115752a24 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_int_btc(10_000), }, TxOut { script_pubkey: internal_desc .at_derivation_index(internal_index) .unwrap() .script_pubkey(), - value: 10_000, + value: Amount::from_int_btc(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::from_int_btc(0), }; 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::from_int_btc(0), }; 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..a11877bcc 100644 --- a/crates/chain/tests/test_spk_txout_index.rs +++ b/crates/chain/tests/test_spk_txout_index.rs @@ -1,5 +1,7 @@ use bdk_chain::{indexed_tx_graph::Indexer, SpkTxOutIndex}; -use bitcoin::{absolute, OutPoint, ScriptBuf, Transaction, TxIn, TxOut}; +use bitcoin::{ + absolute, transaction::Version, Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, +}; #[test] fn spk_txout_sent_and_received() { @@ -11,11 +13,11 @@ fn spk_txout_sent_and_received() { index.insert_spk(1, spk2.clone()); let tx1 = Transaction { - version: 0x02, + version: bitcoin::transaction::Version(0x02), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, + value: Amount::from_int_btc(42_000), script_pubkey: spk1.clone(), }], }; @@ -30,7 +32,7 @@ fn spk_txout_sent_and_received() { ); let tx2 = Transaction { - version: 0x1, + version: Version(0x1), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { @@ -41,12 +43,12 @@ fn spk_txout_sent_and_received() { }], output: vec![ TxOut { - value: 20_000, + value: Amount::from_int_btc(20_000), script_pubkey: spk2, }, TxOut { script_pubkey: spk1, - value: 30_000, + value: Amount::from_int_btc(30_000), }, ], }; @@ -73,11 +75,11 @@ fn mark_used() { assert!(spk_index.is_used(&1)); let tx1 = Transaction { - version: 0x02, + version: Version(0x02), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, + value: Amount::from_int_btc(42_000), script_pubkey: spk1, }], }; diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index a71e24f99..1509cdeb7 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::Version, Amount, BlockHash, OutPoint, ScriptBuf, + Transaction, TxIn, TxOut, Txid, }; use core::iter; use std::vec; @@ -20,14 +21,14 @@ fn insert_txouts() { ( OutPoint::new(h!("tx1"), 1), TxOut { - value: 10_000, + value: Amount::from_int_btc(10_000), script_pubkey: ScriptBuf::new(), }, ), ( OutPoint::new(h!("tx1"), 2), TxOut { - value: 20_000, + value: Amount::from_int_btc(20_000), script_pubkey: ScriptBuf::new(), }, ), @@ -37,21 +38,21 @@ fn insert_txouts() { let update_ops = [( OutPoint::new(h!("tx2"), 0), TxOut { - value: 20_000, + value: Amount::from_int_btc(20_000), script_pubkey: ScriptBuf::new(), }, )]; // One full transaction to be included in the update let update_txs = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], output: vec![TxOut { - value: 30_000, + value: Amount::from_int_btc(30_000), script_pubkey: ScriptBuf::new(), }], }; @@ -161,14 +162,14 @@ fn insert_txouts() { ( 1u32, &TxOut { - value: 10_000, + value: Amount::from_int_btc(10_000), script_pubkey: ScriptBuf::new(), } ), ( 2u32, &TxOut { - value: 20_000, + value: Amount::from_int_btc(20_000), script_pubkey: ScriptBuf::new(), } ) @@ -181,7 +182,7 @@ fn insert_txouts() { [( 0u32, &TxOut { - value: 30_000, + value: Amount::from_int_btc(30_000), script_pubkey: ScriptBuf::new() } )] @@ -203,7 +204,7 @@ fn insert_txouts() { #[test] fn insert_tx_graph_doesnt_count_coinbase_as_spent() { let tx = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), @@ -221,10 +222,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: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], }; let op = OutPoint { @@ -233,7 +234,7 @@ fn insert_tx_graph_keeps_track_of_spend() { }; let tx2 = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: op, @@ -262,13 +263,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: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], }; let mut graph = TxGraph::<()>::default(); @@ -280,11 +281,11 @@ 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: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, + value: Amount::from_int_btc(42_000), script_pubkey: ScriptBuf::default(), }], }; @@ -295,7 +296,7 @@ fn insert_tx_displaces_txouts() { vout: 0, }, TxOut { - value: 1_337_000, + value: Amount::from_int_btc(1_337_000), script_pubkey: ScriptBuf::default(), }, ); @@ -306,7 +307,7 @@ fn insert_tx_displaces_txouts() { vout: 0, }, TxOut { - value: 1_000_000_000, + value: Amount::from_int_btc(1_000_000_000), script_pubkey: ScriptBuf::default(), }, ); @@ -321,7 +322,7 @@ fn insert_tx_displaces_txouts() { }) .unwrap() .value, - 42_000 + Amount::from_int_btc(42_000) ); assert_eq!( tx_graph.get_txout(OutPoint { @@ -336,11 +337,11 @@ fn insert_tx_displaces_txouts() { fn insert_txout_does_not_displace_tx() { let mut tx_graph = TxGraph::<()>::default(); let tx = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 42_000, + value: Amount::from_int_btc(42_000), script_pubkey: ScriptBuf::default(), }], }; @@ -353,7 +354,7 @@ fn insert_txout_does_not_displace_tx() { vout: 0, }, TxOut { - value: 1_337_000, + value: Amount::from_int_btc(1_337_000), script_pubkey: ScriptBuf::default(), }, ); @@ -364,7 +365,7 @@ fn insert_txout_does_not_displace_tx() { vout: 0, }, TxOut { - value: 1_000_000_000, + value: Amount::from_int_btc(1_000_000_000), script_pubkey: ScriptBuf::default(), }, ); @@ -377,7 +378,7 @@ fn insert_txout_does_not_displace_tx() { }) .unwrap() .value, - 42_000 + Amount::from_int_btc(42_000) ); assert_eq!( tx_graph.get_txout(OutPoint { @@ -392,21 +393,21 @@ fn insert_txout_does_not_displace_tx() { fn test_calculate_fee() { let mut graph = TxGraph::<()>::default(); let intx1 = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 100, - ..Default::default() + value: Amount::from_int_btc(100), + script_pubkey: ScriptBuf::default(), }], }; let intx2 = Transaction { - version: 0x02, + version: Version(0x02), lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![TxOut { - value: 200, - ..Default::default() + value: Amount::from_int_btc(200), + script_pubkey: ScriptBuf::default(), }], }; @@ -416,8 +417,8 @@ fn test_calculate_fee() { vout: 0, }, TxOut { - value: 300, - ..Default::default() + value: Amount::from_int_btc(300), + script_pubkey: ScriptBuf::default(), }, ); @@ -426,7 +427,7 @@ fn test_calculate_fee() { let _ = graph.insert_txout(intxout1.0, intxout1.1); let mut tx = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![ TxIn { @@ -449,8 +450,8 @@ fn test_calculate_fee() { }, ], output: vec![TxOut { - value: 500, - ..Default::default() + value: Amount::from_int_btc(500), + script_pubkey: ScriptBuf::default(), }], }; @@ -482,13 +483,13 @@ fn test_calculate_fee() { #[test] fn test_calculate_fee_on_coinbase() { let tx = Transaction { - version: 0x01, + version: Version(0x01), lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint::null(), ..Default::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], }; let graph = TxGraph::<()>::default(); @@ -524,7 +525,10 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(h!("op0"), 0), ..TxIn::default() }], - output: vec![TxOut::default(), TxOut::default()], + output: vec![ + TxOut::minimal_non_dust(ScriptBuf::default()), + TxOut::minimal_non_dust(ScriptBuf::default()), + ], ..common::new_tx(0) }; @@ -534,7 +538,10 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_a0.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default(), TxOut::default()], + output: vec![ + TxOut::minimal_non_dust(ScriptBuf::default()), + TxOut::minimal_non_dust(ScriptBuf::default()), + ], ..common::new_tx(0) }; @@ -544,7 +551,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_a0.txid(), 1), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -553,7 +560,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(h!("op1"), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -563,7 +570,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_b0.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -573,7 +580,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_b0.txid(), 1), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -589,7 +596,7 @@ fn test_walk_ancestors() { ..TxIn::default() }, ], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -598,7 +605,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(h!("op2"), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -608,7 +615,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_c1.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -624,7 +631,7 @@ fn test_walk_ancestors() { ..TxIn::default() }, ], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -634,7 +641,7 @@ fn test_walk_ancestors() { previous_output: OutPoint::new(tx_d1.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -710,7 +717,7 @@ fn test_conflicting_descendants() { previous_output, ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(0) }; @@ -720,7 +727,10 @@ fn test_conflicting_descendants() { previous_output, ..TxIn::default() }], - output: vec![TxOut::default(), TxOut::default()], + output: vec![ + TxOut::minimal_non_dust(ScriptBuf::default()), + TxOut::minimal_non_dust(ScriptBuf::default()), + ], ..common::new_tx(1) }; @@ -730,7 +740,7 @@ fn test_conflicting_descendants() { previous_output: OutPoint::new(tx_a.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(2) }; @@ -752,7 +762,11 @@ 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::minimal_non_dust(ScriptBuf::default()), + TxOut::minimal_non_dust(ScriptBuf::default()), + TxOut::minimal_non_dust(ScriptBuf::default()), + ], ..common::new_tx(0) }; @@ -762,7 +776,7 @@ fn test_descendants_no_repeat() { previous_output: OutPoint::new(tx_a.txid(), vout), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(1) }) .collect::>(); @@ -773,7 +787,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::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(2) }) .collect::>(); @@ -789,7 +803,7 @@ fn test_descendants_no_repeat() { ..TxIn::default() }, ], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(3) }; @@ -798,7 +812,7 @@ fn test_descendants_no_repeat() { previous_output: OutPoint::new(tx_d.txid(), 0), ..TxIn::default() }], - output: vec![TxOut::default()], + output: vec![TxOut::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(4) }; @@ -808,7 +822,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::minimal_non_dust(ScriptBuf::default())], ..common::new_tx(v) }) .collect::>(); @@ -855,11 +869,11 @@ fn test_chain_spends() { input: vec![], output: vec![ TxOut { - value: 10_000, + value: Amount::from_int_btc(10_000), script_pubkey: ScriptBuf::new(), }, TxOut { - value: 20_000, + value: Amount::from_int_btc(20_000), script_pubkey: ScriptBuf::new(), }, ], @@ -874,11 +888,11 @@ fn test_chain_spends() { }], output: vec![ TxOut { - value: 5_000, + value: Amount::from_int_btc(5_000), script_pubkey: ScriptBuf::new(), }, TxOut { - value: 5_000, + value: Amount::from_int_btc(5_000), script_pubkey: ScriptBuf::new(), }, ], @@ -893,11 +907,11 @@ fn test_chain_spends() { }], output: vec![ TxOut { - value: 10_000, + value: Amount::from_int_btc(10_000), script_pubkey: ScriptBuf::new(), }, TxOut { - value: 10_000, + value: Amount::from_int_btc(10_000), script_pubkey: ScriptBuf::new(), }, ], diff --git a/crates/electrum/Cargo.toml b/crates/electrum/Cargo.toml index b0e05264c..f0dc82018 100644 --- a/crates/electrum/Cargo.toml +++ b/crates/electrum/Cargo.toml @@ -13,5 +13,5 @@ readme = "README.md" [dependencies] bdk_chain = { path = "../chain", version = "0.8.0", default-features = false } -electrum-client = { version = "0.18" } +electrum-client = { version = "0.19" } #rustls = { version = "=0.21.1", optional = true, features = ["dangerous_configuration"] } diff --git a/crates/esplora/Cargo.toml b/crates/esplora/Cargo.toml index f4e3d0fe9..c22ae3661 100644 --- a/crates/esplora/Cargo.toml +++ b/crates/esplora/Cargo.toml @@ -13,16 +13,17 @@ readme = "README.md" [dependencies] bdk_chain = { path = "../chain", version = "0.8.0", default-features = false } -esplora-client = { version = "0.6.0", default-features = false } -async-trait = { version = "0.1.66", optional = true } -futures = { version = "0.3.26", optional = true } +# esplora-client = { version = "0.6.0", default-features = false } +esplora-client = {git ="https://github.com/getong/rust-esplora-client", branch = "fix-update", default-features = false } +async-trait = { version = "0.1.77", optional = true } +futures = { version = "0.3.30", 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.1", optional = true, default-features = false } +miniscript = { version = "11.0.0", optional = true, default-features = false } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] -electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } +electrsd = { version= "0.27.1", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [features] diff --git a/crates/hwi/Cargo.toml b/crates/hwi/Cargo.toml index 660b9deff..8923d136a 100644 --- a/crates/hwi/Cargo.toml +++ b/crates/hwi/Cargo.toml @@ -10,4 +10,5 @@ readme = "README.md" [dependencies] bdk = { path = "../bdk" } -hwi = { version = "0.7.0", features = [ "miniscript"] } +# hwi = { version = "0.7.0", features = [ "miniscript"] } +hwi = {git ="https://github.com/tcharding/rust-hwi", branch = "10-16-upgrade-bitcoin", features = [ "miniscript"] } diff --git a/crates/hwi/src/signer.rs b/crates/hwi/src/signer.rs index b16b60c54..3f3fc9ecf 100644 --- a/crates/hwi/src/signer.rs +++ b/crates/hwi/src/signer.rs @@ -1,5 +1,5 @@ use bdk::bitcoin::bip32::Fingerprint; -use bdk::bitcoin::psbt::PartiallySignedTransaction; +use bdk::bitcoin::psbt::Psbt; use bdk::bitcoin::secp256k1::{All, Secp256k1}; use hwi::error::Error; @@ -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/example-crates/example_bitcoind_rpc_polling/Cargo.toml b/example-crates/example_bitcoind_rpc_polling/Cargo.toml index 6728bb13a..b9ed7ad36 100644 --- a/example-crates/example_bitcoind_rpc_polling/Cargo.toml +++ b/example-crates/example_bitcoind_rpc_polling/Cargo.toml @@ -9,4 +9,4 @@ edition = "2021" bdk_chain = { path = "../../crates/chain", features = ["serde"] } bdk_bitcoind_rpc = { path = "../../crates/bitcoind_rpc" } example_cli = { path = "../example_cli" } -ctrlc = { version = "^2" } +ctrlc = { version = "^3" } diff --git a/example-crates/example_bitcoind_rpc_polling/src/main.rs b/example-crates/example_bitcoind_rpc_polling/src/main.rs index 49fce4d9e..0574695c7 100644 --- a/example-crates/example_bitcoind_rpc_polling/src/main.rs +++ b/example-crates/example_bitcoind_rpc_polling/src/main.rs @@ -366,7 +366,7 @@ fn start_ctrlc_handler() -> Arc { let flag = Arc::new(AtomicBool::new(false)); let cloned_flag = flag.clone(); - ctrlc::set_handler(move || cloned_flag.store(true, Ordering::Release)); + _ = ctrlc::set_handler(move || cloned_flag.store(true, Ordering::Release)); flag } diff --git a/example-crates/example_cli/Cargo.toml b/example-crates/example_cli/Cargo.toml index c85d2e996..bf432adc0 100644 --- a/example-crates/example_cli/Cargo.toml +++ b/example-crates/example_cli/Cargo.toml @@ -11,7 +11,7 @@ bdk_file_store = { path = "../../crates/file_store" } bdk_tmp_plan = { path = "../../nursery/tmp_plan" } bdk_coin_select = { path = "../../nursery/coin_select" } -clap = { version = "3.2.23", features = ["derive", "env"] } +clap = { version = "4.4.18", features = ["derive", "env"] } anyhow = "1" serde = { version = "1", features = ["derive"] } serde_json = { version = "^1.0" } diff --git a/example-crates/example_cli/src/lib.rs b/example-crates/example_cli/src/lib.rs index cfc499a06..942ab14aa 100644 --- a/example-crates/example_cli/src/lib.rs +++ b/example-crates/example_cli/src/lib.rs @@ -3,12 +3,13 @@ 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, blockdata::transaction::Version, secp256k1::Secp256k1, + sighash::Prevouts, sighash::SighashCache, Address, Amount, Network, Sequence, Transaction, + TxIn, TxOut, }, indexed_tx_graph::{self, IndexedTxGraph}, keychain::{self, KeychainTxOutIndex}, @@ -189,7 +190,7 @@ impl core::fmt::Display for Keychain { pub fn create_tx( graph: &mut KeychainTxGraph, chain: &O, - keymap: &HashMap, + keymap: &BTreeMap, cs_algorithm: CoinSelectionAlgo, address: Address, value: u64, @@ -230,7 +231,7 @@ where .iter() .map(|(plan, utxo)| { WeightedValue::new( - utxo.txout.value, + utxo.txout.value.to_btc() as u64, plan.expected_weight() as _, plan.witness_version().is_some(), ) @@ -238,7 +239,7 @@ where .collect(); let mut outputs = vec![TxOut { - value, + value: Amount::from_int_btc(value), script_pubkey: address.script_pubkey(), }]; @@ -268,7 +269,7 @@ where .expect("failed to obtain change plan"); let mut change_output = TxOut { - value: 0, + value: Amount::from_int_btc(0), script_pubkey: change_script, }; @@ -306,13 +307,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_int_btc(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: Version(0x02), // 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) @@ -432,7 +433,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/wallet_electrum/src/main.rs b/example-crates/wallet_electrum/src/main.rs index 4f8aba9fd..144d881a6 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_unchecked_fee_rate(); 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..22ced57b3 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_unchecked_fee_rate(); 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..db187ccdf 100644 --- a/example-crates/wallet_esplora_blocking/src/main.rs +++ b/example-crates/wallet_esplora_blocking/src/main.rs @@ -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_unchecked_fee_rate(); client.broadcast(&tx)?; println!("Tx broadcasted! Txid: {}", tx.txid()); diff --git a/example-crates/wallet_rpc/Cargo.toml b/example-crates/wallet_rpc/Cargo.toml index 174144e9b..c9f432f38 100644 --- a/example-crates/wallet_rpc/Cargo.toml +++ b/example-crates/wallet_rpc/Cargo.toml @@ -11,5 +11,5 @@ bdk_file_store = { path = "../../crates/file_store" } bdk_bitcoind_rpc = { path = "../../crates/bitcoind_rpc" } anyhow = "1" -clap = { version = "3.2.25", features = ["derive", "env"] } -ctrlc = "2.0.1" +clap = { version = "4.4.18", features = ["derive", "env"] } +ctrlc = "3.4.2" diff --git a/example-crates/wallet_rpc/src/main.rs b/example-crates/wallet_rpc/src/main.rs index dc3b8bcdc..e4ef534d1 100644 --- a/example-crates/wallet_rpc/src/main.rs +++ b/example-crates/wallet_rpc/src/main.rs @@ -110,7 +110,7 @@ fn main() -> anyhow::Result<()> { let (sender, receiver) = sync_channel::(21); let signal_sender = sender.clone(); - ctrlc::set_handler(move || { + _ = ctrlc::set_handler(move || { signal_sender .send(Emission::SigTerm) .expect("failed to send sigterm") diff --git a/nursery/coin_select/src/coin_selector.rs b/nursery/coin_select/src/coin_selector.rs index 281992a96..b273bad52 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: bdk_chain::bitcoin::transaction::Version(1), 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_btc() as u64).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..22d93a2f1 100644 --- a/nursery/coin_select/src/lib.rs +++ b/nursery/coin_select/src/lib.rs @@ -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..b8e7a705a 100644 --- a/nursery/tmp_plan/src/lib.rs +++ b/nursery/tmp_plan/src/lib.rs @@ -17,8 +17,8 @@ use bdk_chain::{bitcoin, collections::*, miniscript}; use bitcoin::{ absolute, - address::WitnessVersion, bip32::{DerivationPath, Fingerprint, KeySource}, + blockdata::script::witness_version::WitnessVersion, blockdata::transaction::Sequence, ecdsa, hashes::{hash160, ripemd160, sha256}, @@ -32,7 +32,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..1aea81e6f 100644 --- a/nursery/tmp_plan/src/requirements.rs +++ b/nursery/tmp_plan/src/requirements.rs @@ -5,9 +5,9 @@ use bitcoin::{ bip32, hashes::{hash160, ripemd160, sha256}, key::XOnlyPublicKey, - psbt::Prevouts, - secp256k1::{KeyPair, Message, PublicKey, Signing, Verification}, + secp256k1::{Keypair, Message, PublicKey, Signing, Verification}, sighash, + sighash::Prevouts, sighash::{EcdsaSighashType, SighashCache, TapSighashType}, taproot, Transaction, TxOut, }; @@ -163,11 +163,12 @@ 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_slice(sighash.as_ref()).expect("Sighashes are 32 bytes"); let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair); let bitcoin_sig = taproot::Signature { @@ -209,9 +210,9 @@ 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_slice(sighash.as_ref()) + .expect("Sighashes are 32 bytes"); let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair); let bitcoin_sig = taproot::Signature { sig,