[descriptors] Transform a descriptor into its "public" version

This commit is contained in:
Alekos Filini
2020-05-10 17:42:02 +02:00
parent 0e432f3b26
commit c1b01e4d8c
6 changed files with 267 additions and 106 deletions

View File

@@ -19,13 +19,16 @@ use crate::psbt::utils::PSBTUtils;
pub mod checksum;
pub mod error;
pub mod extended_key;
mod keys;
pub mod policy;
pub use self::checksum::get_checksum;
pub use self::error::Error;
use self::error::Error;
pub use self::extended_key::{DerivationIndex, DescriptorExtendedKey};
pub use self::policy::Policy;
use self::keys::Key;
trait MiniscriptExtractPolicy {
fn extract_policy(
&self,
@@ -105,109 +108,6 @@ where
}
}
trait Key: std::fmt::Debug {
fn fingerprint(&self, secp: &Secp256k1<All>) -> Option<Fingerprint>;
fn as_public_key(&self, secp: &Secp256k1<All>, index: Option<u32>) -> Result<PublicKey, Error>;
fn as_secret_key(&self) -> Option<PrivateKey>;
fn xprv(&self) -> Option<ExtendedPrivKey>;
fn full_path(&self, index: u32) -> Option<DerivationPath>;
fn is_fixed(&self) -> bool;
fn has_secret(&self) -> bool {
self.xprv().is_some() || self.as_secret_key().is_some()
}
}
impl Key for PublicKey {
fn fingerprint(&self, _secp: &Secp256k1<All>) -> Option<Fingerprint> {
None
}
fn as_public_key(
&self,
_secp: &Secp256k1<All>,
_index: Option<u32>,
) -> Result<PublicKey, Error> {
Ok(PublicKey::clone(self))
}
fn as_secret_key(&self) -> Option<PrivateKey> {
None
}
fn xprv(&self) -> Option<ExtendedPrivKey> {
None
}
fn full_path(&self, _index: u32) -> Option<DerivationPath> {
None
}
fn is_fixed(&self) -> bool {
true
}
}
impl Key for PrivateKey {
fn fingerprint(&self, _secp: &Secp256k1<All>) -> Option<Fingerprint> {
None
}
fn as_public_key(
&self,
secp: &Secp256k1<All>,
_index: Option<u32>,
) -> Result<PublicKey, Error> {
Ok(self.public_key(secp))
}
fn as_secret_key(&self) -> Option<PrivateKey> {
Some(PrivateKey::clone(self))
}
fn xprv(&self) -> Option<ExtendedPrivKey> {
None
}
fn full_path(&self, _index: u32) -> Option<DerivationPath> {
None
}
fn is_fixed(&self) -> bool {
true
}
}
impl Key for DescriptorExtendedKey {
fn fingerprint(&self, secp: &Secp256k1<All>) -> Option<Fingerprint> {
if let Some(fing) = self.master_fingerprint {
Some(fing.clone())
} else {
Some(self.root_xpub(secp).fingerprint())
}
}
fn as_public_key(&self, secp: &Secp256k1<All>, index: Option<u32>) -> Result<PublicKey, Error> {
Ok(self.derive_xpub(secp, index.unwrap_or(0))?.public_key)
}
fn as_secret_key(&self) -> Option<PrivateKey> {
None
}
fn xprv(&self) -> Option<ExtendedPrivKey> {
self.secret
}
fn full_path(&self, index: u32) -> Option<DerivationPath> {
Some(self.full_path(index))
}
fn is_fixed(&self) -> bool {
self.final_index == DerivationIndex::Fixed
}
}
#[serde(try_from = "&str", into = "String")]
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtendedDescriptor {
@@ -221,6 +121,12 @@ pub struct ExtendedDescriptor {
ctx: Secp256k1<All>,
}
impl fmt::Display for ExtendedDescriptor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.internal)
}
}
impl std::clone::Clone for ExtendedDescriptor {
fn clone(&self) -> Self {
Self {
@@ -421,6 +327,35 @@ impl ExtendedDescriptor {
_ => false,
}
}
pub fn as_public_version(&self) -> Result<ExtendedDescriptor, Error> {
let keys: RefCell<BTreeMap<String, Box<dyn Key>>> = RefCell::new(BTreeMap::new());
let translatefpk = |string: &String| -> Result<_, Error> {
let public = self.keys.get(string).unwrap().public(&self.ctx)?;
let result = format!("{}", public);
keys.borrow_mut().insert(string.clone(), public);
Ok(result)
};
let translatefpkh = |string: &String| -> Result<_, Error> {
let public = self.keys.get(string).unwrap().public(&self.ctx)?;
let result = format!("{}", public);
keys.borrow_mut().insert(string.clone(), public);
Ok(result)
};
let internal = self.internal.translate_pk(translatefpk, translatefpkh)?;
Ok(ExtendedDescriptor {
internal,
keys: keys.into_inner(),
ctx: self.ctx.clone(),
})
}
}
impl ExtractPolicy for ExtendedDescriptor {