Skip to content

Commit 5cb2bcf

Browse files
Refactor PkH to include key.
The test-cases previously containing 40-byte hash for `pk_h` fragment have been replaced with 66-byte pubkey.
1 parent 09299b0 commit 5cb2bcf

File tree

14 files changed

+186
-101
lines changed

14 files changed

+186
-101
lines changed

src/descriptor/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,19 +1253,20 @@ mod tests {
12531253
let p2 = "020000000000000000000000000000000000000000000000000000000000000002";
12541254
let p3 = "020000000000000000000000000000000000000000000000000000000000000003";
12551255
let p4 = "020000000000000000000000000000000000000000000000000000000000000004";
1256-
let p5 = "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31";
1256+
let p5 = "03f8551772d66557da28c1de858124f365a8eb30ce6ad79c10e0f4c546d0ab0f82";
12571257
let descriptor = Tr::<PublicKey>::from_str(&format!(
12581258
"tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})",
12591259
p1, p2, p3, p4, p5
12601260
))
12611261
.unwrap()
12621262
.to_string();
12631263

1264+
// p5.to_pubkeyhash() = 516ca378e588a7ed71336147e2a72848b20aca1a
12641265
assert_eq!(
12651266
descriptor,
12661267
format!(
1267-
"tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh({}))}}}})#fdhmu4fj",
1268-
p1, p2, p3, p4, p5
1268+
"tr({},{{pk({}),{{pk({}),or_d(pk({}),pkh(516ca378e588a7ed71336147e2a72848b20aca1a))}}}})#xz8ny8ae",
1269+
p1, p2, p3, p4,
12691270
)
12701271
)
12711272
}

src/interpreter/mod.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,17 @@ where
595595
return res;
596596
}
597597
}
598-
Terminal::PkH(ref pkh) => {
598+
Terminal::PkH(ref pk) => {
599+
debug_assert_eq!(node_state.n_evaluated, 0);
600+
debug_assert_eq!(node_state.n_satisfied, 0);
601+
let res = self
602+
.stack
603+
.evaluate_pkh(&mut self.verify_sig, pk.to_pubkeyhash());
604+
if res.is_some() {
605+
return res;
606+
}
607+
}
608+
Terminal::RawPkH(ref pkh) => {
599609
debug_assert_eq!(node_state.n_evaluated, 0);
600610
debug_assert_eq!(node_state.n_satisfied, 0);
601611
let res = self.stack.evaluate_pkh(&mut self.verify_sig, *pkh);
@@ -1138,7 +1148,7 @@ mod tests {
11381148
}
11391149

11401150
let pk = no_checks_ms(&format!("c:pk_k({})", pks[0]));
1141-
let pkh = no_checks_ms(&format!("c:pk_h({})", pks[1].to_pubkeyhash()));
1151+
let pkh = no_checks_ms(&format!("c:pk_h({})", pks[1]));
11421152
//Time
11431153
let after = no_checks_ms(&format!("after({})", 1000));
11441154
let older = no_checks_ms(&format!("older({})", 1000));
@@ -1270,11 +1280,7 @@ mod tests {
12701280
stack::Element::Push(&pk_bytes),
12711281
stack::Element::Push(&der_sigs[0]),
12721282
]);
1273-
let elem = no_checks_ms(&format!(
1274-
"and_v(vc:pk_k({}),c:pk_h({}))",
1275-
pks[0],
1276-
pks[1].to_pubkeyhash()
1277-
));
1283+
let elem = no_checks_ms(&format!("and_v(vc:pk_k({}),c:pk_h({}))", pks[0], pks[1]));
12781284
let vfyfn = vfyfn_.clone(); // sigh rust 1.29...
12791285
let constraints = from_stack(Box::new(vfyfn), stack, &elem);
12801286

@@ -1325,9 +1331,7 @@ mod tests {
13251331
]);
13261332
let elem = no_checks_ms(&format!(
13271333
"andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
1328-
pks[0],
1329-
sha256_hash,
1330-
pks[1].to_pubkeyhash(),
1334+
pks[0], sha256_hash, pks[1],
13311335
));
13321336
let vfyfn = vfyfn_.clone(); // sigh rust 1.29...
13331337
let constraints = from_stack(Box::new(vfyfn), stack, &elem);

src/miniscript/astelem.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
8686
{
8787
match *self {
8888
Terminal::PkK(ref p) => pred(ForEach(p)),
89-
Terminal::PkH(ref _p) => todo!("KeyHash should contain Pk"),
90-
Terminal::After(..)
89+
Terminal::PkH(ref p) => pred(ForEach(p)),
90+
Terminal::RawPkH(..)
91+
| Terminal::After(..)
9192
| Terminal::Older(..)
9293
| Terminal::Sha256(..)
9394
| Terminal::Hash256(..)
@@ -130,7 +131,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
130131
{
131132
let frag: Terminal<Q, CtxQ> = match *self {
132133
Terminal::PkK(ref p) => Terminal::PkK(t.pk(p)?),
133-
Terminal::PkH(ref p) => Terminal::PkH(t.pkh(p)?),
134+
Terminal::PkH(ref p) => Terminal::PkH(t.pk(p)?),
135+
Terminal::RawPkH(ref p) => Terminal::RawPkH(t.pkh(p)?),
134136
Terminal::After(n) => Terminal::After(n),
135137
Terminal::Older(n) => Terminal::Older(n),
136138
Terminal::Sha256(ref x) => Terminal::Sha256(t.sha256(&x)?),
@@ -255,7 +257,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
255257
} else {
256258
match *self {
257259
Terminal::PkK(ref pk) => write!(f, "pk_k({:?})", pk),
258-
Terminal::PkH(ref pkh) => write!(f, "pk_h({:?})", pkh),
260+
Terminal::PkH(ref pk) => write!(f, "pk_h({:?})", pk),
261+
Terminal::RawPkH(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(ref h) => write!(f, "sha256({})", h),
@@ -312,7 +315,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
312315
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313316
match *self {
314317
Terminal::PkK(ref pk) => write!(f, "pk_k({})", pk),
315-
Terminal::PkH(ref pkh) => write!(f, "pk_h({})", pkh),
318+
Terminal::PkH(ref pk) => write!(f, "pk_h({})", pk),
319+
Terminal::RawPkH(ref pkh) => write!(f, "pk_h({})", pkh),
316320
Terminal::After(t) => write!(f, "after({})", t),
317321
Terminal::Older(t) => write!(f, "older({})", t),
318322
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
@@ -372,9 +376,13 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
372376
if let Terminal::PkK(ref pk) = sub.node {
373377
// alias: pk(K) = c:pk_k(K)
374378
return write!(f, "pk({})", pk);
375-
} else if let Terminal::PkH(ref pkh) = sub.node {
379+
} else if let Terminal::RawPkH(ref pkh) = sub.node {
380+
// `RawPkH` is currently unsupported in the descriptor spec
376381
// alias: pkh(K) = c:pk_h(K)
377382
return write!(f, "pkh({})", pkh);
383+
} else if let Terminal::PkH(ref pk) = sub.node {
384+
// alias: pkh(K) = c:pk_h(K)
385+
return write!(f, "pkh({})", &pk.to_pubkeyhash());
378386
}
379387
}
380388

@@ -386,7 +394,9 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
386394
// Add a ':' wrapper if there are other wrappers apart from c:pk_k()
387395
// tvc:pk_k() -> tv:pk()
388396
Some(('c', ms)) => match ms.node {
389-
Terminal::PkK(_) | Terminal::PkH(_) => fmt::Write::write_char(f, ':')?,
397+
Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) => {
398+
fmt::Write::write_char(f, ':')?
399+
}
390400
_ => {}
391401
},
392402
_ => {}
@@ -460,9 +470,7 @@ impl_from_tree!(
460470
("pk_k", 1) => {
461471
expression::terminal(&top.args[0], |x| Pk::from_str(x).map(Terminal::PkK))
462472
}
463-
("pk_h", 1) => {
464-
expression::terminal(&top.args[0], |x| Pk::Hash::from_str(x).map(Terminal::PkH))
465-
}
473+
("pk_h", 1) => expression::terminal(&top.args[0], |x| Pk::from_str(x).map(Terminal::PkH)),
466474
("after", 1) => expression::terminal(&top.args[0], |x| {
467475
expression::parse_num(x).map(Terminal::After)
468476
}),
@@ -620,7 +628,12 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
620628
{
621629
match *self {
622630
Terminal::PkK(ref pk) => builder.push_ms_key::<_, Ctx>(pk),
623-
Terminal::PkH(ref hash) => builder
631+
Terminal::PkH(ref pk) => builder
632+
.push_opcode(opcodes::all::OP_DUP)
633+
.push_opcode(opcodes::all::OP_HASH160)
634+
.push_ms_key_hash::<_, Ctx>(pk)
635+
.push_opcode(opcodes::all::OP_EQUALVERIFY),
636+
Terminal::RawPkH(ref hash) => builder
624637
.push_opcode(opcodes::all::OP_DUP)
625638
.push_opcode(opcodes::all::OP_HASH160)
626639
.push_slice(&Pk::hash_to_hash160(hash)[..])
@@ -760,7 +773,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
760773
pub fn script_size(&self) -> usize {
761774
match *self {
762775
Terminal::PkK(ref pk) => Ctx::pk_len(pk),
763-
Terminal::PkH(..) => 24,
776+
Terminal::PkH(..) | Terminal::RawPkH(..) => 24,
764777
Terminal::After(n) => script_num_size(n as usize) + 1,
765778
Terminal::Older(n) => script_num_size(n as usize) + 1,
766779
Terminal::Sha256(..) => 33 + 6,

src/miniscript/context.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ impl ScriptContext for Legacy {
356356
) -> Result<(), ScriptContextError> {
357357
match *frag {
358358
Terminal::PkH(ref _pkh) => Err(ScriptContextError::MalleablePkH),
359+
Terminal::RawPkH(ref _pk) => Err(ScriptContextError::MalleablePkH),
359360
Terminal::OrI(ref _a, ref _b) => Err(ScriptContextError::MalleableOrI),
360361
Terminal::DupIf(ref _ms) => Err(ScriptContextError::MalleableDupIf),
361362
_ => Ok(()),
@@ -747,8 +748,8 @@ impl ScriptContext for BareCtx {
747748
fn other_top_level_checks<Pk: MiniscriptKey>(ms: &Miniscript<Pk, Self>) -> Result<(), Error> {
748749
match &ms.node {
749750
Terminal::Check(ref ms) => match &ms.node {
750-
Terminal::PkH(_pkh) => Ok(()),
751-
Terminal::PkK(_pk) => Ok(()),
751+
Terminal::RawPkH(_pkh) => Ok(()),
752+
Terminal::PkK(_pk) | Terminal::PkH(_pk) => Ok(()),
752753
_ => Err(Error::NonStandardBareScript),
753754
},
754755
Terminal::Multi(_k, subs) if subs.len() <= 3 => Ok(()),

src/miniscript/decode.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ pub enum Terminal<Pk: MiniscriptKey, Ctx: ScriptContext> {
134134
/// `<key>`
135135
PkK(Pk),
136136
/// `DUP HASH160 <keyhash> EQUALVERIFY`
137-
PkH(Pk::Hash),
137+
PkH(Pk),
138+
/// Only for parsing PkH for Script
139+
RawPkH(Pk::Hash),
138140
// timelocks
139141
/// `n CHECKLOCKTIMEVERIFY`
140142
After(u32),
@@ -336,7 +338,7 @@ pub fn parse<Ctx: ScriptContext>(
336338
Tk::Hash160 => match_token!(
337339
tokens,
338340
Tk::Dup => {
339-
term.reduce0(Terminal::PkH(
341+
term.reduce0(Terminal::RawPkH(
340342
hash160::Hash::from_slice(hash).expect("valid size")
341343
))?
342344
},

src/miniscript/iter.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
5858
/// them.
5959
pub fn branches(&self) -> Vec<&Miniscript<Pk, Ctx>> {
6060
match self.node {
61-
Terminal::PkK(_) | Terminal::PkH(_) | Terminal::Multi(_, _) => vec![],
61+
Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) | Terminal::Multi(_, _) => {
62+
vec![]
63+
}
6264

6365
Terminal::Alt(ref node)
6466
| Terminal::Swap(ref node)
@@ -123,7 +125,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
123125
/// `miniscript.iter_pubkeys().collect()`.
124126
pub fn get_leapk(&self) -> Vec<Pk> {
125127
match self.node {
126-
Terminal::PkK(ref key) => vec![key.clone()],
128+
Terminal::PkK(ref key) | Terminal::PkH(ref key) => vec![key.clone()],
127129
Terminal::Multi(_, ref keys) | Terminal::MultiA(_, ref keys) => keys.clone(),
128130
_ => vec![],
129131
}
@@ -140,8 +142,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
140142
/// for example `miniscript.iter_pubkey_hashes().collect()`.
141143
pub fn get_leapkh(&self) -> Vec<Pk::Hash> {
142144
match self.node {
143-
Terminal::PkH(ref hash) => vec![hash.clone()],
144-
Terminal::PkK(ref key) => vec![key.to_pubkeyhash()],
145+
Terminal::RawPkH(ref hash) => vec![hash.clone()],
146+
Terminal::PkK(ref key) | Terminal::PkH(ref key) => vec![key.to_pubkeyhash()],
145147
Terminal::Multi(_, ref keys) | Terminal::MultiA(_, ref keys) => {
146148
keys.iter().map(Pk::to_pubkeyhash).collect()
147149
}
@@ -158,8 +160,10 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
158160
/// function, for example `miniscript.iter_pubkeys_and_hashes().collect()`.
159161
pub fn get_leapk_pkh(&self) -> Vec<PkPkh<Pk>> {
160162
match self.node {
161-
Terminal::PkH(ref hash) => vec![PkPkh::HashedPubkey(hash.clone())],
162-
Terminal::PkK(ref key) => vec![PkPkh::PlainPubkey(key.clone())],
163+
Terminal::RawPkH(ref hash) => vec![PkPkh::HashedPubkey(hash.clone())],
164+
Terminal::PkH(ref key) | Terminal::PkK(ref key) => {
165+
vec![PkPkh::PlainPubkey(key.clone())]
166+
}
163167
Terminal::Multi(_, ref keys) | Terminal::MultiA(_, ref keys) => keys
164168
.iter()
165169
.map(|key| PkPkh::PlainPubkey(key.clone()))
@@ -174,7 +178,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
174178
/// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
175179
pub fn get_nth_pk(&self, n: usize) -> Option<Pk> {
176180
match (&self.node, n) {
177-
(&Terminal::PkK(ref key), 0) => Some(key.clone()),
181+
(&Terminal::PkK(ref key), 0) | (&Terminal::PkH(ref key), 0) => Some(key.clone()),
178182
(&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
179183
keys.get(n).cloned()
180184
}
@@ -191,8 +195,10 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
191195
/// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
192196
pub fn get_nth_pkh(&self, n: usize) -> Option<Pk::Hash> {
193197
match (&self.node, n) {
194-
(&Terminal::PkH(ref hash), 0) => Some(hash.clone()),
195-
(&Terminal::PkK(ref key), 0) => Some(key.to_pubkeyhash()),
198+
(&Terminal::RawPkH(ref hash), 0) => Some(hash.clone()),
199+
(&Terminal::PkK(ref key), 0) | (&Terminal::PkH(ref key), 0) => {
200+
Some(key.to_pubkeyhash())
201+
}
196202
(&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
197203
keys.get(n).map(Pk::to_pubkeyhash)
198204
}
@@ -206,8 +212,10 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
206212
/// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
207213
pub fn get_nth_pk_pkh(&self, n: usize) -> Option<PkPkh<Pk>> {
208214
match (&self.node, n) {
209-
(&Terminal::PkH(ref hash), 0) => Some(PkPkh::HashedPubkey(hash.clone())),
210-
(&Terminal::PkK(ref key), 0) => Some(PkPkh::PlainPubkey(key.clone())),
215+
(&Terminal::RawPkH(ref hash), 0) => Some(PkPkh::HashedPubkey(hash.clone())),
216+
(&Terminal::PkH(ref key), 0) | (&Terminal::PkK(ref key), 0) => {
217+
Some(PkPkh::PlainPubkey(key.clone()))
218+
}
211219
(&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
212220
keys.get(n).map(|key| PkPkh::PlainPubkey(key.clone()))
213221
}
@@ -493,7 +501,7 @@ pub mod test {
493501

494502
pub fn gen_testcases() -> Vec<TestData> {
495503
let k = gen_bitcoin_pubkeys(10, true);
496-
let h: Vec<hash160::Hash> = k
504+
let _h: Vec<hash160::Hash> = k
497505
.iter()
498506
.map(|pk| hash160::Hash::hash(&pk.to_bytes()))
499507
.collect();
@@ -520,11 +528,11 @@ pub mod test {
520528
false,
521529
),
522530
(ms_str!("c:pk_k({})", k[0]), vec![k[0]], vec![], true),
523-
(ms_str!("c:pk_h({})", h[6]), vec![], vec![h[6]], true),
531+
(ms_str!("c:pk_h({})", k[0]), vec![k[0]], vec![], true),
524532
(
525-
ms_str!("and_v(vc:pk_k({}),c:pk_h({}))", k[0], h[1]),
526-
vec![k[0]],
527-
vec![h[1]],
533+
ms_str!("and_v(vc:pk_k({}),c:pk_h({}))", k[0], k[1]),
534+
vec![k[0], k[1]],
535+
vec![],
528536
false,
529537
),
530538
(
@@ -538,10 +546,10 @@ pub mod test {
538546
"andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
539547
k[1],
540548
sha256_hash,
541-
h[2]
549+
k[2]
542550
),
543-
vec![k[1]],
544-
vec![h[2]],
551+
vec![k[1], k[2]],
552+
vec![],
545553
false,
546554
),
547555
(
@@ -585,12 +593,12 @@ pub mod test {
585593
k[4],
586594
k[6],
587595
k[9],
588-
h[8],
589-
h[7],
590-
h[0]
596+
k[1],
597+
k[3],
598+
k[5]
591599
),
592-
vec![k[0], k[2], k[4], k[6], k[9]],
593-
vec![h[8], h[7], h[0]],
600+
vec![k[0], k[2], k[4], k[6], k[9], k[1], k[3], k[5]],
601+
vec![],
594602
false,
595603
),
596604
]

0 commit comments

Comments
 (0)