Skip to content

Commit 3af16d1

Browse files
committed
Extract the explicit_script method out of DescriptorTrait
The code around the `explicit_script` method is a little convoluted because a taproot descriptor does not support it. Extract the `explicit_script` method out of the `DescriptorTrait` as a new `ExplicitScript` trait that is infallible. Implement it for all the descriptor types except taproot.
1 parent 89d798f commit 3af16d1

File tree

9 files changed

+85
-159
lines changed

9 files changed

+85
-159
lines changed

examples/htlc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ extern crate miniscript;
2020
use bitcoin::Network;
2121
use miniscript::descriptor::Wsh;
2222
use miniscript::policy::{Concrete, Liftable};
23-
use miniscript::{DescriptorTrait, ToAddress};
23+
use miniscript::{DescriptorTrait, ExplicitScript, ToAddress};
2424
use std::str::FromStr;
2525

2626
fn main() {
@@ -60,7 +60,7 @@ fn main() {
6060
);
6161

6262
assert_eq!(
63-
format!("{:x}", htlc_descriptor.inner_script()),
63+
format!("{:x}", htlc_descriptor.explicit_script()),
6464
"21022222222222222222222222222222222222222222222222222222222222222222ac6476a91451814f108670aced2d77c1805ddd6634bc9d473188ad025c11b26782012088a82011111111111111111111111111111111111111111111111111111111111111118768"
6565
);
6666

src/descriptor/bare.rs

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::{
3333

3434
use super::{
3535
checksum::{desc_checksum, verify_checksum},
36-
DescriptorTrait, ToAddress,
36+
DescriptorTrait, ExplicitScript, ToAddress,
3737
};
3838

3939
/// Create a Bare Descriptor. That is descriptor that is
@@ -64,13 +64,6 @@ impl<Pk: MiniscriptKey> Bare<Pk> {
6464
}
6565

6666
impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> {
67-
/// Obtains the underlying miniscript for this descriptor.
68-
/// Called by [`DescriptorTrait::explicit_script`] for this descriptor.
69-
/// Equivalent to [`DescriptorTrait::script_pubkey`] for this descriptor.
70-
pub fn inner_script(&self) -> Script {
71-
self.script_pubkey()
72-
}
73-
7467
/// Obtains the pre bip-340 signature script code for this descriptor.
7568
/// Called by [`DescriptorTrait::script_code`] for this descriptor.
7669
/// Equivalent to [`DescriptorTrait::script_pubkey`] for this descriptor.
@@ -149,13 +142,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
149142
Script::new()
150143
}
151144

152-
fn explicit_script(&self) -> Result<Script, Error>
153-
where
154-
Pk: ToPublicKey,
155-
{
156-
Ok(self.inner_script())
157-
}
158-
159145
fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
160146
where
161147
Pk: ToPublicKey,
@@ -191,6 +177,12 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
191177
}
192178
}
193179

180+
impl<Pk: MiniscriptKey + ToPublicKey> ExplicitScript<Pk> for Bare<Pk> {
181+
fn explicit_script(&self) -> Script {
182+
self.script_pubkey()
183+
}
184+
}
185+
194186
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Bare<Pk> {
195187
fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: F) -> bool
196188
where
@@ -248,13 +240,6 @@ impl<Pk: MiniscriptKey> Pkh<Pk> {
248240
}
249241

250242
impl<Pk: MiniscriptKey + ToPublicKey> Pkh<Pk> {
251-
/// Obtains the underlying miniscript for this descriptor.
252-
/// Called by [`DescriptorTrait::explicit_script`] for this descriptor.
253-
/// Equivalent to [`DescriptorTrait::script_pubkey`] for this descriptor.
254-
pub fn inner_script(&self) -> Script {
255-
self.script_pubkey()
256-
}
257-
258243
/// Obtain the pre bip-340 signature script code for this descriptor.
259244
/// Called by [`DescriptorTrait::script_code`] for this descriptor.
260245
/// Equivalent to [`DescriptorTrait::script_pubkey`] for this descriptor.
@@ -342,13 +327,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
342327
Script::new()
343328
}
344329

345-
fn explicit_script(&self) -> Result<Script, Error>
346-
where
347-
Pk: ToPublicKey,
348-
{
349-
Ok(self.inner_script())
350-
}
351-
352330
fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
353331
where
354332
Pk: ToPublicKey,
@@ -393,6 +371,12 @@ impl<Pk: MiniscriptKey + ToPublicKey> ToAddress<Pk> for Pkh<Pk> {
393371
}
394372
}
395373

374+
impl<Pk: MiniscriptKey + ToPublicKey> ExplicitScript<Pk> for Pkh<Pk> {
375+
fn explicit_script(&self) -> Script {
376+
self.script_pubkey()
377+
}
378+
}
379+
396380
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Pkh<Pk> {
397381
fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool
398382
where

src/descriptor/mod.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,6 @@ pub trait DescriptorTrait<Pk: MiniscriptKey> {
109109
where
110110
Pk: ToPublicKey;
111111

112-
/// Computes the "witness script" of the descriptor, i.e. the underlying
113-
/// script before any hashing is done. For `Bare`, `Pkh` and `Wpkh` this
114-
/// is the scriptPubkey; for `ShWpkh` and `Sh` this is the redeemScript;
115-
/// for the others it is the witness script.
116-
/// For `Tr` descriptors, this will error as there is no underlying script
117-
fn explicit_script(&self) -> Result<Script, Error>
118-
where
119-
Pk: ToPublicKey;
120-
121112
/// Returns satisfying non-malleable witness and scriptSig with minimum weight to spend an
122113
/// output controlled by the given descriptor if it possible to
123114
/// construct one using the satisfier S.
@@ -173,6 +164,15 @@ pub trait ToAddress<Pk: MiniscriptKey + ToPublicKey> {
173164
fn to_address(&self, network: Network) -> Address;
174165
}
175166

167+
/// A trait for getting the "witness script" for a descriptor.
168+
pub trait ExplicitScript<Pk: MiniscriptKey + ToPublicKey> {
169+
/// Computes the "witness script" of the descriptor, i.e. the underlying
170+
/// script before any hashing is done. For `Bare`, `Pkh` and `Wpkh` this
171+
/// is the scriptPubkey; for `ShWpkh` and `Sh` this is the redeemScript;
172+
/// for the others it is the witness script.
173+
fn explicit_script(&self) -> Script;
174+
}
175+
176176
/// Script descriptor
177177
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
178178
pub enum Descriptor<Pk: MiniscriptKey> {
@@ -202,6 +202,25 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
202202
Descriptor::Tr(ref tr) => Ok(tr.to_address(network)),
203203
}
204204
}
205+
206+
/// Computes the "witness script" of the descriptor, i.e. the underlying
207+
/// script before any hashing is done. For `Bare`, `Pkh` and `Wpkh` this
208+
/// is the scriptPubkey; for `ShWpkh` and `Sh` this is the redeemScript;
209+
/// for the others it is the witness script.
210+
///
211+
/// # Errors
212+
///
213+
/// If the descriptor is a taproot descriptor (`Tr`).
214+
pub fn explicit_script(&self) -> Result<Script, Error> {
215+
match *self {
216+
Descriptor::Bare(ref bare) => Ok(bare.explicit_script()),
217+
Descriptor::Pkh(ref pkh) => Ok(pkh.explicit_script()),
218+
Descriptor::Wpkh(ref wpkh) => Ok(wpkh.explicit_script()),
219+
Descriptor::Wsh(ref wsh) => Ok(wsh.explicit_script()),
220+
Descriptor::Sh(ref sh) => Ok(sh.explicit_script()),
221+
Descriptor::Tr(_) => Err(Error::TrNoScriptCode),
222+
}
223+
}
205224
}
206225

207226
impl<Pk: MiniscriptKey> From<Bare<Pk>> for Descriptor<Pk> {
@@ -549,26 +568,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Descriptor<Pk> {
549568
}
550569
}
551570

552-
/// Computes the "witness script" of the descriptor, i.e. the underlying
553-
/// script before any hashing is done. For `Bare`, `Pkh` and `Wpkh` this
554-
/// is the scriptPubkey; for `ShWpkh` and `Sh` this is the redeemScript;
555-
/// for the others it is the witness script.
556-
/// Errors:
557-
/// - When the descriptor is Tr
558-
fn explicit_script(&self) -> Result<Script, Error>
559-
where
560-
Pk: ToPublicKey,
561-
{
562-
match *self {
563-
Descriptor::Bare(ref bare) => bare.explicit_script(),
564-
Descriptor::Pkh(ref pkh) => pkh.explicit_script(),
565-
Descriptor::Wpkh(ref wpkh) => wpkh.explicit_script(),
566-
Descriptor::Wsh(ref wsh) => wsh.explicit_script(),
567-
Descriptor::Sh(ref sh) => sh.explicit_script(),
568-
Descriptor::Tr(ref tr) => tr.explicit_script(),
569-
}
570-
}
571-
572571
/// Returns satisfying non-malleable witness and scriptSig to spend an
573572
/// output controlled by the given descriptor if it possible to
574573
/// construct one using the satisfier S.

src/descriptor/pretaproot.rs

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for PreTaprootDescriptor<Pk> {
7777
}
7878
}
7979

80-
/// Computes the "witness script" of the descriptor, i.e. the underlying
81-
/// script before any hashing is done. For `Bare`, `Pkh` and `Wpkh` this
82-
/// is the scriptPubkey; for `ShWpkh` and `Sh` this is the redeemScript;
83-
/// for the others it is the witness script.
84-
/// Errors:
85-
/// - When the descriptor is Tr
86-
fn explicit_script(&self) -> Result<Script, Error>
87-
where
88-
Pk: ToPublicKey,
89-
{
90-
match *self {
91-
PreTaprootDescriptor::Bare(ref bare) => bare.explicit_script(),
92-
PreTaprootDescriptor::Pkh(ref pkh) => pkh.explicit_script(),
93-
PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.explicit_script(),
94-
PreTaprootDescriptor::Wsh(ref wsh) => wsh.explicit_script(),
95-
PreTaprootDescriptor::Sh(ref sh) => sh.explicit_script(),
96-
}
97-
}
98-
9980
/// Returns satisfying non-malleable witness and scriptSig to spend an
10081
/// output controlled by the given descriptor if it possible to
10182
/// construct one using the satisfier S.
@@ -238,18 +219,6 @@ pub(crate) mod traits {
238219
/// A general trait for Pre taproot bitcoin descriptor.
239220
/// Similar to [`DescriptorTrait`], but `explicit_script` and `script_code` methods cannot fail
240221
pub trait PreTaprootDescriptorTrait<Pk: MiniscriptKey>: DescriptorTrait<Pk> {
241-
/// Same as [`DescriptorTrait::explicit_script`], but a non failing version.
242-
/// All PreTaproot descriptors have a unique explicit script
243-
fn explicit_script(&self) -> Script
244-
where
245-
Pk: ToPublicKey,
246-
{
247-
// This expect can technically be avoided if we implement this for types, but
248-
// having this expect saves lots of LoC because of default implementation
249-
<Self as DescriptorTrait<Pk>>::explicit_script(&self)
250-
.expect("Pre taproot descriptor have explicit script")
251-
}
252-
253222
/// Same as [`DescriptorTrait::script_code`], but a non failing version.
254223
/// All PreTaproot descriptors have a script code
255224
fn script_code(&self) -> Script

src/descriptor/segwitv0.rs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131

3232
use super::{
3333
checksum::{desc_checksum, verify_checksum},
34-
DescriptorTrait, SortedMultiVec, ToAddress,
34+
DescriptorTrait, ExplicitScript, SortedMultiVec, ToAddress,
3535
};
3636
/// A Segwitv0 wsh descriptor
3737
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
@@ -79,20 +79,11 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {
7979
}
8080

8181
impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
82-
/// Obtains the underlying miniscript for this descriptor.
83-
/// Called by [`DescriptorTrait::explicit_script`] for this descriptor.
84-
pub fn inner_script(&self) -> Script {
85-
match self.inner {
86-
WshInner::SortedMulti(ref smv) => smv.encode(),
87-
WshInner::Ms(ref ms) => ms.encode(),
88-
}
89-
}
90-
9182
/// Obtains the pre bip-340 signature script code for this descriptor.
9283
/// Called by [`DescriptorTrait::script_code`] for this descriptor.
9384
/// Equivalent to `self.inner_script`.
9485
pub fn ecdsa_sighash_script_code(&self) -> Script {
95-
self.inner_script()
86+
self.explicit_script()
9687
}
9788
}
9889

@@ -189,7 +180,7 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wsh<Pk> {
189180
where
190181
Pk: ToPublicKey,
191182
{
192-
self.inner_script().to_v0_p2wsh()
183+
self.explicit_script().to_v0_p2wsh()
193184
}
194185

195186
fn unsigned_script_sig(&self) -> Script
@@ -199,13 +190,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wsh<Pk> {
199190
Script::new()
200191
}
201192

202-
fn explicit_script(&self) -> Result<Script, Error>
203-
where
204-
Pk: ToPublicKey,
205-
{
206-
Ok(self.inner_script())
207-
}
208-
209193
fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
210194
where
211195
Pk: ToPublicKey,
@@ -215,7 +199,7 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wsh<Pk> {
215199
WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
216200
WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
217201
};
218-
let witness_script = self.inner_script();
202+
let witness_script = self.explicit_script();
219203
witness.push(witness_script.into_bytes());
220204
let script_sig = Script::new();
221205
Ok((witness, script_sig))
@@ -230,7 +214,7 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wsh<Pk> {
230214
WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
231215
WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
232216
};
233-
witness.push(self.inner_script().into_bytes());
217+
witness.push(self.explicit_script().into_bytes());
234218
let script_sig = Script::new();
235219
Ok((witness, script_sig))
236220
}
@@ -272,6 +256,15 @@ impl<Pk: MiniscriptKey + ToPublicKey> ToAddress<Pk> for Wsh<Pk> {
272256
}
273257
}
274258

259+
impl<Pk: MiniscriptKey + ToPublicKey> ExplicitScript<Pk> for Wsh<Pk> {
260+
fn explicit_script(&self) -> Script {
261+
match self.inner {
262+
WshInner::SortedMulti(ref smv) => smv.encode(),
263+
WshInner::Ms(ref ms) => ms.encode(),
264+
}
265+
}
266+
}
267+
275268
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
276269
fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, pred: F) -> bool
277270
where
@@ -347,13 +340,6 @@ impl<Pk: MiniscriptKey> Wpkh<Pk> {
347340
}
348341

349342
impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
350-
/// Obtains the underlying miniscript for this descriptor.
351-
/// Called by [`DescriptorTrait::explicit_script`] for this descriptor.
352-
/// Equivalent to [`DescriptorTrait::script_pubkey`] for this descriptor.
353-
pub fn inner_script(&self) -> Script {
354-
self.script_pubkey()
355-
}
356-
357343
/// Obtains the pre bip-340 signature script code for this descriptor.
358344
/// Called by [`DescriptorTrait::script_code`] for this descriptor.
359345
pub fn ecdsa_sighash_script_code(&self) -> Script {
@@ -452,13 +438,6 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wpkh<Pk> {
452438
Script::new()
453439
}
454440

455-
fn explicit_script(&self) -> Result<Script, Error>
456-
where
457-
Pk: ToPublicKey,
458-
{
459-
Ok(self.inner_script())
460-
}
461-
462441
fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
463442
where
464443
Pk: ToPublicKey,
@@ -504,6 +483,12 @@ impl<Pk: MiniscriptKey + ToPublicKey> ToAddress<Pk> for Wpkh<Pk> {
504483
}
505484
}
506485

486+
impl<Pk: MiniscriptKey + ToPublicKey> ExplicitScript<Pk> for Wpkh<Pk> {
487+
fn explicit_script(&self) -> Script {
488+
self.script_pubkey()
489+
}
490+
}
491+
507492
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
508493
fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool
509494
where

0 commit comments

Comments
 (0)