Skip to content

Commit d5615ac

Browse files
committed
Merge #461: Cleanly separate experimental/insane miniscripts from sane miniscripts
6a06a11 Allow parsing expr fragments from string/script (sanket1729) 94d5eba Cleanup psbt translator APIs (sanket1729) fff727c Remove Hash associated type from RawPkh. (sanket1729) 328d15f Rename the Semantic::translate_pkh to translate_pk (sanket1729) b1d6477 Change Semantic KeyHash(Pk::Hash) to Key(Pk) (sanket1729) 372377a Remove PkTranslator trait (sanket1729) Pull request description: Cleanly separates how we deal with insane and unspecified miniscripts in the library. Insane minsicripts are well-defined that could - It is unsafe(does not require a digital signature to spend it) - It contains a unspendable path because of either a) Resource limitations or b) Timelock Mixing - The script has malleable satisfaction - It has repeated public keys There are some unspecified features like PartialDescriptors that we use to allow parsing miniscripts from scripts or inferring descriptors. For this only includes - Parsing rawpkh fragments with `hash160` All of these can be individually enabled or disabled using the `ExtParams` builder. As a consequence of this, we removed the Miniscript::Hash associated type and change the Semantic policy to operate only on keys. Also fixes another issue in the usage of PkTranslator that made it impossible to implement the trait in downstream libraries ACKs for top commit: apoelstra: ACK 6a06a11 Tree-SHA512: 200cbe8bd9a42f75db8f5c74c6e811d70210f2202352beb82326f6ada3b19ce683feab06419dac2f2c94c8fa5ea0f8ee1fa5f9c84a4ce2e8193b5a631eddd111
2 parents 22ac742 + 6a06a11 commit d5615ac

33 files changed

+676
-965
lines changed

examples/htlc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ fn main() {
4242
assert!(htlc_descriptor.sanity_check().is_ok());
4343
assert_eq!(
4444
format!("{}", htlc_descriptor),
45-
"wsh(andor(pk(022222222222222222222222222222222222222222222222222222222222222222),sha256(1111111111111111111111111111111111111111111111111111111111111111),and_v(v:pkh(51814f108670aced2d77c1805ddd6634bc9d4731),older(4444))))#s0qq76ng"
45+
"wsh(andor(pk(022222222222222222222222222222222222222222222222222222222222222222),sha256(1111111111111111111111111111111111111111111111111111111111111111),and_v(v:pkh(020202020202020202020202020202020202020202020202020202020202020202),older(4444))))#lfytrjen"
4646
);
4747

4848
// Lift the descriptor into an abstract policy.
4949
assert_eq!(
5050
format!("{}", htlc_descriptor.lift().unwrap()),
51-
"or(and(pkh(4377a5acd66dc5cb67148a24818d1e51fa183bd2),sha256(1111111111111111111111111111111111111111111111111111111111111111)),and(pkh(51814f108670aced2d77c1805ddd6634bc9d4731),older(4444)))"
51+
"or(and(pk(022222222222222222222222222222222222222222222222222222222222222222),sha256(1111111111111111111111111111111111111111111111111111111111111111)),and(pk(020202020202020202020202020202020202020202020202020202020202020202),older(4444)))"
5252
);
5353

5454
// Get the scriptPpubkey for this Wsh descriptor.

examples/taproot.rs

+5-21
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use std::collections::HashMap;
22
use std::str::FromStr;
33

4-
use bitcoin::hashes::{hash160, ripemd160, sha256};
54
use bitcoin::util::address::WitnessVersion;
65
use bitcoin::Network;
76
use miniscript::descriptor::DescriptorType;
87
use miniscript::policy::Concrete;
9-
use miniscript::{hash256, Descriptor, Miniscript, Tap, TranslatePk, Translator};
8+
use miniscript::{translate_hash_fail, Descriptor, Miniscript, Tap, TranslatePk, Translator};
109
use secp256k1::{rand, KeyPair};
1110

1211
// Refer to https://github.com/sanket1729/adv_btc_workshop/blob/master/workshop.md#creating-a-taproot-descriptor
@@ -21,25 +20,10 @@ impl Translator<String, bitcoin::XOnlyPublicKey, ()> for StrPkTranslator {
2120
self.pk_map.get(pk).copied().ok_or(())
2221
}
2322

24-
fn pkh(&mut self, _pkh: &String) -> Result<hash160::Hash, ()> {
25-
unreachable!("Policy doesn't contain any pkh fragment");
26-
}
27-
28-
fn sha256(&mut self, _sha256: &String) -> Result<sha256::Hash, ()> {
29-
unreachable!("Policy does not contain any sha256 fragment");
30-
}
31-
32-
fn hash256(&mut self, _sha256: &String) -> Result<hash256::Hash, ()> {
33-
unreachable!("Policy does not contain any hash256 fragment");
34-
}
35-
36-
fn ripemd160(&mut self, _ripemd160: &String) -> Result<ripemd160::Hash, ()> {
37-
unreachable!("Policy does not contain any ripemd160 fragment");
38-
}
39-
40-
fn hash160(&mut self, _hash160: &String) -> Result<hash160::Hash, ()> {
41-
unreachable!("Policy does not contain any hash160 fragment");
42-
}
23+
// We don't need to implement these methods as we are not using them in the policy
24+
// Fail if we encounter any hash fragments.
25+
// See also translate_hash_clone! macro
26+
translate_hash_fail!(String, bitcoin::XOnlyPublicKey, ());
4327
}
4428

4529
fn main() {

src/descriptor/bare.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Bare<Pk> {
167167
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
168168
where
169169
Pk: 'a,
170-
Pk::RawPkHash: 'a,
171170
{
172171
self.ms.for_each_key(pred)
173172
}
@@ -294,7 +293,7 @@ impl<Pk: MiniscriptKey> fmt::Display for Pkh<Pk> {
294293

295294
impl<Pk: MiniscriptKey> Liftable<Pk> for Pkh<Pk> {
296295
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
297-
Ok(semantic::Policy::KeyHash(self.pk.to_pubkeyhash()))
296+
Ok(semantic::Policy::Key(self.pk.clone()))
298297
}
299298
}
300299

@@ -329,7 +328,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Pkh<Pk> {
329328
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
330329
where
331330
Pk: 'a,
332-
Pk::RawPkHash: 'a,
333331
{
334332
pred(&self.pk)
335333
}

src/descriptor/key.rs

-16
Original file line numberDiff line numberDiff line change
@@ -730,8 +730,6 @@ impl<K: InnerXKey> DescriptorXKey<K> {
730730
}
731731

732732
impl MiniscriptKey for DescriptorPublicKey {
733-
// This allows us to be able to derive public keys even for PkH s
734-
type RawPkHash = Self;
735733
type Sha256 = sha256::Hash;
736734
type Hash256 = hash256::Hash;
737735
type Ripemd160 = ripemd160::Hash;
@@ -756,10 +754,6 @@ impl MiniscriptKey for DescriptorPublicKey {
756754
_ => false,
757755
}
758756
}
759-
760-
fn to_pubkeyhash(&self) -> Self {
761-
self.clone()
762-
}
763757
}
764758

765759
impl DefiniteDescriptorKey {
@@ -818,8 +812,6 @@ impl fmt::Display for DefiniteDescriptorKey {
818812
}
819813

820814
impl MiniscriptKey for DefiniteDescriptorKey {
821-
// This allows us to be able to derive public keys even for PkH s
822-
type RawPkHash = Self;
823815
type Sha256 = sha256::Hash;
824816
type Hash256 = hash256::Hash;
825817
type Ripemd160 = ripemd160::Hash;
@@ -832,10 +824,6 @@ impl MiniscriptKey for DefiniteDescriptorKey {
832824
fn is_x_only_key(&self) -> bool {
833825
self.0.is_x_only_key()
834826
}
835-
836-
fn to_pubkeyhash(&self) -> Self {
837-
self.clone()
838-
}
839827
}
840828

841829
impl ToPublicKey for DefiniteDescriptorKey {
@@ -844,10 +832,6 @@ impl ToPublicKey for DefiniteDescriptorKey {
844832
self.0.derive_public_key(&secp).unwrap()
845833
}
846834

847-
fn hash_to_hash160(hash: &Self) -> hash160::Hash {
848-
hash.to_public_key().to_pubkeyhash()
849-
}
850-
851835
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
852836
*hash
853837
}

src/descriptor/mod.rs

+8-24
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ use self::checksum::verify_checksum;
3737
use crate::miniscript::{Legacy, Miniscript, Segwitv0};
3838
use crate::prelude::*;
3939
use crate::{
40-
expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, PkTranslator,
41-
Satisfier, ToPublicKey, TranslatePk, Translator,
40+
expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, Satisfier,
41+
ToPublicKey, TranslatePk, Translator,
4242
};
4343

4444
mod bare;
@@ -498,7 +498,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Descriptor<Pk> {
498498
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
499499
where
500500
Pk: 'a,
501-
Pk::RawPkHash: 'a,
502501
{
503502
match *self {
504503
Descriptor::Bare(ref bare) => bare.for_each_key(pred),
@@ -532,14 +531,12 @@ impl Descriptor<DescriptorPublicKey> {
532531
pub fn at_derivation_index(&self, index: u32) -> Descriptor<DefiniteDescriptorKey> {
533532
struct Derivator(u32);
534533

535-
impl PkTranslator<DescriptorPublicKey, DefiniteDescriptorKey, ()> for Derivator {
534+
impl Translator<DescriptorPublicKey, DefiniteDescriptorKey, ()> for Derivator {
536535
fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<DefiniteDescriptorKey, ()> {
537536
Ok(pk.clone().at_derivation_index(self.0))
538537
}
539538

540-
fn pkh(&mut self, pkh: &DescriptorPublicKey) -> Result<DefiniteDescriptorKey, ()> {
541-
Ok(pkh.clone().at_derivation_index(self.0))
542-
}
539+
translate_hash_clone!(DescriptorPublicKey, DescriptorPublicKey, ());
543540
}
544541
self.translate_pk(&mut Derivator(index))
545542
.expect("BIP 32 key index substitution cannot fail")
@@ -629,10 +626,6 @@ impl Descriptor<DescriptorPublicKey> {
629626
parse_key(pk, &mut self.0, self.1)
630627
}
631628

632-
fn pkh(&mut self, pkh: &String) -> Result<DescriptorPublicKey, Error> {
633-
parse_key(pkh, &mut self.0, self.1)
634-
}
635-
636629
fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, Error> {
637630
let hash =
638631
sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
@@ -675,10 +668,6 @@ impl Descriptor<DescriptorPublicKey> {
675668
key_to_string(pk, self.0)
676669
}
677670

678-
fn pkh(&mut self, pkh: &DescriptorPublicKey) -> Result<String, ()> {
679-
key_to_string(pkh, self.0)
680-
}
681-
682671
fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
683672
Ok(sha256.to_string())
684673
}
@@ -766,7 +755,7 @@ impl Descriptor<DefiniteDescriptorKey> {
766755
struct Derivator<'a, C: secp256k1::Verification>(&'a secp256k1::Secp256k1<C>);
767756

768757
impl<'a, C: secp256k1::Verification>
769-
PkTranslator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
758+
Translator<DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError>
770759
for Derivator<'a, C>
771760
{
772761
fn pk(
@@ -776,12 +765,7 @@ impl Descriptor<DefiniteDescriptorKey> {
776765
pk.derive_public_key(&self.0)
777766
}
778767

779-
fn pkh(
780-
&mut self,
781-
pkh: &DefiniteDescriptorKey,
782-
) -> Result<bitcoin::hashes::hash160::Hash, ConversionError> {
783-
Ok(pkh.derive_public_key(&self.0)?.to_pubkeyhash())
784-
}
768+
translate_hash_clone!(DefiniteDescriptorKey, bitcoin::PublicKey, ConversionError);
785769
}
786770

787771
let derived = self.translate_pk(&mut Derivator(secp))?;
@@ -1340,8 +1324,8 @@ mod tests {
13401324
assert_eq!(
13411325
descriptor,
13421326
format!(
1343-
"tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh(516ca378e588a7ed71336147e2a72848b20aca1a))}}}})#xz8ny8ae",
1344-
p1, p2, p3, p4,
1327+
"tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#tvu28c0s",
1328+
p1, p2, p3, p4, p5
13451329
)
13461330
)
13471331
}

src/descriptor/segwitv0.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
249249
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
250250
where
251251
Pk: 'a,
252-
Pk::RawPkHash: 'a,
253252
{
254253
match self.inner {
255254
WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
@@ -407,7 +406,7 @@ impl<Pk: MiniscriptKey> fmt::Display for Wpkh<Pk> {
407406

408407
impl<Pk: MiniscriptKey> Liftable<Pk> for Wpkh<Pk> {
409408
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
410-
Ok(semantic::Policy::KeyHash(self.pk.to_pubkeyhash()))
409+
Ok(semantic::Policy::Key(self.pk.clone()))
411410
}
412411
}
413412

@@ -442,7 +441,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
442441
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
443442
where
444443
Pk: 'a,
445-
Pk::RawPkHash: 'a,
446444
{
447445
pred(&self.pk)
448446
}

src/descriptor/sh.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Sh<Pk> {
5959
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
6060
match self.inner {
6161
ShInner::Wsh(ref wsh) => wsh.lift(),
62-
ShInner::Wpkh(ref pk) => Ok(semantic::Policy::KeyHash(pk.as_inner().to_pubkeyhash())),
62+
ShInner::Wpkh(ref pk) => Ok(semantic::Policy::Key(pk.as_inner().clone())),
6363
ShInner::SortedMulti(ref smv) => smv.lift(),
6464
ShInner::Ms(ref ms) => ms.lift(),
6565
}
@@ -380,7 +380,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Sh<Pk> {
380380
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
381381
where
382382
Pk: 'a,
383-
Pk::RawPkHash: 'a,
384383
{
385384
match self.inner {
386385
ShInner::Wsh(ref wsh) => wsh.for_each_key(pred),

src/descriptor/sortedmulti.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> ForEachKey<Pk> for SortedMultiVec<Pk
115115
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
116116
where
117117
Pk: 'a,
118-
Pk::RawPkHash: 'a,
119118
{
120119
self.pks.iter().all(|key| pred(key))
121120
}
@@ -216,9 +215,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> policy::Liftable<Pk> for SortedMulti
216215
let ret = policy::semantic::Policy::Threshold(
217216
self.k,
218217
self.pks
219-
.clone()
220-
.into_iter()
221-
.map(|k| policy::semantic::Policy::KeyHash(k.to_pubkeyhash()))
218+
.iter()
219+
.map(|k| policy::semantic::Policy::Key(k.clone()))
222220
.collect(),
223221
);
224222
Ok(ret)

src/descriptor/tr.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -558,12 +558,9 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Tr<Pk> {
558558
match &self.tree {
559559
Some(root) => Ok(Policy::Threshold(
560560
1,
561-
vec![
562-
Policy::KeyHash(self.internal_key.to_pubkeyhash()),
563-
root.lift()?,
564-
],
561+
vec![Policy::Key(self.internal_key.clone()), root.lift()?],
565562
)),
566-
None => Ok(Policy::KeyHash(self.internal_key.to_pubkeyhash())),
563+
None => Ok(Policy::Key(self.internal_key.clone())),
567564
}
568565
}
569566
}
@@ -572,7 +569,6 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Tr<Pk> {
572569
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
573570
where
574571
Pk: 'a,
575-
Pk::RawPkHash: 'a,
576572
{
577573
let script_keys_res = self
578574
.iter_scripts()

0 commit comments

Comments
 (0)