deps(bdk): bump bitcoin to 0.32.0, miniscript to 12.0.0
deps(chain): bump `bitcoin` to `0.32.0`, miniscript to `12.0.0` fix(chain): use `minimal_non_dust()` instead of `dust_value()` fix(chain): use `compute_txid()` instead of `txid` deps(testenv): bump `electrsd` to `0.28.0` deps(electrum): bump `electrum-client` to `0.20.0` fix(electrum): use `compute_txid()` instead of `txid` deps(esplora): bump `esplora-client` to `0.8.0` deps(bitcoind_rpc): bump `bitcoin` to `0.32.0`, `bitcoincore-rpc` to `0.19.0` fix(bitcoind_rpc): use `compute_txid()` instead of `txid` fix(nursery/tmp_plan): use proper `sighash` errors, and fix the expected `Signature` fields fix(sqlite): use `compute_txid()` instead of `txid` deps(hwi): bump `hwi` to `0.9.0` deps(wallet): bump `bitcoin` to `0.32.0`, miniscript to `12.0.0` fix(wallet): use `compute_txid()` and `minimal_non_dust()` - update to use `compute_txid()` instead of deprecated `txid()` - update to use `minimal_non_dust()` instead of `dust_value()` - remove unused `bitcoin::hex::FromHex`. fix(wallet): uses `.into` conversion on `Network` for `NetworkKind` - uses `.into()` when appropriate, otherwise use the explicit `NetworkKind`, and it's `.is_mainnet()` method. fix(wallet): add P2wpkh, Taproot, InputsIndex errors to `SignerError` fix(wallet): fields on taproot, and ecdsa `Signature` structure fix(wallet/wallet): convert `Weight` to `usize` for now - converts the `bitcoin-units::Weight` type to `usize` with help of `to_wu()` method. - it should be updated/refactored in the future to handle the `Weight` type throughout the code instead of current `usize`, only converting it for now. - allows the usage of deprecated `is_provably_unspendable()`, needs further discussion if suggested `is_op_return` is suitable. - update the expect field to `signature`, as it was renamed from `sig`. fix(wallet/wallet): use `is_op_return` instead of `is_provably_unspendable` fix(wallet/wallet): use `relative::Locktime` instead of `Sequence` fix(wallet/descriptor): use `ParsePublicKeyError` fix(wallet/descriptor): use `.into()` to convert from `AbsLockTime` and `RelLockTime` to `absolute::LockTime` and `relative::LockTime` fix(wallet/wallet): use `Message::from_digest()` instead of relying on deprecated `ThirtyTwoByteHash` trait. fix(wallet/descriptor+wallet): expect `Threshold` type, and handle it internally fix(wallet/wallet): remove `0x` prefix from expected `TxId` display fix(examples): use `compute_txid()` instead of `txid` fix(ci): remove usage of `bitcoin/no-std` feature - remove comment: `# The `no-std` feature it's implied when the `std` feature is disabled.`
This commit is contained in:
@@ -15,8 +15,8 @@ rust-version = "1.63"
|
||||
[dependencies]
|
||||
anyhow = { version = "1", default-features = false }
|
||||
rand = "^0.8"
|
||||
miniscript = { version = "11.0.0", features = ["serde"], default-features = false }
|
||||
bitcoin = { version = "0.31.0", features = ["serde", "base64", "rand-std"], default-features = false }
|
||||
miniscript = { version = "12.0.0", features = ["serde"], default-features = false }
|
||||
bitcoin = { version = "0.32.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.15.0", features = ["miniscript", "serde"], default-features = false }
|
||||
|
||||
@@ -703,10 +703,10 @@ macro_rules! fragment {
|
||||
$crate::keys::make_pkh($key, &secp)
|
||||
});
|
||||
( after ( $value:expr ) ) => ({
|
||||
$crate::impl_leaf_opcode_value!(After, $crate::miniscript::AbsLockTime::from_consensus($value))
|
||||
$crate::impl_leaf_opcode_value!(After, $crate::miniscript::AbsLockTime::from_consensus($value).expect("valid `AbsLockTime`"))
|
||||
});
|
||||
( older ( $value:expr ) ) => ({
|
||||
$crate::impl_leaf_opcode_value!(Older, $crate::bitcoin::Sequence($value)) // TODO!!
|
||||
$crate::impl_leaf_opcode_value!(Older, $crate::miniscript::RelLockTime::from_consensus($value).expect("valid `RelLockTime`")) // TODO!!
|
||||
});
|
||||
( sha256 ( $hash:expr ) ) => ({
|
||||
$crate::impl_leaf_opcode_value!(Sha256, $hash)
|
||||
@@ -757,7 +757,8 @@ macro_rules! fragment {
|
||||
(keys_acc, net_acc)
|
||||
});
|
||||
|
||||
$crate::impl_leaf_opcode_value_two!(Thresh, $thresh, items)
|
||||
let thresh = $crate::miniscript::Threshold::new($thresh, items).expect("valid threshold and pks collection");
|
||||
$crate::impl_leaf_opcode_value!(Thresh, thresh)
|
||||
.map(|(minisc, _, _)| (minisc, key_maps, valid_networks))
|
||||
});
|
||||
( thresh ( $thresh:expr, $( $inner:tt )* ) ) => ({
|
||||
@@ -769,7 +770,12 @@ macro_rules! fragment {
|
||||
( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
|
||||
let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
|
||||
|
||||
$crate::keys::make_multi($thresh, $crate::miniscript::Terminal::Multi, $keys, &secp)
|
||||
let fun = |k, pks| {
|
||||
let thresh = $crate::miniscript::Threshold::new(k, pks).expect("valid threshold and pks collection");
|
||||
$crate::miniscript::Terminal::Multi(thresh)
|
||||
};
|
||||
|
||||
$crate::keys::make_multi($thresh, fun, $keys, &secp)
|
||||
});
|
||||
( multi ( $thresh:expr $(, $key:expr )+ ) ) => ({
|
||||
$crate::group_multi_keys!( $( $key ),* )
|
||||
@@ -778,7 +784,12 @@ macro_rules! fragment {
|
||||
( multi_a_vec ( $thresh:expr, $keys:expr ) ) => ({
|
||||
let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
|
||||
|
||||
$crate::keys::make_multi($thresh, $crate::miniscript::Terminal::MultiA, $keys, &secp)
|
||||
let fun = |k, pks| {
|
||||
let thresh = $crate::miniscript::Threshold::new(k, pks).expect("valid threshold and pks collection");
|
||||
$crate::miniscript::Terminal::MultiA(thresh)
|
||||
};
|
||||
|
||||
$crate::keys::make_multi($thresh, fun, $keys, &secp)
|
||||
});
|
||||
( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => ({
|
||||
$crate::group_multi_keys!( $( $key ),* )
|
||||
|
||||
@@ -37,7 +37,7 @@ pub enum Error {
|
||||
/// Error during base58 decoding
|
||||
Base58(bitcoin::base58::Error),
|
||||
/// Key-related error
|
||||
Pk(bitcoin::key::Error),
|
||||
Pk(bitcoin::key::ParsePublicKeyError),
|
||||
/// Miniscript error
|
||||
Miniscript(miniscript::Error),
|
||||
/// Hex decoding error
|
||||
@@ -103,8 +103,8 @@ impl From<bitcoin::base58::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bitcoin::key::Error> for Error {
|
||||
fn from(err: bitcoin::key::Error) -> Self {
|
||||
impl From<bitcoin::key::ParsePublicKeyError> for Error {
|
||||
fn from(err: bitcoin::key::ParsePublicKeyError) -> Self {
|
||||
Error::Pk(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ impl IntoWalletDescriptor for DescriptorTemplateOut {
|
||||
let pk = match pk {
|
||||
DescriptorPublicKey::XPub(ref xpub) => {
|
||||
let mut xpub = xpub.clone();
|
||||
xpub.xkey.network = self.network;
|
||||
xpub.xkey.network = self.network.into();
|
||||
|
||||
DescriptorPublicKey::XPub(xpub)
|
||||
}
|
||||
@@ -264,11 +264,11 @@ impl IntoWalletDescriptor for DescriptorTemplateOut {
|
||||
.map(|(mut k, mut v)| {
|
||||
match (&mut k, &mut v) {
|
||||
(DescriptorPublicKey::XPub(xpub), DescriptorSecretKey::XPrv(xprv)) => {
|
||||
xpub.xkey.network = network;
|
||||
xprv.xkey.network = network;
|
||||
xpub.xkey.network = network.into();
|
||||
xprv.xkey.network = network.into();
|
||||
}
|
||||
(_, DescriptorSecretKey::Single(key)) => {
|
||||
key.key.network = network;
|
||||
key.key.network = network.into();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -606,8 +606,8 @@ mod test {
|
||||
use assert_matches::assert_matches;
|
||||
use bitcoin::hex::FromHex;
|
||||
use bitcoin::secp256k1::Secp256k1;
|
||||
use bitcoin::ScriptBuf;
|
||||
use bitcoin::{bip32, Psbt};
|
||||
use bitcoin::{NetworkKind, ScriptBuf};
|
||||
|
||||
use super::*;
|
||||
use crate::psbt::PsbtUtils;
|
||||
@@ -743,7 +743,7 @@ mod test {
|
||||
.unwrap();
|
||||
|
||||
let mut xprv_testnet = xprv;
|
||||
xprv_testnet.network = Network::Testnet;
|
||||
xprv_testnet.network = NetworkKind::Test;
|
||||
|
||||
let xpub_testnet = bip32::Xpub::from_priv(&secp, &xprv_testnet);
|
||||
let desc_pubkey = DescriptorPublicKey::XPub(DescriptorXKey {
|
||||
|
||||
@@ -40,6 +40,7 @@ use crate::collections::{BTreeMap, HashSet, VecDeque};
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::cmp::max;
|
||||
use miniscript::miniscript::limits::{MAX_PUBKEYS_IN_CHECKSIGADD, MAX_PUBKEYS_PER_MULTISIG};
|
||||
|
||||
use core::fmt;
|
||||
|
||||
@@ -48,12 +49,12 @@ use serde::{Serialize, Serializer};
|
||||
|
||||
use bitcoin::bip32::Fingerprint;
|
||||
use bitcoin::hashes::{hash160, ripemd160, sha256};
|
||||
use bitcoin::{absolute, key::XOnlyPublicKey, PublicKey, Sequence};
|
||||
use bitcoin::{absolute, key::XOnlyPublicKey, relative, PublicKey, Sequence};
|
||||
|
||||
use miniscript::descriptor::{
|
||||
DescriptorPublicKey, ShInner, SinglePub, SinglePubKey, SortedMultiVec, WshInner,
|
||||
};
|
||||
use miniscript::hash256;
|
||||
use miniscript::{hash256, Threshold};
|
||||
use miniscript::{
|
||||
Descriptor, Miniscript, Satisfier, ScriptContext, SigType, Terminal, ToPublicKey,
|
||||
};
|
||||
@@ -137,7 +138,7 @@ pub enum SatisfiableItem {
|
||||
/// Relative timelock locktime
|
||||
RelativeTimelock {
|
||||
/// The timelock value
|
||||
value: Sequence,
|
||||
value: relative::LockTime,
|
||||
},
|
||||
/// Multi-signature public keys with threshold count
|
||||
Multisig {
|
||||
@@ -586,30 +587,25 @@ impl Policy {
|
||||
Ok(Some(policy))
|
||||
}
|
||||
|
||||
fn make_multisig<Ctx: ScriptContext + 'static>(
|
||||
keys: &[DescriptorPublicKey],
|
||||
fn make_multi<Ctx: ScriptContext + 'static>(
|
||||
threshold: &Threshold<DescriptorPublicKey, MAX_PUBKEYS_PER_MULTISIG>,
|
||||
signers: &SignersContainer,
|
||||
build_sat: BuildSatisfaction,
|
||||
threshold: usize,
|
||||
sorted: bool,
|
||||
secp: &SecpCtx,
|
||||
) -> Result<Option<Policy>, PolicyError> {
|
||||
if threshold == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let parsed_keys = keys.iter().map(|k| PkOrF::from_key(k, secp)).collect();
|
||||
let parsed_keys = threshold.iter().map(|k| PkOrF::from_key(k, secp)).collect();
|
||||
|
||||
let mut contribution = Satisfaction::Partial {
|
||||
n: keys.len(),
|
||||
m: threshold,
|
||||
n: threshold.n(),
|
||||
m: threshold.k(),
|
||||
items: vec![],
|
||||
conditions: Default::default(),
|
||||
sorted: Some(sorted),
|
||||
};
|
||||
let mut satisfaction = contribution.clone();
|
||||
|
||||
for (index, key) in keys.iter().enumerate() {
|
||||
for (index, key) in threshold.iter().enumerate() {
|
||||
if signers.find(signer_id(key, secp)).is_some() {
|
||||
contribution.add(
|
||||
&Satisfaction::Complete {
|
||||
@@ -635,7 +631,7 @@ impl Policy {
|
||||
|
||||
let mut policy: Policy = SatisfiableItem::Multisig {
|
||||
keys: parsed_keys,
|
||||
threshold,
|
||||
threshold: threshold.k(),
|
||||
}
|
||||
.into();
|
||||
policy.contribution = contribution;
|
||||
@@ -644,6 +640,57 @@ impl Policy {
|
||||
Ok(Some(policy))
|
||||
}
|
||||
|
||||
fn make_multi_a<Ctx: ScriptContext + 'static>(
|
||||
threshold: &Threshold<DescriptorPublicKey, MAX_PUBKEYS_IN_CHECKSIGADD>,
|
||||
signers: &SignersContainer,
|
||||
build_sat: BuildSatisfaction,
|
||||
sorted: bool,
|
||||
secp: &SecpCtx,
|
||||
) -> Result<Option<Policy>, PolicyError> {
|
||||
let parsed_keys = threshold.iter().map(|k| PkOrF::from_key(k, secp)).collect();
|
||||
|
||||
let mut contribution = Satisfaction::Partial {
|
||||
n: threshold.n(),
|
||||
m: threshold.k(),
|
||||
items: vec![],
|
||||
conditions: Default::default(),
|
||||
sorted: Some(sorted),
|
||||
};
|
||||
let mut satisfaction = contribution.clone();
|
||||
|
||||
for (index, key) in threshold.iter().enumerate() {
|
||||
if signers.find(signer_id(key, secp)).is_some() {
|
||||
contribution.add(
|
||||
&Satisfaction::Complete {
|
||||
condition: Default::default(),
|
||||
},
|
||||
index,
|
||||
)?;
|
||||
}
|
||||
if let Some(psbt) = build_sat.psbt() {
|
||||
if Ctx::find_signature(psbt, key, secp) {
|
||||
satisfaction.add(
|
||||
&Satisfaction::Complete {
|
||||
condition: Default::default(),
|
||||
},
|
||||
index,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
satisfaction.finalize();
|
||||
contribution.finalize();
|
||||
|
||||
let mut policy: Policy = SatisfiableItem::Multisig {
|
||||
keys: parsed_keys,
|
||||
threshold: threshold.k(),
|
||||
}
|
||||
.into();
|
||||
policy.contribution = contribution;
|
||||
policy.satisfaction = satisfaction;
|
||||
Ok(Some(policy))
|
||||
}
|
||||
|
||||
/// Return whether or not a specific path in the policy tree is required to unambiguously
|
||||
/// create a transaction
|
||||
///
|
||||
@@ -725,7 +772,7 @@ impl Policy {
|
||||
timelock: Some(*value),
|
||||
}),
|
||||
SatisfiableItem::RelativeTimelock { value } => Ok(Condition {
|
||||
csv: Some(*value),
|
||||
csv: Some((*value).into()),
|
||||
timelock: None,
|
||||
}),
|
||||
_ => Ok(Condition::default()),
|
||||
@@ -952,11 +999,14 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
|
||||
Some(policy)
|
||||
}
|
||||
Terminal::Older(value) => {
|
||||
let mut policy: Policy = SatisfiableItem::RelativeTimelock { value: *value }.into();
|
||||
let mut policy: Policy = SatisfiableItem::RelativeTimelock {
|
||||
value: (*value).into(),
|
||||
}
|
||||
.into();
|
||||
policy.contribution = Satisfaction::Complete {
|
||||
condition: Condition {
|
||||
timelock: None,
|
||||
csv: Some(*value),
|
||||
csv: Some((*value).into()),
|
||||
},
|
||||
};
|
||||
if let BuildSatisfaction::PsbtTimelocks {
|
||||
@@ -966,9 +1016,11 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
|
||||
} = build_sat
|
||||
{
|
||||
let older = Older::new(Some(current_height), Some(input_max_height), false);
|
||||
let older_sat = Satisfier::<bitcoin::PublicKey>::check_older(&older, *value);
|
||||
let inputs_sat = psbt_inputs_sat(psbt)
|
||||
.all(|sat| Satisfier::<bitcoin::PublicKey>::check_older(&sat, *value));
|
||||
let older_sat =
|
||||
Satisfier::<bitcoin::PublicKey>::check_older(&older, (*value).into());
|
||||
let inputs_sat = psbt_inputs_sat(psbt).all(|sat| {
|
||||
Satisfier::<bitcoin::PublicKey>::check_older(&sat, (*value).into())
|
||||
});
|
||||
if older_sat && inputs_sat {
|
||||
policy.satisfaction = policy.contribution.clone();
|
||||
}
|
||||
@@ -986,8 +1038,11 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
|
||||
Terminal::Hash160(hash) => {
|
||||
Some(SatisfiableItem::Hash160Preimage { hash: *hash }.into())
|
||||
}
|
||||
Terminal::Multi(k, pks) | Terminal::MultiA(k, pks) => {
|
||||
Policy::make_multisig::<Ctx>(pks, signers, build_sat, *k, false, secp)?
|
||||
Terminal::Multi(threshold) => {
|
||||
Policy::make_multi::<Ctx>(threshold, signers, build_sat, false, secp)?
|
||||
}
|
||||
Terminal::MultiA(threshold) => {
|
||||
Policy::make_multi_a::<Ctx>(threshold, signers, build_sat, false, secp)?
|
||||
}
|
||||
// Identities
|
||||
Terminal::Alt(inner)
|
||||
@@ -1016,8 +1071,9 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
|
||||
a.extract_policy(signers, build_sat, secp)?,
|
||||
b.extract_policy(signers, build_sat, secp)?,
|
||||
)?,
|
||||
Terminal::Thresh(k, nodes) => {
|
||||
let mut threshold = *k;
|
||||
Terminal::Thresh(threshold) => {
|
||||
let mut k = threshold.k();
|
||||
let nodes = threshold.data();
|
||||
let mapped: Vec<_> = nodes
|
||||
.iter()
|
||||
.map(|n| n.extract_policy(signers, build_sat, secp))
|
||||
@@ -1027,13 +1083,13 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
|
||||
.collect();
|
||||
|
||||
if mapped.len() < nodes.len() {
|
||||
threshold = match threshold.checked_sub(nodes.len() - mapped.len()) {
|
||||
k = match k.checked_sub(nodes.len() - mapped.len()) {
|
||||
None => return Ok(None),
|
||||
Some(x) => x,
|
||||
};
|
||||
}
|
||||
|
||||
Policy::make_thresh(mapped, threshold)?
|
||||
Policy::make_thresh(mapped, k)?
|
||||
}
|
||||
|
||||
// Unsupported
|
||||
@@ -1087,13 +1143,10 @@ impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
|
||||
build_sat: BuildSatisfaction,
|
||||
secp: &SecpCtx,
|
||||
) -> Result<Option<Policy>, Error> {
|
||||
Ok(Policy::make_multisig::<Ctx>(
|
||||
keys.pks.as_ref(),
|
||||
signers,
|
||||
build_sat,
|
||||
keys.k,
|
||||
true,
|
||||
secp,
|
||||
let threshold = Threshold::new(keys.k(), keys.pks().to_vec())
|
||||
.expect("valid threshold and pks collection");
|
||||
Ok(Policy::make_multi::<Ctx>(
|
||||
&threshold, signers, build_sat, true, secp,
|
||||
)?)
|
||||
}
|
||||
|
||||
|
||||
@@ -583,7 +583,7 @@ mod test {
|
||||
use bitcoin::bip32::ChildNumber::{self, Hardened};
|
||||
|
||||
let xprvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K2fpbqApQL69a4oKdGVnVN52R82Ft7d1pSqgKmajF62acJo3aMszZb6qQ22QsVECSFxvf9uyxFUvFYQMq3QbtwtRSMjLAhMf").unwrap();
|
||||
assert_eq!(Network::Bitcoin, xprvkey.network);
|
||||
assert!(xprvkey.network.is_mainnet());
|
||||
let xdesc = Bip44(xprvkey, KeychainKind::Internal)
|
||||
.build(Network::Bitcoin)
|
||||
.unwrap();
|
||||
@@ -597,7 +597,7 @@ mod test {
|
||||
}
|
||||
|
||||
let tprvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
|
||||
assert_eq!(Network::Testnet, tprvkey.network);
|
||||
assert!(!tprvkey.network.is_mainnet());
|
||||
let tdesc = Bip44(tprvkey, KeychainKind::Internal)
|
||||
.build(Network::Testnet)
|
||||
.unwrap();
|
||||
|
||||
@@ -336,7 +336,7 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
|
||||
pub fn into_xprv(self, network: Network) -> Option<bip32::Xpriv> {
|
||||
match self {
|
||||
ExtendedKey::Private((mut xprv, _)) => {
|
||||
xprv.network = network;
|
||||
xprv.network = network.into();
|
||||
Some(xprv)
|
||||
}
|
||||
ExtendedKey::Public(_) => None,
|
||||
@@ -355,7 +355,7 @@ impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
|
||||
ExtendedKey::Public((xpub, _)) => xpub,
|
||||
};
|
||||
|
||||
xpub.network = network;
|
||||
xpub.network = network.into();
|
||||
xpub
|
||||
}
|
||||
}
|
||||
@@ -402,7 +402,7 @@ impl<Ctx: ScriptContext> From<bip32::Xpriv> for ExtendedKey<Ctx> {
|
||||
/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
|
||||
/// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
||||
/// let xprv = bip32::Xpriv {
|
||||
/// network: self.network,
|
||||
/// network: self.network.into(),
|
||||
/// depth: 0,
|
||||
/// parent_fingerprint: bip32::Fingerprint::default(),
|
||||
/// private_key: self.key_data.inner,
|
||||
@@ -434,7 +434,7 @@ impl<Ctx: ScriptContext> From<bip32::Xpriv> for ExtendedKey<Ctx> {
|
||||
/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
|
||||
/// fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
||||
/// let xprv = bip32::Xpriv {
|
||||
/// network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
|
||||
/// network: bitcoin::Network::Bitcoin.into(), // pick an arbitrary network here
|
||||
/// depth: 0,
|
||||
/// parent_fingerprint: bip32::Fingerprint::default(),
|
||||
/// private_key: self.key_data.inner,
|
||||
@@ -717,7 +717,7 @@ impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey {
|
||||
let inner = secp256k1::SecretKey::from_slice(&entropy)?;
|
||||
let private_key = PrivateKey {
|
||||
compressed: options.compressed,
|
||||
network: Network::Bitcoin,
|
||||
network: Network::Bitcoin.into(),
|
||||
inner,
|
||||
};
|
||||
|
||||
@@ -847,9 +847,7 @@ impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorPublicKey {
|
||||
fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||
let networks = match self {
|
||||
DescriptorPublicKey::Single(_) => any_network(),
|
||||
DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
|
||||
if xkey.network == Network::Bitcoin =>
|
||||
{
|
||||
DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. }) if xkey.network.is_mainnet() => {
|
||||
mainnet_network()
|
||||
}
|
||||
_ => test_networks(),
|
||||
@@ -882,12 +880,8 @@ impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for XOnlyPublicKey {
|
||||
impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorSecretKey {
|
||||
fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||
let networks = match &self {
|
||||
DescriptorSecretKey::Single(sk) if sk.key.network == Network::Bitcoin => {
|
||||
mainnet_network()
|
||||
}
|
||||
DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. })
|
||||
if xkey.network == Network::Bitcoin =>
|
||||
{
|
||||
DescriptorSecretKey::Single(sk) if sk.key.network.is_mainnet() => mainnet_network(),
|
||||
DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. }) if xkey.network.is_mainnet() => {
|
||||
mainnet_network()
|
||||
}
|
||||
_ => test_networks(),
|
||||
@@ -1003,6 +997,6 @@ pub mod test {
|
||||
.unwrap();
|
||||
let xprv = xkey.into_xprv(Network::Testnet).unwrap();
|
||||
|
||||
assert_eq!(xprv.network, Network::Testnet);
|
||||
assert_eq!(xprv.network, Network::Testnet.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ pub fn decide_change(remaining_amount: u64, fee_rate: FeeRate, drain_script: &Sc
|
||||
let drain_val = remaining_amount.saturating_sub(change_fee);
|
||||
|
||||
if drain_val.is_dust(drain_script) {
|
||||
let dust_threshold = drain_script.dust_value().to_sat();
|
||||
let dust_threshold = drain_script.minimal_non_dust().to_sat();
|
||||
Excess::NoChange {
|
||||
dust_threshold,
|
||||
change_fee,
|
||||
|
||||
@@ -164,7 +164,7 @@ impl FullyNodedExport {
|
||||
fn check_ms<Ctx: ScriptContext>(
|
||||
terminal: &Terminal<String, Ctx>,
|
||||
) -> Result<(), &'static str> {
|
||||
if let Terminal::Multi(_, _) = terminal {
|
||||
if let Terminal::Multi(_) = terminal {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("The descriptor contains operators not supported by Bitcoin Core")
|
||||
|
||||
@@ -1177,7 +1177,7 @@ impl Wallet {
|
||||
};
|
||||
|
||||
let mut changeset = ChangeSet::default();
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
changeset.append(self.indexed_graph.insert_tx(tx).into());
|
||||
if let Some(anchor) = anchor {
|
||||
changeset.append(self.indexed_graph.insert_anchor(txid, anchor).into());
|
||||
@@ -1478,10 +1478,7 @@ impl Wallet {
|
||||
let recipients = params.recipients.iter().map(|(r, v)| (r, *v));
|
||||
|
||||
for (index, (script_pubkey, value)) in recipients.enumerate() {
|
||||
if !params.allow_dust
|
||||
&& value.is_dust(script_pubkey)
|
||||
&& !script_pubkey.is_provably_unspendable()
|
||||
{
|
||||
if !params.allow_dust && value.is_dust(script_pubkey) && !script_pubkey.is_op_return() {
|
||||
return Err(CreateTxError::OutputBelowDustLimit(index));
|
||||
}
|
||||
|
||||
@@ -1635,7 +1632,7 @@ impl Wallet {
|
||||
/// 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())?;
|
||||
/// let mut builder = wallet.build_fee_bump(tx.compute_txid())?;
|
||||
/// builder
|
||||
/// .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
|
||||
/// builder.finish()?
|
||||
@@ -1673,7 +1670,9 @@ impl Wallet {
|
||||
.iter()
|
||||
.any(|txin| txin.sequence.to_consensus_u32() <= 0xFFFFFFFD)
|
||||
{
|
||||
return Err(BuildFeeBumpError::IrreplaceableTransaction(tx.txid()));
|
||||
return Err(BuildFeeBumpError::IrreplaceableTransaction(
|
||||
tx.compute_txid(),
|
||||
));
|
||||
}
|
||||
|
||||
let fee = self
|
||||
@@ -1704,7 +1703,8 @@ impl Wallet {
|
||||
let satisfaction_weight = self
|
||||
.get_descriptor_for_keychain(keychain)
|
||||
.max_weight_to_satisfy()
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.to_wu() as usize;
|
||||
WeightedUtxo {
|
||||
utxo: Utxo::Local(LocalOutput {
|
||||
outpoint: txin.previous_output,
|
||||
@@ -2037,6 +2037,7 @@ impl Wallet {
|
||||
self.get_descriptor_for_keychain(keychain)
|
||||
.max_weight_to_satisfy()
|
||||
.unwrap()
|
||||
.to_wu() as usize
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
|
||||
@@ -91,7 +91,7 @@ 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::{ecdsa, psbt, sighash, taproot, transaction};
|
||||
use bitcoin::{key::TapTweak, key::XOnlyPublicKey, secp256k1};
|
||||
use bitcoin::{PrivateKey, Psbt, PublicKey};
|
||||
|
||||
@@ -159,8 +159,12 @@ pub enum SignerError {
|
||||
NonStandardSighash,
|
||||
/// Invalid SIGHASH for the signing context in use
|
||||
InvalidSighash,
|
||||
/// Error while computing the hash to sign
|
||||
SighashError(sighash::Error),
|
||||
/// Error while computing the hash to sign a P2WPKH input.
|
||||
SighashP2wpkh(sighash::P2wpkhError),
|
||||
/// Error while computing the hash to sign a Taproot input.
|
||||
SighashTaproot(sighash::TaprootError),
|
||||
/// Error while computing the hash, out of bounds access on the transaction inputs.
|
||||
TxInputsIndexError(transaction::InputsIndexError),
|
||||
/// Miniscript PSBT error
|
||||
MiniscriptPsbt(MiniscriptPsbtError),
|
||||
/// To be used only by external libraries implementing [`InputSigner`] or
|
||||
@@ -169,9 +173,21 @@ pub enum SignerError {
|
||||
External(String),
|
||||
}
|
||||
|
||||
impl From<sighash::Error> for SignerError {
|
||||
fn from(e: sighash::Error) -> Self {
|
||||
SignerError::SighashError(e)
|
||||
impl From<transaction::InputsIndexError> for SignerError {
|
||||
fn from(v: transaction::InputsIndexError) -> Self {
|
||||
Self::TxInputsIndexError(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sighash::P2wpkhError> for SignerError {
|
||||
fn from(e: sighash::P2wpkhError) -> Self {
|
||||
Self::SighashP2wpkh(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sighash::TaprootError> for SignerError {
|
||||
fn from(e: sighash::TaprootError) -> Self {
|
||||
Self::SighashTaproot(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +205,9 @@ impl fmt::Display for SignerError {
|
||||
Self::MissingHdKeypath => write!(f, "Missing fingerprint and derivation path"),
|
||||
Self::NonStandardSighash => write!(f, "The psbt contains a non standard sighash"),
|
||||
Self::InvalidSighash => write!(f, "Invalid SIGHASH for the signing context in use"),
|
||||
Self::SighashError(err) => write!(f, "Error while computing the hash to sign: {}", err),
|
||||
Self::SighashP2wpkh(err) => write!(f, "Error while computing the hash to sign a P2WPKH input: {}", err),
|
||||
Self::SighashTaproot(err) => write!(f, "Error while computing the hash to sign a Taproot input: {}", err),
|
||||
Self::TxInputsIndexError(err) => write!(f, "Error while computing the hash, out of bounds access on the transaction inputs: {}", err),
|
||||
Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
|
||||
Self::External(err) => write!(f, "{}", err),
|
||||
}
|
||||
@@ -549,21 +567,24 @@ fn sign_psbt_ecdsa(
|
||||
secret_key: &secp256k1::SecretKey,
|
||||
pubkey: PublicKey,
|
||||
psbt_input: &mut psbt::Input,
|
||||
hash: impl bitcoin::hashes::Hash + bitcoin::secp256k1::ThirtyTwoByteHash,
|
||||
hash_ty: EcdsaSighashType,
|
||||
hash: impl bitcoin::hashes::Hash<Bytes = [u8; 32]>,
|
||||
sighash_type: EcdsaSighashType,
|
||||
secp: &SecpCtx,
|
||||
allow_grinding: bool,
|
||||
) {
|
||||
let msg = &Message::from(hash);
|
||||
let sig = if allow_grinding {
|
||||
let msg = &Message::from_digest(hash.to_byte_array());
|
||||
let signature = if allow_grinding {
|
||||
secp.sign_ecdsa_low_r(msg, secret_key)
|
||||
} else {
|
||||
secp.sign_ecdsa(msg, secret_key)
|
||||
};
|
||||
secp.verify_ecdsa(msg, &sig, &pubkey.inner)
|
||||
secp.verify_ecdsa(msg, &signature, &pubkey.inner)
|
||||
.expect("invalid or corrupted ecdsa signature");
|
||||
|
||||
let final_signature = ecdsa::Signature { sig, hash_ty };
|
||||
let final_signature = ecdsa::Signature {
|
||||
signature,
|
||||
sighash_type,
|
||||
};
|
||||
psbt_input.partial_sigs.insert(pubkey, final_signature);
|
||||
}
|
||||
|
||||
@@ -574,7 +595,7 @@ fn sign_psbt_schnorr(
|
||||
leaf_hash: Option<taproot::TapLeafHash>,
|
||||
psbt_input: &mut psbt::Input,
|
||||
hash: TapSighash,
|
||||
hash_ty: TapSighashType,
|
||||
sighash_type: TapSighashType,
|
||||
secp: &SecpCtx,
|
||||
) {
|
||||
let keypair = secp256k1::Keypair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
|
||||
@@ -586,11 +607,14 @@ fn sign_psbt_schnorr(
|
||||
};
|
||||
|
||||
let msg = &Message::from(hash);
|
||||
let sig = secp.sign_schnorr(msg, &keypair);
|
||||
secp.verify_schnorr(&sig, msg, &XOnlyPublicKey::from_keypair(&keypair).0)
|
||||
let signature = secp.sign_schnorr(msg, &keypair);
|
||||
secp.verify_schnorr(&signature, msg, &XOnlyPublicKey::from_keypair(&keypair).0)
|
||||
.expect("invalid or corrupted schnorr signature");
|
||||
|
||||
let final_signature = taproot::Signature { sig, hash_ty };
|
||||
let final_signature = taproot::Signature {
|
||||
signature,
|
||||
sighash_type,
|
||||
};
|
||||
|
||||
if let Some(lh) = leaf_hash {
|
||||
psbt_input
|
||||
@@ -933,7 +957,7 @@ impl ComputeSighash for Segwitv0 {
|
||||
// Always try first with the non-witness utxo
|
||||
let utxo = if let Some(prev_tx) = &psbt_input.non_witness_utxo {
|
||||
// Check the provided prev-tx
|
||||
if prev_tx.txid() != tx_input.previous_output.txid {
|
||||
if prev_tx.compute_txid() != tx_input.previous_output.txid {
|
||||
return Err(SignerError::InvalidNonWitnessUtxo);
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +295,9 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
|
||||
|
||||
for utxo in utxos {
|
||||
let descriptor = wallet.get_descriptor_for_keychain(utxo.keychain);
|
||||
let satisfaction_weight = descriptor.max_weight_to_satisfy().unwrap();
|
||||
|
||||
let satisfaction_weight =
|
||||
descriptor.max_weight_to_satisfy().unwrap().to_wu() as usize;
|
||||
self.params.utxos.push(WeightedUtxo {
|
||||
satisfaction_weight,
|
||||
utxo: Utxo::Local(utxo),
|
||||
@@ -385,9 +387,9 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
|
||||
if psbt_input.witness_utxo.is_none() {
|
||||
match psbt_input.non_witness_utxo.as_ref() {
|
||||
Some(tx) => {
|
||||
if tx.txid() != outpoint.txid {
|
||||
if tx.compute_txid() != outpoint.txid {
|
||||
return Err(AddForeignUtxoError::InvalidTxid {
|
||||
input_txid: tx.txid(),
|
||||
input_txid: tx.compute_txid(),
|
||||
foreign_utxo: outpoint,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// licenses.
|
||||
|
||||
use bitcoin::secp256k1::{All, Secp256k1};
|
||||
use bitcoin::{absolute, Script, Sequence};
|
||||
use bitcoin::{absolute, relative, Script, Sequence};
|
||||
|
||||
use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
|
||||
|
||||
@@ -26,7 +26,7 @@ pub trait IsDust {
|
||||
|
||||
impl IsDust for u64 {
|
||||
fn is_dust(&self, script: &Script) -> bool {
|
||||
*self < script.dust_value().to_sat()
|
||||
*self < script.minimal_non_dust().to_sat()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ impl Older {
|
||||
}
|
||||
|
||||
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Older {
|
||||
fn check_older(&self, n: Sequence) -> bool {
|
||||
fn check_older(&self, n: relative::LockTime) -> bool {
|
||||
if let Some(current_height) = self.current_height {
|
||||
// TODO: test >= / >
|
||||
current_height
|
||||
|
||||
@@ -46,7 +46,7 @@ pub fn get_funded_wallet_with_change(descriptor: &str, change: &str) -> (Wallet,
|
||||
lock_time: bitcoin::absolute::LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint {
|
||||
txid: tx0.txid(),
|
||||
txid: tx0.compute_txid(),
|
||||
vout: 0,
|
||||
},
|
||||
script_sig: Default::default(),
|
||||
@@ -96,7 +96,7 @@ pub fn get_funded_wallet_with_change(descriptor: &str, change: &str) -> (Wallet,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
(wallet, tx1.txid())
|
||||
(wallet, tx1.compute_txid())
|
||||
}
|
||||
|
||||
/// Return a fake wallet that appears to be funded for testing.
|
||||
|
||||
@@ -45,7 +45,7 @@ fn receive_output(wallet: &mut Wallet, value: u64, height: ConfirmationTime) ->
|
||||
wallet.insert_tx(tx.clone(), height).unwrap();
|
||||
|
||||
OutPoint {
|
||||
txid: tx.txid(),
|
||||
txid: tx.compute_txid(),
|
||||
vout: 0,
|
||||
}
|
||||
}
|
||||
@@ -1151,7 +1151,7 @@ fn test_create_tx_add_utxo() {
|
||||
builder
|
||||
.add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
|
||||
.add_utxo(OutPoint {
|
||||
txid: small_output_tx.txid(),
|
||||
txid: small_output_tx.compute_txid(),
|
||||
vout: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1202,7 +1202,7 @@ fn test_create_tx_manually_selected_insufficient() {
|
||||
builder
|
||||
.add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
|
||||
.add_utxo(OutPoint {
|
||||
txid: small_output_tx.txid(),
|
||||
txid: small_output_tx.compute_txid(),
|
||||
vout: 0,
|
||||
})
|
||||
.unwrap()
|
||||
@@ -1306,8 +1306,6 @@ fn test_create_tx_policy_path_ignored_subtree_with_csv() {
|
||||
#[test]
|
||||
fn test_create_tx_global_xpubs_with_origin() {
|
||||
use bitcoin::bip32;
|
||||
use bitcoin::hex::FromHex;
|
||||
|
||||
let (mut wallet, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
|
||||
let addr = wallet.next_unused_address(KeychainKind::External).unwrap();
|
||||
let mut builder = wallet.build_tx();
|
||||
@@ -1348,7 +1346,11 @@ fn test_add_foreign_utxo() {
|
||||
builder
|
||||
.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000))
|
||||
.only_witness_utxo()
|
||||
.add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
|
||||
.add_foreign_utxo(
|
||||
utxo.outpoint,
|
||||
psbt_input,
|
||||
foreign_utxo_satisfaction.to_wu() as usize,
|
||||
)
|
||||
.unwrap();
|
||||
let mut psbt = builder.finish().unwrap();
|
||||
wallet1.insert_txout(utxo.outpoint, utxo.txout);
|
||||
@@ -1399,7 +1401,7 @@ fn test_add_foreign_utxo() {
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "MissingTxOut([OutPoint { txid: 0x21d7fb1bceda00ab4069fc52d06baa13470803e9050edd16f5736e5d8c4925fd, vout: 0 }])"
|
||||
expected = "MissingTxOut([OutPoint { txid: 21d7fb1bceda00ab4069fc52d06baa13470803e9050edd16f5736e5d8c4925fd, vout: 0 }])"
|
||||
)]
|
||||
fn test_calculate_fee_with_missing_foreign_utxo() {
|
||||
let (mut wallet1, _) = get_funded_wallet_wpkh();
|
||||
@@ -1424,7 +1426,11 @@ fn test_calculate_fee_with_missing_foreign_utxo() {
|
||||
builder
|
||||
.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000))
|
||||
.only_witness_utxo()
|
||||
.add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
|
||||
.add_foreign_utxo(
|
||||
utxo.outpoint,
|
||||
psbt_input,
|
||||
foreign_utxo_satisfaction.to_wu() as usize,
|
||||
)
|
||||
.unwrap();
|
||||
let psbt = builder.finish().unwrap();
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
@@ -1441,8 +1447,11 @@ fn test_add_foreign_utxo_invalid_psbt_input() {
|
||||
.unwrap();
|
||||
|
||||
let mut builder = wallet.build_tx();
|
||||
let result =
|
||||
builder.add_foreign_utxo(outpoint, psbt::Input::default(), foreign_utxo_satisfaction);
|
||||
let result = builder.add_foreign_utxo(
|
||||
outpoint,
|
||||
psbt::Input::default(),
|
||||
foreign_utxo_satisfaction.to_wu() as usize,
|
||||
);
|
||||
assert!(matches!(result, Err(AddForeignUtxoError::MissingUtxo)));
|
||||
}
|
||||
|
||||
@@ -1470,7 +1479,7 @@ fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
|
||||
non_witness_utxo: Some(tx1.as_ref().clone()),
|
||||
..Default::default()
|
||||
},
|
||||
satisfaction_weight
|
||||
satisfaction_weight.to_wu() as usize
|
||||
)
|
||||
.is_err(),
|
||||
"should fail when outpoint doesn't match psbt_input"
|
||||
@@ -1483,7 +1492,7 @@ fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
|
||||
non_witness_utxo: Some(tx2.as_ref().clone()),
|
||||
..Default::default()
|
||||
},
|
||||
satisfaction_weight
|
||||
satisfaction_weight.to_wu() as usize
|
||||
)
|
||||
.is_ok(),
|
||||
"should be ok when outpoint does match psbt_input"
|
||||
@@ -1515,7 +1524,11 @@ fn test_add_foreign_utxo_only_witness_utxo() {
|
||||
..Default::default()
|
||||
};
|
||||
builder
|
||||
.add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
|
||||
.add_foreign_utxo(
|
||||
utxo2.outpoint,
|
||||
psbt_input,
|
||||
satisfaction_weight.to_wu() as usize,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(
|
||||
builder.finish().is_err(),
|
||||
@@ -1531,7 +1544,11 @@ fn test_add_foreign_utxo_only_witness_utxo() {
|
||||
};
|
||||
builder
|
||||
.only_witness_utxo()
|
||||
.add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
|
||||
.add_foreign_utxo(
|
||||
utxo2.outpoint,
|
||||
psbt_input,
|
||||
satisfaction_weight.to_wu() as usize,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(
|
||||
builder.finish().is_ok(),
|
||||
@@ -1547,7 +1564,11 @@ fn test_add_foreign_utxo_only_witness_utxo() {
|
||||
..Default::default()
|
||||
};
|
||||
builder
|
||||
.add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
|
||||
.add_foreign_utxo(
|
||||
utxo2.outpoint,
|
||||
psbt_input,
|
||||
satisfaction_weight.to_wu() as usize,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(
|
||||
builder.finish().is_ok(),
|
||||
@@ -1583,8 +1604,6 @@ fn test_create_tx_global_xpubs_origin_missing() {
|
||||
#[test]
|
||||
fn test_create_tx_global_xpubs_master_without_origin() {
|
||||
use bitcoin::bip32;
|
||||
use bitcoin::hex::FromHex;
|
||||
|
||||
let (mut wallet, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
|
||||
let addr = wallet.next_unused_address(KeychainKind::External).unwrap();
|
||||
let mut builder = wallet.build_tx();
|
||||
@@ -1613,7 +1632,7 @@ fn test_bump_fee_irreplaceable_tx() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -1630,7 +1649,7 @@ fn test_bump_fee_confirmed_tx() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
wallet
|
||||
.insert_tx(
|
||||
@@ -1657,7 +1676,7 @@ fn test_bump_fee_low_fee_rate() {
|
||||
let feerate = psbt.fee_rate().unwrap();
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
@@ -1690,7 +1709,7 @@ fn test_bump_fee_low_abs() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
@@ -1713,7 +1732,7 @@ fn test_bump_fee_zero_abs() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -1739,7 +1758,7 @@ fn test_bump_fee_reduce_change() {
|
||||
let original_fee = check_fee!(wallet, psbt);
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -1837,7 +1856,7 @@ fn test_bump_fee_reduce_single_recipient() {
|
||||
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();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -1885,7 +1904,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() {
|
||||
let original_fee = check_fee!(wallet, psbt);
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -1949,7 +1968,7 @@ fn test_bump_fee_drain_wallet() {
|
||||
builder
|
||||
.drain_to(addr.script_pubkey())
|
||||
.add_utxo(OutPoint {
|
||||
txid: tx.txid(),
|
||||
txid: tx.compute_txid(),
|
||||
vout: 0,
|
||||
})
|
||||
.unwrap()
|
||||
@@ -1959,7 +1978,7 @@ fn test_bump_fee_drain_wallet() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -2011,7 +2030,7 @@ fn test_bump_fee_remove_output_manually_selected_only() {
|
||||
)
|
||||
.unwrap();
|
||||
let outpoint = OutPoint {
|
||||
txid: init_tx.txid(),
|
||||
txid: init_tx.compute_txid(),
|
||||
vout: 0,
|
||||
};
|
||||
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX")
|
||||
@@ -2027,7 +2046,7 @@ fn test_bump_fee_remove_output_manually_selected_only() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -2074,7 +2093,7 @@ fn test_bump_fee_add_input() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_details = wallet.sent_and_received(&tx);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -2131,7 +2150,7 @@ fn test_bump_fee_absolute_add_input() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -2197,7 +2216,7 @@ fn test_bump_fee_no_change_add_input_and_change() {
|
||||
let original_fee = check_fee!(wallet, psbt);
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -2267,7 +2286,7 @@ fn test_bump_fee_add_input_change_dust() {
|
||||
let original_tx_weight = tx.weight();
|
||||
assert_eq!(tx.input.len(), 1);
|
||||
assert_eq!(tx.output.len(), 2);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
@@ -2335,7 +2354,7 @@ fn test_bump_fee_force_add_input() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
let mut tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
@@ -2401,7 +2420,7 @@ fn test_bump_fee_absolute_force_add_input() {
|
||||
let psbt = builder.finish().unwrap();
|
||||
let mut tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
// skip saving the new utxos, we know they can't be used anyways
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
@@ -2481,7 +2500,7 @@ fn test_bump_fee_unconfirmed_inputs_only() {
|
||||
ConfirmationTime::Unconfirmed { last_seen: 0 },
|
||||
);
|
||||
let mut tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
@@ -2514,7 +2533,7 @@ fn test_bump_fee_unconfirmed_input() {
|
||||
.enable_rbf();
|
||||
let psbt = builder.finish().unwrap();
|
||||
let mut tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
@@ -3386,7 +3405,11 @@ fn test_taproot_foreign_utxo() {
|
||||
let mut builder = wallet1.build_tx();
|
||||
builder
|
||||
.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000))
|
||||
.add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
|
||||
.add_foreign_utxo(
|
||||
utxo.outpoint,
|
||||
psbt_input,
|
||||
foreign_utxo_satisfaction.to_wu() as usize,
|
||||
)
|
||||
.unwrap();
|
||||
let psbt = builder.finish().unwrap();
|
||||
let sent_received =
|
||||
@@ -3890,7 +3913,10 @@ fn test_fee_rate_sign_no_grinding_high_r() {
|
||||
.unwrap();
|
||||
// We only have one key in the partial_sigs map, this is a trick to retrieve it
|
||||
let key = psbt.inputs[0].partial_sigs.keys().next().unwrap();
|
||||
sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len();
|
||||
sig_len = psbt.inputs[0].partial_sigs[key]
|
||||
.signature
|
||||
.serialize_der()
|
||||
.len();
|
||||
}
|
||||
// Actually finalizing the transaction...
|
||||
wallet
|
||||
@@ -3936,7 +3962,10 @@ fn test_fee_rate_sign_grinding_low_r() {
|
||||
.unwrap();
|
||||
|
||||
let key = psbt.inputs[0].partial_sigs.keys().next().unwrap();
|
||||
let sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len();
|
||||
let sig_len = psbt.inputs[0].partial_sigs[key]
|
||||
.signature
|
||||
.serialize_der()
|
||||
.len();
|
||||
assert_eq!(sig_len, 70);
|
||||
assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), fee_rate);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user