Bump rust-bitcoin to 0.25, fix Cargo dependencies

Closes #112, closes #113, closes #124
This commit is contained in:
Alekos Filini 2020-10-09 12:03:47 +02:00
parent 69ef56cfed
commit 100f0aaa0a
No known key found for this signature in database
GPG Key ID: 5E8AFC3034FDFA4F
11 changed files with 219 additions and 179 deletions

View File

@ -7,15 +7,15 @@ authors = ["Alekos Filini <alekos.filini@gmail.com>", "Riccardo Casatta <riccard
[dependencies]
bdk-macros = { version = "0.1.0-beta.1", path = "./macros" }
log = "^0.4"
bitcoin = { version = "0.23", features = ["use-serde"] }
miniscript = { version = "1.0" }
bitcoin = { version = "0.25", features = ["use-serde"] }
miniscript = { git = "https://github.com/MagicalBitcoin/rust-miniscript", rev = "dfc53201aa5796b6bf3b5a40581d192abaa84133" }
serde = { version = "^1.0", features = ["derive"] }
serde_json = { version = "^1.0" }
rand = "^0.7"
# Optional dependencies
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"] }
futures = { version = "0.3", 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 }
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
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "0.2", features = ["rt-core"] }

View File

@ -46,7 +46,7 @@ fn main() {
let policy = extended_desc.extract_policy(signers).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);
let addr = derived_desc.address(Network::Testnet).unwrap();

View File

@ -31,6 +31,7 @@ pub enum Error {
InvalidPrefix(Vec<u8>),
HardenedDerivationOnXpub,
MalformedInput,
InvalidHDKeyPath,
KeyParsingError(String),
Key(crate::keys::KeyError),

View File

@ -31,7 +31,6 @@ use std::collections::{BTreeMap, HashMap};
use std::fmt;
use std::sync::Arc;
use bitcoin::hashes::hash160;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
use bitcoin::util::psbt;
@ -122,27 +121,26 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap) {
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
use crate::keys::DescriptorKey;
// check the network for the keys
let translated = self.0.translate_pk(
|pk| {
let (pk, _, networks) = if self.0.is_witness() {
let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
} else {
let desciptor_key: DescriptorKey<miniscript::Legacy> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
};
let check_key = |pk: &DescriptorPublicKey| {
let (pk, _, networks) = if self.0.is_witness() {
let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
} else {
let desciptor_key: DescriptorKey<miniscript::Legacy> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
};
if networks.contains(&network) {
Ok(pk)
} else {
Err(KeyError::InvalidNetwork)
}
},
|pkh| Ok::<_, KeyError>(*pkh),
)?;
if networks.contains(&network) {
Ok(pk)
} else {
Err(KeyError::InvalidNetwork)
}
};
// check the network for the keys
let translated = self.0.translate_pk(check_key, check_key)?;
Ok((translated, self.1))
}
@ -155,32 +153,31 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap, ValidNetworks) {
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
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
let translated = self.0.translate_pk(
|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),
)?;
let translated = self.0.translate_pk(fix_key, fix_key)?;
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`]
pub trait ExtractPolicy {
fn extract_policy(
&self,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Result<Option<Policy>, Error>;
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error>;
}
pub(crate) trait XKeyUtils {
@ -201,7 +195,7 @@ pub(crate) trait XKeyUtils {
impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
let full_path = match self.source {
let full_path = match self.origin {
Some((_, ref path)) => 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 {
match self.source {
match self.origin {
Some((fingerprint, _)) => 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> {
let mut answer = BTreeMap::new();
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
fn translate_key(
key: &DescriptorPublicKey,
index: u32,
paths: &mut HDKeyPaths,
) -> Result<DummyKey, Error> {
match key {
DescriptorPublicKey::PubKey(_) => {}
DescriptorPublicKey::SinglePub(_) => {}
DescriptorPublicKey::XPub(xpub) => {
let derive_path = if xpub.is_wildcard {
xpub.derivation_path
@ -299,7 +295,7 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
.xkey
.derive_pub(&Secp256k1::verification_only(), &derive_path)?;
answer.insert(
paths.insert(
derived_pubkey.public_key,
(
xpub.root_fingerprint(),
@ -310,42 +306,54 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
}
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 {
let mut found_wildcard = false;
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
fn check_key(key: &DescriptorPublicKey, flag: &mut bool) -> Result<DummyKey, Error> {
match key {
DescriptorPublicKey::PubKey(_) => {}
DescriptorPublicKey::SinglePub(_) => {}
DescriptorPublicKey::XPub(xpub) => {
if xpub.is_wildcard {
found_wildcard = true;
*flag = true;
}
}
}
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> {
let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
let mut derive_path = None::<DerivationPath>;
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
if derive_path.is_some() {
fn try_key(
key: &DescriptorPublicKey,
index: &HashMap<Fingerprint, DerivationPath>,
found_path: &mut Option<ChildNumber>,
) -> Result<DummyKey, Error> {
if found_path.is_some() {
// already found a matching path, we are done
return Ok(DummyKey::default());
}
@ -353,9 +361,10 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
if let DescriptorPublicKey::XPub(xpub) = key {
// 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
// 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();
derive_path = index
let derivation_path: Option<Vec<ChildNumber>> = index
.get_key_value(&root_fingerprint)
.and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
.map(|prefix| {
@ -367,15 +376,46 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
.cloned()
.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())
};
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(

View File

@ -56,7 +56,7 @@ use bitcoin::util::bip32::Fingerprint;
use bitcoin::PublicKey;
use miniscript::descriptor::DescriptorPublicKey;
use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal, ToPublicKey};
#[allow(unused_imports)]
use log::{debug, error, info, trace};
@ -82,8 +82,8 @@ pub struct PKOrF {
impl PKOrF {
fn from_key(k: &DescriptorPublicKey) -> Self {
match k {
DescriptorPublicKey::PubKey(pubkey) => PKOrF {
pubkey: Some(*pubkey),
DescriptorPublicKey::SinglePub(pubkey) => PKOrF {
pubkey: Some(pubkey.key),
..Default::default()
},
DescriptorPublicKey::XPub(xpub) => PKOrF {
@ -524,7 +524,7 @@ impl Policy {
fn make_multisig(
keys: &[DescriptorPublicKey],
signers: Arc<SignersContainer<DescriptorPublicKey>>,
signers: Arc<SignersContainer>,
threshold: usize,
) -> Result<Option<Policy>, PolicyError> {
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 {
DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
}
}
fn signature(
key: &DescriptorPublicKey,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Policy {
fn signature(key: &DescriptorPublicKey, signers: Arc<SignersContainer>) -> Policy {
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
policy.contribution = if signers.find(signer_id(key)).is_some() {
@ -673,12 +670,13 @@ fn signature(
}
fn signature_key(
key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
key: &<DescriptorPublicKey as MiniscriptKey>::Hash,
signers: Arc<SignersContainer>,
) -> 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 {
condition: Default::default(),
}
@ -688,10 +686,7 @@ fn signature_key(
}
impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
fn extract_policy(
&self,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Result<Option<Policy>, Error> {
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error> {
Ok(match &self.node {
// Leaves
Terminal::True | Terminal::False => None,
@ -781,10 +776,7 @@ impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>
}
impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
fn extract_policy(
&self,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Result<Option<Policy>, Error> {
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error> {
match self {
Descriptor::Pk(pubkey)
| Descriptor::Pkh(pubkey)

View File

@ -32,7 +32,9 @@ use std::ops::Deref;
use bitcoin::util::bip32;
use bitcoin::{Network, PrivateKey, PublicKey};
pub use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey};
pub use miniscript::descriptor::{
DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub,
};
use miniscript::descriptor::{DescriptorXKey, KeyMap};
pub use miniscript::ScriptContext;
use miniscript::{Miniscript, Terminal};
@ -198,7 +200,7 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
/// ```
/// 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 {
/// pubkey: PublicKey,
@ -206,7 +208,10 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
///
/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
/// 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`]
fn add_metadata(
self,
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
derivation_path: bip32::DerivationPath,
) -> Result<DescriptorKey<Ctx>, KeyError>;
}
@ -294,11 +299,11 @@ pub trait DerivableKey<Ctx: ScriptContext> {
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
fn add_metadata(
self,
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
derivation_path: bip32::DerivationPath,
) -> Result<DescriptorKey<Ctx>, KeyError> {
DescriptorPublicKey::XPub(DescriptorXKey {
source,
origin,
xkey: self,
derivation_path,
is_wildcard: true,
@ -310,11 +315,11 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
fn add_metadata(
self,
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
derivation_path: bip32::DerivationPath,
) -> Result<DescriptorKey<Ctx>, KeyError> {
DescriptorSecretKey::XPrv(DescriptorXKey {
source,
origin,
xkey: self,
derivation_path,
is_wildcard: true,
@ -355,10 +360,10 @@ where
{
fn add_metadata(
self,
source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
derivation_path: bip32::DerivationPath,
) -> 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))
}
}
@ -483,7 +488,7 @@ impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx> {
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
let networks = match self {
DescriptorPublicKey::PubKey(_) => any_network(),
DescriptorPublicKey::SinglePub(_) => any_network(),
DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
if xkey.network == Network::Bitcoin =>
{
@ -498,14 +503,20 @@ impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey {
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 {
fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
let networks = match self {
DescriptorSecretKey::PrivKey(sk) if sk.network == Network::Bitcoin => mainnet_network(),
let networks = match &self {
DescriptorSecretKey::SinglePriv(sk) if sk.key.network == Network::Bitcoin => {
mainnet_network()
}
DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. })
if xkey.network == Network::Bitcoin =>
{
@ -520,7 +531,11 @@ impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PrivateKey {
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()
}
}

View File

@ -37,7 +37,7 @@ use bitcoin::util::bip32::ChildNumber;
use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
use miniscript::descriptor::DescriptorPublicKey;
use miniscript::psbt::PsbtInputSatisfier;
#[allow(unused_imports)]
use log::{debug, error, info, trace};
@ -87,8 +87,8 @@ pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> {
descriptor: ExtendedDescriptor,
change_descriptor: Option<ExtendedDescriptor>,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
signers: Arc<SignersContainer>,
change_signers: Arc<SignersContainer>,
address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
@ -158,7 +158,7 @@ where
let index = self.fetch_and_increment_index(ScriptType::External)?;
self.descriptor
.derive(&[ChildNumber::from_normal_idx(index).unwrap()])
.derive(ChildNumber::from_normal_idx(index)?)
.address(self.network)
.ok_or(Error::ScriptDoesntHaveAddressForm)
}
@ -204,7 +204,7 @@ where
pub fn add_signer(
&mut self,
script_type: ScriptType,
id: SignerId<DescriptorPublicKey>,
id: SignerId,
ordering: SignerOrdering,
signer: Arc<Box<dyn Signer>>,
) {
@ -803,7 +803,7 @@ where
match desc.satisfy(
input,
(
psbt_input.clone(),
PsbtInputSatisfier::new(&psbt, n),
After::new(current_height, false),
Older::new(current_height, create_height, false),
),
@ -846,7 +846,7 @@ where
.borrow()
.get_path_from_script_pubkey(&txout.script_pubkey)?
.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> {
@ -854,7 +854,7 @@ where
let index = self.fetch_and_increment_index(script_type)?;
Ok(desc
.derive(&[ChildNumber::from_normal_idx(index).unwrap()])
.derive(ChildNumber::from_normal_idx(index)?)
.script_pubkey())
}
@ -879,7 +879,7 @@ where
let hd_keypaths = descriptor.get_hd_keypaths(index)?;
let script = descriptor
.derive(&[ChildNumber::from_normal_idx(index).unwrap()])
.derive(ChildNumber::from_normal_idx(index)?)
.script_pubkey();
for validator in &self.address_validators {
validator.validate(script_type, &hd_keypaths, &script)?;
@ -909,7 +909,7 @@ where
for i in from..(from + count) {
address_batch.set_script_pubkey(
&descriptor
.derive(&[ChildNumber::from_normal_idx(i).unwrap()])
.derive(ChildNumber::from_normal_idx(i)?)
.script_pubkey(),
script_type,
i,
@ -1004,7 +1004,7 @@ where
let (desc, _) = self.get_descriptor_for_script_type(script_type);
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.witness_script = derived_descriptor.psbt_witness_script();

View File

@ -102,7 +102,7 @@ use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
use bitcoin::util::{bip143, psbt};
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 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
/// multiple of them
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SignerId<Pk: MiniscriptKey> {
PkHash(<Pk as MiniscriptKey>::Hash),
pub enum SignerId {
PkHash(hash160::Hash),
Fingerprint(Fingerprint),
}
impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
impl From<hash160::Hash> for SignerId {
fn from(hash: hash160::Hash) -> SignerId {
SignerId::PkHash(hash)
}
}
impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
impl From<Fingerprint> for SignerId {
fn from(fing: Fingerprint) -> SignerId {
SignerId::Fingerprint(fing)
}
}
@ -284,7 +284,10 @@ impl Signer for PrivateKey {
}
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)]
struct SignersContainerKey<Pk: MiniscriptKey> {
id: SignerId<Pk>,
struct SignersContainerKey {
id: SignerId,
ordering: SignerOrdering,
}
impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
fn from(tuple: (SignerId<Pk>, SignerOrdering)) -> Self {
impl From<(SignerId, SignerOrdering)> for SignersContainerKey {
fn from(tuple: (SignerId, SignerOrdering)) -> Self {
SignersContainerKey {
id: tuple.0,
ordering: tuple.1,
@ -319,11 +322,9 @@ impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContaine
/// Container for multiple signers
#[derive(Debug, Default, Clone)]
pub struct SignersContainer<Pk: MiniscriptKey>(
BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
);
pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<Box<dyn Signer>>>);
impl SignersContainer<DescriptorPublicKey> {
impl SignersContainer {
pub fn as_key_map(&self) -> KeyMap {
self.0
.values()
@ -333,20 +334,21 @@ impl SignersContainer<DescriptorPublicKey> {
}
}
impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
impl From<KeyMap> for SignersContainer {
fn from(keymap: KeyMap) -> SignersContainer {
let mut container = SignersContainer::new();
for (_, secret) in keymap {
match secret {
DescriptorSecretKey::PrivKey(private_key) => container.add_external(
DescriptorSecretKey::SinglePriv(private_key) => container.add_external(
SignerId::from(
private_key
.key
.public_key(&Secp256k1::signing_only())
.to_pubkeyhash(),
),
SignerOrdering::default(),
Arc::new(Box::new(private_key)),
Arc::new(Box::new(private_key.key)),
),
DescriptorSecretKey::XPrv(xprv) => container.add_external(
SignerId::from(xprv.root_fingerprint()),
@ -360,7 +362,7 @@ impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
}
}
impl<Pk: MiniscriptKey> SignersContainer<Pk> {
impl SignersContainer {
/// Default constructor
pub fn new() -> Self {
SignersContainer(Default::default())
@ -370,7 +372,7 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
/// signer that was previosuly in the container, if any
pub fn add_external(
&mut self,
id: SignerId<Pk>,
id: SignerId,
ordering: SignerOrdering,
signer: 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
pub fn remove(
&mut self,
id: SignerId<Pk>,
id: SignerId,
ordering: SignerOrdering,
) -> Option<Arc<Box<dyn Signer>>> {
self.0.remove(&(id, ordering).into())
}
/// 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
.keys()
.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.
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
.range((
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> {
Some(self.cmp(other))
}
}
impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
impl Ord for SignersContainerKey {
fn cmp(&self, other: &Self) -> Ordering {
self.ordering.cmp(&other.ordering)
}
}
impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
impl PartialEq for SignersContainerKey {
fn eq(&self, other: &Self) -> bool {
self.ordering == other.ordering
}
}
impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
impl Eq for SignersContainerKey {}

View File

@ -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
/// 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
}
@ -316,7 +316,7 @@ impl TxOrdering {
///
/// Has a default value of `1`
#[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 {
fn default() -> Self {

View File

@ -9,17 +9,11 @@ name = "testutils"
# 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]
log = "0.4.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serial_test = "0.4"
bitcoin = "0.23"
bitcoincore-rpc = "0.11"
electrum-client = "0.2.0-beta.1"
bitcoin = "0.25"
bitcoincore-rpc = "0.12"
electrum-client = "0.3.0-beta.1"

View File

@ -119,13 +119,13 @@ macro_rules! testutils {
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
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 ) => ({
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;
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) });
( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
@ -386,7 +386,7 @@ impl TestClient {
trace!("getblocktemplate: {:#?}", block_template);
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(
block_template["previousblockhash"].as_str().unwrap(),
)