Skip to content

Commit 8ffda8c

Browse files
committed
CT descriptor: implement at_derivation_index
1 parent da8d16c commit 8ffda8c

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

src/confidential/mod.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ pub mod slip77;
2222

2323
use std::fmt;
2424

25+
use bitcoin::bip32;
2526
use elements::secp256k1_zkp;
2627

2728
use crate::descriptor::checksum::{desc_checksum, verify_checksum};
28-
use crate::descriptor::{DescriptorSecretKey, DescriptorPublicKey};
29+
use crate::descriptor::{
30+
ConversionError, DefiniteDescriptorKey, DescriptorSecretKey, DescriptorPublicKey,
31+
DescriptorXKey, Wildcard
32+
};
2933
use crate::expression::FromTree;
3034
use crate::extensions::{CovExtArgs, CovenantExt, Extension, ParseableExt};
3135
use crate::{expression, Error, MiniscriptKey, ToPublicKey};
@@ -82,6 +86,51 @@ impl<Pk: MiniscriptKey, T: Extension> Descriptor<Pk, T> {
8286
}
8387
}
8488

89+
impl<T: Extension + ParseableExt> Descriptor<DescriptorPublicKey, T> {
90+
/// Replaces all wildcards (i.e. `/*`) in the descriptor and the descriptor blinding key
91+
/// with a particular derivation index, turning it into a *definite* descriptor.
92+
///
93+
/// # Errors
94+
/// - If index ≥ 2^31
95+
pub fn at_derivation_index(&self, index: u32) -> Result<Descriptor<DefiniteDescriptorKey, T>, ConversionError> {
96+
let definite_key = match self.key.clone() {
97+
Key::Slip77(k) => Key::Slip77(k),
98+
Key::Bare(k) => Key::Bare(k.at_derivation_index(index)?.into_descriptor_public_key()),
99+
Key::View(k) => Key::View(match k {
100+
// Consider implementing DescriptorSecretKey::at_derivation_index
101+
DescriptorSecretKey::Single(_) => k,
102+
DescriptorSecretKey::XPrv(xprv) => {
103+
let derivation_path = match xprv.wildcard {
104+
Wildcard::None => xprv.derivation_path,
105+
Wildcard::Unhardened => xprv.derivation_path.into_child(
106+
bip32::ChildNumber::from_normal_idx(index)
107+
.ok()
108+
.ok_or(ConversionError::HardenedChild)?,
109+
),
110+
Wildcard::Hardened => xprv.derivation_path.into_child(
111+
bip32::ChildNumber::from_hardened_idx(index)
112+
.ok()
113+
.ok_or(ConversionError::HardenedChild)?,
114+
),
115+
};
116+
DescriptorSecretKey::XPrv(DescriptorXKey {
117+
origin: xprv.origin,
118+
xkey: xprv.xkey,
119+
derivation_path,
120+
wildcard: Wildcard::None,
121+
})
122+
},
123+
DescriptorSecretKey::MultiXPrv(_) => return Err(ConversionError::MultiKey),
124+
}),
125+
};
126+
let definite_descriptor = self.descriptor.at_derivation_index(index)?;
127+
Ok(Descriptor{
128+
key: definite_key,
129+
descriptor: definite_descriptor,
130+
})
131+
}
132+
}
133+
85134
impl<Pk: MiniscriptKey + ToPublicKey, T: Extension + ParseableExt> Descriptor<Pk, T> {
86135
/// Obtains the unblinded address for this descriptor.
87136
pub fn unconfidential_address(

0 commit comments

Comments
 (0)