Skip to content

Commit 2ad6555

Browse files
committed
Rename "derive" things that are not doing derivation
The words "derive", "derived" and "derivable" were being used to describe things that aren't stricly derivation. Derivation is the process of taking cryptographic data and deterministically producing something else given some inputs. This is how the term is used in bip32, rust-bitcoin and more generally. In rust-miniscript the term is also used to mean "replacing a wildcard in a derivation path with a particular index". This can be quite confusing. For example, `is_derivable` returns true when there is a wildcard in the descriptor -- but it should return the opposite (given the usual meaning)! You can't do a derivation because you don't know the full derivation path yet (it's s got a wildcard in it). This commit replaces all instances where "derive" is used in this way.
1 parent 6dc6aca commit 2ad6555

File tree

6 files changed

+96
-70
lines changed

6 files changed

+96
-70
lines changed

examples/xpub_descriptors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::str::FromStr;
1818

1919
use miniscript::bitcoin::secp256k1::{Secp256k1, Verification};
2020
use miniscript::bitcoin::{Address, Network};
21-
use miniscript::{DerivedDescriptorKey, Descriptor, DescriptorPublicKey};
21+
use miniscript::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
2222

2323
const XPUB_1: &str = "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB";
2424
const XPUB_2: &str = "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH";
@@ -40,7 +40,7 @@ fn p2wsh<C: Verification>(secp: &Secp256k1<C>) -> Address {
4040
let s = format!("wsh(sortedmulti(1,{},{}))", XPUB_1, XPUB_2);
4141
// let s = format!("wsh(sortedmulti(1,{},{}))", XPUB_2, XPUB_1);
4242

43-
let address = Descriptor::<DerivedDescriptorKey>::from_str(&s)
43+
let address = Descriptor::<DefiniteDescriptorKey>::from_str(&s)
4444
.unwrap()
4545
.derived_descriptor(&secp)
4646
.unwrap()

src/descriptor/key.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub enum SinglePubKey {
7272

7373
/// A [`DescriptorPublicKey`] without any wildcards.
7474
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
75-
pub struct DerivedDescriptorKey(DescriptorPublicKey);
75+
pub struct DefiniteDescriptorKey(DescriptorPublicKey);
7676

7777
impl fmt::Display for DescriptorSecretKey {
7878
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -428,15 +428,28 @@ impl DescriptorPublicKey {
428428
}
429429
}
430430

431-
/// Whether or not the key has a wildcards
431+
/// Whether or not the key has a wildcard
432+
#[deprecated(note = "use has_wildcard instead")]
432433
pub fn is_deriveable(&self) -> bool {
434+
self.has_wildcard()
435+
}
436+
437+
/// Whether or not the key has a wildcard
438+
pub fn has_wildcard(&self) -> bool {
433439
match *self {
434440
DescriptorPublicKey::Single(..) => false,
435441
DescriptorPublicKey::XPub(ref xpub) => xpub.wildcard != Wildcard::None,
436442
}
437443
}
438444

439-
/// Derives the [`DescriptorPublicKey`] at `index` if this key is an xpub and has a wildcard.
445+
#[deprecated(note = "use at_derivation_index instead")]
446+
/// Deprecated name of [`at_derivation_index`].
447+
pub fn derive(self, index: u32) -> DefiniteDescriptorKey {
448+
self.at_derivation_index(index)
449+
}
450+
451+
/// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
452+
/// *definite* key (i.e. one where all the derivation paths are set).
440453
///
441454
/// # Returns
442455
///
@@ -447,8 +460,8 @@ impl DescriptorPublicKey {
447460
/// # Panics
448461
///
449462
/// If `index` ≥ 2^31
450-
pub fn derive(self, index: u32) -> DerivedDescriptorKey {
451-
let derived = match self {
463+
pub fn at_derivation_index(self, index: u32) -> DefiniteDescriptorKey {
464+
let definite = match self {
452465
DescriptorPublicKey::Single(_) => self,
453466
DescriptorPublicKey::XPub(xpub) => {
454467
let derivation_path = match xpub.wildcard {
@@ -469,7 +482,7 @@ impl DescriptorPublicKey {
469482
}
470483
};
471484

472-
DerivedDescriptorKey::new(derived)
485+
DefiniteDescriptorKey::new(definite)
473486
.expect("The key should not contain any wildcards at this point")
474487
}
475488

@@ -749,7 +762,7 @@ impl MiniscriptKey for DescriptorPublicKey {
749762
}
750763
}
751764

752-
impl DerivedDescriptorKey {
765+
impl DefiniteDescriptorKey {
753766
/// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
754767
///
755768
/// Will return an error if the key has any hardened derivation steps
@@ -767,7 +780,7 @@ impl DerivedDescriptorKey {
767780
///
768781
/// Returns `None` if the key contains a wildcard
769782
fn new(key: DescriptorPublicKey) -> Option<Self> {
770-
if key.is_deriveable() {
783+
if key.has_wildcard() {
771784
None
772785
} else {
773786
Some(Self(key))
@@ -785,26 +798,26 @@ impl DerivedDescriptorKey {
785798
}
786799
}
787800

788-
impl FromStr for DerivedDescriptorKey {
801+
impl FromStr for DefiniteDescriptorKey {
789802
type Err = DescriptorKeyParseError;
790803

791804
fn from_str(s: &str) -> Result<Self, Self::Err> {
792805
let inner = DescriptorPublicKey::from_str(s)?;
793806
Ok(
794-
DerivedDescriptorKey::new(inner).ok_or(DescriptorKeyParseError(
807+
DefiniteDescriptorKey::new(inner).ok_or(DescriptorKeyParseError(
795808
"cannot parse key with a wilcard as a DerivedDescriptorKey",
796809
))?,
797810
)
798811
}
799812
}
800813

801-
impl fmt::Display for DerivedDescriptorKey {
814+
impl fmt::Display for DefiniteDescriptorKey {
802815
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
803816
self.0.fmt(f)
804817
}
805818
}
806819

807-
impl MiniscriptKey for DerivedDescriptorKey {
820+
impl MiniscriptKey for DefiniteDescriptorKey {
808821
// This allows us to be able to derive public keys even for PkH s
809822
type RawPkHash = Self;
810823
type Sha256 = sha256::Hash;
@@ -825,7 +838,7 @@ impl MiniscriptKey for DerivedDescriptorKey {
825838
}
826839
}
827840

828-
impl ToPublicKey for DerivedDescriptorKey {
841+
impl ToPublicKey for DefiniteDescriptorKey {
829842
fn to_public_key(&self) -> bitcoin::PublicKey {
830843
let secp = Secp256k1::verification_only();
831844
self.0.derive_public_key(&secp).unwrap()
@@ -852,8 +865,8 @@ impl ToPublicKey for DerivedDescriptorKey {
852865
}
853866
}
854867

855-
impl From<DerivedDescriptorKey> for DescriptorPublicKey {
856-
fn from(d: DerivedDescriptorKey) -> Self {
868+
impl From<DefiniteDescriptorKey> for DescriptorPublicKey {
869+
fn from(d: DefiniteDescriptorKey) -> Self {
857870
d.0
858871
}
859872
}
@@ -964,17 +977,17 @@ mod test {
964977
let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2").unwrap();
965978
assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
966979
assert_eq!(public_key.full_derivation_path().to_string(), "m/0'/1'/2");
967-
assert_eq!(public_key.is_deriveable(), false);
980+
assert_eq!(public_key.has_wildcard(), false);
968981

969982
let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*").unwrap();
970983
assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
971984
assert_eq!(public_key.full_derivation_path().to_string(), "m/0'/1'");
972-
assert_eq!(public_key.is_deriveable(), true);
985+
assert_eq!(public_key.has_wildcard(), true);
973986

974987
let public_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h").unwrap();
975988
assert_eq!(public_key.master_fingerprint().to_string(), "abcdef00");
976989
assert_eq!(public_key.full_derivation_path().to_string(), "m/0'/1'");
977-
assert_eq!(public_key.is_deriveable(), true);
990+
assert_eq!(public_key.has_wildcard(), true);
978991
}
979992

980993
#[test]
@@ -986,7 +999,7 @@ mod test {
986999
assert_eq!(public_key.to_string(), "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2");
9871000
assert_eq!(public_key.master_fingerprint().to_string(), "2cbe2a6d");
9881001
assert_eq!(public_key.full_derivation_path().to_string(), "m/0'/1'/2");
989-
assert_eq!(public_key.is_deriveable(), false);
1002+
assert_eq!(public_key.has_wildcard(), false);
9901003

9911004
let secret_key = DescriptorSecretKey::from_str("tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'").unwrap();
9921005
let public_key = secret_key.to_public(&secp).unwrap();

src/descriptor/mod.rs

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ mod checksum;
5858
mod key;
5959

6060
pub use self::key::{
61-
ConversionError, DerivedDescriptorKey, DescriptorKeyParseError, DescriptorPublicKey,
61+
ConversionError, DefiniteDescriptorKey, DescriptorKeyParseError, DescriptorPublicKey,
6262
DescriptorSecretKey, DescriptorXKey, InnerXKey, SinglePriv, SinglePub, SinglePubKey, Wildcard,
6363
};
6464

@@ -513,32 +513,44 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Descriptor<Pk> {
513513

514514
impl Descriptor<DescriptorPublicKey> {
515515
/// Whether or not the descriptor has any wildcards
516+
#[deprecated(note = "use has_wildcards instead")]
516517
pub fn is_deriveable(&self) -> bool {
517-
self.for_any_key(|key| key.is_deriveable())
518+
self.has_wildcard()
518519
}
519520

520-
/// Derives all wildcard keys in the descriptor using the supplied index
521+
/// Whether or not the descriptor has any wildcards i.e. `/*`.
522+
pub fn has_wildcard(&self) -> bool {
523+
self.for_any_key(|key| key.has_wildcard())
524+
}
525+
526+
/// Replaces all wildcards (i.e. `/*`) in the descriptor with a particular derivation index,
527+
/// turning it into a *definite* descriptor.
521528
///
522-
/// Panics if given an index ≥ 2^31
529+
/// # Panics
523530
///
524-
/// In most cases, you would want to use [`Self::derived_descriptor`] directly to obtain
525-
/// a [`Descriptor<bitcoin::PublicKey>`]
526-
pub fn derive(&self, index: u32) -> Descriptor<DerivedDescriptorKey> {
531+
/// If index ≥ 2^31
532+
pub fn at_derivation_index(&self, index: u32) -> Descriptor<DefiniteDescriptorKey> {
527533
struct Derivator(u32);
528534

529-
impl PkTranslator<DescriptorPublicKey, DerivedDescriptorKey, ()> for Derivator {
530-
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DerivedDescriptorKey, ()> {
531-
Ok(pk.clone().derive(self.0))
535+
impl PkTranslator<DescriptorPublicKey, DefiniteDescriptorKey, ()> for Derivator {
536+
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DefiniteDescriptorKey, ()> {
537+
Ok(pk.clone().at_derivation_index(self.0))
532538
}
533539

534-
fn pkh(&mut self, pkh: &DescriptorPublicKey) -> Result<DerivedDescriptorKey, ()> {
535-
Ok(pkh.clone().derive(self.0))
540+
fn pkh(&mut self, pkh: &DescriptorPublicKey) -> Result<DefiniteDescriptorKey, ()> {
541+
Ok(pkh.clone().at_derivation_index(self.0))
536542
}
537543
}
538544
self.translate_pk(&mut Derivator(index))
539545
.expect("BIP 32 key index substitution cannot fail")
540546
}
541547

548+
#[deprecated(note = "use at_derivation_index instead")]
549+
/// Deprecated name for [`at_derivation_index`].
550+
pub fn derive(&self, index: u32) -> Descriptor<DefiniteDescriptorKey> {
551+
self.at_derivation_index(index)
552+
}
553+
542554
/// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or
543555
/// otherwise converting them. All [`bitcoin::XOnlyPublicKey`]s are converted to by adding a
544556
/// default(0x02) y-coordinate.
@@ -552,14 +564,14 @@ impl Descriptor<DescriptorPublicKey> {
552564
/// .expect("Valid ranged descriptor");
553565
/// # let index = 42;
554566
/// # let secp = Secp256k1::verification_only();
555-
/// let derived_descriptor = descriptor.derive(index).derived_descriptor(&secp);
567+
/// let derived_descriptor = descriptor.at_derivation_index(index).derived_descriptor(&secp);
556568
/// # assert_eq!(descriptor.derived_descriptor(&secp, index), derived_descriptor);
557569
/// ```
558570
///
559571
/// and is only here really here for backwards compatbility.
560-
/// See [`derive`] and `[derived_descriptor`] for more documentation.
572+
/// See [`at_derivation_index`] and `[derived_descriptor`] for more documentation.
561573
///
562-
/// [`derive`]: Self::derive
574+
/// [`at_derivation_index`]: Self::at_derivation_index
563575
/// [`derived_descriptor`]: crate::DerivedDescriptor::derived_descriptor
564576
///
565577
/// # Errors
@@ -570,7 +582,7 @@ impl Descriptor<DescriptorPublicKey> {
570582
secp: &secp256k1::Secp256k1<C>,
571583
index: u32,
572584
) -> Result<Descriptor<bitcoin::PublicKey>, ConversionError> {
573-
self.derive(index).derived_descriptor(&secp)
585+
self.at_derivation_index(index).derived_descriptor(&secp)
574586
}
575587

576588
/// Parse a descriptor that may contain secret keys
@@ -711,7 +723,7 @@ impl Descriptor<DescriptorPublicKey> {
711723
script_pubkey: &Script,
712724
range: Range<u32>,
713725
) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey>)>, ConversionError> {
714-
let range = if self.is_deriveable() { range } else { 0..1 };
726+
let range = if self.has_wildcard() { range } else { 0..1 };
715727

716728
for i in range {
717729
let concrete = self.derived_descriptor(secp, i)?;
@@ -724,7 +736,7 @@ impl Descriptor<DescriptorPublicKey> {
724736
}
725737
}
726738

727-
impl Descriptor<DerivedDescriptorKey> {
739+
impl Descriptor<DefiniteDescriptorKey> {
728740
/// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or
729741
/// otherwise converting them. All [`bitcoin::XOnlyPublicKey`]s are converted to by adding a
730742
/// default(0x02) y-coordinate.
@@ -740,7 +752,7 @@ impl Descriptor<DerivedDescriptorKey> {
740752
/// let secp = secp256k1::Secp256k1::verification_only();
741753
/// let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
742754
/// .expect("Valid ranged descriptor");
743-
/// let result = descriptor.derive(0).derived_descriptor(&secp).expect("Non-hardened derivation");
755+
/// let result = descriptor.at_derivation_index(0).derived_descriptor(&secp).expect("Non-hardened derivation");
744756
/// assert_eq!(result.to_string(), "tr(03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115)#6qm9h8ym");
745757
/// ```
746758
///
@@ -754,19 +766,19 @@ impl Descriptor<DerivedDescriptorKey> {
754766
struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
755767

756768
impl<'a, C: secp256k1::Verification>
757-
PkTranslator<DerivedDescriptorKey, bitcoin::PublicKey, ConversionError>
769+
PkTranslator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
758770
for Derivator<'a, C>
759771
{
760772
fn pk(
761773
&mut self,
762-
pk: &DerivedDescriptorKey,
774+
pk: &DefiniteDescriptorKey,
763775
) -> Result<bitcoin::PublicKey, ConversionError> {
764776
pk.derive_public_key(&self.0)
765777
}
766778

767779
fn pkh(
768780
&mut self,
769-
pkh: &DerivedDescriptorKey,
781+
pkh: &DefiniteDescriptorKey,
770782
) -> Result<bitcoin::hashes::hash160::Hash, ConversionError> {
771783
Ok(pkh.derive_public_key(&self.0)?.to_pubkeyhash())
772784
}
@@ -1597,13 +1609,13 @@ mod tests {
15971609

15981610
// Same address
15991611
let addr_one = desc_one
1600-
.derive(index)
1612+
.at_derivation_index(index)
16011613
.derived_descriptor(&secp_ctx)
16021614
.unwrap()
16031615
.address(bitcoin::Network::Bitcoin)
16041616
.unwrap();
16051617
let addr_two = desc_two
1606-
.derive(index)
1618+
.at_derivation_index(index)
16071619
.derived_descriptor(&secp_ctx)
16081620
.unwrap()
16091621
.address(bitcoin::Network::Bitcoin)
@@ -1681,7 +1693,7 @@ pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHW
16811693
pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
16821694
let policy: policy::concrete::Policy<DescriptorPublicKey> = descriptor_str.parse().unwrap();
16831695
let descriptor = Descriptor::new_sh(policy.compile().unwrap()).unwrap();
1684-
let derived_descriptor = descriptor.derive(42);
1696+
let definite_descriptor = descriptor.at_derivation_index(42);
16851697

16861698
let res_descriptor_str = "thresh(2,\
16871699
pk([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/42),\
@@ -1691,7 +1703,7 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
16911703
res_descriptor_str.parse().unwrap();
16921704
let res_descriptor = Descriptor::new_sh(res_policy.compile().unwrap()).unwrap();
16931705

1694-
assert_eq!(res_descriptor.to_string(), derived_descriptor.to_string());
1706+
assert_eq!(res_descriptor.to_string(), definite_descriptor.to_string());
16951707
}
16961708

16971709
#[test]

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ use std::error;
135135
use bitcoin::blockdata::{opcodes, script};
136136
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
137137

138-
pub use crate::descriptor::{DerivedDescriptorKey, Descriptor, DescriptorPublicKey};
138+
pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
139139
pub use crate::interpreter::Interpreter;
140140
pub use crate::miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, Tap};
141141
pub use crate::miniscript::decode::Terminal;

0 commit comments

Comments
 (0)