[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 }
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"] }
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();
InvalidPrefix(Vec<u8>),
HardenedDerivationOnXpub,
MalformedInput,
+ InvalidHDKeyPath,
KeyParsingError(String),
Key(crate::keys::KeyError),
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;
) -> 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)
+ }
+ };
- if networks.contains(&network) {
- Ok(pk)
- } else {
- 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))
}
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
let valid_networks = &self.2;
- // 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(),
- };
+ 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)
- }
- },
- |pkh| Ok::<_, KeyError>(*pkh),
- )?;
+ Ok(pk)
+ } else {
+ Err(KeyError::InvalidNetwork)
+ }
+ };
+
+ // fixup the network for keys that need it
+ let translated = self.0.translate_pk(fix_key, fix_key)?;
Ok((translated, self.1))
}
/// 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 {
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())
}
fn root_fingerprint(&self) -> Fingerprint {
- match self.source {
+ match self.origin {
Some((fingerprint, _)) => fingerprint,
None => self.xkey.xkey_fingerprint(),
}
}
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
.xkey
.derive_pub(&Secp256k1::verification_only(), &derive_path)?;
- answer.insert(
+ paths.insert(
derived_pubkey.public_key,
(
xpub.root_fingerprint(),
}
Ok(DummyKey::default())
- };
- let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+ }
+
+ let mut answer_pk = BTreeMap::new();
+ let mut answer_pkh = BTreeMap::new();
- self.translate_pk(translatefpk, translatefpkh)?;
+ 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)
+ 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());
}
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| {
.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();
+
+ 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),
+ };
- derive_path.map(|path| self.derive(path.as_ref()))
+ merged_path.map(|path| self.derive(path))
}
fn derive_from_psbt_input(
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};
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 {
fn make_multisig(
keys: &[DescriptorPublicKey],
- signers: Arc<SignersContainer<DescriptorPublicKey>>,
+ signers: Arc<SignersContainer>,
threshold: usize,
) -> Result<Option<Policy>, PolicyError> {
if threshold == 0 {
}
}
-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() {
}
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(),
}
}
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,
}
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)
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};
/// ```
/// 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,
///
/// 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()))
/// }
/// }
/// ```
/// 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>;
}
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,
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,
{
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))
}
}
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 =>
{
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 =>
{
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()
}
}
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};
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>>>,
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)
}
pub fn add_signer(
&mut self,
script_type: ScriptType,
- id: SignerId<DescriptorPublicKey>,
+ id: SignerId,
ordering: SignerOrdering,
signer: Arc<Box<dyn Signer>>,
) {
match desc.satisfy(
input,
(
- psbt_input.clone(),
+ PsbtInputSatisfier::new(&psbt, n),
After::new(current_height, false),
Older::new(current_height, create_height, false),
),
.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> {
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())
}
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)?;
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,
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();
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;
/// 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)
}
}
}
fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
- Some(DescriptorSecretKey::PrivKey(*self))
+ Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
+ key: *self,
+ origin: None,
+ }))
}
}
}
#[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,
/// 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()
}
}
-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()),
}
}
-impl<Pk: MiniscriptKey> SignersContainer<Pk> {
+impl SignersContainer {
/// Default constructor
pub fn new() -> Self {
SignersContainer(Default::default())
/// 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>>> {
/// 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)
}
/// 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()),
}
}
-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 {}
///
/// 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
}
///
/// 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 {
# 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"
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) });
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(),
)