Upgrade miniscript/bitcoin dependency
Upgrade: - bitcoin to v0.31.0 - miniscript to v11.0.0 Note: The bitcoin upgrade includes improvements to the `Transaction::weight()` function, it appears those guys did good, we no longer need to add the 2 additional weight units "just in case".
This commit is contained in:
parent
53791eb6c5
commit
984c758f96
@ -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 }
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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),
|
||||
|
@ -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(
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,10 @@
|
||||
//! .scan(
|
||||
//! (&mut selected_amount, &mut additional_weight),
|
||||
//! |(selected_amount, additional_weight), weighted_utxo| {
|
||||
//! **selected_amount += weighted_utxo.utxo.txout().value;
|
||||
//! **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
|
||||
//! **additional_weight += Weight::from_wu(
|
||||
//! (TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight)
|
||||
//! (TxIn::default().segwit_weight().to_wu()
|
||||
//! + weighted_utxo.satisfaction_weight as u64)
|
||||
//! as u64,
|
||||
//! );
|
||||
//! Some(weighted_utxo.utxo)
|
||||
@ -192,7 +193,7 @@ pub struct CoinSelectionResult {
|
||||
impl CoinSelectionResult {
|
||||
/// The total value of the inputs selected.
|
||||
pub fn selected_amount(&self) -> u64 {
|
||||
self.selected.iter().map(|u| u.txout().value).sum()
|
||||
self.selected.iter().map(|u| u.txout().value.to_sat()).sum()
|
||||
}
|
||||
|
||||
/// The total value of the inputs selected from the local wallet.
|
||||
@ -200,7 +201,7 @@ impl CoinSelectionResult {
|
||||
self.selected
|
||||
.iter()
|
||||
.filter_map(|u| match u {
|
||||
Utxo::Local(_) => Some(u.txout().value),
|
||||
Utxo::Local(_) => Some(u.txout().value.to_sat()),
|
||||
_ => None,
|
||||
})
|
||||
.sum()
|
||||
@ -344,11 +345,11 @@ fn select_sorted_utxos(
|
||||
if must_use || **selected_amount < target_amount + **fee_amount {
|
||||
**fee_amount += (fee_rate
|
||||
* Weight::from_wu(
|
||||
(TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight)
|
||||
as u64,
|
||||
TxIn::default().segwit_weight().to_wu()
|
||||
+ weighted_utxo.satisfaction_weight as u64,
|
||||
))
|
||||
.to_sat();
|
||||
**selected_amount += weighted_utxo.utxo.txout().value;
|
||||
**selected_amount += weighted_utxo.utxo.txout().value.to_sat();
|
||||
Some(weighted_utxo.utxo)
|
||||
} else {
|
||||
None
|
||||
@ -390,10 +391,10 @@ impl OutputGroup {
|
||||
fn new(weighted_utxo: WeightedUtxo, fee_rate: FeeRate) -> Self {
|
||||
let fee = (fee_rate
|
||||
* Weight::from_wu(
|
||||
(TxIn::default().segwit_weight() + weighted_utxo.satisfaction_weight) as u64,
|
||||
TxIn::default().segwit_weight().to_wu() + weighted_utxo.satisfaction_weight as u64,
|
||||
))
|
||||
.to_sat();
|
||||
let effective_value = weighted_utxo.utxo.txout().value as i64 - fee as i64;
|
||||
let effective_value = weighted_utxo.utxo.txout().value.to_sat() as i64 - fee as i64;
|
||||
OutputGroup {
|
||||
weighted_utxo,
|
||||
fee,
|
||||
@ -484,7 +485,7 @@ impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection {
|
||||
.chain(optional_utxos.iter())
|
||||
.fold((0, 0), |(mut fees, mut value), utxo| {
|
||||
fees += utxo.fee;
|
||||
value += utxo.weighted_utxo.utxo.txout().value;
|
||||
value += utxo.weighted_utxo.utxo.txout().value.to_sat();
|
||||
|
||||
(fees, value)
|
||||
});
|
||||
@ -588,7 +589,7 @@ impl BranchAndBoundCoinSelection {
|
||||
// If we found a solution better than the previous one, or if there wasn't previous
|
||||
// solution, update the best solution
|
||||
if best_selection_value.is_none() || curr_value < best_selection_value.unwrap() {
|
||||
best_selection = current_selection.clone();
|
||||
best_selection.clone_from(¤t_selection);
|
||||
best_selection_value = Some(curr_value);
|
||||
}
|
||||
|
||||
@ -742,7 +743,7 @@ mod test {
|
||||
use core::str::FromStr;
|
||||
|
||||
use bdk_chain::ConfirmationTime;
|
||||
use bitcoin::{Amount, OutPoint, ScriptBuf, TxIn, TxOut};
|
||||
use bitcoin::{Amount, ScriptBuf, TxIn, TxOut};
|
||||
|
||||
use super::*;
|
||||
use crate::types::*;
|
||||
@ -770,7 +771,7 @@ mod test {
|
||||
utxo: Utxo::Local(LocalOutput {
|
||||
outpoint,
|
||||
txout: TxOut {
|
||||
value,
|
||||
value: Amount::from_sat(value),
|
||||
script_pubkey: ScriptBuf::new(),
|
||||
},
|
||||
keychain: KeychainKind::External,
|
||||
@ -834,7 +835,7 @@ mod test {
|
||||
))
|
||||
.unwrap(),
|
||||
txout: TxOut {
|
||||
value: rng.gen_range(0..200000000),
|
||||
value: Amount::from_sat(rng.gen_range(0..200000000)),
|
||||
script_pubkey: ScriptBuf::new(),
|
||||
},
|
||||
keychain: KeychainKind::External,
|
||||
@ -865,7 +866,7 @@ mod test {
|
||||
))
|
||||
.unwrap(),
|
||||
txout: TxOut {
|
||||
value: utxos_value,
|
||||
value: Amount::from_sat(utxos_value),
|
||||
script_pubkey: ScriptBuf::new(),
|
||||
},
|
||||
keychain: KeychainKind::External,
|
||||
@ -882,7 +883,7 @@ mod test {
|
||||
utxos.shuffle(&mut rng);
|
||||
utxos[..utxos_picked_len]
|
||||
.iter()
|
||||
.map(|u| u.utxo.txout().value)
|
||||
.map(|u| u.utxo.txout().value.to_sat())
|
||||
.sum()
|
||||
}
|
||||
|
||||
@ -1071,7 +1072,11 @@ mod test {
|
||||
fn test_oldest_first_coin_selection_insufficient_funds_high_fees() {
|
||||
let utxos = get_oldest_first_test_utxos();
|
||||
|
||||
let target_amount: u64 = utxos.iter().map(|wu| wu.utxo.txout().value).sum::<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,
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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(),
|
||||
}],
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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(),
|
||||
},
|
||||
],
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -807,7 +807,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()
|
||||
@ -1063,7 +1063,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(),
|
||||
},
|
||||
)))
|
||||
},
|
||||
@ -1166,16 +1166,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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![],
|
||||
|
@ -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(),
|
||||
},
|
||||
})
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
|
@ -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,
|
||||
}],
|
||||
};
|
||||
|
@ -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(),
|
||||
},
|
||||
],
|
||||
|
@ -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"
|
@ -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.
|
||||
|
@ -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]
|
||||
|
@ -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),
|
||||
},
|
||||
))
|
||||
});
|
||||
|
@ -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),
|
||||
},
|
||||
))
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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"] }
|
||||
|
@ -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> {
|
||||
|
@ -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]
|
||||
|
@ -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()),
|
||||
}],
|
||||
}];
|
||||
|
@ -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>,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||
assert!(finalized);
|
||||
|
||||
let tx = psbt.extract_tx();
|
||||
let tx = psbt.extract_tx()?;
|
||||
client.transaction_broadcast(&tx)?;
|
||||
println!("Tx broadcasted! Txid: {}", tx.txid());
|
||||
|
||||
|
@ -90,7 +90,7 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||
assert!(finalized);
|
||||
|
||||
let tx = psbt.extract_tx();
|
||||
let tx = psbt.extract_tx()?;
|
||||
client.broadcast(&tx).await?;
|
||||
println!("Tx broadcasted! Txid: {}", tx.txid());
|
||||
|
||||
|
@ -34,7 +34,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
|
||||
print!("Syncing...");
|
||||
let client =
|
||||
esplora_client::Builder::new("https://blockstream.info/testnet/api").build_blocking()?;
|
||||
esplora_client::Builder::new("https://blockstream.info/testnet/api").build_blocking();
|
||||
|
||||
let prev_tip = wallet.latest_checkpoint();
|
||||
let keychain_spks = wallet
|
||||
@ -90,7 +90,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||
assert!(finalized);
|
||||
|
||||
let tx = psbt.extract_tx();
|
||||
let tx = psbt.extract_tx()?;
|
||||
client.broadcast(&tx)?;
|
||||
println!("Tx broadcasted! Txid: {}", tx.txid());
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user