Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up the MiniscriptKey and ToPublicKey traits #620

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ impl MiniscriptKey for BitcoinKey {
type Hash256 = hash256::Hash;
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;

fn is_uncompressed(&self) -> bool {
match *self {
BitcoinKey::Fullkey(pk) => !pk.compressed,
BitcoinKey::XOnlyPublicKey(_) => false,
}
}
fn is_x_only_key(&self) -> bool { false }
fn num_der_paths(&self) -> usize { 0 }
}

impl<'txin> Interpreter<'txin> {
Expand Down
86 changes: 50 additions & 36 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,52 +153,52 @@ use crate::prelude::*;
pub use crate::primitives::absolute_locktime::{AbsLockTime, AbsLockTimeError};
pub use crate::primitives::relative_locktime::{RelLockTime, RelLockTimeError};

/// Public key trait which can be converted to Hash type
/// Trait representing a key which can be converted to a hash type.
pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
/// Returns true if the pubkey is uncompressed. Defaults to `false`.
fn is_uncompressed(&self) -> bool { false }

/// Returns true if the pubkey is an x-only pubkey. Defaults to `false`.
// This is required to know what in DescriptorPublicKey to know whether the inner
// key in allowed in descriptor context
fn is_x_only_key(&self) -> bool { false }

/// Returns the number of different derivation paths in this key. Only >1 for keys
/// in BIP389 multipath descriptors.
fn num_der_paths(&self) -> usize { 0 }

/// The associated [`bitcoin::hashes::sha256::Hash`] for this [`MiniscriptKey`], used in the
/// sha256 fragment.
/// The type used in the sha256 fragment.
type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

/// The associated [`miniscript::hash256::Hash`] for this [`MiniscriptKey`], used in the
/// hash256 fragment.
/// The type used in the hash256 fragment.
type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

/// The associated [`bitcoin::hashes::ripemd160::Hash`] for this [`MiniscriptKey`] type, used
/// in the ripemd160 fragment.
/// The type used in the ripemd160 fragment.
type Ripemd160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

/// The associated [`bitcoin::hashes::hash160::Hash`] for this [`MiniscriptKey`] type, used in
/// the hash160 fragment.
/// The type used in the hash160 fragment.
type Hash160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

/// Returns true if the key is serialized uncompressed.
fn is_uncompressed(&self) -> bool;

/// Returns true if the key is an x-only pubkey.
fn is_x_only_key(&self) -> bool;

/// Returns the number of different derivation paths in this key.
///
/// Only >1 for keys in BIP389 multipath descriptors.
fn num_der_paths(&self) -> usize;
}

impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
type Sha256 = sha256::Hash;
type Hash256 = hash256::Hash;
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;

fn is_uncompressed(&self) -> bool { false }
fn is_x_only_key(&self) -> bool { false }
fn num_der_paths(&self) -> usize { 0 }
}

impl MiniscriptKey for bitcoin::PublicKey {
/// Returns the compressed-ness of the underlying secp256k1 key.
fn is_uncompressed(&self) -> bool { !self.compressed }

type Sha256 = sha256::Hash;
type Hash256 = hash256::Hash;
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;

fn is_uncompressed(&self) -> bool { !self.compressed }
fn is_x_only_key(&self) -> bool { false }
fn num_der_paths(&self) -> usize { 0 }
}

impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
Expand All @@ -207,48 +207,62 @@ impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;

fn is_uncompressed(&self) -> bool { false }
fn is_x_only_key(&self) -> bool { true }
fn num_der_paths(&self) -> usize { 0 }
}

impl MiniscriptKey for String {
type Sha256 = String; // specify hashes as string
type Sha256 = String;
type Hash256 = String;
type Ripemd160 = String;
type Hash160 = String;

fn is_uncompressed(&self) -> bool { false }
fn is_x_only_key(&self) -> bool { false }
fn num_der_paths(&self) -> usize { 0 }
}

/// Trait describing public key types which can be converted to bitcoin pubkeys
/// Trait describing key types that can be converted to bitcoin public keys.
pub trait ToPublicKey: MiniscriptKey {
/// Converts an object to a public key
/// Converts key to a public key.
fn to_public_key(&self) -> bitcoin::PublicKey;

/// Convert an object to x-only pubkey
/// Converts key to an x-only public key.
fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
let pk = self.to_public_key();
bitcoin::secp256k1::XOnlyPublicKey::from(pk.inner)
}

/// Obtain the public key hash for this MiniscriptKey
/// Expects an argument to specify the signature type.
/// This would determine whether to serialize the key as 32 byte x-only pubkey
/// or regular public key when computing the hash160
/// Obtains the pubkey hash for this key (as a `MiniscriptKey`).
///
/// Expects an argument to specify the signature type. This determines whether to serialize
/// the key as 32 byte x-only pubkey or regular public key when computing the hash160.
fn to_pubkeyhash(&self, sig_type: SigType) -> hash160::Hash {
match sig_type {
SigType::Ecdsa => hash160::Hash::hash(&self.to_public_key().to_bytes()),
SigType::Schnorr => hash160::Hash::hash(&self.to_x_only_pubkey().serialize()),
}
}

/// Converts the generic associated [`MiniscriptKey::Sha256`] to [`sha256::Hash`]
/// Converts the associated [`MiniscriptKey::Sha256`] type to a [`sha256::Hash`].
///
/// [`sha256::Hash`]: bitcoin::hashes::sha256::Hash
fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;

/// Converts the generic associated [`MiniscriptKey::Hash256`] to [`hash256::Hash`]
/// Converts the associated [`MiniscriptKey::Hash256`] type to a [`hash256::Hash`].
///
/// [`hash256::Hash`]: crate::hash256::Hash
fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;

/// Converts the generic associated [`MiniscriptKey::Ripemd160`] to [`ripemd160::Hash`]
/// Converts the associated [`MiniscriptKey::Ripemd160`] type to a [`ripemd160::Hash`].
///
/// [`ripemd160::Hash`]: bitcoin::hashes::ripemd160::Hash
fn to_ripemd160(hash: &<Self as MiniscriptKey>::Ripemd160) -> ripemd160::Hash;

/// Converts the generic associated [`MiniscriptKey::Hash160`] to [`hash160::Hash`]
/// Converts the associated [`MiniscriptKey::Hash160`] type to a [`hash160::Hash`].
///
/// [`hash160::Hash`]: bitcoin::hashes::hash160::Hash
fn to_hash160(hash: &<Self as MiniscriptKey>::Hash160) -> hash160::Hash;
}

Expand Down
Loading