diff --git a/examples/htlc.rs b/examples/htlc.rs index 7e7425808..7b69e2692 100644 --- a/examples/htlc.rs +++ b/examples/htlc.rs @@ -35,7 +35,7 @@ fn main() { assert_eq!( format!("{}", htlc_descriptor), - "wsh(andor(pk(022222222222222222222222222222222222222222222222222222222222222222),sha256(1111111111111111111111111111111111111111111111111111111111111111),and_v(vc:pk_h(4377a5acd66dc5cb67148a24818d1e51fa183bd2),older(4444))))" + "wsh(andor(pk(022222222222222222222222222222222222222222222222222222222222222222),sha256(1111111111111111111111111111111111111111111111111111111111111111),and_v(v:pkh(4377a5acd66dc5cb67148a24818d1e51fa183bd2),older(4444))))" ); assert_eq!( diff --git a/fuzz/fuzz_targets/compile_descriptor.rs b/fuzz/fuzz_targets/compile_descriptor.rs index 140e230ec..a65e47a22 100644 --- a/fuzz/fuzz_targets/compile_descriptor.rs +++ b/fuzz/fuzz_targets/compile_descriptor.rs @@ -19,7 +19,7 @@ fn do_test(data: &[u8]) { let output = desc.to_string(); if let Ok(desc) = DummyScript::from_str(&output) { let rtt = desc.to_string(); - assert_eq!(output, rtt); + assert_eq!(output.to_lowercase(), rtt.to_lowercase()); } else { panic!("compiler output something unparseable: {}", output) } diff --git a/fuzz/fuzz_targets/roundtrip_concrete.rs b/fuzz/fuzz_targets/roundtrip_concrete.rs index d5805b236..a966b43a0 100644 --- a/fuzz/fuzz_targets/roundtrip_concrete.rs +++ b/fuzz/fuzz_targets/roundtrip_concrete.rs @@ -15,7 +15,7 @@ fn do_test(data: &[u8]) { let re = Regex::new("(\\D)1@").unwrap(); let output = re.replace_all(&output, "$1"); let data_str = re.replace_all(&data_str, "$1"); - assert_eq!(data_str, output); + assert_eq!(data_str.to_lowercase(), output.to_lowercase()); } } diff --git a/fuzz/fuzz_targets/roundtrip_descriptor.rs b/fuzz/fuzz_targets/roundtrip_descriptor.rs index 7f462938d..6294cc3cb 100644 --- a/fuzz/fuzz_targets/roundtrip_descriptor.rs +++ b/fuzz/fuzz_targets/roundtrip_descriptor.rs @@ -18,7 +18,7 @@ fn do_test(data: &[u8]) { let normalize_aliases = multi_wrap_pkh_re.replace_all(&normalize_aliases, "$1:pkh("); let normalize_aliases = normalize_aliases.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh("); - assert_eq!(normalize_aliases, output); + assert_eq!(normalize_aliases.to_lowercase(), output.to_lowercase()); } } diff --git a/fuzz/fuzz_targets/roundtrip_miniscript_str.rs b/fuzz/fuzz_targets/roundtrip_miniscript_str.rs index df4650ab8..23083d947 100644 --- a/fuzz/fuzz_targets/roundtrip_miniscript_str.rs +++ b/fuzz/fuzz_targets/roundtrip_miniscript_str.rs @@ -20,7 +20,7 @@ fn do_test(data: &[u8]) { let normalize_aliases = multi_wrap_pkh_re.replace_all(&normalize_aliases, "$1:pkh("); let normalize_aliases = normalize_aliases.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh("); - assert_eq!(normalize_aliases, output); + assert_eq!(normalize_aliases.to_lowercase(), output.to_lowercase()); } } diff --git a/fuzz/fuzz_targets/roundtrip_semantic.rs b/fuzz/fuzz_targets/roundtrip_semantic.rs index 75b1dac2f..eb97e55a7 100644 --- a/fuzz/fuzz_targets/roundtrip_semantic.rs +++ b/fuzz/fuzz_targets/roundtrip_semantic.rs @@ -10,7 +10,7 @@ fn do_test(data: &[u8]) { let data_str = String::from_utf8_lossy(data); if let Ok(pol) = DummyPolicy::from_str(&data_str) { let output = pol.to_string(); - assert_eq!(data_str, output); + assert_eq!(data_str.to_lowercase(), output.to_lowercase()); } } diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index 32b8c1aed..4bb7972fe 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -565,7 +565,7 @@ mod tests { fn roundtrip_descriptor(s: &str) { let desc = Descriptor::::from_str(&s).unwrap(); let output = desc.to_string(); - let normalize_aliases = s.replace("c:pk_k(", "pk("); + let normalize_aliases = s.replace("c:pk_k(", "pk(").replace("c:pk_h(", "pkh("); assert_eq!(normalize_aliases, output); } @@ -574,6 +574,7 @@ mod tests { roundtrip_descriptor("c:pk_k()"); roundtrip_descriptor("wsh(pk())"); roundtrip_descriptor("wsh(c:pk_k())"); + roundtrip_descriptor("c:pk_h()"); } #[test] fn parse_descriptor() { diff --git a/src/miniscript/astelem.rs b/src/miniscript/astelem.rs index 90ed3e6c1..b442a0874 100644 --- a/src/miniscript/astelem.rs +++ b/src/miniscript/astelem.rs @@ -301,6 +301,9 @@ impl fmt::Display for Terminal { if let Terminal::PkK(ref pk) = sub.node { // alias: pk(K) = c:pk_k(K) return write!(f, "pk({})", pk); + } else if let Terminal::PkH(ref pkh) = sub.node { + // alias: pkh(K) = c:pk_h(K) + return write!(f, "pkh({})", pkh); } } @@ -314,6 +317,8 @@ impl fmt::Display for Terminal { Some(('c', ms)) => { if let Terminal::PkK(ref _pk) = ms.node { fmt::Write::write_char(f, ':')?; + } else if let Terminal::PkH(ref _pkh) = ms.node { + fmt::Write::write_char(f, ':')?; } } _ => {} @@ -345,7 +350,7 @@ where <::Hash as str::FromStr>::Err: ToString, { fn from_tree(top: &expression::Tree) -> Result, Error> { - let aliased_wrap; + let mut aliased_wrap; let frag_name; let frag_wrap; let mut name_split = top.name.split(':'); @@ -358,6 +363,9 @@ where if name == "pk" { frag_name = "pk_k"; frag_wrap = "c"; + } else if name == "pkh" { + frag_name = "pk_h"; + frag_wrap = "c"; } else { frag_name = name; frag_wrap = ""; @@ -369,7 +377,13 @@ where } if name == "pk" { frag_name = "pk_k"; - aliased_wrap = wrap.to_owned() + &"c"; + aliased_wrap = wrap.to_owned(); + aliased_wrap.push_str("c"); + frag_wrap = &aliased_wrap; + } else if name == "pkh" { + frag_name = "pk_h"; + aliased_wrap = wrap.to_owned(); + aliased_wrap.push_str("c"); frag_wrap = &aliased_wrap; } else { frag_name = name; diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index 36e17efad..a061cfdbc 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -526,11 +526,7 @@ mod tests { ty: Type::cast_check(Type::from_pk_h()).unwrap(), ext: ExtData::cast_check(ExtData::from_pk_h()).unwrap(), }; - string_rtt( - pkh_ms, - "[B/nduesm]c:[K/nduesm]pk_h(DummyKeyHash)", - "c:pk_h()", - ); + string_rtt(pkh_ms, "[B/nduesm]c:[K/nduesm]pk_h(DummyKeyHash)", "pkh()"); let pkk_ms: Miniscript = Miniscript { node: Terminal::Check(Arc::new(Miniscript { @@ -605,6 +601,32 @@ mod tests { "[B/onufsm]t[V/onfsm]v[B/onduesm]c:[K/onduesm]pk_k(PublicKey { compressed: true, key: PublicKey(aa4c32e50fb34a95a372940ae3654b692ea35294748c3dd2c08b29f87ba9288c8294efcb73dc719e45b91c45f084e77aebc07c1ff3ed8f37935130a36304a340) })", "tv:pk(028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa)" ); + + let pubkey_hash = + hash160::Hash::from_str("f54a5851e9372b87810a8e60cdd2e7cfd80b6e31").unwrap(); + let script: Miniscript = ms_str!("c:pk_h({})", pubkey_hash.to_string()); + + string_rtt( + script, + "[B/nduesm]c:[K/nduesm]pk_h(f54a5851e9372b87810a8e60cdd2e7cfd80b6e31)", + "pkh(f54a5851e9372b87810a8e60cdd2e7cfd80b6e31)", + ); + + let script: Miniscript = ms_str!("pkh({})", pubkey_hash.to_string()); + + string_rtt( + script, + "[B/nduesm]c:[K/nduesm]pk_h(f54a5851e9372b87810a8e60cdd2e7cfd80b6e31)", + "pkh(f54a5851e9372b87810a8e60cdd2e7cfd80b6e31)", + ); + + let script: Miniscript = ms_str!("tv:pkh({})", pubkey_hash.to_string()); + + string_rtt( + script, + "[B/nufsm]t[V/nfsm]v[B/nduesm]c:[K/nduesm]pk_h(f54a5851e9372b87810a8e60cdd2e7cfd80b6e31)", + "tv:pkh(f54a5851e9372b87810a8e60cdd2e7cfd80b6e31)", + ); } #[test] diff --git a/src/policy/mod.rs b/src/policy/mod.rs index e9e93160e..3332ab93f 100644 --- a/src/policy/mod.rs +++ b/src/policy/mod.rs @@ -155,13 +155,13 @@ mod tests { fn concrete_policy_rtt(s: &str) { let conc = ConcretePol::from_str(s).unwrap(); let output = conc.to_string(); - assert_eq!(s, output); + assert_eq!(s.to_lowercase(), output.to_lowercase()); } fn semantic_policy_rtt(s: &str) { let sem = SemanticPol::from_str(s).unwrap(); let output = sem.to_string(); - assert_eq!(s, output); + assert_eq!(s.to_lowercase(), output.to_lowercase()); } #[test] @@ -177,6 +177,7 @@ mod tests { //fuzzer crashes assert!(ConcretePol::from_str("thresh()").is_err()); assert!(SemanticPol::from_str("thresh()").is_err()); + concrete_policy_rtt("ripemd160(aaaaaaaaaaaaaaaaaaaaaa0Daaaaaaaaaabaaaaa)"); } #[test]