Bump rust-bitcoin to 0.25, fix Cargo dependencies
Closes #112, closes #113, closes #124
This commit is contained in:
parent
69ef56cfed
commit
100f0aaa0a
10
Cargo.toml
10
Cargo.toml
@ -7,15 +7,15 @@ authors = ["Alekos Filini <alekos.filini@gmail.com>", "Riccardo Casatta <riccard
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bdk-macros = { version = "0.1.0-beta.1", path = "./macros" }
|
bdk-macros = { version = "0.1.0-beta.1", path = "./macros" }
|
||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
bitcoin = { version = "0.23", features = ["use-serde"] }
|
bitcoin = { version = "0.25", features = ["use-serde"] }
|
||||||
miniscript = { version = "1.0" }
|
miniscript = { git = "https://github.com/MagicalBitcoin/rust-miniscript", rev = "dfc53201aa5796b6bf3b5a40581d192abaa84133" }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = { version = "^1.0" }
|
serde_json = { version = "^1.0" }
|
||||||
rand = "^0.7"
|
rand = "^0.7"
|
||||||
|
|
||||||
# Optional dependencies
|
# Optional dependencies
|
||||||
sled = { version = "0.34", optional = true }
|
sled = { version = "0.34", optional = true }
|
||||||
electrum-client = { version = "0.2.0-beta.1", optional = true }
|
electrum-client = { version = "0.3.0-beta.1", optional = true }
|
||||||
reqwest = { version = "0.10", optional = true, features = ["json"] }
|
reqwest = { version = "0.10", optional = true, features = ["json"] }
|
||||||
futures = { version = "0.3", optional = true }
|
futures = { version = "0.3", optional = true }
|
||||||
clap = { version = "2.33", optional = true }
|
clap = { version = "2.33", optional = true }
|
||||||
@ -26,10 +26,6 @@ socks = { version = "0.3", optional = true }
|
|||||||
lazy_static = { version = "1.4", optional = true }
|
lazy_static = { version = "1.4", optional = true }
|
||||||
tiny-bip39 = { version = "^0.7", optional = true }
|
tiny-bip39 = { version = "^0.7", optional = true }
|
||||||
|
|
||||||
[patch.crates-io]
|
|
||||||
bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin/", rev = "478e091" }
|
|
||||||
miniscript = { git = "https://github.com/MagicalBitcoin/rust-miniscript", rev = "d0322ac" }
|
|
||||||
|
|
||||||
# Platform-specific dependencies
|
# Platform-specific dependencies
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
tokio = { version = "0.2", features = ["rt-core"] }
|
tokio = { version = "0.2", features = ["rt-core"] }
|
||||||
|
@ -46,7 +46,7 @@ fn main() {
|
|||||||
let policy = extended_desc.extract_policy(signers).unwrap();
|
let policy = extended_desc.extract_policy(signers).unwrap();
|
||||||
println!("policy: {}", serde_json::to_string(&policy).unwrap());
|
println!("policy: {}", serde_json::to_string(&policy).unwrap());
|
||||||
|
|
||||||
let derived_desc = extended_desc.derive(&[ChildNumber::from_normal_idx(42).unwrap()]);
|
let derived_desc = extended_desc.derive(ChildNumber::from_normal_idx(42).unwrap());
|
||||||
println!("{:?}", derived_desc);
|
println!("{:?}", derived_desc);
|
||||||
|
|
||||||
let addr = derived_desc.address(Network::Testnet).unwrap();
|
let addr = derived_desc.address(Network::Testnet).unwrap();
|
||||||
|
@ -31,6 +31,7 @@ pub enum Error {
|
|||||||
InvalidPrefix(Vec<u8>),
|
InvalidPrefix(Vec<u8>),
|
||||||
HardenedDerivationOnXpub,
|
HardenedDerivationOnXpub,
|
||||||
MalformedInput,
|
MalformedInput,
|
||||||
|
InvalidHDKeyPath,
|
||||||
|
|
||||||
KeyParsingError(String),
|
KeyParsingError(String),
|
||||||
Key(crate::keys::KeyError),
|
Key(crate::keys::KeyError),
|
||||||
|
@ -31,7 +31,6 @@ use std::collections::{BTreeMap, HashMap};
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bitcoin::hashes::hash160;
|
|
||||||
use bitcoin::secp256k1::Secp256k1;
|
use bitcoin::secp256k1::Secp256k1;
|
||||||
use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
|
use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
|
||||||
use bitcoin::util::psbt;
|
use bitcoin::util::psbt;
|
||||||
@ -122,27 +121,26 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap) {
|
|||||||
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
|
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
|
||||||
use crate::keys::DescriptorKey;
|
use crate::keys::DescriptorKey;
|
||||||
|
|
||||||
// check the network for the keys
|
let check_key = |pk: &DescriptorPublicKey| {
|
||||||
let translated = self.0.translate_pk(
|
let (pk, _, networks) = if self.0.is_witness() {
|
||||||
|pk| {
|
let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
|
||||||
let (pk, _, networks) = if self.0.is_witness() {
|
pk.clone().to_descriptor_key()?;
|
||||||
let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
|
desciptor_key.extract()?
|
||||||
pk.clone().to_descriptor_key()?;
|
} else {
|
||||||
desciptor_key.extract()?
|
let desciptor_key: DescriptorKey<miniscript::Legacy> =
|
||||||
} else {
|
pk.clone().to_descriptor_key()?;
|
||||||
let desciptor_key: DescriptorKey<miniscript::Legacy> =
|
desciptor_key.extract()?
|
||||||
pk.clone().to_descriptor_key()?;
|
};
|
||||||
desciptor_key.extract()?
|
|
||||||
};
|
|
||||||
|
|
||||||
if networks.contains(&network) {
|
if networks.contains(&network) {
|
||||||
Ok(pk)
|
Ok(pk)
|
||||||
} else {
|
} else {
|
||||||
Err(KeyError::InvalidNetwork)
|
Err(KeyError::InvalidNetwork)
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|pkh| Ok::<_, KeyError>(*pkh),
|
|
||||||
)?;
|
// check the network for the keys
|
||||||
|
let translated = self.0.translate_pk(check_key, check_key)?;
|
||||||
|
|
||||||
Ok((translated, self.1))
|
Ok((translated, self.1))
|
||||||
}
|
}
|
||||||
@ -155,32 +153,31 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap, ValidNetworks) {
|
|||||||
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
|
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
|
||||||
let valid_networks = &self.2;
|
let valid_networks = &self.2;
|
||||||
|
|
||||||
|
let fix_key = |pk: &DescriptorPublicKey| {
|
||||||
|
if valid_networks.contains(&network) {
|
||||||
|
// workaround for xpubs generated by other key types, like bip39: since when the
|
||||||
|
// conversion is made one network has to be chosen, what we generally choose
|
||||||
|
// "mainnet", but then override the set of valid networks to specify that all of
|
||||||
|
// them are valid. here we reset the network to make sure the wallet struct gets a
|
||||||
|
// descriptor with the right network everywhere.
|
||||||
|
let pk = match pk {
|
||||||
|
DescriptorPublicKey::XPub(ref xpub) => {
|
||||||
|
let mut xpub = xpub.clone();
|
||||||
|
xpub.xkey.network = network;
|
||||||
|
|
||||||
|
DescriptorPublicKey::XPub(xpub)
|
||||||
|
}
|
||||||
|
other => other.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(pk)
|
||||||
|
} else {
|
||||||
|
Err(KeyError::InvalidNetwork)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// fixup the network for keys that need it
|
// fixup the network for keys that need it
|
||||||
let translated = self.0.translate_pk(
|
let translated = self.0.translate_pk(fix_key, fix_key)?;
|
||||||
|pk| {
|
|
||||||
if valid_networks.contains(&network) {
|
|
||||||
// workaround for xpubs generated by other key types, like bip39: since when the
|
|
||||||
// conversion is made one network has to be chosen, what we generally choose
|
|
||||||
// "mainnet", but then override the set of valid networks to specify that all of
|
|
||||||
// them are valid. here we reset the network to make sure the wallet struct gets a
|
|
||||||
// descriptor with the right network everywhere.
|
|
||||||
let pk = match pk {
|
|
||||||
DescriptorPublicKey::XPub(ref xpub) => {
|
|
||||||
let mut xpub = xpub.clone();
|
|
||||||
xpub.xkey.network = network;
|
|
||||||
|
|
||||||
DescriptorPublicKey::XPub(xpub)
|
|
||||||
}
|
|
||||||
other => other.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(pk)
|
|
||||||
} else {
|
|
||||||
Err(KeyError::InvalidNetwork)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|pkh| Ok::<_, KeyError>(*pkh),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok((translated, self.1))
|
Ok((translated, self.1))
|
||||||
}
|
}
|
||||||
@ -188,10 +185,7 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap, ValidNetworks) {
|
|||||||
|
|
||||||
/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
|
/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
|
||||||
pub trait ExtractPolicy {
|
pub trait ExtractPolicy {
|
||||||
fn extract_policy(
|
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error>;
|
||||||
&self,
|
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
|
||||||
) -> Result<Option<Policy>, Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait XKeyUtils {
|
pub(crate) trait XKeyUtils {
|
||||||
@ -201,7 +195,7 @@ pub(crate) trait XKeyUtils {
|
|||||||
|
|
||||||
impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
|
impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
|
||||||
fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
|
fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
|
||||||
let full_path = match self.source {
|
let full_path = match self.origin {
|
||||||
Some((_, ref path)) => path
|
Some((_, ref path)) => path
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(self.derivation_path.into_iter())
|
.chain(self.derivation_path.into_iter())
|
||||||
@ -222,7 +216,7 @@ impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn root_fingerprint(&self) -> Fingerprint {
|
fn root_fingerprint(&self) -> Fingerprint {
|
||||||
match self.source {
|
match self.origin {
|
||||||
Some((fingerprint, _)) => fingerprint,
|
Some((fingerprint, _)) => fingerprint,
|
||||||
None => self.xkey.xkey_fingerprint(),
|
None => self.xkey.xkey_fingerprint(),
|
||||||
}
|
}
|
||||||
@ -280,11 +274,13 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
|
fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
|
||||||
let mut answer = BTreeMap::new();
|
fn translate_key(
|
||||||
|
key: &DescriptorPublicKey,
|
||||||
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
|
index: u32,
|
||||||
|
paths: &mut HDKeyPaths,
|
||||||
|
) -> Result<DummyKey, Error> {
|
||||||
match key {
|
match key {
|
||||||
DescriptorPublicKey::PubKey(_) => {}
|
DescriptorPublicKey::SinglePub(_) => {}
|
||||||
DescriptorPublicKey::XPub(xpub) => {
|
DescriptorPublicKey::XPub(xpub) => {
|
||||||
let derive_path = if xpub.is_wildcard {
|
let derive_path = if xpub.is_wildcard {
|
||||||
xpub.derivation_path
|
xpub.derivation_path
|
||||||
@ -299,7 +295,7 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
|
|||||||
.xkey
|
.xkey
|
||||||
.derive_pub(&Secp256k1::verification_only(), &derive_path)?;
|
.derive_pub(&Secp256k1::verification_only(), &derive_path)?;
|
||||||
|
|
||||||
answer.insert(
|
paths.insert(
|
||||||
derived_pubkey.public_key,
|
derived_pubkey.public_key,
|
||||||
(
|
(
|
||||||
xpub.root_fingerprint(),
|
xpub.root_fingerprint(),
|
||||||
@ -310,42 +306,54 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(DummyKey::default())
|
Ok(DummyKey::default())
|
||||||
};
|
}
|
||||||
let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
|
|
||||||
|
|
||||||
self.translate_pk(translatefpk, translatefpkh)?;
|
let mut answer_pk = BTreeMap::new();
|
||||||
|
let mut answer_pkh = BTreeMap::new();
|
||||||
|
|
||||||
Ok(answer)
|
self.translate_pk(
|
||||||
|
|pk| translate_key(pk, index, &mut answer_pk),
|
||||||
|
|pkh| translate_key(pkh, index, &mut answer_pkh),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
answer_pk.append(&mut answer_pkh);
|
||||||
|
|
||||||
|
Ok(answer_pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_fixed(&self) -> bool {
|
fn is_fixed(&self) -> bool {
|
||||||
let mut found_wildcard = false;
|
fn check_key(key: &DescriptorPublicKey, flag: &mut bool) -> Result<DummyKey, Error> {
|
||||||
|
|
||||||
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
|
|
||||||
match key {
|
match key {
|
||||||
DescriptorPublicKey::PubKey(_) => {}
|
DescriptorPublicKey::SinglePub(_) => {}
|
||||||
DescriptorPublicKey::XPub(xpub) => {
|
DescriptorPublicKey::XPub(xpub) => {
|
||||||
if xpub.is_wildcard {
|
if xpub.is_wildcard {
|
||||||
found_wildcard = true;
|
*flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DummyKey::default())
|
Ok(DummyKey::default())
|
||||||
};
|
}
|
||||||
let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
|
|
||||||
|
|
||||||
self.translate_pk(translatefpk, translatefpkh).unwrap();
|
let mut found_wildcard_pk = false;
|
||||||
|
let mut found_wildcard_pkh = false;
|
||||||
|
|
||||||
!found_wildcard
|
self.translate_pk(
|
||||||
|
|pk| check_key(pk, &mut found_wildcard_pk),
|
||||||
|
|pkh| check_key(pkh, &mut found_wildcard_pkh),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
!found_wildcard_pk && !found_wildcard_pkh
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
|
fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
|
||||||
let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
|
fn try_key(
|
||||||
|
key: &DescriptorPublicKey,
|
||||||
let mut derive_path = None::<DerivationPath>;
|
index: &HashMap<Fingerprint, DerivationPath>,
|
||||||
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
|
found_path: &mut Option<ChildNumber>,
|
||||||
if derive_path.is_some() {
|
) -> Result<DummyKey, Error> {
|
||||||
|
if found_path.is_some() {
|
||||||
// already found a matching path, we are done
|
// already found a matching path, we are done
|
||||||
return Ok(DummyKey::default());
|
return Ok(DummyKey::default());
|
||||||
}
|
}
|
||||||
@ -353,9 +361,10 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
|
|||||||
if let DescriptorPublicKey::XPub(xpub) = key {
|
if let DescriptorPublicKey::XPub(xpub) = key {
|
||||||
// Check if the key matches one entry in our `index`. If it does, `matches()` will
|
// Check if the key matches one entry in our `index`. If it does, `matches()` will
|
||||||
// return the "prefix" that matched, so we remove that prefix from the full path
|
// return the "prefix" that matched, so we remove that prefix from the full path
|
||||||
// found in `index` and save it in `derive_path`
|
// found in `index` and save it in `derive_path`. We expect this to be a derivation
|
||||||
|
// path of length 1 if the key `is_wildcard` and an empty path otherwise.
|
||||||
let root_fingerprint = xpub.root_fingerprint();
|
let root_fingerprint = xpub.root_fingerprint();
|
||||||
derive_path = index
|
let derivation_path: Option<Vec<ChildNumber>> = index
|
||||||
.get_key_value(&root_fingerprint)
|
.get_key_value(&root_fingerprint)
|
||||||
.and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
|
.and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
|
||||||
.map(|prefix| {
|
.map(|prefix| {
|
||||||
@ -367,15 +376,46 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
match derivation_path {
|
||||||
|
Some(path) if xpub.is_wildcard && path.len() == 1 => {
|
||||||
|
*found_path = Some(path[0])
|
||||||
|
}
|
||||||
|
Some(path) if !xpub.is_wildcard && path.is_empty() => {
|
||||||
|
*found_path = Some(ChildNumber::Normal { index: 0 })
|
||||||
|
}
|
||||||
|
Some(_) => return Err(Error::InvalidHDKeyPath),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DummyKey::default())
|
Ok(DummyKey::default())
|
||||||
};
|
};
|
||||||
let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
|
|
||||||
|
|
||||||
self.translate_pk(translatefpk, translatefpkh).unwrap();
|
let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
|
||||||
|
|
||||||
derive_path.map(|path| self.derive(path.as_ref()))
|
let mut found_path_pk = None;
|
||||||
|
let mut found_path_pkh = None;
|
||||||
|
|
||||||
|
if self
|
||||||
|
.translate_pk(
|
||||||
|
|pk| try_key(pk, &index, &mut found_path_pk),
|
||||||
|
|pkh| try_key(pkh, &index, &mut found_path_pkh),
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have found a path for both `found_path_pk` and `found_path_pkh` but they are
|
||||||
|
// different we consider this an error and return None. we only return a path either if
|
||||||
|
// they are equal or if only one of them is Some(_)
|
||||||
|
let merged_path = match (found_path_pk, found_path_pkh) {
|
||||||
|
(Some(a), Some(b)) if a != b => return None,
|
||||||
|
(a, b) => a.or(b),
|
||||||
|
};
|
||||||
|
|
||||||
|
merged_path.map(|path| self.derive(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_from_psbt_input(
|
fn derive_from_psbt_input(
|
||||||
|
@ -56,7 +56,7 @@ use bitcoin::util::bip32::Fingerprint;
|
|||||||
use bitcoin::PublicKey;
|
use bitcoin::PublicKey;
|
||||||
|
|
||||||
use miniscript::descriptor::DescriptorPublicKey;
|
use miniscript::descriptor::DescriptorPublicKey;
|
||||||
use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
|
use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal, ToPublicKey};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{debug, error, info, trace};
|
use log::{debug, error, info, trace};
|
||||||
@ -82,8 +82,8 @@ pub struct PKOrF {
|
|||||||
impl PKOrF {
|
impl PKOrF {
|
||||||
fn from_key(k: &DescriptorPublicKey) -> Self {
|
fn from_key(k: &DescriptorPublicKey) -> Self {
|
||||||
match k {
|
match k {
|
||||||
DescriptorPublicKey::PubKey(pubkey) => PKOrF {
|
DescriptorPublicKey::SinglePub(pubkey) => PKOrF {
|
||||||
pubkey: Some(*pubkey),
|
pubkey: Some(pubkey.key),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
DescriptorPublicKey::XPub(xpub) => PKOrF {
|
DescriptorPublicKey::XPub(xpub) => PKOrF {
|
||||||
@ -524,7 +524,7 @@ impl Policy {
|
|||||||
|
|
||||||
fn make_multisig(
|
fn make_multisig(
|
||||||
keys: &[DescriptorPublicKey],
|
keys: &[DescriptorPublicKey],
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
signers: Arc<SignersContainer>,
|
||||||
threshold: usize,
|
threshold: usize,
|
||||||
) -> Result<Option<Policy>, PolicyError> {
|
) -> Result<Option<Policy>, PolicyError> {
|
||||||
if threshold == 0 {
|
if threshold == 0 {
|
||||||
@ -648,17 +648,14 @@ impl From<SatisfiableItem> for Policy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signer_id(key: &DescriptorPublicKey) -> SignerId<DescriptorPublicKey> {
|
fn signer_id(key: &DescriptorPublicKey) -> SignerId {
|
||||||
match key {
|
match key {
|
||||||
DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
|
DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
|
||||||
DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
|
DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(
|
fn signature(key: &DescriptorPublicKey, signers: Arc<SignersContainer>) -> Policy {
|
||||||
key: &DescriptorPublicKey,
|
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
|
||||||
) -> Policy {
|
|
||||||
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
|
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
|
||||||
|
|
||||||
policy.contribution = if signers.find(signer_id(key)).is_some() {
|
policy.contribution = if signers.find(signer_id(key)).is_some() {
|
||||||
@ -673,12 +670,13 @@ fn signature(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature_key(
|
fn signature_key(
|
||||||
key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
|
key: &<DescriptorPublicKey as MiniscriptKey>::Hash,
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
signers: Arc<SignersContainer>,
|
||||||
) -> Policy {
|
) -> Policy {
|
||||||
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(*key_hash)).into();
|
let key_hash = key.to_public_key().to_pubkeyhash();
|
||||||
|
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(key_hash)).into();
|
||||||
|
|
||||||
if signers.find(SignerId::PkHash(*key_hash)).is_some() {
|
if signers.find(SignerId::PkHash(key_hash)).is_some() {
|
||||||
policy.contribution = Satisfaction::Complete {
|
policy.contribution = Satisfaction::Complete {
|
||||||
condition: Default::default(),
|
condition: Default::default(),
|
||||||
}
|
}
|
||||||
@ -688,10 +686,7 @@ fn signature_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
|
impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
|
||||||
fn extract_policy(
|
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error> {
|
||||||
&self,
|
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
|
||||||
) -> Result<Option<Policy>, Error> {
|
|
||||||
Ok(match &self.node {
|
Ok(match &self.node {
|
||||||
// Leaves
|
// Leaves
|
||||||
Terminal::True | Terminal::False => None,
|
Terminal::True | Terminal::False => None,
|
||||||
@ -781,10 +776,7 @@ impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
|
impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
|
||||||
fn extract_policy(
|
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error> {
|
||||||
&self,
|
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
|
||||||
) -> Result<Option<Policy>, Error> {
|
|
||||||
match self {
|
match self {
|
||||||
Descriptor::Pk(pubkey)
|
Descriptor::Pk(pubkey)
|
||||||
| Descriptor::Pkh(pubkey)
|
| Descriptor::Pkh(pubkey)
|
||||||
|
@ -32,7 +32,9 @@ use std::ops::Deref;
|
|||||||
use bitcoin::util::bip32;
|
use bitcoin::util::bip32;
|
||||||
use bitcoin::{Network, PrivateKey, PublicKey};
|
use bitcoin::{Network, PrivateKey, PublicKey};
|
||||||
|
|
||||||
pub use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey};
|
pub use miniscript::descriptor::{
|
||||||
|
DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub,
|
||||||
|
};
|
||||||
use miniscript::descriptor::{DescriptorXKey, KeyMap};
|
use miniscript::descriptor::{DescriptorXKey, KeyMap};
|
||||||
pub use miniscript::ScriptContext;
|
pub use miniscript::ScriptContext;
|
||||||
use miniscript::{Miniscript, Terminal};
|
use miniscript::{Miniscript, Terminal};
|
||||||
@ -198,7 +200,7 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
|
|||||||
/// ```
|
/// ```
|
||||||
/// use bdk::bitcoin::PublicKey;
|
/// use bdk::bitcoin::PublicKey;
|
||||||
///
|
///
|
||||||
/// use bdk::keys::{mainnet_network, ScriptContext, ToDescriptorKey, DescriptorKey, DescriptorPublicKey, KeyError};
|
/// use bdk::keys::{mainnet_network, ScriptContext, ToDescriptorKey, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError};
|
||||||
///
|
///
|
||||||
/// pub struct MyKeyType {
|
/// pub struct MyKeyType {
|
||||||
/// pubkey: PublicKey,
|
/// pubkey: PublicKey,
|
||||||
@ -206,7 +208,10 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
|
|||||||
///
|
///
|
||||||
/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
|
/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
|
||||||
/// fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
/// fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
/// Ok(DescriptorKey::from_public(DescriptorPublicKey::PubKey(self.pubkey), mainnet_network()))
|
/// Ok(DescriptorKey::from_public(DescriptorPublicKey::SinglePub(DescriptorSinglePub {
|
||||||
|
/// origin: None,
|
||||||
|
/// key: self.pubkey
|
||||||
|
/// }), mainnet_network()))
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -286,7 +291,7 @@ pub trait DerivableKey<Ctx: ScriptContext> {
|
|||||||
/// Add a extra metadata, consume `self` and turn it into a [`DescriptorKey`]
|
/// Add a extra metadata, consume `self` and turn it into a [`DescriptorKey`]
|
||||||
fn add_metadata(
|
fn add_metadata(
|
||||||
self,
|
self,
|
||||||
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
||||||
derivation_path: bip32::DerivationPath,
|
derivation_path: bip32::DerivationPath,
|
||||||
) -> Result<DescriptorKey<Ctx>, KeyError>;
|
) -> Result<DescriptorKey<Ctx>, KeyError>;
|
||||||
}
|
}
|
||||||
@ -294,11 +299,11 @@ pub trait DerivableKey<Ctx: ScriptContext> {
|
|||||||
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
|
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
|
||||||
fn add_metadata(
|
fn add_metadata(
|
||||||
self,
|
self,
|
||||||
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
||||||
derivation_path: bip32::DerivationPath,
|
derivation_path: bip32::DerivationPath,
|
||||||
) -> Result<DescriptorKey<Ctx>, KeyError> {
|
) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
DescriptorPublicKey::XPub(DescriptorXKey {
|
DescriptorPublicKey::XPub(DescriptorXKey {
|
||||||
source,
|
origin,
|
||||||
xkey: self,
|
xkey: self,
|
||||||
derivation_path,
|
derivation_path,
|
||||||
is_wildcard: true,
|
is_wildcard: true,
|
||||||
@ -310,11 +315,11 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
|
|||||||
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
|
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
|
||||||
fn add_metadata(
|
fn add_metadata(
|
||||||
self,
|
self,
|
||||||
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
||||||
derivation_path: bip32::DerivationPath,
|
derivation_path: bip32::DerivationPath,
|
||||||
) -> Result<DescriptorKey<Ctx>, KeyError> {
|
) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
DescriptorSecretKey::XPrv(DescriptorXKey {
|
DescriptorSecretKey::XPrv(DescriptorXKey {
|
||||||
source,
|
origin,
|
||||||
xkey: self,
|
xkey: self,
|
||||||
derivation_path,
|
derivation_path,
|
||||||
is_wildcard: true,
|
is_wildcard: true,
|
||||||
@ -355,10 +360,10 @@ where
|
|||||||
{
|
{
|
||||||
fn add_metadata(
|
fn add_metadata(
|
||||||
self,
|
self,
|
||||||
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
|
||||||
derivation_path: bip32::DerivationPath,
|
derivation_path: bip32::DerivationPath,
|
||||||
) -> Result<DescriptorKey<Ctx>, KeyError> {
|
) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
let descriptor_key = self.key.add_metadata(source, derivation_path)?;
|
let descriptor_key = self.key.add_metadata(origin, derivation_path)?;
|
||||||
Ok(descriptor_key.override_valid_networks(self.valid_networks))
|
Ok(descriptor_key.override_valid_networks(self.valid_networks))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +488,7 @@ impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx> {
|
|||||||
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
|
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
|
||||||
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
let networks = match self {
|
let networks = match self {
|
||||||
DescriptorPublicKey::PubKey(_) => any_network(),
|
DescriptorPublicKey::SinglePub(_) => any_network(),
|
||||||
DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
|
DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
|
||||||
if xkey.network == Network::Bitcoin =>
|
if xkey.network == Network::Bitcoin =>
|
||||||
{
|
{
|
||||||
@ -498,14 +503,20 @@ impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
|
|||||||
|
|
||||||
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey {
|
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey {
|
||||||
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
DescriptorPublicKey::PubKey(self).to_descriptor_key()
|
DescriptorPublicKey::SinglePub(DescriptorSinglePub {
|
||||||
|
key: self,
|
||||||
|
origin: None,
|
||||||
|
})
|
||||||
|
.to_descriptor_key()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
|
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
|
||||||
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
let networks = match self {
|
let networks = match &self {
|
||||||
DescriptorSecretKey::PrivKey(sk) if sk.network == Network::Bitcoin => mainnet_network(),
|
DescriptorSecretKey::SinglePriv(sk) if sk.key.network == Network::Bitcoin => {
|
||||||
|
mainnet_network()
|
||||||
|
}
|
||||||
DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. })
|
DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. })
|
||||||
if xkey.network == Network::Bitcoin =>
|
if xkey.network == Network::Bitcoin =>
|
||||||
{
|
{
|
||||||
@ -520,7 +531,11 @@ impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
|
|||||||
|
|
||||||
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PrivateKey {
|
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PrivateKey {
|
||||||
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
|
||||||
DescriptorSecretKey::PrivKey(self).to_descriptor_key()
|
DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
|
||||||
|
key: self,
|
||||||
|
origin: None,
|
||||||
|
})
|
||||||
|
.to_descriptor_key()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ use bitcoin::util::bip32::ChildNumber;
|
|||||||
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
|
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
|
||||||
use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
|
use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
|
||||||
|
|
||||||
use miniscript::descriptor::DescriptorPublicKey;
|
use miniscript::psbt::PsbtInputSatisfier;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{debug, error, info, trace};
|
use log::{debug, error, info, trace};
|
||||||
@ -87,8 +87,8 @@ pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> {
|
|||||||
descriptor: ExtendedDescriptor,
|
descriptor: ExtendedDescriptor,
|
||||||
change_descriptor: Option<ExtendedDescriptor>,
|
change_descriptor: Option<ExtendedDescriptor>,
|
||||||
|
|
||||||
signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
signers: Arc<SignersContainer>,
|
||||||
change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
|
change_signers: Arc<SignersContainer>,
|
||||||
|
|
||||||
address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
|
address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ where
|
|||||||
let index = self.fetch_and_increment_index(ScriptType::External)?;
|
let index = self.fetch_and_increment_index(ScriptType::External)?;
|
||||||
|
|
||||||
self.descriptor
|
self.descriptor
|
||||||
.derive(&[ChildNumber::from_normal_idx(index).unwrap()])
|
.derive(ChildNumber::from_normal_idx(index)?)
|
||||||
.address(self.network)
|
.address(self.network)
|
||||||
.ok_or(Error::ScriptDoesntHaveAddressForm)
|
.ok_or(Error::ScriptDoesntHaveAddressForm)
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ where
|
|||||||
pub fn add_signer(
|
pub fn add_signer(
|
||||||
&mut self,
|
&mut self,
|
||||||
script_type: ScriptType,
|
script_type: ScriptType,
|
||||||
id: SignerId<DescriptorPublicKey>,
|
id: SignerId,
|
||||||
ordering: SignerOrdering,
|
ordering: SignerOrdering,
|
||||||
signer: Arc<Box<dyn Signer>>,
|
signer: Arc<Box<dyn Signer>>,
|
||||||
) {
|
) {
|
||||||
@ -803,7 +803,7 @@ where
|
|||||||
match desc.satisfy(
|
match desc.satisfy(
|
||||||
input,
|
input,
|
||||||
(
|
(
|
||||||
psbt_input.clone(),
|
PsbtInputSatisfier::new(&psbt, n),
|
||||||
After::new(current_height, false),
|
After::new(current_height, false),
|
||||||
Older::new(current_height, create_height, false),
|
Older::new(current_height, create_height, false),
|
||||||
),
|
),
|
||||||
@ -846,7 +846,7 @@ where
|
|||||||
.borrow()
|
.borrow()
|
||||||
.get_path_from_script_pubkey(&txout.script_pubkey)?
|
.get_path_from_script_pubkey(&txout.script_pubkey)?
|
||||||
.map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child))
|
.map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child))
|
||||||
.map(|(desc, child)| desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()])))
|
.map(|(desc, child)| desc.derive(ChildNumber::from_normal_idx(child).unwrap())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_change_address(&self) -> Result<Script, Error> {
|
fn get_change_address(&self) -> Result<Script, Error> {
|
||||||
@ -854,7 +854,7 @@ where
|
|||||||
let index = self.fetch_and_increment_index(script_type)?;
|
let index = self.fetch_and_increment_index(script_type)?;
|
||||||
|
|
||||||
Ok(desc
|
Ok(desc
|
||||||
.derive(&[ChildNumber::from_normal_idx(index).unwrap()])
|
.derive(ChildNumber::from_normal_idx(index)?)
|
||||||
.script_pubkey())
|
.script_pubkey())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -879,7 +879,7 @@ where
|
|||||||
|
|
||||||
let hd_keypaths = descriptor.get_hd_keypaths(index)?;
|
let hd_keypaths = descriptor.get_hd_keypaths(index)?;
|
||||||
let script = descriptor
|
let script = descriptor
|
||||||
.derive(&[ChildNumber::from_normal_idx(index).unwrap()])
|
.derive(ChildNumber::from_normal_idx(index)?)
|
||||||
.script_pubkey();
|
.script_pubkey();
|
||||||
for validator in &self.address_validators {
|
for validator in &self.address_validators {
|
||||||
validator.validate(script_type, &hd_keypaths, &script)?;
|
validator.validate(script_type, &hd_keypaths, &script)?;
|
||||||
@ -909,7 +909,7 @@ where
|
|||||||
for i in from..(from + count) {
|
for i in from..(from + count) {
|
||||||
address_batch.set_script_pubkey(
|
address_batch.set_script_pubkey(
|
||||||
&descriptor
|
&descriptor
|
||||||
.derive(&[ChildNumber::from_normal_idx(i).unwrap()])
|
.derive(ChildNumber::from_normal_idx(i)?)
|
||||||
.script_pubkey(),
|
.script_pubkey(),
|
||||||
script_type,
|
script_type,
|
||||||
i,
|
i,
|
||||||
@ -1004,7 +1004,7 @@ where
|
|||||||
|
|
||||||
let (desc, _) = self.get_descriptor_for_script_type(script_type);
|
let (desc, _) = self.get_descriptor_for_script_type(script_type);
|
||||||
psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?;
|
psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?;
|
||||||
let derived_descriptor = desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]);
|
let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
|
||||||
|
|
||||||
psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
|
psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
|
||||||
psbt_input.witness_script = derived_descriptor.psbt_witness_script();
|
psbt_input.witness_script = derived_descriptor.psbt_witness_script();
|
||||||
|
@ -102,7 +102,7 @@ use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
|
|||||||
use bitcoin::util::{bip143, psbt};
|
use bitcoin::util::{bip143, psbt};
|
||||||
use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
|
use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
|
||||||
|
|
||||||
use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap};
|
use miniscript::descriptor::{DescriptorSecretKey, DescriptorSinglePriv, DescriptorXKey, KeyMap};
|
||||||
use miniscript::{Legacy, MiniscriptKey, Segwitv0};
|
use miniscript::{Legacy, MiniscriptKey, Segwitv0};
|
||||||
|
|
||||||
use crate::descriptor::XKeyUtils;
|
use crate::descriptor::XKeyUtils;
|
||||||
@ -110,19 +110,19 @@ use crate::descriptor::XKeyUtils;
|
|||||||
/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
|
/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
|
||||||
/// multiple of them
|
/// multiple of them
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum SignerId<Pk: MiniscriptKey> {
|
pub enum SignerId {
|
||||||
PkHash(<Pk as MiniscriptKey>::Hash),
|
PkHash(hash160::Hash),
|
||||||
Fingerprint(Fingerprint),
|
Fingerprint(Fingerprint),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
|
impl From<hash160::Hash> for SignerId {
|
||||||
fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
|
fn from(hash: hash160::Hash) -> SignerId {
|
||||||
SignerId::PkHash(hash)
|
SignerId::PkHash(hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
|
impl From<Fingerprint> for SignerId {
|
||||||
fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
|
fn from(fing: Fingerprint) -> SignerId {
|
||||||
SignerId::Fingerprint(fing)
|
SignerId::Fingerprint(fing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,7 +284,10 @@ impl Signer for PrivateKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
|
fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
|
||||||
Some(DescriptorSecretKey::PrivKey(*self))
|
Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
|
||||||
|
key: *self,
|
||||||
|
origin: None,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,13 +306,13 @@ impl std::default::Default for SignerOrdering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct SignersContainerKey<Pk: MiniscriptKey> {
|
struct SignersContainerKey {
|
||||||
id: SignerId<Pk>,
|
id: SignerId,
|
||||||
ordering: SignerOrdering,
|
ordering: SignerOrdering,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
|
impl From<(SignerId, SignerOrdering)> for SignersContainerKey {
|
||||||
fn from(tuple: (SignerId<Pk>, SignerOrdering)) -> Self {
|
fn from(tuple: (SignerId, SignerOrdering)) -> Self {
|
||||||
SignersContainerKey {
|
SignersContainerKey {
|
||||||
id: tuple.0,
|
id: tuple.0,
|
||||||
ordering: tuple.1,
|
ordering: tuple.1,
|
||||||
@ -319,11 +322,9 @@ impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContaine
|
|||||||
|
|
||||||
/// Container for multiple signers
|
/// Container for multiple signers
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct SignersContainer<Pk: MiniscriptKey>(
|
pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<Box<dyn Signer>>>);
|
||||||
BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl SignersContainer<DescriptorPublicKey> {
|
impl SignersContainer {
|
||||||
pub fn as_key_map(&self) -> KeyMap {
|
pub fn as_key_map(&self) -> KeyMap {
|
||||||
self.0
|
self.0
|
||||||
.values()
|
.values()
|
||||||
@ -333,20 +334,21 @@ impl SignersContainer<DescriptorPublicKey> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
|
impl From<KeyMap> for SignersContainer {
|
||||||
fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
|
fn from(keymap: KeyMap) -> SignersContainer {
|
||||||
let mut container = SignersContainer::new();
|
let mut container = SignersContainer::new();
|
||||||
|
|
||||||
for (_, secret) in keymap {
|
for (_, secret) in keymap {
|
||||||
match secret {
|
match secret {
|
||||||
DescriptorSecretKey::PrivKey(private_key) => container.add_external(
|
DescriptorSecretKey::SinglePriv(private_key) => container.add_external(
|
||||||
SignerId::from(
|
SignerId::from(
|
||||||
private_key
|
private_key
|
||||||
|
.key
|
||||||
.public_key(&Secp256k1::signing_only())
|
.public_key(&Secp256k1::signing_only())
|
||||||
.to_pubkeyhash(),
|
.to_pubkeyhash(),
|
||||||
),
|
),
|
||||||
SignerOrdering::default(),
|
SignerOrdering::default(),
|
||||||
Arc::new(Box::new(private_key)),
|
Arc::new(Box::new(private_key.key)),
|
||||||
),
|
),
|
||||||
DescriptorSecretKey::XPrv(xprv) => container.add_external(
|
DescriptorSecretKey::XPrv(xprv) => container.add_external(
|
||||||
SignerId::from(xprv.root_fingerprint()),
|
SignerId::from(xprv.root_fingerprint()),
|
||||||
@ -360,7 +362,7 @@ impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pk: MiniscriptKey> SignersContainer<Pk> {
|
impl SignersContainer {
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SignersContainer(Default::default())
|
SignersContainer(Default::default())
|
||||||
@ -370,7 +372,7 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
|
|||||||
/// signer that was previosuly in the container, if any
|
/// signer that was previosuly in the container, if any
|
||||||
pub fn add_external(
|
pub fn add_external(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: SignerId<Pk>,
|
id: SignerId,
|
||||||
ordering: SignerOrdering,
|
ordering: SignerOrdering,
|
||||||
signer: Arc<Box<dyn Signer>>,
|
signer: Arc<Box<dyn Signer>>,
|
||||||
) -> Option<Arc<Box<dyn Signer>>> {
|
) -> Option<Arc<Box<dyn Signer>>> {
|
||||||
@ -380,14 +382,14 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
|
|||||||
/// Removes a signer from the container and returns it
|
/// Removes a signer from the container and returns it
|
||||||
pub fn remove(
|
pub fn remove(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: SignerId<Pk>,
|
id: SignerId,
|
||||||
ordering: SignerOrdering,
|
ordering: SignerOrdering,
|
||||||
) -> Option<Arc<Box<dyn Signer>>> {
|
) -> Option<Arc<Box<dyn Signer>>> {
|
||||||
self.0.remove(&(id, ordering).into())
|
self.0.remove(&(id, ordering).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the list of identifiers of all the signers in the container
|
/// Returns the list of identifiers of all the signers in the container
|
||||||
pub fn ids(&self) -> Vec<&SignerId<Pk>> {
|
pub fn ids(&self) -> Vec<&SignerId> {
|
||||||
self.0
|
self.0
|
||||||
.keys()
|
.keys()
|
||||||
.map(|SignersContainerKey { id, .. }| id)
|
.map(|SignersContainerKey { id, .. }| id)
|
||||||
@ -400,7 +402,7 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the signer with lowest ordering for a given id in the container.
|
/// Finds the signer with lowest ordering for a given id in the container.
|
||||||
pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>> {
|
pub fn find(&self, id: SignerId) -> Option<&Arc<Box<dyn Signer>>> {
|
||||||
self.0
|
self.0
|
||||||
.range((
|
.range((
|
||||||
Included(&(id.clone(), SignerOrdering(0)).into()),
|
Included(&(id.clone(), SignerOrdering(0)).into()),
|
||||||
@ -515,22 +517,22 @@ impl ComputeSighash for Segwitv0 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pk: MiniscriptKey> PartialOrd for SignersContainerKey<Pk> {
|
impl PartialOrd for SignersContainerKey {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
|
impl Ord for SignersContainerKey {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
self.ordering.cmp(&other.ordering)
|
self.ordering.cmp(&other.ordering)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
|
impl PartialEq for SignersContainerKey {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.ordering == other.ordering
|
self.ordering == other.ordering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
|
impl Eq for SignersContainerKey {}
|
||||||
|
@ -206,7 +206,7 @@ impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
|
|||||||
///
|
///
|
||||||
/// The `version` should always be greater than `0` and greater than `1` if the wallet's
|
/// The `version` should always be greater than `0` and greater than `1` if the wallet's
|
||||||
/// descriptors contain an "older" (OP_CSV) operator.
|
/// descriptors contain an "older" (OP_CSV) operator.
|
||||||
pub fn version(mut self, version: u32) -> Self {
|
pub fn version(mut self, version: i32) -> Self {
|
||||||
self.version = Some(Version(version));
|
self.version = Some(Version(version));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ impl TxOrdering {
|
|||||||
///
|
///
|
||||||
/// Has a default value of `1`
|
/// Has a default value of `1`
|
||||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
pub(crate) struct Version(pub(crate) u32);
|
pub(crate) struct Version(pub(crate) i32);
|
||||||
|
|
||||||
impl Default for Version {
|
impl Default for Version {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -9,17 +9,11 @@ name = "testutils"
|
|||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
# The latest bitcoincore-rpc depends on an older version of bitcoin, which in turns depends on an
|
|
||||||
# older version of secp256k1, which causes conflicts during linking. Use my fork right now, we can
|
|
||||||
# switch back to crates.io as soon as rust-bitcoin is updated in rust-bitcoincore-rpc.
|
|
||||||
#
|
|
||||||
# Tracking issue: https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/80
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serial_test = "0.4"
|
serial_test = "0.4"
|
||||||
bitcoin = "0.23"
|
bitcoin = "0.25"
|
||||||
bitcoincore-rpc = "0.11"
|
bitcoincore-rpc = "0.12"
|
||||||
electrum-client = "0.2.0-beta.1"
|
electrum-client = "0.3.0-beta.1"
|
||||||
|
@ -119,13 +119,13 @@ macro_rules! testutils {
|
|||||||
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
|
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
|
||||||
|
|
||||||
let parsed = Descriptor::<DescriptorPublicKey>::parse_secret(&$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0;
|
let parsed = Descriptor::<DescriptorPublicKey>::parse_secret(&$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0;
|
||||||
parsed.derive(&[bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()]).address(bitcoin::Network::Regtest).expect("No address form")
|
parsed.derive(bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()).address(bitcoin::Network::Regtest).expect("No address form")
|
||||||
});
|
});
|
||||||
( @internal $descriptors:expr, $child:expr ) => ({
|
( @internal $descriptors:expr, $child:expr ) => ({
|
||||||
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
|
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
|
||||||
|
|
||||||
let parsed = Descriptor::<DescriptorPublicKey>::parse_secret(&$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0;
|
let parsed = Descriptor::<DescriptorPublicKey>::parse_secret(&$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0;
|
||||||
parsed.derive(&[bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()]).address(bitcoin::Network::Regtest).expect("No address form")
|
parsed.derive(bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()).address(bitcoin::Network::Regtest).expect("No address form")
|
||||||
});
|
});
|
||||||
( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) });
|
( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) });
|
||||||
( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
|
( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
|
||||||
@ -386,7 +386,7 @@ impl TestClient {
|
|||||||
trace!("getblocktemplate: {:#?}", block_template);
|
trace!("getblocktemplate: {:#?}", block_template);
|
||||||
|
|
||||||
let header = BlockHeader {
|
let header = BlockHeader {
|
||||||
version: block_template["version"].as_u64().unwrap() as u32,
|
version: block_template["version"].as_i64().unwrap() as i32,
|
||||||
prev_blockhash: BlockHash::from_hex(
|
prev_blockhash: BlockHash::from_hex(
|
||||||
block_template["previousblockhash"].as_str().unwrap(),
|
block_template["previousblockhash"].as_str().unwrap(),
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user