Skip to content

Commit 7797e60

Browse files
committed
miniscript: add an optional Pk to PkH nodes
This allows to access the actual public key behind the pubkey_hash. This can be used to derive public keys behind pubkey_hash in Miniscripts with extended public keys by modifying the translation function. However, the preimage is not available when parsing Miniscript from Script so it is inherently Option'al. Signed-off-by: Antoine Poinsot <[email protected]>
1 parent cd2459c commit 7797e60

File tree

8 files changed

+24
-18
lines changed

8 files changed

+24
-18
lines changed

src/descriptor/satisfied_constraints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ where
370370
return res;
371371
}
372372
}
373-
Terminal::PkH(ref pkh) => {
373+
Terminal::PkH(_, ref pkh) => {
374374
debug_assert_eq!(node_state.n_evaluated, 0);
375375
debug_assert_eq!(node_state.n_satisfied, 0);
376376
let res = self.stack.evaluate_pkh(&mut self.verify_sig, pkh);

src/miniscript/astelem.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
7575
{
7676
let frag = match *self {
7777
Terminal::PkK(ref p) => Terminal::PkK(translatefpk(p)?),
78-
Terminal::PkH(ref p) => Terminal::PkH(translatefpkh(p)?),
78+
Terminal::PkH(ref pk, ref pkh) => match pk {
79+
Some(pk) => Terminal::PkH(Some(translatefpk(pk)?), translatefpkh(pkh)?),
80+
None => Terminal::PkH(None, translatefpkh(pkh)?),
81+
},
7982
Terminal::After(n) => Terminal::After(n),
8083
Terminal::Older(n) => Terminal::Older(n),
8184
Terminal::Sha256(x) => Terminal::Sha256(x),
@@ -205,7 +208,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
205208
} else {
206209
match *self {
207210
Terminal::PkK(ref pk) => write!(f, "pk_k({:?})", pk),
208-
Terminal::PkH(ref pkh) => write!(f, "pk_h({:?})", pkh),
211+
Terminal::PkH(_, ref pkh) => write!(f, "pk_h({:?})", pkh),
209212
Terminal::After(t) => write!(f, "after({})", t),
210213
Terminal::Older(t) => write!(f, "older({})", t),
211214
Terminal::Sha256(h) => write!(f, "sha256({})", h),
@@ -255,7 +258,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
255258
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256259
match *self {
257260
Terminal::PkK(ref pk) => write!(f, "pk_k({})", pk),
258-
Terminal::PkH(ref pkh) => write!(f, "pk_h({})", pkh),
261+
Terminal::PkH(_, ref pkh) => write!(f, "pk_h({})", pkh),
259262
Terminal::After(t) => write!(f, "after({})", t),
260263
Terminal::Older(t) => write!(f, "older({})", t),
261264
Terminal::Sha256(h) => write!(f, "sha256({})", h),
@@ -308,7 +311,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
308311
if let Terminal::PkK(ref pk) = sub.node {
309312
// alias: pk(K) = c:pk_k(K)
310313
return write!(f, "pk({})", pk);
311-
} else if let Terminal::PkH(ref pkh) = sub.node {
314+
} else if let Terminal::PkH(_, ref pkh) = sub.node {
312315
// alias: pkh(K) = c:pk_h(K)
313316
return write!(f, "pkh({})", pkh);
314317
}
@@ -324,7 +327,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
324327
Some(('c', ms)) => {
325328
if let Terminal::PkK(ref _pk) = ms.node {
326329
fmt::Write::write_char(f, ':')?;
327-
} else if let Terminal::PkH(ref _pkh) = ms.node {
330+
} else if let Terminal::PkH(_, ref _pkh) = ms.node {
328331
fmt::Write::write_char(f, ':')?;
329332
}
330333
}
@@ -407,9 +410,9 @@ where
407410
("pk_k", 1) => {
408411
expression::terminal(&top.args[0], |x| Pk::from_str(x).map(Terminal::PkK))
409412
}
410-
("pk_h", 1) => {
411-
expression::terminal(&top.args[0], |x| Pk::Hash::from_str(x).map(Terminal::PkH))
412-
}
413+
("pk_h", 1) => expression::terminal(&top.args[0], |x| {
414+
Pk::Hash::from_str(x).map(|x| Terminal::PkH(None, x))
415+
}),
413416
("after", 1) => expression::terminal(&top.args[0], |x| {
414417
expression::parse_num(x).map(Terminal::After)
415418
}),
@@ -570,7 +573,7 @@ impl<Pk: MiniscriptKey + ToPublicKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
570573
pub fn encode(&self, mut builder: script::Builder) -> script::Builder {
571574
match *self {
572575
Terminal::PkK(ref pk) => builder.push_key(&pk.to_public_key()),
573-
Terminal::PkH(ref hash) => builder
576+
Terminal::PkH(_, ref hash) => builder
574577
.push_opcode(opcodes::all::OP_DUP)
575578
.push_opcode(opcodes::all::OP_HASH160)
576579
.push_slice(&Pk::hash_to_hash160(&hash)[..])

src/miniscript/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl ScriptContext for Legacy {
8282
frag: &Terminal<Pk, Ctx>,
8383
) -> Result<(), ScriptContextError> {
8484
match *frag {
85-
Terminal::PkH(ref _pkh) => Err(ScriptContextError::MalleablePkH),
85+
Terminal::PkH(..) => Err(ScriptContextError::MalleablePkH),
8686
Terminal::OrI(ref _a, ref _b) => Err(ScriptContextError::MalleableOrI),
8787
Terminal::DupIf(ref _ms) => Err(ScriptContextError::MalleableDupIf),
8888
_ => Ok(()),

src/miniscript/decode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub enum Terminal<Pk: MiniscriptKey, Ctx: ScriptContext> {
7171
/// `<key>`
7272
PkK(Pk),
7373
/// `DUP HASH160 <keyhash> EQUALVERIFY`
74-
PkH(Pk::Hash),
74+
PkH(Option<Pk>, Pk::Hash),
7575
// timelocks
7676
/// `n CHECKLOCKTIMEVERIFY`
7777
After(u32),
@@ -240,6 +240,7 @@ pub fn parse<Ctx: ScriptContext>(
240240
tokens,
241241
Tk::Hash20(hash), Tk::Hash160, Tk::Dup => {
242242
term.reduce0(Terminal::PkH(
243+
None,
243244
hash160::Hash::from_inner(hash)
244245
))?
245246
},

src/miniscript/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ mod tests {
493493

494494
let pkh_ms: Miniscript<DummyKey, Segwitv0> = Miniscript {
495495
node: Terminal::Check(Arc::new(Miniscript {
496-
node: Terminal::PkH(DummyKeyHash),
496+
node: Terminal::PkH(None, DummyKeyHash),
497497
ty: Type::from_pk_h(),
498498
ext: types::extra_props::ExtData::from_pk_h(),
499499
phantom: PhantomData,
@@ -524,7 +524,7 @@ mod tests {
524524

525525
let pkh_ms: Segwitv0Script = Miniscript {
526526
node: Terminal::Check(Arc::new(Miniscript {
527-
node: Terminal::PkH(hash),
527+
node: Terminal::PkH(None, hash),
528528
ty: Type::from_pk_h(),
529529
ext: types::extra_props::ExtData::from_pk_h(),
530530
phantom: PhantomData,

src/miniscript/satisfy.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ impl Satisfaction {
520520
stack: Witness::signature(stfr, pk),
521521
has_sig: true,
522522
},
523-
Terminal::PkH(ref pkh) => Satisfaction {
523+
Terminal::PkH(_, ref pkh) => Satisfaction {
524524
stack: Witness::pkh_signature(stfr, pkh),
525525
has_sig: true,
526526
},
@@ -760,7 +760,7 @@ impl Satisfaction {
760760
stack: Witness::push_0(),
761761
has_sig: false,
762762
},
763-
Terminal::PkH(ref pkh) => Satisfaction {
763+
Terminal::PkH(_, ref pkh) => Satisfaction {
764764
stack: Witness::combine(Witness::push_0(), Witness::pkh_public_key(stfr, pkh)),
765765
has_sig: false,
766766
},

src/policy/compiler.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ where
813813
match *policy {
814814
Concrete::Key(ref pk) => {
815815
insert_wrap!(AstElemExt::terminal(Terminal::PkH(
816+
Some(pk.clone()),
816817
pk.to_pubkeyhash().clone()
817818
)));
818819
insert_wrap!(AstElemExt::terminal(Terminal::PkK(pk.clone())));
@@ -1325,7 +1326,8 @@ mod tests {
13251326
keys[7].to_pubkeyhash()
13261327
);
13271328

1328-
assert_eq!(ms, ms_comp_res);
1329+
// We compare the Script encoding as the parsed miniscript could not detect the keys for PkHs.
1330+
assert_eq!(ms.encode(), ms_comp_res.encode());
13291331

13301332
let mut abs = policy.lift();
13311333
assert_eq!(abs.n_keys(), 8);

src/policy/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Liftable<Pk> for Terminal<Pk, Ctx> {
5959
fn lift(&self) -> Semantic<Pk> {
6060
match *self {
6161
Terminal::PkK(ref pk) => Semantic::KeyHash(pk.to_pubkeyhash()),
62-
Terminal::PkH(ref pkh) => Semantic::KeyHash(pkh.clone()),
62+
Terminal::PkH(_, ref pkh) => Semantic::KeyHash(pkh.clone()),
6363
Terminal::After(t) => Semantic::After(t),
6464
Terminal::Older(t) => Semantic::Older(t),
6565
Terminal::Sha256(h) => Semantic::Sha256(h),

0 commit comments

Comments
 (0)