Skip to content

Commit ba02e75

Browse files
kiminuoapoelstra
authored andcommitted
Fix parser for issue #63
1 parent 7248f32 commit ba02e75

File tree

2 files changed

+75
-15
lines changed

2 files changed

+75
-15
lines changed

src/miniscript/decode.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,20 @@ pub fn parse(tokens: &mut TokenIter) -> Result<Miniscript<bitcoin::PublicKey>, E
224224
// pubkeyhash and [T] VERIFY and [T] 0NOTEQUAL
225225
Tk::Verify => match_token!(
226226
tokens,
227-
Tk::Equal, Tk::Hash20(hash), Tk::Hash160, Tk::Dup
228-
=> term.reduce0(Terminal::PkH(
229-
hash160::Hash::from_inner(hash)
230-
))?,
227+
Tk::Equal => match_token!(
228+
tokens,
229+
Tk::Hash20(hash), Tk::Hash160, Tk::Dup => {
230+
term.reduce0(Terminal::PkH(
231+
hash160::Hash::from_inner(hash)
232+
))?
233+
},
234+
Tk::Hash32(hash), Tk::Sha256, Tk::Verify, Tk::Equal, Tk::Num(32), Tk::Size => {
235+
non_term.push(NonTerm::Verify);
236+
term.reduce0(Terminal::Sha256(
237+
sha256::Hash::from_inner(hash)
238+
))?
239+
},
240+
),
231241
x => {
232242
tokens.un_next(x);
233243
non_term.push(NonTerm::Verify);
@@ -343,16 +353,9 @@ pub fn parse(tokens: &mut TokenIter) -> Result<Miniscript<bitcoin::PublicKey>, E
343353
}
344354
Some(NonTerm::MaybeAndV) => {
345355
// Handle `and_v` prefixing
346-
match tokens.peek() {
347-
None
348-
| Some(&Tk::If)
349-
| Some(&Tk::NotIf)
350-
| Some(&Tk::Else)
351-
| Some(&Tk::ToAltStack) => {}
352-
_ => {
353-
non_term.push(NonTerm::AndV);
354-
non_term.push(NonTerm::Expression);
355-
}
356+
if is_and_v(tokens) {
357+
non_term.push(NonTerm::AndV);
358+
non_term.push(NonTerm::Expression);
356359
}
357360
}
358361
Some(NonTerm::MaybeSwap) => {
@@ -377,7 +380,14 @@ pub fn parse(tokens: &mut TokenIter) -> Result<Miniscript<bitcoin::PublicKey>, E
377380
Some(NonTerm::Verify) => term.reduce1(Terminal::Verify)?,
378381
Some(NonTerm::NonZero) => term.reduce1(Terminal::NonZero)?,
379382
Some(NonTerm::ZeroNotEqual) => term.reduce1(Terminal::ZeroNotEqual)?,
380-
Some(NonTerm::AndV) => term.reduce2(Terminal::AndV)?,
383+
Some(NonTerm::AndV) => {
384+
if is_and_v(tokens) {
385+
non_term.push(NonTerm::AndV);
386+
non_term.push(NonTerm::MaybeAndV);
387+
} else {
388+
term.reduce2(Terminal::AndV)?
389+
}
390+
}
381391
Some(NonTerm::AndB) => term.reduce2(Terminal::AndB)?,
382392
Some(NonTerm::OrB) => term.reduce2(Terminal::OrB)?,
383393
Some(NonTerm::OrC) => term.reduce2(Terminal::OrC)?,
@@ -472,3 +482,10 @@ pub fn parse(tokens: &mut TokenIter) -> Result<Miniscript<bitcoin::PublicKey>, E
472482
assert_eq!(term.0.len(), 1);
473483
Ok(term.pop().unwrap())
474484
}
485+
486+
fn is_and_v(tokens: &mut TokenIter) -> bool {
487+
match tokens.peek() {
488+
None | Some(&Tk::If) | Some(&Tk::NotIf) | Some(&Tk::Else) | Some(&Tk::ToAltStack) => false,
489+
_ => true,
490+
}
491+
}

src/miniscript/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,49 @@ mod tests {
686686
OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff \
687687
OP_PUSHNUM_5 OP_CHECKMULTISIG)",
688688
);
689+
690+
roundtrip(
691+
&ms_str!(
692+
"t:and_v(\
693+
vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),\
694+
v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5)\
695+
)"),
696+
"Script(OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY OP_PUSHNUM_1)"
697+
);
698+
roundtrip(
699+
&ms_str!("and_n(pk(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))"),
700+
"Script(OP_PUSHBYTES_33 03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729 OP_CHECKSIG OP_NOTIF OP_0 OP_ELSE OP_IF OP_0 OP_ELSE OP_PUSHBYTES_3 e2e440 OP_CSV OP_ENDIF OP_TOALTSTACK OP_PUSHNUM_16 OP_CSV OP_FROMALTSTACK OP_BOOLAND OP_ENDIF)"
701+
);
702+
roundtrip(
703+
&ms_str!(
704+
"t:andor(multi(\
705+
3,\
706+
02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,\
707+
03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,\
708+
02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13\
709+
),\
710+
v:older(4194305),\
711+
v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2)\
712+
)"),
713+
"Script(OP_PUSHNUM_3 OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e \
714+
OP_PUSHBYTES_33 03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556 \
715+
OP_PUSHBYTES_33 02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 \
716+
OP_PUSHNUM_3 OP_CHECKMULTISIG OP_NOTIF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 \
717+
OP_PUSHBYTES_32 9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2 OP_EQUALVERIFY \
718+
OP_ELSE OP_PUSHBYTES_3 010040 OP_CSV OP_VERIFY OP_ENDIF OP_PUSHNUM_1)"
719+
);
720+
roundtrip(
721+
&ms_str!(
722+
"t:and_v(\
723+
vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),\
724+
v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5)\
725+
)"),
726+
"Script(\
727+
OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL \
728+
OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY \
729+
OP_PUSHNUM_1\
730+
)"
731+
);
689732
}
690733

691734
#[test]

0 commit comments

Comments
 (0)