Skip to content

Commit b106a06

Browse files
committed
Add parse_insane
1 parent acd8163 commit b106a06

File tree

1 file changed

+40
-21
lines changed

1 file changed

+40
-21
lines changed

src/miniscript/mod.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,16 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
137137
}
138138

139139
impl<Ctx: ScriptContext> Miniscript<bitcoin::PublicKey, Ctx> {
140-
/// Attempt to parse a script into a Miniscript representation
141-
pub fn parse(script: &script::Script) -> Result<Miniscript<bitcoin::PublicKey, Ctx>, Error> {
140+
/// Attempt to parse an insane(scripts don't clear sanity checks)
141+
/// script into a Miniscript representation.
142+
/// Use this to parse scripts with repeated pubkeys, timelock mixing, malleable
143+
/// scripts without sig or scripts that can exceed resource limits.
144+
/// Some of the analysis gurantees of miniscript are lost when dealing with
145+
/// insane scripts. In general, in a multi-party setting users should only
146+
/// accept sane scripts.
147+
pub fn parse_insane(
148+
script: &script::Script,
149+
) -> Result<Miniscript<bitcoin::PublicKey, Ctx>, Error> {
142150
let tokens = lex(script)?;
143151
let mut iter = TokenIter::new(tokens);
144152

@@ -154,6 +162,16 @@ impl<Ctx: ScriptContext> Miniscript<bitcoin::PublicKey, Ctx> {
154162
Ok(top)
155163
}
156164
}
165+
166+
/// Attempt to parse a Script into Miniscript representation.
167+
/// This function will fail parsing for scripts that do not clear
168+
/// the [fn.analyzable.sanity_check] checks. Use [fn.parse_insane] to
169+
/// parse such scripts.
170+
pub fn parse(script: &script::Script) -> Result<Miniscript<bitcoin::PublicKey, Ctx>, Error> {
171+
let ms = Self::parse_insane(script)?;
172+
ms.sanity_check()?;
173+
Ok(ms)
174+
}
157175
}
158176

159177
impl<Pk, Ctx> Miniscript<Pk, Ctx>
@@ -399,7 +417,8 @@ mod tests {
399417
if let Some(expected) = expected_hex.into() {
400418
assert_eq!(format!("{:x}", bitcoin_script), expected);
401419
}
402-
let roundtrip = Segwitv0Script::parse(&bitcoin_script).expect("parse string serialization");
420+
let roundtrip =
421+
Segwitv0Script::parse_insane(&bitcoin_script).expect("parse string serialization");
403422
assert_eq!(roundtrip, script);
404423
}
405424

@@ -408,7 +427,7 @@ mod tests {
408427
let ser = tree.encode(NullCtx);
409428
assert_eq!(ser.len(), tree.script_size(NullCtx));
410429
assert_eq!(ser.to_string(), s);
411-
let deser = Segwitv0Script::parse(&ser).expect("deserialize result of serialize");
430+
let deser = Segwitv0Script::parse_insane(&ser).expect("deserialize result of serialize");
412431
assert_eq!(*tree, deser);
413432
}
414433

@@ -573,19 +592,19 @@ mod tests {
573592
fn verify_parse() {
574593
let ms = "and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
575594
let ms: Segwitv0Script = Miniscript::from_str(ms).unwrap();
576-
assert_eq!(ms, Miniscript::parse(&ms.encode(NullCtx)).unwrap());
595+
assert_eq!(ms, Miniscript::parse_insane(&ms.encode(NullCtx)).unwrap());
577596

578597
let ms = "and_v(v:sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
579598
let ms: Segwitv0Script = Miniscript::from_str(ms).unwrap();
580-
assert_eq!(ms, Miniscript::parse(&ms.encode(NullCtx)).unwrap());
599+
assert_eq!(ms, Miniscript::parse_insane(&ms.encode(NullCtx)).unwrap());
581600

582601
let ms = "and_v(v:ripemd160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
583602
let ms: Segwitv0Script = Miniscript::from_str(ms).unwrap();
584-
assert_eq!(ms, Miniscript::parse(&ms.encode(NullCtx)).unwrap());
603+
assert_eq!(ms, Miniscript::parse_insane(&ms.encode(NullCtx)).unwrap());
585604

586605
let ms = "and_v(v:hash256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))";
587606
let ms: Segwitv0Script = Miniscript::from_str(ms).unwrap();
588-
assert_eq!(ms, Miniscript::parse(&ms.encode(NullCtx)).unwrap());
607+
assert_eq!(ms, Miniscript::parse_insane(&ms.encode(NullCtx)).unwrap());
589608
}
590609

591610
#[test]
@@ -778,21 +797,21 @@ mod tests {
778797
#[test]
779798
fn deserialize() {
780799
// Most of these came from fuzzing, hence the increasing lengths
781-
assert!(Segwitv0Script::parse(&hex_script("")).is_err()); // empty
782-
assert!(Segwitv0Script::parse(&hex_script("00")).is_ok()); // FALSE
783-
assert!(Segwitv0Script::parse(&hex_script("51")).is_ok()); // TRUE
784-
assert!(Segwitv0Script::parse(&hex_script("69")).is_err()); // VERIFY
785-
assert!(Segwitv0Script::parse(&hex_script("0000")).is_err()); //and_v(FALSE,FALSE)
786-
assert!(Segwitv0Script::parse(&hex_script("1001")).is_err()); // incomplete push
787-
assert!(Segwitv0Script::parse(&hex_script("03990300b2")).is_err()); // non-minimal #
788-
assert!(Segwitv0Script::parse(&hex_script("8559b2")).is_err()); // leading bytes
789-
assert!(Segwitv0Script::parse(&hex_script("4c0169b2")).is_err()); // non-minimal push
790-
assert!(Segwitv0Script::parse(&hex_script("0000af0000ae85")).is_err()); // OR not BOOLOR
800+
assert!(Segwitv0Script::parse_insane(&hex_script("")).is_err()); // empty
801+
assert!(Segwitv0Script::parse_insane(&hex_script("00")).is_ok()); // FALSE
802+
assert!(Segwitv0Script::parse_insane(&hex_script("51")).is_ok()); // TRUE
803+
assert!(Segwitv0Script::parse_insane(&hex_script("69")).is_err()); // VERIFY
804+
assert!(Segwitv0Script::parse_insane(&hex_script("0000")).is_err()); //and_v(FALSE,FALSE)
805+
assert!(Segwitv0Script::parse_insane(&hex_script("1001")).is_err()); // incomplete push
806+
assert!(Segwitv0Script::parse_insane(&hex_script("03990300b2")).is_err()); // non-minimal #
807+
assert!(Segwitv0Script::parse_insane(&hex_script("8559b2")).is_err()); // leading bytes
808+
assert!(Segwitv0Script::parse_insane(&hex_script("4c0169b2")).is_err()); // non-minimal push
809+
assert!(Segwitv0Script::parse_insane(&hex_script("0000af0000ae85")).is_err()); // OR not BOOLOR
791810

792811
// misc fuzzer problems
793-
assert!(Segwitv0Script::parse(&hex_script("0000000000af")).is_err());
794-
assert!(Segwitv0Script::parse(&hex_script("04009a2970af00")).is_err()); // giant CMS key num
795-
assert!(Segwitv0Script::parse(&hex_script(
812+
assert!(Segwitv0Script::parse_insane(&hex_script("0000000000af")).is_err());
813+
assert!(Segwitv0Script::parse_insane(&hex_script("04009a2970af00")).is_err()); // giant CMS key num
814+
assert!(Segwitv0Script::parse_insane(&hex_script(
796815
"2102ffffffffffffffefefefefefefefefefefef394c0fe5b711179e124008584753ac6900"
797816
))
798817
.is_err());

0 commit comments

Comments
 (0)