Merge bitcoindevkit/bdk#1177: Upgrade bitcoin/miniscript dependencies

984c758f964f8fee687d21885b43b0b4705f318c Upgrade miniscript/bitcoin dependency (Tobin C. Harding)

Pull request description:

  Upgrade:

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

  Fix: #1196

ACKs for top commit:
  ValuedMammal:
    ACK 984c758f964f8fee687d21885b43b0b4705f318c
  notmandatory:
    ACK 984c758f964f8fee687d21885b43b0b4705f318c
  oleonardolima:
    ACK 984c758f964f8fee687d21885b43b0b4705f318c
  storopoli:
    ACK 984c758f964f8fee687d21885b43b0b4705f318c

Tree-SHA512: d64d530e93cc36688ba07d3677d5c1689b61f246f05d08092bbf86ddbba8a5ec49648e6825b950ef17729dc064da50d50b793475a288862a0461976876807170
This commit is contained in:
Steve Myers 2024-04-12 10:48:48 -05:00
commit 358e842dcd
No known key found for this signature in database
GPG Key ID: 8105A46B22C2D051
49 changed files with 556 additions and 519 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -1137,7 +1137,7 @@ impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
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<Ctx>, DescriptorKey<Ctx>, 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();

View File

@ -195,7 +195,7 @@ impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
/// # 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<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
/// # 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<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
/// # 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<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
/// # 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<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
/// # 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<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
/// # 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<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
/// # 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<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
/// # 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),

View File

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

View File

@ -110,7 +110,7 @@ impl<Ctx: ScriptContext> DescriptorKey<Ctx> {
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<Ctx: ScriptContext>: 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<Ctx: ScriptContext = miniscript::Legacy> {
/// A private extended key, aka an `xprv`
Private((bip32::ExtendedPrivKey, PhantomData<Ctx>)),
Private((bip32::Xpriv, PhantomData<Ctx>)),
/// A public extended key, aka an `xpub`
Public((bip32::ExtendedPubKey, PhantomData<Ctx>)),
Public((bip32::Xpub, PhantomData<Ctx>)),
}
impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
@ -329,9 +329,9 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
}
}
/// Transform the [`ExtendedKey`] into an [`ExtendedPrivKey`](bip32::ExtendedPrivKey) for the
/// Transform the [`ExtendedKey`] into an [`Xpriv`](bip32::Xpriv) for the
/// given [`Network`], if the key contains the private data
pub fn into_xprv(self, network: Network) -> Option<bip32::ExtendedPrivKey> {
pub fn into_xprv(self, network: Network) -> Option<bip32::Xpriv> {
match self {
ExtendedKey::Private((mut xprv, _)) => {
xprv.network = network;
@ -341,15 +341,15 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
}
}
/// Transform the [`ExtendedKey`] into an [`ExtendedPubKey`](bip32::ExtendedPubKey) for the
/// Transform the [`ExtendedKey`] into an [`Xpub`](bip32::Xpub) for the
/// given [`Network`]
pub fn into_xpub<C: Signing>(
self,
network: bitcoin::Network,
secp: &Secp256k1<C>,
) -> 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<Ctx: ScriptContext> ExtendedKey<Ctx> {
}
}
impl<Ctx: ScriptContext> From<bip32::ExtendedPubKey> for ExtendedKey<Ctx> {
fn from(xpub: bip32::ExtendedPubKey) -> Self {
impl<Ctx: ScriptContext> From<bip32::Xpub> for ExtendedKey<Ctx> {
fn from(xpub: bip32::Xpub) -> Self {
ExtendedKey::Public((xpub, PhantomData))
}
}
impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
fn from(xprv: bip32::ExtendedPrivKey) -> Self {
impl<Ctx: ScriptContext> From<bip32::Xpriv> for ExtendedKey<Ctx> {
fn from(xprv: bip32::Xpriv) -> Self {
ExtendedKey::Private((xprv, PhantomData))
}
}
@ -383,8 +383,8 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
///
/// ## 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<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
///
/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
/// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
/// let xprv = bip32::ExtendedPrivKey {
/// let xprv = bip32::Xpriv {
/// network: self.network,
/// depth: 0,
/// parent_fingerprint: bip32::Fingerprint::default(),
@ -415,7 +415,7 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
///
/// Types that don't internally encode the [`Network`] in which they are valid need some extra
/// 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<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
///
/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
/// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
/// let xprv = bip32::ExtendedPrivKey {
/// let xprv = bip32::Xpriv {
/// network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
/// depth: 0,
/// parent_fingerprint: bip32::Fingerprint::default(),
@ -459,8 +459,8 @@ impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
/// ```
///
/// [`DerivationPath`]: (bip32::DerivationPath)
/// [`ExtendedPrivKey`]: (bip32::ExtendedPrivKey)
/// [`ExtendedPubKey`]: (bip32::ExtendedPubKey)
/// [`Xpriv`]: (bip32::Xpriv)
/// [`Xpub`]: (bip32::Xpub)
pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
/// Consume `self` and turn it into an [`ExtendedKey`]
#[cfg_attr(
@ -520,13 +520,13 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedKey<Ctx> {
}
}
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpub {
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
Ok(self.into())
}
}
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpriv {
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
Ok(self.into())
}
@ -670,7 +670,7 @@ where
{
}
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::ExtendedPrivKey {
impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
type Entropy = [u8; 32];
type Options = ();
@ -681,7 +681,7 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::ExtendedPrivKey {
entropy: Self::Entropy,
) -> Result<GeneratedKey<Self, Ctx>, 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");

View File

@ -9,12 +9,12 @@
// You may not use this file except in accordance with one or both of these
// licenses.
//! Additional functions on the `rust-bitcoin` `PartiallySignedTransaction` structure.
//! Additional functions on the `rust-bitcoin` `Psbt` structure.
use alloc::vec::Vec;
use bitcoin::psbt::PartiallySignedTransaction as Psbt;
use bitcoin::Amount;
use bitcoin::FeeRate;
use bitcoin::Psbt;
use bitcoin::TxOut;
// TODO upstream the functions here to `rust-bitcoin`?
@ -29,7 +29,7 @@ pub trait PsbtUtils {
fn fee_amount(&self) -> Option<u64>;
/// 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<FeeRate>;
@ -54,8 +54,13 @@ impl PsbtUtils for Psbt {
let utxos: Option<Vec<TxOut>> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect();
utxos.map(|inputs| {
let input_amount: u64 = inputs.iter().map(|i| i.value).sum();
let output_amount: u64 = self.unsigned_tx.output.iter().map(|o| o.value).sum();
let input_amount: u64 = inputs.iter().map(|i| i.value.to_sat()).sum();
let output_amount: u64 = self
.unsigned_tx
.output
.iter()
.map(|o| o.value.to_sat())
.sum();
input_amount
.checked_sub(output_amount)
.expect("input amount must be greater than output amount")
@ -64,9 +69,7 @@ impl PsbtUtils for Psbt {
fn fee_rate(&self) -> Option<FeeRate> {
let fee_amount = self.fee_amount();
fee_amount.map(|fee| {
let weight = self.clone().extract_tx().weight();
Amount::from_sat(fee) / weight
})
let weight = self.clone().extract_tx().ok()?.weight();
fee_amount.map(|fee| Amount::from_sat(fee) / weight)
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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