From d5d3ea51f96684a148e7522b9a4ab6fabe7472aa Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Sun, 20 Sep 2026 15:35:07 +0300 Subject: [PATCH 1/2] use Bitcoin hash and hex APIs --- fuzz/fuzz_targets/compile_descriptor.rs | 2 +- fuzz/fuzz_targets/parse_descriptor.rs | 2 +- fuzz/fuzz_targets/parse_descriptor_secret.rs | 2 +- fuzz/fuzz_targets/roundtrip_concrete.rs | 2 +- fuzz/fuzz_targets/roundtrip_confidential.rs | 2 +- fuzz/fuzz_targets/roundtrip_descriptor.rs | 2 +- fuzz/fuzz_targets/roundtrip_miniscript_script.rs | 2 +- fuzz/fuzz_targets/roundtrip_miniscript_str.rs | 2 +- fuzz/fuzz_targets/roundtrip_semantic.rs | 2 +- src/descriptor/csfs_cov/satisfy.rs | 2 +- src/descriptor/key.rs | 4 ++-- src/descriptor/pegin/dynafed_pegin.rs | 2 +- src/extensions/csfs.rs | 10 +++++----- src/extensions/mod.rs | 4 ++-- src/extensions/outputs_pref.rs | 6 +++--- src/extensions/param.rs | 6 +++--- src/interpreter/error.rs | 8 ++++---- src/interpreter/stack.rs | 2 +- src/lib.rs | 8 ++++---- src/miniscript/decode.rs | 2 +- src/miniscript/iter.rs | 2 +- src/miniscript/mod.rs | 4 ++-- src/miniscript/satisfy.rs | 3 +-- src/policy/compiler.rs | 4 ++-- 24 files changed, 42 insertions(+), 43 deletions(-) diff --git a/fuzz/fuzz_targets/compile_descriptor.rs b/fuzz/fuzz_targets/compile_descriptor.rs index 0b34281c..7db41bee 100644 --- a/fuzz/fuzz_targets/compile_descriptor.rs +++ b/fuzz/fuzz_targets/compile_descriptor.rs @@ -37,7 +37,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/parse_descriptor.rs b/fuzz/fuzz_targets/parse_descriptor.rs index c9bf3c24..f99642fc 100644 --- a/fuzz/fuzz_targets/parse_descriptor.rs +++ b/fuzz/fuzz_targets/parse_descriptor.rs @@ -22,7 +22,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/parse_descriptor_secret.rs b/fuzz/fuzz_targets/parse_descriptor_secret.rs index d9cc9714..1a6121d7 100644 --- a/fuzz/fuzz_targets/parse_descriptor_secret.rs +++ b/fuzz/fuzz_targets/parse_descriptor_secret.rs @@ -22,7 +22,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/roundtrip_concrete.rs b/fuzz/fuzz_targets/roundtrip_concrete.rs index 70cfd43e..793b13f5 100644 --- a/fuzz/fuzz_targets/roundtrip_concrete.rs +++ b/fuzz/fuzz_targets/roundtrip_concrete.rs @@ -29,7 +29,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/roundtrip_confidential.rs b/fuzz/fuzz_targets/roundtrip_confidential.rs index 58fc5057..f179711c 100644 --- a/fuzz/fuzz_targets/roundtrip_confidential.rs +++ b/fuzz/fuzz_targets/roundtrip_confidential.rs @@ -28,7 +28,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/roundtrip_descriptor.rs b/fuzz/fuzz_targets/roundtrip_descriptor.rs index b9182860..d58539f9 100644 --- a/fuzz/fuzz_targets/roundtrip_descriptor.rs +++ b/fuzz/fuzz_targets/roundtrip_descriptor.rs @@ -28,7 +28,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/roundtrip_miniscript_script.rs b/fuzz/fuzz_targets/roundtrip_miniscript_script.rs index 051257c7..d0b3f882 100644 --- a/fuzz/fuzz_targets/roundtrip_miniscript_script.rs +++ b/fuzz/fuzz_targets/roundtrip_miniscript_script.rs @@ -25,7 +25,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/roundtrip_miniscript_str.rs b/fuzz/fuzz_targets/roundtrip_miniscript_str.rs index 372320ce..e4704edf 100644 --- a/fuzz/fuzz_targets/roundtrip_miniscript_str.rs +++ b/fuzz/fuzz_targets/roundtrip_miniscript_str.rs @@ -24,7 +24,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/fuzz/fuzz_targets/roundtrip_semantic.rs b/fuzz/fuzz_targets/roundtrip_semantic.rs index 7cda5cad..4787377e 100644 --- a/fuzz/fuzz_targets/roundtrip_semantic.rs +++ b/fuzz/fuzz_targets/roundtrip_semantic.rs @@ -24,7 +24,7 @@ fn main() { #[cfg(test)] mod tests { - use miniscript::elements::hex::FromHex; + use miniscript::bitcoin::hex::FromHex; #[test] fn duplicate_crash() { diff --git a/src/descriptor/csfs_cov/satisfy.rs b/src/descriptor/csfs_cov/satisfy.rs index d65077ef..f356dfda 100644 --- a/src/descriptor/csfs_cov/satisfy.rs +++ b/src/descriptor/csfs_cov/satisfy.rs @@ -14,8 +14,8 @@ // //! Covenant Descriptor Satisfaction +use bitcoin::hashes::{sha256d, Hash}; use elements::encode::Encodable; -use elements::hashes::{sha256d, Hash}; use elements::sighash::SighashCache; use elements::{self, confidential, EcdsaSighashType, OutPoint, Script, Sighash, Transaction}; diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index e2700033..7e457ced 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -5,9 +5,9 @@ use std::str::FromStr; use std::{error, fmt, hash}; use bitcoin::bip32::XKeyIdentifier; +use bitcoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine}; +use bitcoin::hex::FromHex; use bitcoin::{self, bip32}; -use elements::hashes::{hash160, ripemd160, sha256, Hash, HashEngine}; -use elements::hex::FromHex; use elements::secp256k1_zkp::{Secp256k1, Signing, Verification}; #[cfg(feature = "serde")] diff --git a/src/descriptor/pegin/dynafed_pegin.rs b/src/descriptor/pegin/dynafed_pegin.rs index 22d57fc0..233d5311 100644 --- a/src/descriptor/pegin/dynafed_pegin.rs +++ b/src/descriptor/pegin/dynafed_pegin.rs @@ -330,8 +330,8 @@ where #[cfg(test)] mod tests { + use bitcoin::hex::FromHex; use bitcoin::PublicKey; - use elements::hex::FromHex; use crate::descriptor::pegin::Pegin; use crate::{BtcDescriptor, ConfidentialDescriptor, DescriptorPublicKey}; diff --git a/src/extensions/csfs.rs b/src/extensions/csfs.rs index db8cca12..f11e3afe 100644 --- a/src/extensions/csfs.rs +++ b/src/extensions/csfs.rs @@ -4,8 +4,8 @@ use std::fmt; use std::str::FromStr; +use bitcoin::hex::{DisplayHex, FromHex}; use bitcoin::key::XOnlyPublicKey; -use elements::hex::{self, FromHex, ToHex}; use elements::{self, opcodes, secp256k1_zkp}; use super::param::{ExtParamTranslator, TranslateExtParam}; @@ -181,7 +181,7 @@ impl CsfsMsg { impl fmt::Display for CsfsMsg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.to_hex()) + write!(f, "{}", self.0.as_hex()) } } @@ -194,9 +194,9 @@ impl ArgFromStr for CsfsMsg { } let inner = Vec::::from_hex(s).map_err(|e| Error::Unexpected(e.to_string()))?; let inner_len = inner.len(); - let x = Self::new(inner) - .ok_or(hex::Error::InvalidLength(32, inner_len)) - .map_err(|e| Error::Unexpected(e.to_string()))?; + let x = Self::new(inner).ok_or_else(|| { + Error::Unexpected(format!("Expected 32-byte message, got {} bytes", inner_len)) + })?; Ok(x) } } diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 2bdd4c4a..966ca785 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -422,7 +422,7 @@ pub fn check_sig_price_oracle_1( let mut buf = Vec::with_capacity(16); buf.extend(×tamp.to_le_bytes()); buf.extend(&price.to_le_bytes()); - let sha_msg = elements::hashes::sha256::Hash::hash(&buf); + let sha_msg = bitcoin::hashes::sha256::Hash::hash(&buf); let msg = elements::secp256k1_zkp::Message::from_digest_slice(&sha_msg[..]).unwrap(); secp.verify_schnorr(sig, &msg, pk).is_ok() @@ -434,7 +434,7 @@ pub fn sighash_msg_price_oracle_1(timestamp: u64, price: u64) -> secp256k1_zkp:: let mut buf = Vec::with_capacity(16); buf.extend(×tamp.to_le_bytes()); buf.extend(&price.to_le_bytes()); - let sha_msg = elements::hashes::sha256::Hash::hash(&buf); + let sha_msg = bitcoin::hashes::sha256::Hash::hash(&buf); elements::secp256k1_zkp::Message::from_digest_slice(&sha_msg[..]).unwrap() } diff --git a/src/extensions/outputs_pref.rs b/src/extensions/outputs_pref.rs index 344ece30..8bc19d4d 100644 --- a/src/extensions/outputs_pref.rs +++ b/src/extensions/outputs_pref.rs @@ -4,9 +4,9 @@ use std::fmt; +use bitcoin::hashes::{sha256d, Hash}; +use bitcoin::hex::{DisplayHex, FromHex}; use elements::encode::serialize; -use elements::hashes::{sha256d, Hash}; -use elements::hex::{FromHex, ToHex}; use super::{FromTokenIterError, ParseableExt, TxEnv}; use crate::descriptor::CovError; @@ -41,7 +41,7 @@ pub struct LegacyOutputsPref { impl fmt::Display for LegacyOutputsPref { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "outputs_pref({})", self.pref.to_hex()) + write!(f, "outputs_pref({})", self.pref.as_hex()) } } diff --git a/src/extensions/param.rs b/src/extensions/param.rs index b2ebe512..8e0c0de1 100644 --- a/src/extensions/param.rs +++ b/src/extensions/param.rs @@ -2,9 +2,9 @@ use std::{fmt, hash}; +use bitcoin::hex::DisplayHex; use elements::confidential; use elements::encode::serialize; -use elements::hex::ToHex; use super::csfs::{CsfsKey, CsfsMsg}; use super::introspect_ops::Spk; @@ -149,8 +149,8 @@ impl fmt::Display for CovExtArgs { match self { CovExtArgs::XOnlyKey(x) => write!(f, "{}", x), CovExtArgs::CsfsMsg(m) => write!(f, "{}", m), - CovExtArgs::Asset(a) => write!(f, "{}", serialize(a).to_hex()), - CovExtArgs::Value(v) => write!(f, "{}", serialize(v).to_hex()), + CovExtArgs::Asset(a) => write!(f, "{}", serialize(a).as_hex()), + CovExtArgs::Value(v) => write!(f, "{}", serialize(v).as_hex()), CovExtArgs::Script(s) => write!(f, "{}", s), } } diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs index 636ab593..067d8fa6 100644 --- a/src/interpreter/error.rs +++ b/src/interpreter/error.rs @@ -3,8 +3,8 @@ use std::{error, fmt}; -use elements::hashes::hash160; -use elements::hex::ToHex; +use bitcoin::hashes::hash160; +use bitcoin::hex::DisplayHex; use elements::{secp256k1_zkp, taproot}; use {bitcoin, elements}; @@ -157,14 +157,14 @@ impl fmt::Display for Error { Error::InvalidSchnorrSighashType(ref sig) => write!( f, "Invalid sighash type for schnorr signature '{}'", - sig.to_hex() + sig.as_hex() ), Error::InvalidEcdsaSignature(pk) => write!(f, "bad ecdsa signature with pk {}", pk), Error::InvalidSchnorrSignature(pk) => write!(f, "bad schnorr signature with pk {}", pk), Error::NonStandardSighash(ref sig) => write!( f, "Non standard sighash type for signature '{}'", - sig.to_hex() + sig.as_hex() ), Error::NonEmptyWitness => f.write_str("legacy spend had nonempty witness"), Error::NonEmptyScriptSig => f.write_str("segwit spend had nonempty scriptsig"), diff --git a/src/interpreter/stack.rs b/src/interpreter/stack.rs index 5238d4c4..93fe9b61 100644 --- a/src/interpreter/stack.rs +++ b/src/interpreter/stack.rs @@ -5,7 +5,7 @@ use std::ops::Index; -use elements::hashes::{hash160, ripemd160, sha256, Hash}; +use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; use elements::{self, opcodes, script, LockTime, Sequence}; use super::error::PkEvalErrInner; diff --git a/src/lib.rs b/src/lib.rs index 8ed37443..489f6495 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -142,7 +142,7 @@ mod util; use std::{cmp, error, fmt, str}; -use elements::hashes::sha256; +use bitcoin::hashes::sha256; use elements::secp256k1_zkp::Secp256k1; use elements::{locktime, opcodes, script, secp256k1_zkp}; @@ -160,9 +160,9 @@ pub use crate::miniscript::satisfy::{ pub use crate::miniscript::Miniscript; // minimal implementation of contract hash module mod contracthash { + use bitcoin::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine}; use bitcoin::secp256k1::Scalar; use bitcoin::PublicKey; - use elements::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine}; use elements::secp256k1_zkp::{self, Secp256k1}; /// Tweak a single key using some arbitrary data @@ -477,7 +477,7 @@ impl fmt::Display for Error { Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok), Error::InvalidPush(ref push) => { write!(f, "invalid push ")?; - elements::hex::format_hex(push, f) + fmt::LowerHex::fmt(&bitcoin::hex::DisplayHex::as_hex(push), f) }, Error::Script(ref e) => fmt::Display::fmt(e, f), Error::AddrError(ref e) => fmt::Display::fmt(e, f), @@ -711,7 +711,7 @@ impl fmt::Display for AbsLockTime { /// Helper function used by tests #[cfg(test)] fn hex_script(s: &str) -> elements::Script { - let v: Vec = elements::hex::FromHex::from_hex(s).unwrap(); + let v: Vec = bitcoin::hex::FromHex::from_hex(s).unwrap(); elements::Script::from(v) } diff --git a/src/miniscript/decode.rs b/src/miniscript/decode.rs index ea2a5052..564cab1c 100644 --- a/src/miniscript/decode.rs +++ b/src/miniscript/decode.rs @@ -10,7 +10,7 @@ use std::marker::PhantomData; use std::sync::Arc; use std::{error, fmt}; -use elements::hashes::{hash160, ripemd160, sha256, Hash}; +use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; use crate::elements::Sequence; use crate::extensions::ParseableExt; diff --git a/src/miniscript/iter.rs b/src/miniscript/iter.rs index 18e4cc15..1f4fc6c3 100644 --- a/src/miniscript/iter.rs +++ b/src/miniscript/iter.rs @@ -219,7 +219,7 @@ impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext, Ext: Extension> Iterator #[cfg(test)] pub mod test { use bitcoin; - use elements::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; + use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; use elements::secp256k1_zkp; use super::Miniscript; diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index 9e783bc4..f5fd378d 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -202,7 +202,7 @@ where /// use elements_miniscript::bitcoin::secp256k1::XOnlyPublicKey; /// type Segwitv0Script = Miniscript; /// type TapScript = Miniscript; - /// use elements::hex::FromHex; + /// use bitcoin::hex::FromHex; /// /// // parse x-only miniscript in Taproot context /// let tapscript_ms = TapScript::parse(&elements::Script::from(Vec::::from_hex( @@ -534,9 +534,9 @@ mod tests { use std::str::FromStr; use std::sync::Arc; + use bitcoin::hashes::{hash160, sha256, Hash}; use bitcoin::key::XOnlyPublicKey; use bitcoin::{self}; - use elements::hashes::{hash160, sha256, Hash}; use elements::taproot::TapLeafHash; use elements::{self, secp256k1_zkp, Sequence}; diff --git a/src/miniscript/satisfy.rs b/src/miniscript/satisfy.rs index 903bb684..7c011506 100644 --- a/src/miniscript/satisfy.rs +++ b/src/miniscript/satisfy.rs @@ -11,9 +11,8 @@ use std::collections::{BTreeMap, HashMap}; use std::sync::Arc; use std::{cmp, mem}; -use bitcoin::hashes::hash160; +use bitcoin::hashes::{hash160, sha256d}; use bitcoin::secp256k1::XOnlyPublicKey; -use elements::hashes::sha256d; use elements::secp256k1_zkp::schnorr; use elements::taproot::{ControlBlock, LeafVersion, TapLeafHash}; use elements::{self, confidential, secp256k1_zkp, LockTime, OutPoint, Script, Sequence}; diff --git a/src/policy/compiler.rs b/src/policy/compiler.rs index 0704d823..1683ba6b 100644 --- a/src/policy/compiler.rs +++ b/src/policy/compiler.rs @@ -1369,7 +1369,7 @@ mod tests { use std::string::String; use bitcoin; - use elements::{self, hashes, opcodes, script, secp256k1_zkp, Sequence}; + use elements::{self, opcodes, script, secp256k1_zkp, Sequence}; use super::*; use crate::miniscript::{Legacy, Segwitv0, Tap}; @@ -1576,7 +1576,7 @@ mod tests { let no_sat = HashMap::::new(); let mut left_sat = HashMap::::new(); let mut right_sat = - HashMap::::new(); + HashMap::::new(); for key in keys.iter().take(5) { left_sat.insert(*key, elements_sig); From 88a57abac95e46c94045b3e62105c9fa1dab2276 Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Sun, 20 Sep 2026 15:35:26 +0300 Subject: [PATCH 2/2] prepare 0.5.0 with Elements 0.27 and Simplicity 0.9 --- .github/workflows/fuzz.yml | 2 +- CHANGELOG.md | 8 +- Cargo-latest.lock | 130 +++++++++++++++--------- Cargo.toml | 8 +- README.md | 4 +- bitcoind-tests/tests/setup/mod.rs | 2 +- bitcoind-tests/tests/setup/test_util.rs | 31 ++---- bitcoind-tests/tests/test_arith.rs | 8 +- bitcoind-tests/tests/test_cpp.rs | 19 ++-- bitcoind-tests/tests/test_csfs.rs | 8 +- bitcoind-tests/tests/test_desc.rs | 20 ++-- bitcoind-tests/tests/test_introspect.rs | 8 +- clippy.toml | 2 +- examples/psbt_sign_finalize.rs | 5 +- examples/verify_tx.rs | 16 +-- fuzz/generate-files.sh | 5 +- src/confidential/slip77.rs | 18 ++-- src/descriptor/csfs_cov/cov.rs | 10 +- src/descriptor/csfs_cov/mod.rs | 34 +++---- src/descriptor/mod.rs | 14 +-- src/descriptor/tr.rs | 61 ++++++++++- src/extensions/introspect_ops.rs | 13 +-- src/extensions/mod.rs | 6 +- src/interpreter/inner.rs | 40 +++++--- src/interpreter/mod.rs | 11 +- src/policy/compiler.rs | 4 +- src/psbt/finalizer.rs | 9 +- src/psbt/mod.rs | 33 ++++-- src/simplicity.rs | 37 +------ 29 files changed, 327 insertions(+), 239 deletions(-) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 39a1cf3c..0f0ac0b1 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -40,7 +40,7 @@ roundtrip_confidential, key: cache-${{ matrix.target }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} - uses: actions-rs/toolchain@v1 with: - toolchain: 1.65 + toolchain: 1.74.0 override: true profile: minimal - name: fuzz diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f30d1b6..51ca41d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.5.0 - Sep 20, 2026 + +- Update rust-elements to 0.27.0 and simplicity-lang to 0.9.0. +- Raise MSRV to Rust 1.74.0. +- Adapt hash, hex, witness, asset and PSET handling to the updated Elements APIs. +- Report Simplicity leaves as unsatisfiable until their descriptor integration is rewritten. + # 0.4.0 - Oct 8, 2024 - Use rust-bitcoin 0.32.0 and rust-elements 0.25.0 [#90](https://github.com/ElementsProject/elements-miniscript/pull/90) @@ -22,4 +29,3 @@ # 0.2.0 - June 15, 2023 - Still rapid iteration, very unstable. - diff --git a/Cargo-latest.lock b/Cargo-latest.lock index e64fbe7a..c78d9bc8 100644 --- a/Cargo-latest.lock +++ b/Cargo-latest.lock @@ -25,12 +25,11 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "base58ck" -version = "0.1.0" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +checksum = "365c0acd5b2e8dd0111a46c4faea83fb3cfb6e39a49a7c73a06e090db7b2eff0" dependencies = [ - "bitcoin-internals 0.3.0", - "bitcoin_hashes 0.14.0", + "bitcoin_hashes 0.14.101", ] [[package]] @@ -74,46 +73,57 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.32.7" +version = "0.32.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda569d741b895131a88ee5589a467e73e9c4718e958ac9308e4f7dc44b6945" +checksum = "bb0ce8bd5baaa0d303a19915a6d93afed161f528654e42da2a7a97d05c59499a" dependencies = [ "base58ck", "base64 0.21.7", "bech32 0.11.0", - "bitcoin-internals 0.3.0", + "bitcoin-consensus-encoding", "bitcoin-io", "bitcoin-units", - "bitcoin_hashes 0.14.0", - "hex-conservative 0.2.1", + "bitcoin_hashes 0.14.101", + "hex-conservative 0.2.2", "hex_lit", "secp256k1 0.29.1", "serde", ] [[package]] -name = "bitcoin-internals" -version = "0.2.0" +name = "bitcoin-consensus-encoding" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +checksum = "6712f9c6fd6785b3b270884e57c441c403dc5d7e19ca45368c97c7a1de3000ec" dependencies = [ + "bitcoin-internals 0.6.0", + "hex-conservative 1.2.0", "serde", ] [[package]] name = "bitcoin-internals" -version = "0.3.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" dependencies = [ "serde", ] +[[package]] +name = "bitcoin-internals" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d573f4cf32996a8dce612e4348cece65a241f1882ed594047c9ba348e8869fa5" + [[package]] name = "bitcoin-io" -version = "0.1.3" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" +checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78" +dependencies = [ + "bitcoin-consensus-encoding", +] [[package]] name = "bitcoin-private" @@ -123,11 +133,11 @@ checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" [[package]] name = "bitcoin-units" -version = "0.1.2" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +checksum = "9cb95693f371d089a4b5b6fc41c6f3ea6e01ee8c15388335dfac8ea685173b51" dependencies = [ - "bitcoin-internals 0.3.0", + "bitcoin-consensus-encoding", "serde", ] @@ -144,12 +154,24 @@ dependencies = [ [[package]] name = "bitcoin_hashes" -version = "0.14.0" +version = "0.14.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "bitcoin-io", - "hex-conservative 0.2.1", + "hex-conservative 0.2.2", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5304e53726dbe5f93141535e102ed97b5bf4714fbecefdda8f9fb98d7fdaff0e" +dependencies = [ + "bitcoin-consensus-encoding", + "bitcoin-internals 0.6.0", + "hex-conservative 1.2.0", "serde", ] @@ -256,12 +278,16 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elements" -version = "0.25.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b2569d3495bfdfce36c504fd4d78752ff4a7699f8a33e6f3ee523bddf9f6ad" +checksum = "34e00f7ddcd826d2f4c9bd72d79a6b6991a0ac4286e7e2b2ff8eecd130549073" dependencies = [ "bech32 0.11.0", - "bitcoin 0.32.7", + "bitcoin 0.32.102", + "bitcoin-consensus-encoding", + "bitcoin-internals 0.6.0", + "bitcoin_hashes 1.2.0", + "hex-conservative 1.2.0", "secp256k1-zkp", "serde", "serde_json", @@ -269,10 +295,10 @@ dependencies = [ [[package]] name = "elements-miniscript" -version = "0.4.0" +version = "0.5.0" dependencies = [ "base64 0.13.1", - "bitcoin 0.32.7", + "bitcoin 0.32.102", "elements", "getrandom", "miniscript", @@ -316,6 +342,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ghost-cell" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8449d342b1c67f49169e92e71deb7b9b27f30062301a16dbc27a4cc8d2351b7" + [[package]] name = "hex-conservative" version = "0.1.2" @@ -324,9 +356,18 @@ checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" [[package]] name = "hex-conservative" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35431185f361ccf3ffc58254628af5f1f5d5f28531da2e02e5d6c82bbc282a10" dependencies = [ "arrayvec", ] @@ -431,7 +472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" dependencies = [ "bech32 0.11.0", - "bitcoin 0.32.7", + "bitcoin 0.32.102", ] [[package]] @@ -560,15 +601,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "santiago" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de36022292bc2086eb8f55bffa460fef3475e4459b478820711f4c421feb87ec" -dependencies = [ - "regex", -] - [[package]] name = "secp256k1" version = "0.28.2" @@ -587,7 +619,7 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "bitcoin_hashes 0.14.0", + "bitcoin_hashes 0.14.101", "rand", "secp256k1-sys 0.10.1", "serde", @@ -689,28 +721,28 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simplicity-lang" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75c8fb4a18e63fbce4cf16026c36a6c38066e4f4a09ce5e81be817d0e36d8f8" +checksum = "cff7b10251528d46d9cf60238267911984fedbb0948cccea98dd74fc6bf9f729" dependencies = [ - "bitcoin 0.32.7", - "bitcoin_hashes 0.14.0", + "bitcoin 0.32.102", + "bitcoin_hashes 1.2.0", "byteorder", "elements", "getrandom", - "hex-conservative 0.1.2", + "ghost-cell", + "hex-conservative 1.2.0", "miniscript", - "santiago", "simplicity-sys", ] [[package]] name = "simplicity-sys" -version = "0.3.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd2cc5d458a8032d328ea85e824f54f61664ab84c3d42b3b7f8804fb9b81572" +checksum = "955935733b2735665b4735d9b1361eade6be4c7aea6bca2640345e4c81756f58" dependencies = [ - "bitcoin_hashes 0.14.0", + "bitcoin_hashes 1.2.0", "cc", ] diff --git a/Cargo.toml b/Cargo.toml index fcce1038..f7918393 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elements-miniscript" -version = "0.4.0" +version = "0.5.0" authors = ["Andrew Poelstra , Sanket Kanjalkar "] repository = "https://github.com/ElementsProject/elements-miniscript" description = "Elements Miniscript: Miniscript, but for elements" @@ -9,7 +9,7 @@ keywords = [ "crypto", "bitcoin", "miniscript", "script" ] readme = "README.md" homepage = "https://github.com/rust-bitcoin/rust-miniscript/" edition = "2018" -rust-version = "1.63.0" +rust-version = "1.74.0" [features] compiler = [] @@ -21,9 +21,9 @@ base64 = ["bitcoin/base64", "elements/base64"] [dependencies] bitcoin = "0.32.0" -elements = "0.25.0" +elements = "0.27.0" bitcoin-miniscript = { package = "miniscript", version = "12.0" } -simplicity = { package = "simplicity-lang", version = "0.3.0", optional = true } +simplicity = { package = "simplicity-lang", version = "0.9.0", optional = true } # Do NOT use this as a feature! Use the `serde` feature instead. actual-serde = { package = "serde", version = "1.0", optional = true } diff --git a/README.md b/README.md index d8962f24..79e0d720 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Build](https://github.com/ElementsProject/elements-miniscript/workflows/Continuous%20integration/badge.svg) -**Minimum Supported Rust Version:** 1.63.0 +**Minimum Supported Rust Version:** 1.74.0 *This crate uses "2018" edition @@ -40,7 +40,7 @@ Enabling the `no-std` feature does not disable `std`. To disable the `std` featu To run the benchmarks run `RUSTFLAGS=--cfg=miniscript_bench cargo +nightly bench --all-features`. ## Minimum Supported Rust Version (MSRV) -This library should always compile with any combination of features on **Rust 1.63.0**. +This library should always compile with any combination of features on **Rust 1.74.0**. Some dependencies do not play nicely with our MSRV, if you are running the tests diff --git a/bitcoind-tests/tests/setup/mod.rs b/bitcoind-tests/tests/setup/mod.rs index aa966fb4..ba09a9bf 100644 --- a/bitcoind-tests/tests/setup/mod.rs +++ b/bitcoind-tests/tests/setup/mod.rs @@ -3,9 +3,9 @@ pub extern crate elements_miniscript; use std::str::FromStr; use elements::encode::{deserialize, serialize_hex}; -use elements::hex::FromHex; use elements::BlockHash; pub use elements_miniscript as miniscript; +use elements_miniscript::bitcoin::hex::FromHex; use elementsd::bitcoincore_rpc::jsonrpc::serde_json::{json, Value}; use elementsd::bitcoind::bitcoincore_rpc::RpcApi; use elementsd::bitcoind::{self, BitcoinD}; diff --git a/bitcoind-tests/tests/setup/test_util.rs b/bitcoind-tests/tests/setup/test_util.rs index 93849f09..f7bb9c20 100644 --- a/bitcoind-tests/tests/setup/test_util.rs +++ b/bitcoind-tests/tests/setup/test_util.rs @@ -20,8 +20,8 @@ use std::collections::HashMap; use std::str::FromStr; -use elements::hashes::{hash160, ripemd160, sha256, Hash}; -use elements::hex::{FromHex, ToHex}; +use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; +use bitcoin::hex::{DisplayHex, FromHex}; use elements::{confidential, encode, secp256k1_zkp as secp256k1, AddressParams, BlockHash}; use miniscript::descriptor::{SinglePub, SinglePubKey}; use miniscript::extensions::param::ExtParamTranslator; @@ -195,7 +195,7 @@ impl<'a> ExtParamTranslator for StrExtTranslator<'a> { self.0 += 1; Ok(csfs_pk) } else if e.starts_with("spk") { - let default = elements::Script::from_str( + let default = elements::Script::from_hex_no_prefix( "5120c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0", ) .unwrap(); @@ -350,33 +350,24 @@ pub fn parse_test_desc( // substitute hash fragments in the string as the per rules fn subs_hash_frag(ms: &str, pubdata: &PubData) -> String { - let ms = ms.replace( - "sha256(H)", - &format!("sha256({})", &pubdata.sha256.to_hex()), - ); - let ms = ms.replace( - "hash256(H)", - &format!("hash256({})", &pubdata.hash256.to_hex()), - ); + let ms = ms.replace("sha256(H)", &format!("sha256({})", &pubdata.sha256)); + let ms = ms.replace("hash256(H)", &format!("hash256({})", &pubdata.hash256)); let ms = ms.replace( "ripemd160(H)", - &format!("ripemd160({})", &pubdata.ripemd160.to_hex()), - ); - let ms = ms.replace( - "hash160(H)", - &format!("hash160({})", &pubdata.hash160.to_hex()), + &format!("ripemd160({})", &pubdata.ripemd160), ); + let ms = ms.replace("hash160(H)", &format!("hash160({})", &pubdata.hash160)); let mut rand_hash32 = [0u8; 32]; rand::thread_rng().fill_bytes(&mut rand_hash32); let mut rand_hash20 = [0u8; 20]; rand::thread_rng().fill_bytes(&mut rand_hash20); - let ms = ms.replace("sha256(H!)", &format!("sha256({})", rand_hash32.to_hex())); - let ms = ms.replace("hash256(H!)", &format!("hash256({})", rand_hash32.to_hex())); + let ms = ms.replace("sha256(H!)", &format!("sha256({})", rand_hash32.as_hex())); + let ms = ms.replace("hash256(H!)", &format!("hash256({})", rand_hash32.as_hex())); let ms = ms.replace( "ripemd160(H!)", - &format!("ripemd160({})", rand_hash20.to_hex()), + &format!("ripemd160({})", rand_hash20.as_hex()), ); - ms.replace("hash160(H!)", &format!("hash160({})", rand_hash20.to_hex())) + ms.replace("hash160(H!)", &format!("hash160({})", rand_hash20.as_hex())) } diff --git a/bitcoind-tests/tests/test_arith.rs b/bitcoind-tests/tests/test_arith.rs index 9a11c916..c67e844f 100644 --- a/bitcoind-tests/tests/test_arith.rs +++ b/bitcoind-tests/tests/test_arith.rs @@ -3,6 +3,7 @@ //! Arith expression fragment integration tests //! +use elements::hashes::sha256::Hash as ElementsSha256; use elements::pset::PartiallySignedTransaction as Psbt; use elements::sighash::SighashCache; use elements::taproot::TapLeafHash; @@ -11,6 +12,7 @@ use elements::{ TxIn, TxOut, Txid, }; use elementsd::ElementsD; +use miniscript::bitcoin::hashes::Hash; use miniscript::psbt::{PsbtExt, PsbtInputExt}; use miniscript::{elements, Descriptor, ToPublicKey}; use rand::RngCore; @@ -125,7 +127,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec testdata.pubdata.genesis_hash, ) .unwrap(); - let msg = secp256k1::Message::from_digest_slice(&sighash_msg[..]).unwrap(); + let msg = secp256k1::Message::from_digest_slice(sighash_msg.as_ref()).unwrap(); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill_bytes(&mut aux_rand); let sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &aux_rand); @@ -146,7 +148,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec } // Add the hash preimages to the psbt psbt.inputs_mut()[0].sha256_preimages.insert( - testdata.pubdata.sha256, + ElementsSha256::from_byte_array(testdata.pubdata.sha256.to_byte_array()), testdata.secretdata.sha256_pre.to_vec(), ); println!("Testing descriptor: {}", desc); @@ -177,7 +179,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec .as_u64() .unwrap(); assert!(num_conf > 0); - tx.input[0].witness.script_witness.clone() + tx.input[0].witness.script_witness.to_vec() } fn test_descs(cl: &ElementsD, testdata: &TestData) { diff --git a/bitcoind-tests/tests/test_cpp.rs b/bitcoind-tests/tests/test_cpp.rs index 98c5518a..8c04c995 100644 --- a/bitcoind-tests/tests/test_cpp.rs +++ b/bitcoind-tests/tests/test_cpp.rs @@ -8,12 +8,13 @@ use std::fs::File; use std::io::{self, BufRead}; use std::path::Path; -use bitcoin::hashes::{sha256d, Hash}; +use bitcoin::hashes::Hash as BitcoinHash; use bitcoin::secp256k1::{self, Secp256k1}; +use elements::hashes::{hash160, ripemd160, sha256, sha256d}; use elements::pset::PartiallySignedTransaction as Psbt; use elements::{ - confidential, pset as psbt, secp256k1_zkp, AssetIssuance, LockTime, OutPoint, Script, Sequence, - TxIn, TxInWitness, TxOut, TxOutWitness, Txid, + confidential, pset as psbt, secp256k1_zkp, AssetIssuance, BlockHash, LockTime, OutPoint, + Script, Sequence, TxIn, TxInWitness, TxOut, TxOutWitness, Txid, }; use elements_miniscript as miniscript; use elementsd::ElementsD; @@ -148,7 +149,7 @@ pub fn test_from_cpp_ms(cl: &ElementsD, testdata: &TestData) { // requires both signing and verification because we check the tx // after we psbt extract it - let msg = secp256k1_zkp::Message::from_digest_slice(&sighash[..]).unwrap(); + let msg = secp256k1_zkp::Message::from_digest_slice(sighash.as_ref()).unwrap(); // Finally construct the signature and add to psbt for sk in sks_reqd { @@ -159,7 +160,7 @@ pub fn test_from_cpp_ms(cl: &ElementsD, testdata: &TestData) { } // Add the hash preimages to the psbt psbts[i].inputs_mut()[0].sha256_preimages.insert( - testdata.pubdata.sha256, + sha256::Hash::from_byte_array(testdata.pubdata.sha256.to_byte_array()), testdata.secretdata.sha256_pre.to_vec(), ); psbts[i].inputs_mut()[0].hash256_preimages.insert( @@ -168,22 +169,22 @@ pub fn test_from_cpp_ms(cl: &ElementsD, testdata: &TestData) { ); println!("{}", ms); psbts[i].inputs_mut()[0].hash160_preimages.insert( - testdata.pubdata.hash160, + hash160::Hash::from_byte_array(testdata.pubdata.hash160.to_byte_array()), testdata.secretdata.hash160_pre.to_vec(), ); psbts[i].inputs_mut()[0].ripemd160_preimages.insert( - testdata.pubdata.ripemd160, + ripemd160::Hash::from_byte_array(testdata.pubdata.ripemd160.to_byte_array()), testdata.secretdata.ripemd160_pre.to_vec(), ); // Finalize the transaction using psbt // Let miniscript do it's magic! - if let Err(e) = psbts[i].finalize_mall_mut(&secp, elements::BlockHash::all_zeros()) { + if let Err(e) = psbts[i].finalize_mall_mut(&secp, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH) { // All miniscripts should satisfy panic!("Could not satisfy: error{} ms:{} at ind:{}", e[0], ms, i); } else { // default genesis hash let tx = psbts[i] - .extract(&secp, elements::BlockHash::all_zeros()) + .extract(&secp, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH) .unwrap(); // Send the transactions to bitcoin node for mining. diff --git a/bitcoind-tests/tests/test_csfs.rs b/bitcoind-tests/tests/test_csfs.rs index 2e4a356a..05bb15be 100644 --- a/bitcoind-tests/tests/test_csfs.rs +++ b/bitcoind-tests/tests/test_csfs.rs @@ -3,6 +3,7 @@ //! CheckSigFromStack integration tests //! +use elements::hashes::sha256::Hash as ElementsSha256; use elements::pset::PartiallySignedTransaction as Psbt; use elements::sighash::SighashCache; use elements::taproot::TapLeafHash; @@ -11,6 +12,7 @@ use elements::{ TxIn, TxOut, Txid, }; use elementsd::ElementsD; +use miniscript::bitcoin::hashes::Hash; use miniscript::extensions::{check_sig_price_oracle_1, sighash_msg_price_oracle_1}; use miniscript::psbt::{PsbtInputExt, PsbtInputSatisfier}; use miniscript::{bitcoin, elements, Descriptor, Satisfier, ToPublicKey, TxEnv}; @@ -126,7 +128,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec testdata.pubdata.genesis_hash, ) .unwrap(); - let msg = secp256k1::Message::from_digest_slice(&sighash_msg[..]).unwrap(); + let msg = secp256k1::Message::from_digest_slice(sighash_msg.as_ref()).unwrap(); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill_bytes(&mut aux_rand); let sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &aux_rand); @@ -147,7 +149,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec } // Add the hash preimages to the psbt psbt.inputs_mut()[0].sha256_preimages.insert( - testdata.pubdata.sha256, + ElementsSha256::from_byte_array(testdata.pubdata.sha256.to_byte_array()), testdata.secretdata.sha256_pre.to_vec(), ); println!("Testing descriptor: {}", desc); @@ -236,7 +238,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec .as_u64() .unwrap(); assert!(num_conf > 0); - tx.input[0].witness.script_witness.clone() + tx.input[0].witness.script_witness.to_vec() } fn test_descs(cl: &ElementsD, testdata: &TestData) { diff --git a/bitcoind-tests/tests/test_desc.rs b/bitcoind-tests/tests/test_desc.rs index fae4977e..719dbb15 100644 --- a/bitcoind-tests/tests/test_desc.rs +++ b/bitcoind-tests/tests/test_desc.rs @@ -6,7 +6,11 @@ use std::{error, fmt}; -use elements::hashes::{sha256d, Hash}; +use bitcoin::hashes::Hash; +use elements::hashes::hash160::Hash as ElementsHash160; +use elements::hashes::ripemd160::Hash as ElementsRipemd160; +use elements::hashes::sha256::Hash as ElementsSha256; +use elements::hashes::sha256d::Hash as ElementsSha256d; use elements::pset::PartiallySignedTransaction as Psbt; use elements::sighash::SighashCache; use elements::taproot::TapLeafHash; @@ -163,7 +167,7 @@ pub fn test_desc_satisfy( testdata.pubdata.genesis_hash, ) .unwrap(); - let msg = secp256k1::Message::from_digest_slice(&sighash_msg[..]).unwrap(); + let msg = secp256k1::Message::from_digest_slice(sighash_msg.as_ref()).unwrap(); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill_bytes(&mut aux_rand); let schnorr_sig = @@ -196,7 +200,7 @@ pub fn test_desc_satisfy( testdata.pubdata.genesis_hash, ) .unwrap(); - let msg = secp256k1::Message::from_digest_slice(&sighash_msg[..]).unwrap(); + let msg = secp256k1::Message::from_digest_slice(sighash_msg.as_ref()).unwrap(); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill_bytes(&mut aux_rand); let sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &aux_rand); @@ -266,19 +270,19 @@ pub fn test_desc_satisfy( } // Add the hash preimages to the psbt psbt.inputs_mut()[0].sha256_preimages.insert( - testdata.pubdata.sha256, + ElementsSha256::from_byte_array(testdata.pubdata.sha256.to_byte_array()), testdata.secretdata.sha256_pre.to_vec(), ); psbt.inputs_mut()[0].hash256_preimages.insert( - sha256d::Hash::from_byte_array(testdata.pubdata.hash256.to_byte_array()), + ElementsSha256d::from_byte_array(testdata.pubdata.hash256.to_byte_array()), testdata.secretdata.hash256_pre.to_vec(), ); psbt.inputs_mut()[0].hash160_preimages.insert( - testdata.pubdata.hash160, + ElementsHash160::from_byte_array(testdata.pubdata.hash160.to_byte_array()), testdata.secretdata.hash160_pre.to_vec(), ); psbt.inputs_mut()[0].ripemd160_preimages.insert( - testdata.pubdata.ripemd160, + ElementsRipemd160::from_byte_array(testdata.pubdata.ripemd160.to_byte_array()), testdata.secretdata.ripemd160_pre.to_vec(), ); println!("Testing descriptor: {}", definite_desc); @@ -308,7 +312,7 @@ pub fn test_desc_satisfy( .as_u64() .unwrap(); assert!(num_conf > 0); - Ok(tx.input[0].witness.script_witness.clone()) + Ok(tx.input[0].witness.script_witness.to_vec()) } // Find all secret corresponding to the known public keys in ms diff --git a/bitcoind-tests/tests/test_introspect.rs b/bitcoind-tests/tests/test_introspect.rs index 67aed69f..e6aee474 100644 --- a/bitcoind-tests/tests/test_introspect.rs +++ b/bitcoind-tests/tests/test_introspect.rs @@ -3,6 +3,7 @@ //! Arith expression fragment integration tests //! +use elements::hashes::sha256::Hash as ElementsSha256; use elements::pset::PartiallySignedTransaction as Psbt; use elements::sighash::SighashCache; use elements::taproot::TapLeafHash; @@ -11,6 +12,7 @@ use elements::{ TxIn, TxOut, Txid, }; use elementsd::ElementsD; +use miniscript::bitcoin::hashes::Hash; use miniscript::psbt::{PsbtExt, PsbtInputExt}; use miniscript::{elements, Descriptor, ToPublicKey}; use rand::RngCore; @@ -125,7 +127,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec testdata.pubdata.genesis_hash, ) .unwrap(); - let msg = secp256k1::Message::from_digest_slice(&sighash_msg[..]).unwrap(); + let msg = secp256k1::Message::from_digest_slice(sighash_msg.as_ref()).unwrap(); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill_bytes(&mut aux_rand); let sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &aux_rand); @@ -146,7 +148,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec } // Add the hash preimages to the psbt psbt.inputs_mut()[0].sha256_preimages.insert( - testdata.pubdata.sha256, + ElementsSha256::from_byte_array(testdata.pubdata.sha256.to_byte_array()), testdata.secretdata.sha256_pre.to_vec(), ); println!("Testing descriptor: {}", desc); @@ -177,7 +179,7 @@ pub fn test_desc_satisfy(cl: &ElementsD, testdata: &TestData, desc: &str) -> Vec .as_u64() .unwrap(); assert!(num_conf > 0); - tx.input[0].witness.script_witness.clone() + tx.input[0].witness.script_witness.to_vec() } #[rustfmt::skip] diff --git a/clippy.toml b/clippy.toml index dfe5dd9b..9c7dde4a 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,3 +1,3 @@ -msrv = "1.63.0" +msrv = "1.74.0" # PSBT API returns Self as an error type for an large-ish enum large-error-threshold = 289 diff --git a/examples/psbt_sign_finalize.rs b/examples/psbt_sign_finalize.rs index 616f068f..54b5aaab 100644 --- a/examples/psbt_sign_finalize.rs +++ b/examples/psbt_sign_finalize.rs @@ -2,9 +2,8 @@ use std::str::FromStr; use elements::bitcoin::PrivateKey; use elements::encode::{serialize, serialize_hex}; -use elements::hashes::Hash; use elements::sighash::SighashCache; -use elements::{confidential, AssetId, LockTime, TxOutWitness}; +use elements::{confidential, AssetId, BlockHash, LockTime, TxOutWitness}; use miniscript::elements::pset::PartiallySignedTransaction as Psbt; use miniscript::elements::{ self, pset, secp256k1_zkp as secp256k1, Address, AddressParams, OutPoint, Script, Sequence, @@ -138,7 +137,7 @@ fn main() { let mut sighash_cache = SighashCache::new(tx); // genesis hash is not used at all for sighash calculation - let genesis_hash = elements::BlockHash::all_zeros(); + let genesis_hash = BlockHash::GENESIS_PREVIOUS_BLOCK_HASH; let msg = psbt .sighash_msg(0, &mut sighash_cache, None, genesis_hash) .unwrap() diff --git a/examples/verify_tx.rs b/examples/verify_tx.rs index eb43036b..188b62b6 100644 --- a/examples/verify_tx.rs +++ b/examples/verify_tx.rs @@ -21,19 +21,19 @@ extern crate elements_miniscript as miniscript; use std::str::FromStr; use elements::encode::Decodable; -use elements::hashes::Hash; -use elements::{confidential, secp256k1_zkp, LockTime, Sequence}; +use elements::{confidential, secp256k1_zkp, BlockHash, LockTime, Sequence}; use miniscript::TxEnv; use crate::miniscript::interpreter::KeySigPair; // secp256k1 re-exported from rust-bitcoin fn main() { // some random liquid tx from mempool(Dec 3rd 2020) // txid: f23c8973027aa8c1e86580a729833914f5b1fa710367db07f1f5515aa3729f16 - let tx_bytes : Vec = elements::hex::FromHex::from_hex( + let tx_bytes : Vec = bitcoin::hex::FromHex::from_hex( "02000000010232228caa1ed022bba919d55646169e6094fcff7580cfd51767c52ad1f1f7be1501000000171600142e7c87cd55d9163b58a0e98cb0c076e8fbc916c5feffffff28b3920a83b2507ca5f3993c84cf7b69021be6887e86e1ec8855ac432199de6b0100000017160014edfc058e1c059532d7aa90cfd47d1bf4f7d2d9b3feffffff030ae977a025f8432195181d77bc6523b7769b8b4d4c3cf8f5a45bdb940c7dfb561e0878ac4e6ab21b09f64a262d0342e88928cfa68bc9e8d004109f9caca1b305d37e0217abccf88d3488db1e40f79dfaf14ca816431441095bcb2570c9a0dcca01456c17a914b5687f4af9ba5dfb00ed22cb32a857e607bc844d870b892d93c6accf6253edd8340a6c27caaee3d5dc067e626d3c1647dd895299404a0936e562586398b4e95fb34c108afd4a9de4268bd5cd41749833e7a9265e383a0e02658aa567bb9656cd06b563855dfd63fb3e8b37b7991f86895c536af5692e819d17a9149f03346fa3e2a4fbeed0e5c379f2f2ba28025bc187016d521c38ec1ea15734ae22b7c46064412829c0d0579f0a713d1c04ede979026f0100000000000001060000e6bf1000000002473044022020d643f80c3cab90a76dfca198bdba119db97cf4fd8d8adfa2609cdbcf594f570220324c54a8e3170d06cea60511e5e8a84d1f41b21fc252181d69aa8b7d190c26a90121029e831ee2345cc698c730b713b82b99e8c16ffe5ddd51c9b36607bb1fa68b1395000000024730440220645f22a912344b4f8d165814c3513e9bfa06d42066fa4d392f783a57444eff0202200b98199177d9e13c9f3872f433154be430e82cc2e312791a47bea2a91167ff4c01210303a640e79b1e941f2d7867e4eabffd79f30daaabc80fe1c4d974775fc29339810063020003c7b8cf924dff6cef0c9f9b507abc741e431e1a793206b5fca623748f583e6ad3f3f7a4fd1b27d78bf3b4debc9a2c849b5f85722cab872a9c08f19e6eb59ceef74fcf9a7c38acd6fdb7821c33bc731011b6440e8aae7beff3ee6ffc1009c849bcfd4e10603300000000000000012361c401dc40cd92cf93029e64c20c463d17c6e15d2997ab43e8c4b1c412b99a1a337c3cff34c6e7269580727c27404a131606aa85dd8bdf6d46b6ddb23948a0507e31666b531e753eb8fece006050bc7b7e2e06db86833f9adc4f6b77c7b88537617c3accea246a8fe303a23697801181efa8bbcded7690aeac04b58e32f4cd94279cff059a5c9f679d973007042fa1e5e4268a884dbce7acba614d57e1f7a56f81354779ab353c04806ad280417f656a10bcbc683348608d7f6e08367d9c21318cfe6f03a0a60bb8269d667a3ddd57f77f8774364e6a946a6163896db4a8b7e2446d229d8d3718f9a8d7b57a2dfe43baa79bce705512635c775602404d55a2a61fee93c00f1e0cc466bf2cf0bc070591e228de578bc51a38b1927ae29f0e7daad95380f5be599f50367ae1028e57f2e1d9b35d45f0fd860491c2c03a46500f2fabf3c8c7cc9ede16af01eb3d42633ddb8ef87bc043c136f727fffcb4aebdb19f674864e2d2a20aa0d61f7e635c582a79320ff2dbbe8ee74c4c51ee09e03e89581378fcc4d2a6f44524add57be3d31d3054468662a805fb82bd047e5b52e13415ea92c57532940985ded222477f5bed2bdedbbe1f2471b0a85c32a70b0d07a5c734ce90e62b51babee95c63f2cd5ba7b6716a9ecb2f44e5f30f2bc07ea7fef5257aff812558385b23966608191436cbeb1f9fc6a907c1841e1dfcea0e5719749969d447bbb9b332389b2e046d107a873c1b557319250c6469ea03c7bd2c61e6a31963921f1854c5546479044dc992f09c2e781c782fa7dc116074787495bedd991b530a7a8b49bd0f85e32ea19bdfac28152bf63eef1a8bd9294b51eaba8b5bc4db1d89031e4dafffff9bae4329fce27eac3db83e6d5d22ec4e04850b7af49329828e087f2c998882249cb74234002c6ea20641f6b4dd0199e4d6d932e75cf0e59a07b25724826fdfedae239d8275c992456c53a2d4c469f08120554e86c4693c32284616279eeb048d434288f6f73dec16d3d37ef0ed2a98e5c11cf6ac046137bbd8b76c1ebb00e8804133e0e647751ab6b395cc49c92d5084bbac242cbd8369c8f56548ca92b8a1da586e12f6163d2d0b42b4774e6c8eac23240c51ec79d71dbd1a69441265c6d5e4974e3ef6358b30106649744c9799f6ec1de0cc98929f02be8396c4d807e87a767e3e2903633da774ff39141e14aba0c01fe3331d7b888360722ebb1c3e1fdb1b3226ecd2003cfe2400ec9ef29f431d6e5182eb98c8aa4384b60dca8dd0d28ea52fdb6b181c4788b6d0d2ce9c5dad4dad259a83eda33c21704d4230660f8962c69d290e77e60f16916d5e1bf811eadd054d464fe33232541070371a69b120402a9598ceeb9c8ffe0622c90fcffcf271eda70128ed21c5c1990c3361c11f7f697eb56a32bc15c5e79596274043eb80da990fb40e31a0d8a83d62e53e9d9f3f786de418ee3c9a1adc54ebb43b74db84d550dc8fb64aa5a0947f23d9e07fc370e141217b0766186315ad088c2ccbb426e3a184ad74b5469ff24b596670617bb967aaf8976438415d851bc89a98887e2388161c967b8ae9e5814af518097c4e0604b6ecf755527ade18ae0a50234a95f4b45c1bf68ada13991928dc88b61abf23445ec95d3f06830852bba27e09a7747b1c06a1d4948214be7e0bb47f2c14f6ac02715a250232ed15767da55717adb239149d8021f33bb14316622947d98d30506aaabadf90add3cd639f5e558450642ac7b4457da522efb710124518a0a3f41b6798127d209768cc526ecc9a6f70edbe3c3b9f45536295c2bcccc384b0d13bd6d741e8d1d01ac83e09cf35a9e7ff71ffbe2926d8b3c5d5eb131fe9b023d427c4c8c3e4310df6b3c45c2de0092df59e98176b1bcce17889b3667854785a668e3c08aec571506e5074ddc5e53eba12a5c2adde7a0fb7c1e5b86b1463e7634980985dff039d90abdb0d11cc701bc8122e22000d3eb4ee0ef422a08e85bf13d5bc856e79c0eb00f415a8a76d6d7bcb087b090954e0476c81ad1ba3ef89b8b5338c78a8c0b5b25cda36ff35c307900066fcf775cf71069a1e396b0efc611b21ecde8b5f080252d16690767137307aade91486ff23fd4ebd206d0b9bbe9f2221003967fb76e51925954fd5df40d0c331277c35bc7bd40c05ed32a4cf577ccd5219b113df6454258cf1cdf123e8ffb7fab3debb05ac9f3a3874221bc6d08db4c0e2676257ba26d2b780c6102014f980987c6826cdab6a713cbfeae703af2dd8838378dec58b406ce2e796a560e1bf1f7f4d09f32c0cad9ad2fc3720ce3963273b6768250c3119eb4d9c0c722cf64733432fa76abf07e845d55f089df83dfb784cd7bae06e1fa26b7464667945774f2c61afac025d4f5dcc909cfaf064ff9b622b680eab1e5ba31b8374fd2402ffae1481cb8ef180060c8ac01aac5a4f9df8b5e84b7872cdeda17cc5b37a4438b6c31b917a88336cbbd535f95710f1d4bda8dee8f9613c0e62e9914dbc8f2f812783b7b8a154c74c17ceb1df61880f61a9038ade4a15542a2258d0533988303e1d22910448fa3d8aa29660efc1af8d8c470da4071960ab55a83627da6c1d955e337fff0f18e6e4b0516ef21beabdd3174ffe816ac945ab7c54a60a56898fce13b782820ad6b6e4f72a82122366695b4d5c332490fe8caf98b3e77749ac06fcaa0a1be7e283201e7dd0ec43cb728da2597af4a4d1d20836d1d443c6fd24d57881ec9b9d0af6b99f04511ba2f526c1647f0c67328f7ea7952bbeaf41198ba56ddeca73e8f1e028d64c9e8bc9515aa9f16830add7c705d6aa4fbf20ba5aef213088d6e4ef4453dfe0b0c531ea19ba772969881e5945e353b43ce2940d9b6898855092f6426b32ff0f1037e1d9799e30d93b1b1df71b70bdc52fcd9db0cc87c55894244da38cc6534dae903d84f7b636cac2d26ee2ee3c60a60c9482dcf3ad679936b6fb4e6a16bd3275f6452a0a47dc0f5acdcf9fe17c9fb34ac669ff277964d5d77062d4dc69ffb3f376665972fc8300df0d3eca41c769891013cb14d70b7600300d030e3ad5d6f9394786551857c5beb49c0eab658b6253ad647365912062b1895ceb0e5ddcfbc73034414bb7eef9bc7a201f735d67edfc7c07c89f3ea8a98bdef324f606ed2b4b3989d0d019b73cd8ac9bdf062c53a40c13ca97f848e152756c388bc54d4ec86104962ea8df3a9430ee4f1bf6eb57862faf2cd49e21db5982dfb5386a23b47b4d010b4ad79f600161ba2d5307b9199977493c1e8a696d2aed4b85d7d52074438c76203baaa50bd96f5d2c9063b4e3033f090021c996261344e44aece16bf926614a5163b70d7f6a03d13462e0858b1911763700503b96505f471bf084d966dd7cd8603e3ffb9b22c572526526d8568e6bb55fa77bfe334ffee4edab2a58719aab70e9e8e8102eadb5391d6a188006a42daee2b2ca71da99b80360fadc4710e7a33d8c3173cc69b5824d93b5021718a276b0ab706029d4378df2fd1183cff056d463a2984c5aa397b9cafd1d3e4a209c04e499130980265d5e2930638bd12656145667bf0dfa09bb61c5c6801d158fead98b3ccc6619c5ff643bc629a57cd6e9b535033d29d4ebdfcff607c50b6ff979fd22fc1a07d796672d98d8b2be6c6c4a4f4911179d18cb29c4c8c490a091d334975033e2ae1a0db38f77ee252f22d4555d0202b39671b6ff29d564cf7b0252ed748cb1a5770bb5aa913d37a7e6e86814e1f34baa5ce474fdaca3bb316cebc4e7893c6452d856a4245434b26b52a37d8aab8f5da3a325e313858e40a9405307de7f4e80d25b3cddea6c75f8595a1c235005a3f0fc948019cfe9e68e3cd0a2affb2f073374d0a03ac55ce9644a92b28409173f763e6a1f7946c1d16ac14a792bd5aea57e404d8a684bdea0b430572d2e5034c949e6c9e74a989d0f91dd740b174e4853e2e693c011d2d29e50bef9fee62079eafe87516448c5a045a16eb569314c9410d4363619ea19aee6460e72440d1cc2a368429c99f10dc8707662d64262113d8eda7842a6233e9ec5c1f7d8c71dc6efedc4bfed53fa9646171caa26daaa0bf4ce50d7b02864ffa0d860014e4d08425f0c1fb840d69a55ec84a833b45dd4572d05d2bcd7dbc6a78974dd2ed0bd52a0343fbd5421c05900da0b7c4e9e42e59183bd2f6e5058482fdd165e346b3ca22f35934538e97110321709394ee446087d97630aa17305fd5d1fd697a4ff3477fc7d02a65afd16e2a5aeccf9402c9dc90f4550140b6bebe6554203e44b9b02472a47c524f4a9554dc25484eb8f173a878a975cdabdfb7993b5e097dc04ef93a7833e51a61b64a6b62743252bf60bf665b9c398688eb24db0d8d2acea848859864f426c08649d29aa7e1d1027318d55624ef750572616ca5b5a118afb83b6e0c872c29a5388f954fcaf8f6d0e67396bd54b9115abe02ffdf52878cd55cb0c5d97cedf41794880ca2b88f960a37d0241ad3e268b3ed142285cfb464c9b0917234df19aa37daa95b935b9f035687d1ac0b7334855e5bf0473175d54c31cf520735d04f5b4ac272cb57999fbb8cf49bd5de6b44616c6a103f53dfc86f874cd847c5adda25c50f3615c0c9c63b34c32142ed62e49f72921fd35753e0ec9333add42838b383684e5246c154cd3ff6310933a36798a4020a027e8f0f951f0dc2dcdb26f0922c69a8dee7183332aa534fa25523469e7bca5917f37fc822b4e7ea5123ef1b8250b2d3dfc9c24ade46394ade3694d528db41108801c3618fd98878e837794023e5ca756e584fd2853829c53380bbb8a281998db43e3ee44e4e6cd08a46c958fee413af351467b7c8275f4c74d4111614eb90b3b10c044c88e1c00f3c2b7959b71bbabb25afa0f564b1449ca585066cd77721fbde395a2c6337be3d546a58498c5f21abf8177c7299fca76e4ae951847858f50fb07cfb10744b770f115e35f57dc70858cafe3a9f66fa406b8a5da94a07699672eefb557fa6adbea267961fd9e4af73a1efdea261a249a573258dae670de24a3d96f36cd146d02370921cacdc155b30a80ad5b43c5db9390ee94e5fcb33b574f82e039371d25fe1128effcb536d5d53727ef341043dd7b07db4c41c117356b3c5379e486f19a4bdef1d3afd4cd0f5fced5a2fba436ee2b84d0b326cc4fe19e69ce05906d3e36c62d9b9a4695bd3ec0d0e5c5e8578dc36094fe879702cf95577a2616244fa3dd7f07c998836793f367d973f640138896f18461b877df9c5a86b046bfab5ac5692d85c5ae632ac51dd726aea59ff471e3f50579204ba6c5868530205faaf81821a57d462ffc697bdd82ba50edd8d3d7973235b57be2d0f9a84ded1d0f3cb68555c2300987f2d14768d2f0214abaf29a06d5d37c5296b5c2db62b2169e1a7bd425cef00db2745d5e246f66191c522f58f0c14fb1d1c8fe6b5b95a45570334125c190a3a9a3e77deb9ae7ca45d973fc64a89d2bb6420286ce01649d5de80ccf89d34bc0c2d9e49d8ec713d2c83286bded0d30a8c42740678c6538d8a7e491b2d1007df7d5037016018c6bd36a21247c13c1cccad168a6a0c2dab4c01185b6d61c31f0f2410b83c16a58d7cdcc0f2522fbe62fb27b1094f77229bff259433e9265d5656931b6d47210bd1e1a66a6c6a3dc9c6a2912a8fc1f05eecf40b751555e569ac2f92d1e5b540037c0cf5c9e658a17fb9dabdd23a087ebb90411f5e75f70bc7786855a2adbebd889d1946ecd6be827e2a624e256c36226ec87f2b92f978be8ffa98169f8dd4947390509d2397322da63757dff25a86f9872414209c50983c570558fc1a630d3caa8f6a59a16cd024f00b2323d2884187ec92feb19e078690f51940229c6076dea7064e71fcc6c55ffd643ccff5b63020003f6512e0b2e6dd0d8cf0a8cde59f4ae60632a902889a27e469b0e844d8477b471a779f720b7650e56645f8a044bebcf4660405a5185e75d13d0c15a221fc707860cfc260b9f9ab3c98e616cc574bd05a494faea98c1e06f9c7ff9643b72692a4afd4e1060330000000000000001cda9b801f96b13ea639d611a15e8f3e899ccf6718b7add1e0309d6c16a3f9b5699cea2fe90fb96147e22f3b025013bb9e7e824614a2c2c2e2e9a420a98b91d71170d89e7aebb414266337a636ec3031021a51701dda9113e9c1ce1291fa9ccab9dd8f30ab98d9c5ba12894af05b42573202c8a5a35d4a49dea9873c2f9aa51ee263a10e49cced91debeff76caca98e07cb7e7705fb647f3ea846cafa1ea4e8449022aedc5210ac18c0a2585a435cc2249cc997aa7e2e180fcee7ee92b1dfee29b3fb125c3d78938b8e6cec68f9fa16643460617013d0bf65b453a124fb843326020adba9ea96bb1832cefd6ac4126329187329b1f31f713b097d34cd2be2c42b70db5e5153a7c5508496f4608c8b7c1c3d8fa7dad87c76c06c278caf0a429d49f4d4fe367894ed493b1e91f331e0533b8364241527adbb867a29bb47fa8e8b5156d5c0ec9042c900f5b9bbe352488b0c671bcd381f090b7fd5ce469d21e01cf5b3f01fcdd51b3fb0eefb4145de49a9444ab161522dbd465169f6d9814b2646142fcc9020aee9742246442a63486e80aa341c81be71f8568080f7d700308f0f79dd8295345da0bd852f5aca16e5fc0e686d7642ef70f46f6d836f3a5bd2b14919fcd5e55ed2dfa8d6920681cc26d1a31f68bf6580c6693b8b877630746cf3a4bea53b4862872941f535345e69a7e7f0108cc72b741a952f4aee5436e918c6fae307277cf20b1fc4035f9235b82c18a24e3159563afd240b0cbe671f2138e6d3b9a4efb5e073b5428e4073a3610c79643b441165121d2d85a311f334b751fac62afec8e1bab82138c5ccd2154f1e00d11e00fae9fc1621ed68e1a32c71b7bd98d5d6328bf7bb3ab5227391eed36335fccd1f83a4b6854a2ddeca1942f8478391be3468693cec629918dd66f00f3a520b495c7f6eaa22aa90a3ee22f29c9ff4e473b739e7a7581411ae966f0d5aa9f157d33066f868a39a0af75199fe886d62c8112ba5242becc11cbbf038c28c41674c643d24448ec7336c98dec3ce09db944476df456e661dec9ffe471243b16888496d17093cb21f0cf5360c884107ed584a24ea151f6f91ddbf92848afe9ca936aa68f992d13aa42e470284454e3b7fe31ec28c33480cbd17d44b941f4f99fe269aa51319cdae2f454d548a41d801061beb6466cf3c27c0efdbf4ea556d57dfd9f52798214f73c3506525426a59820d037285f61465a141e394de9970b6c9b6297ada4d4d65fc5b9921a8f9e6aad8a9ab2d587f193b741c8e5ed879498e7374bf1744f6a72566745e21012cec8412ea8b8eab9712c740cc71c1c798c1d2df850426f69ce311ff1f537b87ae9a31935525eda54780f15dc73214043ece83f1629e36c55747af1ad8e84fa5e535422b09db9a3145022691e189c9ccbacae70ebea3f6b5f2e09376b6402767c85a2ede43761b4ee5edb436d9f711dfdd84e1ff0dbd35c607ea59d9d5c8adf7fa4bf08634e8cb5027da6bb8a8cd7ba1e87c40be3bd9c5554fae6bf7683d25a57320b63d20c66f0df976dbd688e8c4ccf0dbe755f0d31fd6d1b81c6f1ea0538f73c99cd239efbe92b32b946f07b8b53aba95f05d9e0686e188027061c0c912bf2c27cb83a46cff714e57e4f072bd1df08e23640bb64143ee7c866097f8d360800abbff28a94ef7b035563ce396c9c68ee5c7751c070c364e0fcfb015749b480a8bf4cd9626541e40af879213812612c2e04d688629239f609219a45657693c4cb81c85e156a0c9b377d6123340f009a265cec1a2fde0dfa4676b80dec9b6544712b202cec1467d8f440c2c2a1d13862fab29cb266e9185ed6bbb2c3f3e168bce4720ae079194948d41ed8bf7913fa1d9d8c0dbd39e4f7855f807f6192d3269fa0a98a3d6c27992798b70b59e04dd63918c7ca99054abe15fad0f567d9e993ca49eae695a820552575ee569c4aae328c5db0c3d04d1692ff561064345ed32571d072ea4a2613ce163022287b86b9797223619e556f978deb6711051eab698b43fcac2d62729addc0d699f775b516ed1952af9c5faad43601a4a23007ee2d6fbb10316bbb047e04596a57d5ee871496f85ea460f3f078e6c5a3f629aa6b67e4dbba3ace0a3ebf870a2800a5c7f27a866f6d58b33b1daf49c27a0e8057c169eb9be30d3a42e92676f45be824c12aee3f35a59e1cd23bb39e0ab5a87d43e5894e7aedfa7e74ee6554873db5646eb0e7d2b79f970c4210bd9be2b9294284aa26156ba9773c3422aac0489ba21878bf569c79cc548519221c3c90a706460a2d32e073564d7b6133ef25e14a6e327bc15e33555a299251ca49006225b18d8890b45b49e8c16aab18b6e7ba1e932750e81de679d7b6dff571a4cdf737e06eeec7cbac678b8a58e2142615b71cce7f26187a9c1490407b32c48783bf848a830a41ae89989fe68e50307044c34ac27f360b3679b1e4b76bf590cc131f2e25634c9979b4c98c392fa862cbda18e5c5ac0dd25f3ea6d9fe88691aa4d6399d4bc1da5218b95a8f8ab6683a1916eca043fbdb23137799f8e8e6e240ae4693e1896b942ae548a9e948ba77b2770ac8d98737bdb47d04e5c233da80d84c806e8585e73ab7d4f24ef5415a8ff01392e05b267159736f222a7e88652801cc7b9a3ce955494df7c556d1747255f9492da41ce8dc9a615c9b926f83436190e458f7b3994e425d560f35d3a79753e637c8f7dcfae559e8a76a956927c870e5f6da04a8fbb805253af55e52f3895811825d720e35e305c164ebad8a8f5535e6f1a9023bf6a6f1087361a93741a245b4b98920f539b21958c47b68e8f11bd764b10fba33c607fc70b126263a07216d72eef2d432083a6e373747e345cf6f9362a9bcd52e865062cb026484a21a5794dd4a1171560caec70cb607c324537007b74a36a1ec02033d8fe76196854c4158c47d0535a98eb15b74e347ec308728a32f7b75f06f3ee753cd0598ecc47a563978eba8535eaa012ae9555551a1c3f39c1fadbb66b08cf6f560a820fc4ae281f2bf57fb092f4d2c61568192483e86e65d5d58e86b1a873d06541227228209a98050728216b70185cb0243b893882db43e9a7aaeea366b2dbb13e9c3e707f1be4473d790d676695f1ae7bf1064c6f0a38e8706d37b652cff8e9e1979236a1482dcedb391f7f62da88843221043e472328e7b3fa57e7e06e4eaad1afe822f65002b18382ee5ccd890bd84f26ab467bef4265828e7331c31f119beadf4dca3773ff4a1f1b55b6377bfd9ff5277e740e2c60faa7111547f3ed0325a509582c4185de57a7f0b97b841736df3e69f7f73dfd831967ca615e29c4ffece4c229a3da65ce8e9e7bf12ae10b338290fd80f887cd11cc452ac0b89800c1694e38fbae1d83d7ca0112ad57797354315adceecef61c35fecf618144ed59f84c6f5b9be75de6aa218616bac4eade6dd148b9d692f5df6dcded45b3c3e4a3d679ac91a4eff540f608a86432a749aa119db5e3ea92ceec1ffea5c467bdd5dd3798dd8893e8e3972709025619cada7a880f675faff2a257e18164dbfb1752cfbd5dd8194cfca896298165c0dc4369724b59af981350c4514107c8ff09fa39eed4d76e636a21cdbb3e0c0e5e8f510d087a591135b52f974576432d3e3bf2f46b036c7e140547f96ebabfd0cb242102b3f66aee8560be27657d0900494c33eb8a02dd36b8d8b0e6df3d9931fceeefbc32590050838eec27fa778ae6347102442dd21e300b50faf8fdfabbc1161a6bfe5bc795fbcda8994091ee954edf66f1ba75c4acf7965b31d56db077396bb1e7e9c8286e63e54b34cf5ca11bd8998e40f2c4594c55d7fa8fc2cf9476612d567996307d21caf06e49daf16300bc1f70d70d145e64d92a0b307df6a3d3554d6ccd0c550ba193ff6b818c6f2b0008f17359e8617aa927b9f771203faf28c2a04116f8f048ab0228adad39c8aa3e8c8381b1e60886138face97ae7f3c02d2ef854fab2ef27425b23fcf05bcbeb3d752db854313084ddf7a8833369c17123c92d63c744df22ffaf10188b2f4f4cdb53e5f530279d4419b0858d44a8a8f76a26b78be327bd233bf12709ea04a4cc6b6ccfb20808519f316d293bb4d605e4cee8373202f4e95e28bfef9c42354672526a7a81391239783b64d74c2b04686438411614e7228d34e457151f71d742bc514aedfc96966ea35297d5efa513e8dbbc10e8e16eac2ae14848a20c165f59f1362b57b457f6786b0e1fd492ca47d6aba03774e58f4e09fb480156b9c96ddd13c441fc8202e40a12b30396482778ebc439b5abebcd140ad3848726b2908f6b594e0ac7b307857d68fad4ab05e4362140ad2e4b4606e365e894224dfc033f4c069dafdd7f819d340f6a202592243a27f67a38f20e5b07136f5b503c3ca209736c0a7b99749a9d36a82b2a6926a426c95b5f60c835ab85038469e1e5bce2b6bc2d47345d8f1beed8e678423ca3db106b554890e8a701e5d43f6358d957b8c799d1cf20da1f577df0261717227113e5d1127849bccc076947beab3e3aed964b83c94de9322591b67d6fad860d5a5c642a545aee2d1ee6756723a96d74ae2f431876fce6d8da50628fc51560760c97aa66a258f41a9d958a1e3bb0e27a58eda5f6806a115ac6aadab545aebe2d9c6c6c01cb2dc7e8b36c7b37609563f84f409b0813047fea9220872becbc9cd976d502576d1dc2a0a5612a7a1452e46b35149528ed2cb74b18a221c2281d7b766d28a30f763d7375f6242f4c361807efb711d21426696f77606cf1c37c4c162fe79e444c622297b0849c88995cf248a47c49d1932b6ee79c2c2f3dc77fe97389855c50cb797b0fddaa94c31d5b23f4b7f7d24131aa24d6d53e9a43a3e2c360c3254573355ddbe850299f7ad13f8d0676c8a39ee2a63ec700eb3b53d9abee536a6a2bef272527ede483a09913d8d839cf69c828654ccac0581552b342b0735f49cd5af77bca8e8926173e58320fd4738e574114736cd480900c001766cc72266f7c7ee34dd27a109ad4e932c28d0ce1292df46a0df42f23a48531da38ee14bae23d27e3370434efb85546c5e53c10e8407084e833a65a91d07df741174fbdd7e1e5475d273b1c30fc3db1227d32739889b45ac3ce208f82523d51e2c5a54b6c325ed1fbda4748b61090a838bdc5ebdbf1eb2280ad73028ed8ec40fda49cdf17ce0e158521ea5c99cb8fca79a91e7a4011e6aefa4235b4cdd5344356ed7fb31b1e575592fa2dd89c0a2ce151e07d049d67463d6fff3b2b830451fd89c596d9c807f57aba74fba0a24649e27c849376ab134c5c7f501fd1746b75866f3e74f854029e2e73455a60ec76df9df208b8ce5feccf2b6a2bb743e461924cbd22b91c9e89dcbe231474f26678dd91bda846034f4d55ae97aa1a569c5a3bbb399682ba6b066597a1be9d9a1612cf3faa7cd9b0dc9a3d47c9e382604d7004bb10b2e29fadfa2e374c806a1c7f95b169c4e461bcbe907d3a7ffa6af042f351fc908dd67c522802f0ef18eb57ecfc6f2e95322928e5b561d715a29667ee44382be6eba5ea8577fc926ba742d0d1f345263991610174ec46c5989d8546cd37904089d5327e0787d136d3b13412b536bbdc385990ed35cf6454874c9ce362acb0a8146f78b3f20140c34519c9be23051ad0e0620d50dc3319bfe072c46952cccfa44a62c7afeb9bd596673dcaead2a279175b9324c922a6c17959eef9e6b15a1d952bdbdd74e6eaca13735db8132e0c26fd8eaac1acc66feb76e62760e6746dba93492891a048babd276ae5c4ec2fdd0afc8c1e570a2be342e6d98c3ed004e627ce95e06770227f7b6976a0b2b8e2769e8a1061b15834582c581cc36c0e28909153881e4ee0f8770392a04b3459b1bea67a4f4a68270000" ).unwrap(); let transaction = elements::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction"); + let witness = transaction.input[0].witness.script_witness.to_vec(); let spk_input_1 = elements::Script::from(vec![ 0xa9, 0x14, 0x10, 0xc4, 0x65, 0x2c, 0x0d, 0x2d, 0xf7, 0xaf, 0xaa, 0xaf, 0x82, 0x0e, 0x48, @@ -42,7 +42,7 @@ fn main() { let interpreter = miniscript::Interpreter::from_txdata( &spk_input_1, &transaction.input[0].script_sig, - &transaction.input[0].witness.script_witness, + &witness, Sequence::ZERO, LockTime::ZERO, ) @@ -81,14 +81,14 @@ fn main() { let interpreter = miniscript::Interpreter::from_txdata( &spk_input_1, &transaction.input[0].script_sig, - &transaction.input[0].witness.script_witness, + &witness, Sequence::ZERO, LockTime::ZERO, ) .unwrap(); // Get the previous confidential amount - let conf_val: Vec = elements::hex::FromHex::from_hex( + let conf_val: Vec = bitcoin::hex::FromHex::from_hex( "080e8899a3c271573359a179b27b59af180b36461f959ee00f762d9c2d84192a06", ) .unwrap(); @@ -104,7 +104,7 @@ fn main() { let utxos = [spent_utxo, elements::TxOut::default()]; let env = TxEnv::new(&transaction, &utxos, 0).expect("Input len == witness utxo len"); // segwit spends don't require genesis hash - let genesis_hash = elements::BlockHash::all_zeros(); + let genesis_hash = BlockHash::GENESIS_PREVIOUS_BLOCK_HASH; println!("\nExample two"); for elem in interpreter.iter(&secp, &env, genesis_hash) { @@ -124,7 +124,7 @@ fn main() { let interpreter = miniscript::Interpreter::from_txdata( &spk_input_1, &transaction.input[0].script_sig, - &transaction.input[0].witness.script_witness, + &witness, Sequence::ZERO, LockTime::ZERO, ) diff --git a/fuzz/generate-files.sh b/fuzz/generate-files.sh index 232480a8..5f62ae15 100755 --- a/fuzz/generate-files.sh +++ b/fuzz/generate-files.sh @@ -71,7 +71,7 @@ $(for name in $(listTargetNames); do echo "$name,"; done) key: cache-\${{ matrix.target }}-\${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} - uses: actions-rs/toolchain@v1 with: - toolchain: 1.63 + toolchain: 1.74.0 override: true profile: minimal - name: fuzz @@ -93,10 +93,9 @@ $(for name in $(listTargetNames); do echo "$name,"; done) runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 - name: Display structure of downloaded files run: ls -R - run: find executed_* -type f -exec cat {} + | sort > executed - run: source ./fuzz/fuzz-util.sh && listTargetNames | sort | diff - executed EOF - diff --git a/src/confidential/slip77.rs b/src/confidential/slip77.rs index da19e568..a440f47e 100644 --- a/src/confidential/slip77.rs +++ b/src/confidential/slip77.rs @@ -20,7 +20,8 @@ use std::{borrow, fmt}; -use elements::hashes::{hex, sha256, sha512, Hash, HashEngine, Hmac, HmacEngine}; +use bitcoin::hashes::{sha256, sha512, Hash, HashEngine, Hmac, HmacEngine}; +use bitcoin::hex::{self, DisplayHex}; use elements::secp256k1_zkp; /// A master blinding key, used for SLIP77-derived confidential addresses @@ -29,7 +30,7 @@ pub struct MasterBlindingKey([u8; 32]); impl fmt::Display for MasterBlindingKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - elements::hex::format_hex(&self.0, f) + fmt::LowerHex::fmt(&self.0.as_hex(), f) } } @@ -110,12 +111,12 @@ impl std::str::FromStr for MasterBlindingKey { mod tests { use std::str::FromStr; - use elements::hashes::hex::FromHex; + use bitcoin::hashes::hex::FromHex; use super::*; fn unhex(s: &str) -> Vec { - elements::hex::FromHex::from_hex(s).unwrap() + bitcoin::hex::FromHex::from_hex(s).unwrap() } #[test] @@ -128,8 +129,10 @@ mod tests { ); let secp = secp256k1_zkp::Secp256k1::new(); - let spk = elements::Script::from_str("76a914a579388225827d9f2fe9014add644487808c695d88ac") - .unwrap(); + let spk = elements::Script::from_hex_no_prefix( + "76a914a579388225827d9f2fe9014add644487808c695d88ac", + ) + .unwrap(); let mut addr = elements::Address::from_str("2dpWh6jbhAowNsQ5agtFzi7j6nKscj6UnEr").unwrap(); addr.blinding_pubkey = Some(mbk.blinding_key(&secp, &spk)); assert_eq!( @@ -150,7 +153,8 @@ mod tests { ); let spk = - elements::Script::from_str("a914afa92d77cd3541b443771649572db096cf49bf8c87").unwrap(); + elements::Script::from_hex_no_prefix("a914afa92d77cd3541b443771649572db096cf49bf8c87") + .unwrap(); let expected = secp256k1_zkp::SecretKey::from_slice(&unhex( "02b067c374bb56c54c016fae29218c000ada60f81ef45b4aeebbeb24931bb8bc", )) diff --git a/src/descriptor/csfs_cov/cov.rs b/src/descriptor/csfs_cov/cov.rs index 2c6a5a08..1e5b82a2 100644 --- a/src/descriptor/csfs_cov/cov.rs +++ b/src/descriptor/csfs_cov/cov.rs @@ -43,8 +43,8 @@ use std::fmt; use bitcoin; +use bitcoin::hashes::{sha256d, Hash}; use elements::encode::{serialize, Encodable}; -use elements::hashes::{sha256d, Hash}; use elements::{self, script, secp256k1_zkp, Script}; use super::super::ELMTS_STR; @@ -170,14 +170,14 @@ impl LegacyCSFSCov { Vec::from(sig.serialize_der().as_ref()), // The covenant sig serialize(&sighash_ty), // item 10(11) serialize(&n_locktime), // item 9(10) - serialize(&hash_outputs), // item 8(9) + hash_outputs.to_byte_array().to_vec(), // item 8(9) serialize(&n_sequence), // item 7(8) serialize(&value), // item 6(7) serialize(script_code), // item 5(6) serialize(&outpoint), // item 4(5) - serialize(&hash_issuances), // ELEMENTS EXTRA: item 3b(4) - serialize(&hash_sequence), // item 3 - serialize(&hash_prevouts), // item 2 + hash_issuances.to_byte_array().to_vec(), // ELEMENTS EXTRA: item 3b(4) + hash_sequence.to_byte_array().to_vec(), // item 3 + hash_prevouts.to_byte_array().to_vec(), // item 2 serialize(&n_version), // item 1 ] }; diff --git a/src/descriptor/csfs_cov/mod.rs b/src/descriptor/csfs_cov/mod.rs index 8c9b824b..345fca79 100644 --- a/src/descriptor/csfs_cov/mod.rs +++ b/src/descriptor/csfs_cov/mod.rs @@ -58,14 +58,14 @@ mod tests { use std::str::FromStr; use bitcoin; - use elements::encode::serialize; - use elements::hex::ToHex; + use elements::encoding::encode_to_hex; + use elements::hex::Case; use elements::opcodes::all::OP_PUSHNUM_1; use elements::secp256k1_zkp::ZERO_TWEAK; use elements::{ - self, confidential, opcodes, script, secp256k1_zkp, AssetId, AssetIssuance, - EcdsaSighashType, LockTime, OutPoint, Script, Sequence, Transaction, TxIn, TxInWitness, - TxOut, Txid, + self, confidential, opcodes, script, secp256k1_zkp, AssetBlindingNonce, AssetEntropy, + AssetId, AssetIssuance, EcdsaSighashType, LockTime, OutPoint, Script, Sequence, + Transaction, TxIn, TxInWitness, TxOut, Txid, }; use super::cov::*; @@ -206,7 +206,7 @@ mod tests { .to_v0_p2wsh(); spend_tx.output[0].value = confidential::Value::Explicit(99_000); spend_tx.output[0].asset = - confidential::Asset::Explicit(AssetId::from_slice(&BTC_ASSET).unwrap()); + confidential::Asset::Explicit(AssetId::from_byte_array(BTC_ASSET)); // same second output let second_out = spend_tx.output[0].clone(); @@ -215,7 +215,7 @@ mod tests { // Add a fee output spend_tx.output.push(TxOut::default()); spend_tx.output[2].asset = - confidential::Asset::Explicit(AssetId::from_slice(&BTC_ASSET).unwrap()); + confidential::Asset::Explicit(AssetId::from_byte_array(BTC_ASSET)); spend_tx.output[2].value = confidential::Value::Explicit(2_000); // Try to satisfy the covenant part @@ -233,7 +233,7 @@ mod tests { let sighash_u256 = cov_sat.segwit_sighash().unwrap(); let secp = secp256k1_zkp::Secp256k1::signing_only(); let sig = secp.sign_ecdsa( - &secp256k1_zkp::Message::from_digest_slice(&sighash_u256[..]).unwrap(), + &secp256k1_zkp::Message::from_digest(sighash_u256.to_byte_array()), &cov_sk, ); let el_sig = (sig, EcdsaSighashType::All); @@ -320,13 +320,13 @@ mod tests { .into_script() .to_v0_p2wsh(), value: confidential::Value::Explicit(99_000), - asset: confidential::Asset::Explicit(AssetId::from_slice(&BTC_ASSET).unwrap()), + asset: confidential::Asset::Explicit(AssetId::from_byte_array(BTC_ASSET)), ..Default::default() }; let desc = Descriptor::::from_str(&format!( "elcovwsh({},outputs_pref({}))", pks[0], - serialize(&out).to_hex(), + encode_to_hex(&out, Case::Lower), )) .unwrap(); _satisfy_and_interpret(desc, sks[0]).unwrap(); @@ -338,13 +338,13 @@ mod tests { .into_script() .to_v0_p2wsh(), value: confidential::Value::Explicit(99_001), // Changed to +1 - asset: confidential::Asset::Explicit(AssetId::from_slice(&BTC_ASSET).unwrap()), + asset: confidential::Asset::Explicit(AssetId::from_byte_array(BTC_ASSET)), ..Default::default() }; let desc = Descriptor::::from_str(&format!( "elcovwsh({},outputs_pref({}))", pks[0], - serialize(&out).to_hex(), + encode_to_hex(&out, Case::Lower), )) .unwrap(); _satisfy_and_interpret(desc, sks[0]).unwrap_err(); @@ -402,7 +402,7 @@ mod tests { spend_tx.output[0].script_pubkey = desc.script_pubkey(); // send back to self spend_tx.output[0].value = confidential::Value::Explicit(99_000); spend_tx.output[0].asset = - confidential::Asset::Explicit(AssetId::from_slice(&BTC_ASSET).unwrap()); + confidential::Asset::Explicit(AssetId::from_byte_array(BTC_ASSET)); // same second output let second_out = spend_tx.output[0].clone(); @@ -411,7 +411,7 @@ mod tests { // Add a fee output spend_tx.output.push(TxOut::default()); spend_tx.output[2].asset = - confidential::Asset::Explicit(AssetId::from_slice(&BTC_ASSET).unwrap()); + confidential::Asset::Explicit(AssetId::from_byte_array(BTC_ASSET)); spend_tx.output[2].value = confidential::Value::Explicit(2_000); // Try to satisfy the covenant part @@ -430,7 +430,7 @@ mod tests { let sighash_u256 = cov_sat.segwit_sighash().unwrap(); let secp = secp256k1_zkp::Secp256k1::signing_only(); let sig = secp.sign_ecdsa( - &secp256k1_zkp::Message::from_digest_slice(&sighash_u256[..]).unwrap(), + &secp256k1_zkp::Message::from_digest(sighash_u256.to_byte_array()), &sks[0], ); let sig = (sig, EcdsaSighashType::All); @@ -488,8 +488,8 @@ mod tests { is_pegin: false, // perhaps make this an option in elements upstream? asset_issuance: AssetIssuance { - asset_blinding_nonce: secp256k1_zkp::ZERO_TWEAK, - asset_entropy: [0; 32], + asset_blinding_nonce: AssetBlindingNonce::NEW_ISSUANCE, + asset_entropy: AssetEntropy::NEW_ISSUANCE, amount: confidential::Value::Null, inflation_keys: confidential::Value::Null, }, diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index d9917ea5..6b60e922 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -20,8 +20,8 @@ use std::sync::Arc; pub mod pegin; +use bitcoin::hashes::{hash160, ripemd160, sha256}; use bitcoin::WitnessVersion; -use elements::hashes::{hash160, ripemd160, sha256}; use elements::{secp256k1_zkp as secp256k1, secp256k1_zkp, Script, TxIn}; use {bitcoin, elements}; @@ -722,7 +722,7 @@ impl Descriptor< S: Satisfier, { let (witness, script_sig) = self.get_satisfaction(satisfier)?; - txin.witness.script_witness = witness; + txin.witness.script_witness = witness.into(); txin.script_sig = script_sig; Ok(()) } @@ -1269,9 +1269,9 @@ mod tests { use std::str::FromStr; use bitcoin; + use bitcoin::hashes::{hash160, sha256}; + use bitcoin::hex::{DisplayHex, FromHex}; use bitcoin::{bip32, PublicKey}; - use elements::hashes::{hash160, sha256}; - use elements::hex::{FromHex, ToHex}; use elements::opcodes::all::{OP_CLTV, OP_CSV}; use elements::script::Instruction; use elements::{opcodes, script, Sequence}; @@ -1307,7 +1307,7 @@ mod tests { // helper function to create elements txin from scriptsig and witness fn elements_txin(script_sig: Script, witness: Vec>) -> elements::TxIn { let txin_witness = elements::TxInWitness { - script_witness: witness, + script_witness: witness.into(), ..Default::default() }; elements::TxIn { @@ -1755,7 +1755,7 @@ mod tests { ) .unwrap(); assert_eq!( - key.script_pubkey().to_hex(), + key.script_pubkey().as_bytes().to_lower_hex_string(), "51203f48e7c6203a75722733e3d9d06638da38d946066159c64684caf1622b2b0e33" ) } @@ -2141,7 +2141,7 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))"; fn test_find_derivation_index_for_spk() { let secp = secp256k1_zkp::Secp256k1::verification_only(); let descriptor = Descriptor::<_, NoExt>::from_str("eltr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap(); - let script_at_0_1 = Script::from_str( + let script_at_0_1 = Script::from_hex_no_prefix( "5120c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0", ) .unwrap(); diff --git a/src/descriptor/tr.rs b/src/descriptor/tr.rs index 36b49889..02c16295 100644 --- a/src/descriptor/tr.rs +++ b/src/descriptor/tr.rs @@ -536,6 +536,9 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> { } /// Attempt to produce a malleable satisfying witness for the leaf script. + /// + /// Returns [`Error::CouldNotSatisfy`] for Simplicity leaves until their descriptor + /// integration is rewritten. pub fn satisfy_malleable>(&self, satisfier: S) -> Result>, Error> { match self { TapLeafScript::Miniscript(ms) => ms.satisfy_malleable(satisfier), @@ -546,15 +549,17 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> { } /// Attempt to produce a non-malleable satisfying witness for the leaf script. + /// + /// Returns [`Error::CouldNotSatisfy`] for Simplicity leaves until their descriptor + /// integration is rewritten. pub fn satisfy>(&self, satisfier: S) -> Result>, Error> { match self { TapLeafScript::Miniscript(ms) => ms.satisfy(satisfier), #[cfg(feature = "simplicity")] - TapLeafScript::Simplicity(sim) => { - let satisfier = crate::simplicity::SatisfierWrapper::new(satisfier); - let program = sim.satisfy(&satisfier).map_err(|_| Error::CouldNotSatisfy)?; - let (program_bytes, witness_bytes) = program.encode_to_vec(); - Ok(vec![witness_bytes, program_bytes]) + TapLeafScript::Simplicity(..) => { + // TODO: The descriptor rewrite must supply a real ElementsEnv and + // branded inference context for Simplicity 0.9 satisfaction. + Err(Error::CouldNotSatisfy) } } } @@ -950,6 +955,52 @@ mod tests { use super::*; use crate::{ForEachKey, NoExt}; + #[cfg(feature = "simplicity")] + #[test] + fn mixed_tree_satisfaction_skips_simplicity() { + let key = bitcoin::XOnlyPublicKey::from_str( + "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + ) + .unwrap(); + let ms = + Miniscript::::from_str(&format!("pk({})", key)).unwrap(); + let script = ms.encode(); + let leaf_hash = + elements::taproot::TapLeafHash::from_script(&script, LeafVersion::default()); + let sig = elements::SchnorrSig { + sig: secp256k1_zkp::schnorr::Signature::from_slice(&[1; 64]).unwrap(), + hash_ty: elements::SchnorrSighashType::Default, + }; + let mut satisfier = std::collections::HashMap::new(); + satisfier.insert((key, leaf_hash), sig); + + for tree in [ + format!("{{pk({0}),sim{{pk({0})}}}}", key), + format!("{{sim{{pk({0})}},pk({0})}}", key), + ] { + let desc = Tr::::from_str(&format!("eltr({},{})", key, tree)) + .unwrap(); + let control_block = desc + .spend_info() + .control_block(&(script.clone(), LeafVersion::default())) + .unwrap(); + let expected = ( + vec![sig.to_vec(), script.to_bytes(), control_block.serialize()], + Script::new(), + ); + assert_eq!(desc.get_satisfaction(&satisfier).unwrap(), expected); + assert_eq!(desc.get_satisfaction_mall(&satisfier).unwrap(), expected); + assert!(matches!( + desc.get_satisfaction(()), + Err(Error::CouldNotSatisfy) + )); + assert!(matches!( + desc.get_satisfaction_mall(()), + Err(Error::CouldNotSatisfy) + )); + } + } + #[test] fn test_for_each() { let desc = "eltr(acc0, { diff --git a/src/extensions/introspect_ops.rs b/src/extensions/introspect_ops.rs index fcb943c0..d4dc4f61 100644 --- a/src/extensions/introspect_ops.rs +++ b/src/extensions/introspect_ops.rs @@ -5,9 +5,9 @@ use std::fmt; use std::str::FromStr; use bitcoin::hashes::{sha256, Hash}; +use bitcoin::hex::{DisplayHex, FromHex}; use elements::address::Payload; use elements::confidential::Asset; -use elements::hex::{FromHex, ToHex}; use elements::opcodes::all::*; use elements::{confidential, encode, script, Address, AddressParams}; @@ -541,7 +541,7 @@ pub enum SpkInner { impl fmt::Display for Spk { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.0 { - SpkInner::Script(s) => write!(f, "{}", s.to_hex()), + SpkInner::Script(s) => write!(f, "{}", s.as_bytes().as_hex()), SpkInner::Hashed(_h) => write!(f, "hashed_spk"), // This should never be used } } @@ -554,7 +554,8 @@ impl ArgFromStr for Spk { "spk expressions can only used in spk_eq".to_string(), )); } - let inner = elements::Script::from_hex(s).map_err(|e| Error::Unexpected(e.to_string()))?; + let inner = elements::Script::from_hex_no_prefix(s) + .map_err(|e| Error::Unexpected(e.to_string()))?; Ok(Spk::new(inner)) } } @@ -661,7 +662,7 @@ impl AssetExpr { AssetExpr::Const(CovExtArgs::Asset(a)) => { match a { Asset::Null => unreachable!("Attempt to push Null asset"), - Asset::Explicit(a) => builder.push_slice(a.into_inner().as_ref()).push_int(1), // explicit prefix + Asset::Explicit(a) => builder.push_slice(a.as_byte_array()).push_int(1), // explicit prefix Asset::Confidential(c) => { let ser = c.serialize(); builder.push_slice(&ser[1..]).push_int(i64::from(ser[0])) @@ -1307,8 +1308,8 @@ mod tests { let mut t = StrXOnlyKeyTranslator::default(); let mut ext_t = StrExtTranslator::default(); { - ext_t.ext_map.insert("V1Spk".to_string(),CovExtArgs::spk(elements::Script::from_str("5120c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0").unwrap())); - ext_t.ext_map.insert("V0Spk".to_string(),CovExtArgs::spk(elements::Script::from_str("0020c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0").unwrap())); + ext_t.ext_map.insert("V1Spk".to_string(),CovExtArgs::spk(elements::Script::from_hex_no_prefix("5120c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0").unwrap())); + ext_t.ext_map.insert("V0Spk".to_string(),CovExtArgs::spk(elements::Script::from_hex_no_prefix("0020c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0").unwrap())); ext_t.ext_map.insert("ConfAst".to_string(),CovExtArgs::asset(encode::deserialize(&Vec::::from_hex("0adef814ab021498562ab4717287305d3f7abb5686832fe6183e1db495abef7cc7").unwrap()).unwrap())); ext_t.ext_map.insert("ExpAst".to_string(),CovExtArgs::asset(encode::deserialize(&Vec::::from_hex("01c73ac1b7a518499b9642aed8cfa15d5401e5bd85ad760b937b69521c297722f0").unwrap()).unwrap())); ext_t.ext_map.insert("ConfVal".to_string(),CovExtArgs::value(encode::deserialize(&Vec::::from_hex("09def814ab021498562ab4717287305d3f7abb5686832fe6183e1db495abef7cc7").unwrap()).unwrap())); diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 966ca785..0234a0bf 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -4,7 +4,7 @@ use std::{fmt, hash}; -use bitcoin::hashes::Hash; +use bitcoin::hashes::{sha256, Hash}; use elements::script::Builder; use elements::{secp256k1_zkp, Transaction, TxOut}; @@ -422,7 +422,7 @@ pub fn check_sig_price_oracle_1( let mut buf = Vec::with_capacity(16); buf.extend(×tamp.to_le_bytes()); buf.extend(&price.to_le_bytes()); - let sha_msg = bitcoin::hashes::sha256::Hash::hash(&buf); + let sha_msg = sha256::Hash::hash(&buf); let msg = elements::secp256k1_zkp::Message::from_digest_slice(&sha_msg[..]).unwrap(); secp.verify_schnorr(sig, &msg, pk).is_ok() @@ -434,7 +434,7 @@ pub fn sighash_msg_price_oracle_1(timestamp: u64, price: u64) -> secp256k1_zkp:: let mut buf = Vec::with_capacity(16); buf.extend(×tamp.to_le_bytes()); buf.extend(&price.to_le_bytes()); - let sha_msg = bitcoin::hashes::sha256::Hash::hash(&buf); + let sha_msg = sha256::Hash::hash(&buf); elements::secp256k1_zkp::Message::from_digest_slice(&sha_msg[..]).unwrap() } diff --git a/src/interpreter/inner.rs b/src/interpreter/inner.rs index c99219ae..8003d463 100644 --- a/src/interpreter/inner.rs +++ b/src/interpreter/inner.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: CC0-1.0 use bitcoin; +use bitcoin::hashes::{hash160, sha256, Hash}; use bitcoin::taproot::TAPROOT_ANNEX_PREFIX; -use elements::hashes::{hash160, sha256, Hash}; use elements::schnorr::TweakedPublicKey; use elements::taproot::ControlBlock; use elements::{self, script}; @@ -224,7 +224,11 @@ pub fn from_txdata<'txin, Ext: ParseableExt>( let miniscript = as ToNoChecks<_>>::to_no_checks_ms(&miniscript); let scripthash = sha256::Hash::hash(&script[..]); - if *spk == elements::Script::new_v0_wsh(&scripthash.into()) { + if *spk + == elements::Script::new_v0_wsh(&elements::WScriptHash::from_byte_array( + scripthash.to_byte_array(), + )) + { Ok(( Inner::Script(miniscript, ScriptType::Wsh), wit_stack, @@ -306,7 +310,11 @@ pub fn from_txdata<'txin, Ext: ParseableExt>( Some(elem) => { if let stack::Element::Push(slice) = elem { let scripthash = hash160::Hash::hash(slice); - if *spk != elements::Script::new_p2sh(&scripthash.into()) { + if *spk + != elements::Script::new_p2sh(&elements::ScriptHash::from_byte_array( + scripthash.to_byte_array(), + )) + { return Err(Error::IncorrectScriptHash); } // ** p2sh-wrapped wpkh ** @@ -346,7 +354,11 @@ pub fn from_txdata<'txin, Ext: ParseableExt>( let miniscript = miniscript.to_no_checks_ms(); let scripthash = sha256::Hash::hash(&script[..]); if slice - == &elements::Script::new_v0_wsh(&scripthash.into())[..] + == &elements::Script::new_v0_wsh( + &elements::WScriptHash::from_byte_array( + scripthash.to_byte_array(), + ), + )[..] { Ok(( Inner::Script(miniscript, ScriptType::ShWsh), @@ -368,7 +380,11 @@ pub fn from_txdata<'txin, Ext: ParseableExt>( let miniscript = miniscript.to_no_checks_ms(); if wit_stack.is_empty() { let scripthash = hash160::Hash::hash(&script[..]); - if *spk == elements::Script::new_p2sh(&scripthash.into()) { + if *spk + == elements::Script::new_p2sh(&elements::ScriptHash::from_byte_array( + scripthash.to_byte_array(), + )) + { Ok(( Inner::Script(miniscript, ScriptType::Sh), ssig_stack, @@ -457,8 +473,8 @@ mod tests { use std::str::FromStr; - use elements::hashes::{hash160, sha256, Hash}; - use elements::hex::FromHex; + use bitcoin::hashes::{hash160, Hash}; + use bitcoin::hex::FromHex; use elements::{self, script, Script}; use super::*; @@ -494,7 +510,7 @@ mod tests { let pkhash = key.to_pubkeyhash(SigType::Ecdsa).into(); let wpkhash = key.to_pubkeyhash(SigType::Ecdsa).into(); let wpkh_spk = elements::Script::new_v0_wpkh(&wpkhash); - let wpkh_scripthash = hash160::Hash::hash(&wpkh_spk[..]).into(); + let wpkh_scripthash = wpkh_spk.script_hash(); KeyTestData { pk_spk: elements::Script::new_p2pk(&key), @@ -847,7 +863,7 @@ mod tests { let preimage = b"12345678----____12345678----____"; let hash = hash160::Hash::hash(&preimage[..]); let (miniscript, redeem_script) = ms_inner_script(&format!("hash160({})", hash)); - let rs_hash = hash160::Hash::hash(&redeem_script[..]).into(); + let rs_hash = redeem_script.script_hash(); let spk = Script::new_p2sh(&rs_hash); let script_sig = script::Builder::new() @@ -883,7 +899,7 @@ mod tests { let (miniscript, witness_script) = ms_inner_script(&format!("hash160({})", hash)); - let wit_hash = sha256::Hash::hash(&witness_script[..]).into(); + let wit_hash = witness_script.wscript_hash(); let wit_stack = vec![witness_script.to_bytes()]; let spk = Script::new_v0_wsh(&wit_hash); @@ -919,7 +935,7 @@ mod tests { let (miniscript, witness_script) = ms_inner_script(&format!("hash160({})", hash)); - let wit_hash = sha256::Hash::hash(&witness_script[..]).into(); + let wit_hash = witness_script.wscript_hash(); let wit_stack = vec![witness_script.to_bytes()]; let redeem_script = Script::new_v0_wsh(&wit_hash); @@ -928,7 +944,7 @@ mod tests { .into_script(); let blank_script = elements::Script::new(); - let rs_hash = hash160::Hash::hash(&redeem_script[..]).into(); + let rs_hash = redeem_script.script_hash(); let spk = Script::new_p2sh(&rs_hash); // shwsh without witness or scriptsig diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index c186f3a7..b370c35b 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -13,8 +13,8 @@ use std::fmt; use std::str::FromStr; use bitcoin; -use elements::hashes::{hash160, ripemd160, sha256, Hash, HashEngine}; -use elements::{self, secp256k1_zkp, sighash, EcdsaSighashType, LockTime, Sequence, Sighash}; +use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash, HashEngine}; +use elements::{self, secp256k1_zkp, sighash, EcdsaSighashType, LockTime, Sequence}; use crate::extensions::{CovExtArgs, ParseableExt, TxEnv}; use crate::miniscript::context::{NoChecks, SigType}; @@ -1110,11 +1110,12 @@ where .rev() .flat_map(|x| Vec::from(x.as_push().expect("Push checked above"))) .collect(); - let mut eng = Sighash::engine(); + let mut eng = sha256d::Hash::engine(); eng.input(&sighash_msg); - let sighash_u256 = Sighash::from_engine(eng); + let sighash_u256 = sha256d::Hash::from_engine(eng); let msg = - elements::secp256k1_zkp::Message::from_digest_slice(&sighash_u256[..]).unwrap(); + elements::secp256k1_zkp::Message::from_digest_slice(sighash_u256.as_ref()) + .unwrap(); // Legacy Cov scripts only operate on Ecdsa key sig pairs let (ec_pk, ecdsa_sig) = match sig { diff --git a/src/policy/compiler.rs b/src/policy/compiler.rs index 1683ba6b..6da13a57 100644 --- a/src/policy/compiler.rs +++ b/src/policy/compiler.rs @@ -1369,6 +1369,7 @@ mod tests { use std::string::String; use bitcoin; + use bitcoin::hashes::hash160; use elements::{self, opcodes, script, secp256k1_zkp, Sequence}; use super::*; @@ -1575,8 +1576,7 @@ mod tests { let no_sat = HashMap::::new(); let mut left_sat = HashMap::::new(); - let mut right_sat = - HashMap::::new(); + let mut right_sat = HashMap::::new(); for key in keys.iter().take(5) { left_sat.insert(*key, elements_sig); diff --git a/src/psbt/finalizer.rs b/src/psbt/finalizer.rs index a78b23a1..8991d17e 100644 --- a/src/psbt/finalizer.rs +++ b/src/psbt/finalizer.rs @@ -287,7 +287,7 @@ pub fn _interpreter_inp_check( let spk = get_scriptpubkey(psbt, index).map_err(|e| Error::InputError(e, index))?; let empty_script_sig = Script::new(); - let empty_witness = Vec::new(); + let empty_witness = elements::Witness::new(); let script_sig = input.final_script_sig.as_ref().unwrap_or(&empty_script_sig); let witness = input .final_script_witness @@ -300,7 +300,8 @@ pub fn _interpreter_inp_check( let csv = psbt.inputs()[index].sequence.unwrap_or(Sequence::MAX); let _amt = get_amt(psbt, index).map_err(|e| Error::InputError(e, index))?; - let interpreter = interpreter::Interpreter::from_txdata(spk, script_sig, witness, csv, cltv) + let witness = witness.to_vec(); + let interpreter = interpreter::Interpreter::from_txdata(spk, script_sig, &witness, csv, cltv) .map_err(|e| Error::InputError(InputError::Interpreter(e), index))?; let prevouts = prevouts(psbt)?; @@ -459,7 +460,7 @@ fn _finalize_inp( input.final_script_witness = if witness.is_empty() { None } else { - Some(witness) + Some(witness.into()) }; //reset everything input.redeem_script = None; @@ -535,7 +536,7 @@ pub fn finalize( // mod tests { // use super::*; // use elements::encode::{deserialize, serialize}; -// use elements::hex::FromHex; +// use bitcoin::hex::FromHex; // #[test] // fn test_inp_finalize_520bytes() { diff --git a/src/psbt/mod.rs b/src/psbt/mod.rs index e20c795b..9fad0318 100644 --- a/src/psbt/mod.rs +++ b/src/psbt/mod.rs @@ -14,7 +14,11 @@ use std::{error, fmt}; use bitcoin; use bitcoin::bip32; -use elements::hashes::{hash160, sha256d, Hash}; +use bitcoin::hashes::{hash160, Hash}; +use elements::hashes::hash160::Hash as ElementsHash160; +use elements::hashes::ripemd160::Hash as ElementsRipemd160; +use elements::hashes::sha256::Hash as ElementsSha256; +use elements::hashes::sha256d::Hash as ElementsSha256d; use elements::pset::PartiallySignedTransaction as Psbt; use elements::secp256k1_zkp::{self as secp256k1, Secp256k1, VerifyOnly}; use elements::sighash::SighashCache; @@ -415,21 +419,25 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie fn lookup_hash160(&self, h: &Pk::Hash160) -> Option { self.psbt.inputs()[self.index] .hash160_preimages - .get(&Pk::to_hash160(h)) + .get(&ElementsHash160::from_byte_array( + Pk::to_hash160(h).to_byte_array(), + )) .and_then(try_vec_as_preimage32) } fn lookup_sha256(&self, h: &Pk::Sha256) -> Option { self.psbt.inputs()[self.index] .sha256_preimages - .get(&Pk::to_sha256(h)) + .get(&ElementsSha256::from_byte_array( + Pk::to_sha256(h).to_byte_array(), + )) .and_then(try_vec_as_preimage32) } fn lookup_hash256(&self, h: &Pk::Hash256) -> Option { self.psbt.inputs()[self.index] .hash256_preimages - .get(&sha256d::Hash::from_byte_array( + .get(&ElementsSha256d::from_byte_array( Pk::to_hash256(h).to_byte_array(), )) // upstream psbt operates on hash256 .and_then(try_vec_as_preimage32) @@ -438,7 +446,9 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie fn lookup_ripemd160(&self, h: &Pk::Ripemd160) -> Option { self.psbt.inputs()[self.index] .ripemd160_preimages - .get(&Pk::to_ripemd160(h)) + .get(&ElementsRipemd160::from_byte_array( + Pk::to_ripemd160(h).to_byte_array(), + )) .and_then(try_vec_as_preimage32) } } @@ -1537,11 +1547,12 @@ mod tests { use std::str::FromStr; use bitcoin::bip32::{DerivationPath, Xpub}; + use bitcoin::hex::FromHex; use elements::encode::deserialize; - use elements::hex::FromHex; use elements::secp256k1_zkp::XOnlyPublicKey; use elements::{ - confidential, AssetId, AssetIssuance, LockTime, OutPoint, TxIn, TxInWitness, TxOut, + confidential, AssetId, AssetIssuance, BlockHash, LockTime, OutPoint, TxIn, TxInWitness, + TxOut, }; use super::*; @@ -1552,7 +1563,7 @@ mod tests { fn test_extract_psbt() { let psbt: Psbt = deserialize(&Vec::::from_hex("70736574ff01020402000000010401020105010401fb04020000000001017a0bab8c49f1fce77440be124c72ce22bb23b58c6f52baf4cdde1f656056cd6b96440980610bc88e4ab656c2e5ff6fe6c6a39967a1c0d386682240c5ff039148dc335d03b636cc4beba2967c418a9443e161cd0ac77bec5e44c4bf98e72fc28857abca331600142d2186719dc0c245e7b4a30f17834f371ca7377c01086b02473044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801210334c307ad8142e7c8a6bf1ad3552b12fbb860885ea7f2d76c1f49f93a7c4bbbe7010e20cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae010f04000000000001017a0b90df52169792d13db9b7d074d091aaa3e83aff261b1cc19d291441b62e7a03190899a91403ca5cd8bded09945bc99c2f980fd27601cada66833a5f4bc108baf63902e8bed2778bf381d17241be029f228664c7d1522ced55379e275b83fe805b370216001403bb7619d51d2af2c5538d3908ead081a7ef2b2b01086b02473044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa012103df8f51c053ba0dfb443cce9793b6dc3339ffb0ce97af4792dade3aae1eb890f6010e20cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae010f04010000000007fc0470736574012108a337e7e0ecf24c121a17193623254c277a306e9fd39cd5aaf8b7d374f4011c6507fc047073657403210b8e11e3b8904ac80caeb16af1c93053f8a11a963269bcefa96823d75b8640ae940104220020c731ad44c00a2928d508ad82b05868cb42733a5b0d0b208f483307ce8c328d9307fc047073657404fd4e1060330000000000000001efdfbc0022a6437ec10c672d76c513868f403f6b9706e09733d6624e3cda831c2c199dd4c5763054a1c219e079e8cf3ce0c00dc2f16516972e1e64d576adfd9f5d778675c8a3172450a4cc82d6e6c59f2b16dffddc902d0aaa647b750d6224cafca7239a4fa81219cf2ee89741ffc5b7dd7e47d332ca931cffb1d1d432935a6013207629118c965b7a5102e62c43ca9d06bca191307a476738548536809ff6b01c6b5b25d76ff2f67d99e20fdf7d2eff6fc248186d21d054196023c5e4f572ccf0f3aad8728c46f2ff6756ea39de46028610a3d26cd42978b09e0e29e0a8aa46e4fd39d28d028592560264cf1a794c27f6c95d382f486dfe900a81d9d92935c7e0e6306549b3e49b1f60182512ccb994338c3541a2956139b2ccb3dd156853105abf5fb394cb2c45915dfd4106c7472dc5d360ab5bca408203a3fef58b4dd33b0c11c367dde2f19c8af7682be067244bf49a2b8cd4685f5481cc31ba27fe2f3d7b7a353be9b41e4eee2342fd70b8408c91951c71c75dde8fbc03e3f28e6d3d3b41e0e963d3ba0c25b2eb50560c21221950b0699d2615f0128e6cb7fa1b04ac1a046e569a7e87df98c14360b8ffc43db5e17548c7ea5056f84ffd14f4cdfc68a4f10e9b391cfa63eef2c2d623e7cdcdfae2fc4d63496d81462174ff360809b7e3b4305979d9cb8e9ad5b0f012494d31ce51ee6489555b09dddb16641ed9e2534fc34db99d2a4fa736eeabacf2f8cdca97f9e84c964277c6f30f1af7fe2b51b39b487d56ebaf593a3f98e811cb09849c5b445d5b7c9ba37807bd0189c8bdb2709fa70c230f9aba41dd3c62384aea6e1ca098ffec26367aa65a09459fca074d1da0365cf7fc2d8310ae099b838ca78e62cee10f95ec549faac1ff0f8236fb8cf2c0f6654e471d3950ef45e0159c44f9e343d05b3af59b939cf76090d040376407c41661eeda7d2cb61cad0088a286948787dae0cc5abdcb97f7f42026c65a13e1df1357c25d376955942adc858e73876e1d8812969055d55decac9a689dcd11dffe5cf6e06088b93a11e153ffed104266bba472cebffb2b0cfc8ef132309bd7836071d3b6ed459a5950c64cccf230015c98f9210f2d57b7f3a07c382f3df09f055c88e1f312db0d60d471afdc0b780d319a6229babd8f45edecff8d1073fa850f755219a3ea14e7234cbc7590c60eba0ba0cc1afde6ce91c8e8835b1ca809926b3e7d8d7a0941425e5f08e884f12693eeea1b3651f53da90972aaa37d426f37db3edae4285db114cbad5964c269e03b15358ad2a7242e0af538a594fc779ec3c43c3d94fab2028310c6d0acf3efdf0acf028ee757c5c02bb5b8b691aa5eed1a62acbabd0d61faa478cdcd54c6db2cec6144d8d1185115097a7da79c16ad3118d12e36dbcb7a70b0ddb27bddfcb1c6e5426b7e411f607d22c3ac2b8d3e41f55faf5e2105bf3b943846cc4c33edc64f902c1eeda09c8110d4f3ed0a5e511156a3e368f02161b92126abf649341ddb8ed03d1d41b91fc34548c6d94dfb47c088ef27a3cbfe1c9cb05f2ab2f18b8746394c8080c4cd92e818e46f861614ab870cb7ae3446e376793f3a6568a2ccfc2ab0ed0365567671436fee6cf427b6410a046d80b9d88f094924ad370da363e8eb70355b711687e92d88a08ed811ff241c7a6dbbad9dcfc18e6a42493483b938e36c1edd2a1c6e078a17c5d145c9c058b4dd69afc44c345f1c88afb95c1deb5c4994161ba25783165d43b9e50a2d8333a8037cec2ae809a3dbe026d6ba40d60badd05bce73b0f9f36966c30b9c0cb5776544c1182024a96e746a3b01f9db10b45aaffd3b055b02b40bccd41e57c10719bedb0fba99a0f6b0868b186fca0397ab8c219f33190f81e4cce2fbcbc0975c394919c98fdfd7e25a33e5f31fefd06c8dc409cbd3e743f0f48dc90abe45b2e68948436caa37fe9932a77b7e0fe0819d8283964b0eee2249d9190f3eb0bb8178e10a287be1059f35cc1a153dda14def65f3c49cdc5186da86bd3e965446f914e3c9b4cbfcfd2c379f306c5ef8844c4fd398b3c6f96601e90d2dc8810875663939f63abe3ee2e1c8a9c2c2010a01d0dcaebb556a7c98421f8e6465cb0434c07dcea9db1a142f9684e50b06c545785f0dee4def1257e4bb22d87a2b37ca9eb53081eb8f1ea0439c4575abac435868a36552df569ccc63477594ccf7eadfed6adbb8e81800a2e2fdd7effdd1e2f09cf76c9e780f6f8eb8408a3fcc06cb8bcd28db7a37edb0232a6f0e509c684318f179d0c91a97718ce3956c266790361ea3a1bf70cdb8a2f2a59b06dee18075745c7302db9b13a452c188c5624964af2d5d4bbb1138dec59df5dfb077a0f62ac4db3de81f54365f2a4a6dee63a6092b4660d3f5dca3cc8de3bb5350f5dcebabd515c72c9114bc58d96e2e863106f0982c2632bbacf2fe5cf6a8df880c550f7008fd09227baff82d4eb031802fbe7d50f6174860c70fcd9f0356e34c0d45df66492dc309b260b7158adf678e2da66348ca84de3e721c6196e0c717f59cb802c6866defdd9032a4b7da82b816d9681e5eb9115fc2a572fbbe105f479ab339bfa5961aa1920346c9ae4185a74aa828da78a71e55876c657249e83f5812cfb055400da1db8bbb5ed3ce2ca4655b0c39b698ed7d235fb0ed4f29a7e8925cb873176efcd1c6981dd23865468c6e01ddf61fa3e40d6fed18d8e3dbd97a08c68bfb092e441e512d44089cf563509785dd58203949a1ca9b66a700db14060a760aa404e5e9f31eaac015f1527f6d760d8714c88040b87fc8a4d183230cfae35326947e28a7a37eefe1d77070f5232a0d67e278a45d649709a7398cbd43094c5001263671517f83e62e79fb75e6f9bc592fb3bbececa3f597dee71dda0fc909079ea49d81554d2fd79d1cf3cf25d1186efb83cf972b7426600d7d6eb6c48a5f0e26af640c733f3f771e0926e6b38b6f39d7882b0538dcf281d92a6bd361bb32e16f3988d6790fa0a45f549e983f4eb68ce5ff11647b37f8e4c444aae8bc0f7c49ce7215545a29215b55f37dc42aa6add6fd1fb45d9ae580434097e7a8686e23cdbdbf6f8b6b1e5579a7908bafd8878b004c7c94e045fdf2b94f8c1a75ccee7bfabd9bb6d0ea8a60dca61053636160c19f8f3fff3d0330fc95d20a1393629f33f281e5da80a5ff66aaa5eefcf495f8bf7e24744778841d7c633f01af2305a122ee093837998e87f060105ffbc083c0d71f68c2c63820d7a547d9af5618544efb9736af56736e73cb696f191c68970ea1deb587231c889672b3b5399b9b5e915e3c567474c3905ec5b6468da826f1a6438ec335da847db540a091ab311c6846f96a2f17befa2f29ea491a41d7630e42583ad1212e6c606dc258a49f756e2480f90775c04c5c533300e37f8bc7afe7b155fb95877252ce4a53f78491ebf9d8a4aa41da1848633816542901d56e66f126316c80efdaf4b457f9ce771edb012a0b3c27c717f5cb3cc99ffcc959a02289e30d5b1ff936320579c469bd55cba6e79a0c5f1bda59981b71840a8c1ca56863e91eb21fbaf84525d5f04e0f282d03bb56d6dc2352f163d8357b86bc6e4e621bb693db3565eb9ef5629af537874c1cb3459582463362dab3c6fed7e574ce9bffcc685b8eea61599292cc69860c4f9584818182f94d719dcc463e9a6f854405ca2deb3de29ffa1826f795b7e7ac2555c0ee576c75494cb832c59de8d9620927167bc136549b731ef79a39fbf8789831cc003a772fa00d4d699d089d47037e12e1c6eb8c20c5535225a33a1a787ba866ad481e9a4d689c83d75f1986405c82154e312ce8b3494ac5721b96193c025bb75b2cc974f9171297da058d2ed4f00d94e60737af29da660fc51fb9bb4d241e78c9d1815d7e3ea90aa541c4c512ab423ece93f9ff2f479f464b953b4171217b758b280c5d8acda32cced7bb0c92cd9b405afb3a8405602da914e1831fec5b6a291f90635afe82b9389a8b41d957f81be125de2f943b7cda9e873fcd74b446bacc00bdfcbe643053f6cc8162c0a98343242b489f59f7ebac016a7fbf620dafc15c8ecfe20b954153dba19eb81087673a1e847238864036e9a300239a00a5a03d8b39aae2bc201c04c477b1f2a37552670c06ea65551c5c88a42476d0d797af494b077737cb48050bd35f4980964b8b9b98bde84615e8fdca407230f5d15e97ae65d63a96f3d88518fde12d6a82881db5c8d4cd79e724312e88b394129de3569c5c99bf842a90f193c91fa55a82116e237c877dec2da6dc652cb33e33df47420c5238fb6ba5fd96cb77f0cf6c8a12be1a95186680d16a064d9b1a7c2461fdf5e0a512a5a3ed2f8dc0eeadb6c95a658aa1c2713fea473de51f65b13a40a2fe64e5227bc9248f59c2bd60dd2fc14918e333faab6e792ce2f0597be47cee70f5a8b788a50c9cd153bf24786aa80f631ad21926e3285f41c5125a15c12cc889112df0b1857020160122c2595ab3359bcab184ecb32f7cf8f38eea23f4f9135104629d8f1e8273c44f8afa129d3a74cf58ce494214629cd53b99a8489ddc5d339e317ce75dd6c5dbd098d811c56ec5f19c00fa00b5465e39f8f2022c71ab3ed0d5a24058c197719551985ab30a851390ab5e11420c521b1398bff0038d904e5879db37d60c623a0a82e191cd0b6bd20a9e956d41d5daef703bdedd6bd0e20fb096423dd39706e939e796aa8bdf071e44791d2e1ed4a81ffd018cb79c5b6bdfd6297cc6cd379845fd7ddfdb0b83d7b26c21e3edb58185e71472a79cb65322579bd5e0e7b1fe081dcae5447834d70459f8a96b341a26d8922a2b1412f95f3533e04b5f65be112cca03ca45ee0eca10adc7593c78c041281c880d879125e585e68f5c7fbf8686f245cd736ab5aadc57c032c637b753b49575acf4bbff46883382f408417438d7817097accae3fc54afc6015b84b3b05627d7c83c4627c87727bd24c4b4d96a08c64164ab8d4abe3fff5c3b09e8fd12498e3cc3627e799e4ef72a870cd89598d51ba396655b4de66e48997faa51d05d581c52f52852cffc9f89252f26d314d2fb8fcbce197f3a8f330339c2ec3c710710b74f0915da3bbb638b1f1a0cb0c176adc151da0ab52796d466b23e8a269c5b22b76fe7586cbc217621acc955a43571dc04f69deb50066cc587595cf0ca4e9a00a261ff2791ada8de04bcbbea249d2a7840bd8fd3ef98a248eacb7fea5318b2e207668e13ab4e5578c03315d44b478df5247d8afd0624d2a57adf85fd16d86ae54cca21f6c91d8cafb3b31e3f9c4e903c04f39d67c90560dd10b2d28c6ee937cae01e921c98ddd833a9b9247053110c0f29d2f35f8ea322a738636f17648b627db622a9cc891fc1d066d5fcabc168f1b492479b0578d0bd8de0298d4bb96a4351714a10a39de49d57ad66bd6b458ae0d799a19da54bf620c0e6979a95b61a83cd06e46d7d263d53d66f77557232983268f5fd01d10442af0c840ab09c6cc4ad77add6379eeaf98f7cdbd70fffcb035abae4efecdb7e6f63ed8acebd8449b3a910e5eb06b0ee6d80dd45026c9e6c2f978f813b2800386a4d7ad9d127d76c4286c1b2facccfd16e6a263ba3e2893ae5e42049d421e08a62ee9e9574a1f70f0add7b68344256592513cc15f4bc64c5a029f60d617c245c1c34d06c095b2d0a9647e65dadb33ea79e3e0ea62ce55347d24eaab7cf9fc33fd70c07363771f78a13d92941daf7970c97b43d2fbe3e789a52ae7bed64736e6ce59f95322d20f9d6dc00b5824a0ce9072dd051c66ac20d39bd953f567a831d75fa91fb4d49b200fc893489e60df95c2810f7fc57b7f6b7725ae600e1c2def6a943b8d111ff3e9a5ac80aa981fad8709e98ee1550005bb8f65dedffbfe3793abb407fc0470736574056302000359a33e8f3d0439eb7d60aa79255858269bc1011e4cd0d4aa753bc2793f9638fe70dda4a99191f08700047a8b66d9cf7a53bf70756013c8630419e3a0bf428158dd02ab6e16822f239df0a6f1b67b6e1335509a286b30c4b11a22dcea9f95d51307fc04707365740721027fa518c54bb326d5ce3da5c2eb8a6521ab99df86b511477d0f5ebcd616f063ac0007fc04707365740121081271c10f0caf52a40e015e7d35966dbad39525a6c0691d4beeb3bfb22af5304d07fc047073657403210b85bd6dc21b4919f6ebda7ab86ac8122c793be3fad19e44455945ddec8b59e9f6010422002058037c2d81d3122185c8704d4276e2629122c95b8ea68575c451628d37eea84507fc047073657404fd4e1060330000000000000001cb6f1101e2b960c9a2fe480eb88fc76c63e58b57445c78d88e04f740580a36d6956006ef12ba606aaca89796dad5ff7cb4c4c7f4e65a07fea8a2ce3b58b265d4b3220013a09ecf4e01023aabca5586d61ecd5d7f2bedceb8b18a8e41451c97a192098b196add06a8a6b619e1e731fd9ae2973741aff6358c1ad45cc873a2d497271e3a20873a6f701d4c44ef670c8c7a9793079d9bdfe956bdc02a52d1de8b2de58b0f7d309240999f13985fa8c98e57fe1bb75219ae6330e9495b523e891dba7885a5302817d68a9891ae0c2597d4d7833b91b073c4f9b27be1cf81ca1c2c1014c57a4affe7b402c0e0c1862bd17bc1d43428671a106c26cab61d5e4ffd1c01f6af1c6e97f7a25ae8aaa8d2c91c57881df52bd5f242b127ec7aed5880101caa01783884dfe943ec9764473323f59b27a204f34aa1fe7fd4433fa606608b0f253247d149e3e269ae5445e917390be83d5650c05859e3a817a6c7e561e2b12baf6d4ca4221df0b7f29fa134269139afd9cee5c7d60149dfa23031705c6a8b72d00d659d7a085de8330de2e5c168ee3eba2180a9319f5e8e0806dadaf0fffbc2df839571360b8cd32300504a527cf914da7a1e788261c9cca2872ebec5a17cad33b15a7a7427c200b8746761359194520f0da1d7ae03f26190d07cf92d515e04815f514c66a98997320a028ad24e83182f213d991accf19a8a59003a2ca666ca505c0d8349e2cb22887efb7db9e4a4e3e2d8da0d5f032603e03f48fb967fd018fc99c6eb72acee4178edeb48703903a89e9462a2d1f447234c3373fff8b205848c7a9d6e45ccc31eeeb0105ed3af1188fb847cf6f03a7f0a646fa325b672796168dbbd9d1d19b2f41685b18c3c96f1cfb7ecb1dea132e8815b62647820ac4b12597d8e737a01a970704b03ba5ae68f8d64a1810db10427fbff1d74cfac91561484cfc8d3b23f74ba0f37e7db2f942c58fb1dd30f6a50c57b5eae720c6ed69b0fb81a6e0260c53028c732a544391e319987a24548230378f8f1ddf65a2d654c7b26951d5c6546cc8fda6003228e8913c9e3c5adf7b7b72f4ff5c4aedba6096097f9a4b58ea1e060609e8d1f0fb0e5dd905b29fec72b118d40c5f599a63f9a37041742a7f1af3ef951c31833621842ec212f9fc5cd3e8c08278ea192f8032ade447d2f35ab59810aff371f598b7dd57b3cde2ad854ecad0c786150748ac241ecd67cb868663a6fcbe9d68c3dc221d4fcec9b0ad89c337c1e10b91a38ab1357f260ca3a084da536e56262973e6c6cca838601fb2f335811375aed78295c4b17d3798d39d4cbf6254ce57680a102907e5c08b5c7ec0a1e73bf3d7b8babdc6156c6ca3f09c0423d6716ff4e6ee0338cfd778158202b5ffb60b74558dc6d0be9b5aed6892c4e0ad3e20de5b604b2b010af09ceaba7c0fba5a7fed39d31cb2769909a251ba5b0668330f734728f5c6786a8f1a35df77f3d739eec71d9268fb2a494a14bf7ab91c075023e76856d1745f5813d83878822934d0b4cc0538048c3f96cad7aef2bbc49bab139915dd4998ed3c6701973eb7913530b14c688f0b344ca9cb990de2a9b12fa7ad8b292234a33428b4d16813693964365bd412fb936c1461fdf8dfb0bba31202685f29addf95fc65f841e97042bc5d82f103e41017c6ac91d3d266e12db2dc195ac4f6d4353924270c7144cd96dcd07b9612e2bf1e0f7fc46ef83690648395c575a13c2b2df0fa04f740340e6b116b0866a401de22f68fa3f621d75b9f5f625cd5d5d7e12a5b0ff795749d742eb2648ddf068a451059390da566b3de84f9d528b2663de7dcc562eb014071e8277a054783d322fa67b9e5261b87e9c354ff58fc52bf9df404139311d6bf9650658fc94835a6220ca02a4bfbf46b2af4f30b1ba681c0de7c134d98dd52eb1e937c191cc9557aa73a343b99ae0b8954a3e929174984b574da75e90a9b71af1215317b04e4090770ab596091fc05c82235a324f86280f7fa081360ac758c1980c6a6763453e6b344611e46b05760941f9517ceb298ed7a2d6f96b11f5719ed0dec803c511dadb8d056d4ca06ca0ad090558a4fbf3a886f3ea9c33e1bb4bb5ddef4798cdfb384bea75a3794c42a53af60f12c95fe9b38d7f6a5d914ef100508091fc84756b596b9ba08d1dc42a7e253435b5481d1470ef00a1172cb036b5bdfaccaee02b15d099da17f9753846226325232e71ed9b48f57697bb3d1db75ed214310e6e3608ded6f188e37b21b96eefaa396db0df05a86416fe64aa950eea87e7af4407c828a8822b17be661269c9f9e365cdc79d20503e2d5e575c5387fa961206118dd379834aade7727a1b2477a24f05f6c2ba3156fe7f5b5ba6d7487b1a124f38e3ed3cda92a8edf05f28e3d699f0c12de9cfeb30ec8d4cd253287a6d3f596db0c06006a531e80083f5b41ee26c05d529e0a59ec151b4a9260a7ea8c1a175ca41b59f464adc122f448fc43e90dfa7b88f81caa7a84e3d6d4dbb85e5828b6ae7455dc2c87c8d9c706af2e62763675851b4ca449c9c0f95d953ce53c5327ba8981321a1cbfb76bafac7fa17c99567725d8e0ac288f3ccd3bad666e515156517281c97a3dbfbd5f345f8eb80bb3c4230301a38b7c920d74eb910d380f884a683f7d3e2738fabf9646138e8a32c35e43786e67925508e4cc7b1e7a36abdf6a497077704e216f1e730c20ecfcddfbdf2484d8eb0ef9b7478f77063fa90b8afbcd019d1a584df58c537b40b193f246598ae4c53958a947dd3916b14a5a4227f01bf543a8c5d6ab8eaefdfb959c8715b756a9c797fe39229dc56a86364cb367fa37e16e96cf8dca1fdc8b6a46ce88e3d29c75b6cc718ca8c28e9e1ae991b28c286107c1dced150814d6369cc8003b2976018941df7fb8eeb68be57adcf8a0e813d2fcd16dc390ce17dd0a91dd674d766d21b5de7f4678a548d75cc3de7d099b418fbdb66b2a2b12a56b1dd8b3f84a7b45e36db9bb63b3ef9fdadebc21c6a75364173925ffc69d481024e49076dca105795e7a64a3c82011889aacf0114a1bd31414e288cbb63eb47d399d0e025a54f11670c8ad4a793d0e7ebd3b0d8eb30b87cf62b131c61a4c55d2e56e47ae99fc543c57a1877ce44dac4c6f9fd99552701ade43858e0b4020230cb4d42d1990bfb509471a5c1c5557c29c00072c5cbbc056de6d465ea2ba2f4a1a5dd604dbf998e834b9200c59fdf90bec38af9218e47ea5ed5512cf8b0146126a15d49bf915eb893ad1ef83d8faf6c93f944ebce3704f930b6f69a1afe767ac2c9fdf092c804c7372ae1a64bca3a3b5a31f2ad430ba9e61dab3daa3be90a538cf0fba00796de511cddb5a594f14aa6d215bd0be19c0ca5f043403b7dc56c87b092d9436eb79509c3dbe367c2fcbc2b09f9818cf5a55d5ee0e477888166bbfece661b62812ffed3e4167ecc81dba148f89a8f2e7c27424a2ee091ac487e68fbbf9798e8caf46b35de8dde66a7cad6dc98a426ea7b8b930cf2d7d71fe71066dbe51e8a1c7151e97fecbeedef3d6f8e01cd5576dd58097b46153f9c3bcecf30bc82b4cdfb1bbfa826c7c5b217a023e4da02a35d0947b2c4d24d50a292e4c70fe854a420c54490d4850ee8c372756671fe130532f89878a64977ead60bf604b73859ae64ed62536423bb51b30c6fedbc819fdae05cb64b87b153f4252b832d6b866100a7b307d1e705643f96f0724858e6211802b2ce706d5424b99315db90c7d74fac66951251f6cb739ea008f839c7f62318f795337ca4ff05886a2640819873ae00b933081b64da1101d1b17451357921a2f4d4dc86c92a5eb346fd6cd3a63315768b94b90a15162aec91cea706b9221330db154d1fd71acac90be47055c725bce38710f1b4b4144f331cfa9fe15ebf6535747669e4aa1f0d72092ef395f16a4ec9014029b5c9d1b4bed9ec81a7568f8f1c87e0ce0f4ef9cf49e3fe4960b0b7904614772c63147f3c5463fffed182919c4973a8256346116be40b10a38cdea5bad5878760daaeda57476e86ec65e58030bc8ff99ebf017e9bf6383f981edc83b538e2bf4bb573637e6f4717d74a3ac71f5e151259b29c1b7226e3a8ab176baa2f27e3e385cd48c6f072bb6e8e9c92e35d7ff51177f4e3553555d967c04befc1847003a8592738c82eef231ce3d372372a19a01b27dc7916f986ff3f3ea8872d4986bc1ca649a92924c8f582ae2b44028e711e955d2563c33db3b7734aa246de553dab2c5268538f7c2b6dbe9a70657e2a26e52f5d216dfa9aa8e197a227c86a7d3b468880a721b804a0c51af1592043eee7fe3657b40c1832a858cfb4e037d208ee69c4fd697b929383a971b2a0864544505af2267e334db5f3f3f4ed88e2f6f2b3d7b96016ff92a120556e4d1e50440943893b00508c6242bcc41b6d06dc29ba20564b42257b9fa1b5f4f453e94e72501d31e8947e09a38261020400db4b8cf675b1854639a962a57905cbbee14ea0daa9bd281fd635c8f900fcabdcbcfb140f4f24b47731782ca899284fadfc9d0d6eff77045792e139afad34c7672bacfa22d85fcc05652178cc169bcf52ee3cef281d99935abf9c9910caa7994cfe33b9319d9854aa6e2590a86297f23b0cada7251a6ee1b2f3d2cb5a193cae8768d92f556994e416d4bcf5bba3a295d9e2215291237df74e3c493189bc5a27b3fec3e1a1329c6c6c75e0802b40fc74776476dd2d9e3453ec1709a8a2d162a936d9fe7dd4b6f7abdadfa429aed4cbd5896cfb24a2d91f1cee781d0ed73cf7306d6f9545fd3346c2232b8799553357a5a531d6085d04af5f183019dfd3483baf23b0ba5a6b58bba4b7a1eb0a32626bebb5cc0c4dad45c55d135be8b0a4dee787ed48b90a2a3fc120a753b52290c27ad0eb32b668a9540986ca0256c1676debc4d19b1b80bedd81e505154264a199ef1a54e1fff1b3589fbb6b2d87a1e04e67066571b68fe04f030d473f8d135585f8b7be91f0ae1a4fa2f44008c0f727f6aba9c5c60c3a9ff22911e267ffa2a5d1c71ff25f96ad257be29a2ec641e2055d785765cadd0c2fe513c44154e74f4b8cc4b24d9ee2f6cfe245549713f9dada1935247a2ac7ccc13c4a5c00c6ffe7ca33c0cde4c75c4fe2ea041a965e4c7385ebfdbc348da8c4216a02fa829892c827adbcbb87745120667cdc5a4aef28b190a54b422df45b8547c447765838dbf9f05de338ab672706b59b2f0644d6735d9316e64a1a15d3dfad893bb1bbcbe1b574a0b8ef5265e195a929148cc5e97c8bfb032d4528b523b6a6b29209428f38115cd102e3b4e268333e490140964278238e7ea9638ac34559e05300dad0c3f18e9228474cd3a7186102967c33fc14f086b4f1ec3957d87f2609d140dbb9e7ff793101d1cb90d004565c6a32924715b1bcab483e6389e2e824054edef350f328870f16412aca0fee39edcbd02a6a667aaaeabb6654c4762c639a26286a3c1730ab75defcd9451b4377f6acdc3b905684658c0844d904c47d313d85eb54963fd71a9a76dc8e345e479004f00e446b886ec41cf7bbb9311463e877aa4e357a0dd0b185a5cf12244296f5f8568e84cf6ac3b6125db6897e4e7c183cafc04f61b3263456f61a7880b446e3cffe986c3bf027c7deba490ec8544d2627e6596ef8f8a5cb577796e7c36ffc4f4346263b5d86ae1d7b8d04709367349d590047a8bfb34fbf6481adce60eddfdd1e148ab83874d70b5303fa0ce60c0ba7a047a477dc4c513d2218b0bb2bdf9b60be9a39e928976464e333ce0cb19aa21fda1c6851c6db9d5bbc6552e080f8e448637af711fed92e72c8d8530187de94603377dc387041a9eb42ac70b3923b9828de33bb337d55409cb419bf4089cb2bec79ffc3afc6dcc3cb82bc903d956d28e307fc0470736574056302000318eb22887126df9062243038440ef3fca2aa024fff8739db4930b314822b00cab172e83c33b7e5b959b0c3f27c714e447120833ef69bd634d1e011fc3c2585beaa882a29c2dabddfd31a48c0255d1ab57c6796aa4625a546a02cef51a9ee2e8007fc047073657407210302e71fc2fff37aeb6d2e2a7b7f2308d4ab7d4bf0a4cf9be7c06e89a66442b48300010308f40100000000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20104000007fc047073657401210970cb1dff96101101e24bed1a66fb0794d2fcb26aba11e7f2393edc1534df8a9607fc047073657403210b9991881df2ec384ff5616f6c03d45cf033ee64536297c3557f9fffec716c1fbe0104220020cd4ed5f0db8c450e8b0be595b6410c1759c19f1f6926279095c83dade9862b6d07fc047073657404fd4e10603300000000000000018b6d2d00790f618171a9e8eb6051fc14dc27c502a54f5ccecacb4bcb350581a8f4b1a887a1e58865a21f51ef5098400c115cca84f489637718d8c3ca4350ad677374d40d2b64fe949ca34bd4ba845a87c7693421b70aa8d852e021aee329762883b9820bc0a47ea2fc6a8411ef773703632849094e51c73997c67f3e922d2801b6abc445375cd963a62c2bb28d733bf9274fe503081b51a56023a94200743e7d38865c190331449d19bf3d4eb7bf0b2a9b90696484aab906b9470e10946744838fc428f88461864d6601e93f10909e049a315fcc0ea7f4d71507fe5ed19b9ac2f55b0d3902b153ee27da9c55ab66debfb5ca440dfbb1a600cd8875049c4c13bbf242d26b10035002c7859f9c3ea631d955914adfa0817e4801e85b3f250cd9e7523db62c4ecb17a49028a02a1b61eb96a410643f1fec0ac664d96f99a1db4ac335c2bfec2946707c3c779a56373db197039af9a903e833af6f51de5cf8fc667dbf5416845d415dc98641e0984ebdfab88bbcdf305f605d36f7a472a516206d7ec722251e269800a00e8adb8f2ce161395c1c6ad4b406e1fda77bc7f0af07ea075011cee6cc5e7fd1b6e96e321171ca7d28a35595ddf0b0c831d28a88d30c7391c5832d90f906539aa49185fc6c0864e2d10b21160991fc19a1d084006d03fe3fb6f571f1ffd9f06ffbc0c076689373f9c2f8655758f7f44618345a6d5f8edae46e73a09c38157d5c39dd51a47756ea761e6320d6a91a1bb22d8dd35e4e7806b0242bcc4cae8720a953c6f933c0ee3216513cce6742a2cb4bf44553d8eaf175471dbc0f71c7c245fe99ab4240ccac637a16c82f0c60586f00d83ff852af48a239289d8b70a2638b0aff02572d6d2d68e22b87ba93f3db51bb27825265607ba4b6e9a194c7351f220b9e715a23237c40024fb7cfedaf7c8e0a1c4c6aebef8841fcf2609a3dd7f44dfd8895077df41f10790372eac8adff5ea7eeb28e371b4700d5044b41fd358dc4ba29158213e0f93711026fac8abfbe7cd80a939477ce545bc91cd1d32e8f2268563b0fe3e80855777d51cdf4835050a557d3c7b7f6905ba744ae5450d22837d2c2fa0c0755934654a78601a1fe236f11b6d72f368880ed938ff4a2e8d82c118493a1bb9a9ee95cf329f2d175d467aacc2c6cd73ed59ce64d508604db77942f9b7f3b0f86d913d3e1b489d2190a6da1ed997ab1eee356c885270e4e0192acc9c2b8702107c96aed654318bbb7724b913808dd2cfbbf6ace8db9c4cbf26f2c90a76eb967e365c58855b83550819cb5b28ea5e6ec1ea153ad3ee5e6292a174f7cab1b39e852194a6926bdc4d42326e17998cc057f614e91f6acab5a5bbedd93d9a13dc61977aa2accaf35370a3f1d3819c43c9430d0e767e92de96bb225007a7b6576ed7c4f05c984ce2e437d3b7f7f50c270caf90f8e5dbecb992be2972ef8d79c7674e025ee06b1302bcbd57fe5be9d9b4e38f17d9dca898ef3d71918550fd77a15c7aa2b66ee1a2f38b81040f3d6ec6693f54cc3fe39515275849e9e24b0af3e81705dea95e8f1bb1b4665cfdeb0630a5542a2857f2b58c36761d743299d77872d6894302123f4347702572f04d9876191d771e87655c071fbd29338eef0f9acb0a8ca3f0327ead8e875bc2e7ba38f249e6eda1fb74162e972ff523d20c6638b93297d406e9b2264187c06d0a78203d771f2525227d029b27b23192f747492b9774b12b039729ef75d11ce8d701e56fbb202f3e4bd68686f096f13680456529e5f132915595e0e0b4061b3014219f1fbef4d7403dbfcac01c701b7727c2463cb838d427e07706400be4fdd9140a800e47e7ac15a7a8a897187a38a0080726349d8b7566252076b1ae1366496b50e9a6d236837ffa0c4c3e61bb409a7d9faf8662109ef7213007a76a6d94cb79ad07183a33a4cdedd78896278a3b5531ec0efda9d77076d85a63536b426a6b58c3d0e8a46faf0fdf678e4964272e8410b346cc753edb94a61a2f309f8e753ff332f5b15215e0a20ef32e6a6faa044a431764e008e66b4af820bb6afe4d8dc1679219fe7614482517fdc523d4d7ce2bad9d59f7b9aed89b813e5b36b58a7c668e53181c0e1da45e4ba3851b46de8e056d63e440c471fbe23fbffc31ece7cd20658784f2d2fca3f730a1f8a90ea6995ccb490fca475b1441e38468433d1423c1d83a20b04f1216aff13c8e035c2ed389695c2bb0bedadc38c8a6222d687f0235bda3566c0865774bb6098acd674ff9091db1a6c4f0c2955c1759730b361f310d956f892089f500eae0084022e610ca4e758ce2c680d213bd1b5e00a6c991976e93189159bb98a1e4eff14f681d47694060126c0852ad52489c15d7302d82c66aa830208a9fd13da87a2aac3e44dddae632f2e4d56dc768ee6b3622c61e59aee27fee5aa0bfa9c56402ae3525f00634b11381d0b9637ac699e4c4b225c32bef9dc563e87cfc33bf07450c2cdd015bbd94df63697cdd9b6cf4169cfe1f626c126dbb588c57542662d02eeed561946ce94b46571f72ca3cf7fe52a8a6ea24fa216f01655dadbeb0f74e383e522da69db64b368cb155c2ba4c4fc8aea8745b1081223317003f0cd7ae620fc7d9a6c9c4f39a237d5d9d7f3e756c77daeccbd5d06ed28ac2f089db5449340872bc444aa4aecf6552621b84e4fabfd6baf0e1b61cab00e5c2050bfa38899e9840e2dac55c7d5e7105f65dc3afe3c35dd3e8ebb1a013d65fb0b9d76665f3c4eff5b766fbb0c03cc10c411987ef516405296437a91a67d7398d788e30f55bc1e6236b317784504c53800cc07f4eaf78bac03a025a7943573edcc67db3d5d5281f85ee993238fee3580cb846efae33b45ee2ee1ad640b1d068302504521269a31a166435e8fd964d2e15048f299a95ec1cbeb0c8d5d119e24670112d61d56ea120d7bc30fcd924fc7b812404ac45798af3fb590570a4d7a3f41639b879d1bdf2c72c979105460892fb41570cffee716679eb7b4124be188e28ca4c68d206c1cc9d49cd7489d63372853dbe83f874579238ecdd28c0dc265871d6dccf782b571f1004702121e8b15c9d8af9e6812dbbe742812c7e7cd1dafbdbe3d189f618936e270855700be8f6a7b528f271a936a2cae204b44d909ae3f6a8bcbfcda44b430397b1c96187e5a8362afe92bb9afb0a0a482cb6c8cac39a0fb1fe0034f8a965a3be425b4b34f67ff38a8ab30f8219a8933539c1d06d9b2997b6de743c568caea8b269642b8503b546c9e136d0e47775c8fef45d4489e6b4747c6accd6fad3d34fdd6cbafe07264e7ae1e025306c97d77a130093cc8d5ab8e4abe095787183a9084c569168011766b47dade4e3e1353a78f9f3464d8237b7de02da10c7a7b8951bafbaa898003ad9de997c89d8507393c6fb782b8f41aa99d5c92d5ed93e02a2e7550d42f178739898406badb6da850e305c10063b1a687a2b321a1f867ddfc7949d9764493af4f9681137101f87ec3c3733c0ee23a758a69dd5dbfccd20e0e7cc8543c213688ef9cc85bf9c539d3b6758e24befb3c1b617b7d59a17e915bb985df8229429430dd3057a8225d22afc2775e352a2d7c2f2f46786d4e6e984fb35ac6d7e1b57da82a6d1470895e56521c88c166f8124a4f0c5ada7d5e43174e319c21b9416735858ab50958def63c9a38e853d28a0f47b8e601beb0cdfb30d87070003f957ae347d5b03e80890311ded8018de0227c430f29ff20f0d0d1331dd5f22cff547847c0a26c1fdc272cd234b668823635f68e0797bf68fb1e531a423b1fae9b056fb8c0589908cd2774a7bea8da465248a438a22919d35e0ed8c5020f06824aa856c1a75e0d50d8e9c2dca471d249a97e8e8055d0927432577ef07e6658aa6ab3e9f5f4f50848b12dcdcd9594dae732864f9c6253cccf39922b5f1f8e16458a0c11db397017821de73a331400a76c2a5a29c7661405e9f244a92862a8ca13bc86a78a36744e52019c067573574f75e01b21c36e19a714e9cc0860e9df8e659cefab57002dc2b3d1a2918dc20ff25bc0d87023813abcbbe29defa514bd71fedf314a140508c7e8dd4ace82d56cfd6307fc8299a65c8b3b0719881dc06070d670729902ebfa1dc0b88050e5824cc186454ec2727d0fb2f95eb677f949375a0a31661c7f2bc452426a052b160b0654bffae35766a5317b845582176f1ec52e5bb7d814651781e268cfaefcf6da560810d84343dab8a8b2f2f7976334043498f529d75f9dec893bafdde0ebf003ea7d43f22d8e4eb3afea7be8bd22a9adb9334db2d6b05b8bfe72a96ca2c5ecc925333e4076bf5b7d9ed519ac3eb87c73d0c8121b1034424991561eccb669807a722bcd43141915c9db90f7a8a8e732054970645da1845b988f21cd5d2a89abd8e14c0e6532a3db89e43571b795d6f475b11c16cd7253a4538f4e73d0e3791e0c8f3e51ce3d9645062f249549d9165185fe6920659fe72ae01f69c6d5cef5a01cbbce0fcfd671e1a0aac35d541210a723d2fde91f37c130657d8825662bc46ca7780e07422ce2e7e5cbc1b15ad29b8473ffb832f45c480e960d620267561b3e3112c54359459c3f0235eb6eb2720dd5cf65f88267e099ae87ec7e35b3a915f18a4ab67583ccb4d907637812d797dfa51acc7b5cb13ab58934217a562b00a4a3d030bd9d3565a47c95396034bd65d39d39a6e7795f13e5031d148db16eddba996e1e70730eee02c47bd8b5c42812a12a2db5490fc3ad50d7d03c72c0e933ed8b43f8e34124e272cb39e06e628f18acfe4488dcced67a2c47008801e8d2db5dc7f7556d38020d53512993f3efeb4b07fd1e7b631deeeda74983011ca401ec7b86eb2a7a4d341f97337d37ada0dbbe124fe481ecac3e9b8e8f3b8b90ccf81ec028f2ee4e62934abcfcc2647966f6eea6563a0fc8fc75348f5fb3d2390db24d49858bbca822217fa81d240cacb7b2f6c2e4bad8a7a112b83a5d35ad68ec1cd599afee41fd4e860097f33afbc2cd790b2933f1194549c5aa3fe5c651a456c8ba7c8fa5ee5492233c21a80bd9216fcfccc03ecb76af3849711a0f69d5a261ce94484c30f4b74ca6cb4d7d5c4dcc0be1f0390c208e1e7e863700c6dce7ea5ab3831c00e586094a6a1f3b32dfbbf99a7581f90001dd558738804d0663a59d77407b6ab1ef3a82c156bc58d5a694a365b300a90ebbcddc49bbe5ba63c88e7a6e0faf5364ea17cabc602ddbf87a4c2f55b068ef296be5bb66befc1e37ad77f8e97c08f02d17dcdeb47959b0f46c2ae2c3d99a948f2a52c5793d53fe57876c38336a74786042abafb63c2154096eaed98598aed76da5a17ae179e79f848b237bdd6db63e5fbe77ee28b2bdcae462905ce1827800407317c2a42fc0dc234b2183db9097c0fae23da91aca6b1b7894537b0dc8524536573a34ef68596021cba863ece0de4a068f806d888aa03ed88ad92f375860f8885c5533c637a7a330c24aa0357f007ac3678e59cb1f6aa7c6979e15fd107a98ab42a635a3c3e70b58a19ec73b4bdc482000c3dfb4af84012ea3957d3d30b80857d9e06a2e677c84e5d9041ad4bf22afbdf0351f6d5c7a7a2ada3dd5ab4e48e37d51e5fad56cf9963715438c5f04b9772773893a59e2e46c6b7e19e9001650b66b469f4b1c4d188b286d5ce8b21269179e772147c7cb09eaee9b9de684ffc33068e5d346e79b710d82fd1278aee64ddd4ed37a944e6c745217c6a626444aa95b565c1f68a12cd2b86a61927896884bd5a76a9df4f6fe548bc16444272ec1e856334d64e0f32ba90daa77085b0683e3e010abf571dc564fc703a12998c72b6712386cfa4ccc802c850a3604bb0b2d5cd2eb6e788d475ff198f94a220c925a32ab6d69b037f1b9f0f4ce1d1b89cc0d07fc047073657405630200033fb971149dc9881cf31b7bd90de445f0ada69611016c5fde4af5bffe2b40a1a27d651a1d2127b0a95539b18fbb835f5145c1c4c7492866c6bd08ba260abb300720d2d42b729b72c6166f9ae0e4ac09a0f6851ca65444bed00b72b7f12befbbd007fc047073657407210252a4b012198c2131d70498b5939c401c01eb1178dfd58123b55766b03f008f7b00").unwrap()).unwrap(); let secp = Secp256k1::verification_only(); - let dummy_hash = elements::BlockHash::all_zeros(); + let dummy_hash = BlockHash::GENESIS_PREVIOUS_BLOCK_HASH; let tx = psbt.extract(&secp, dummy_hash).unwrap(); let expected: elements::Transaction = deserialize(&Vec::::from_hex("020000000102cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae0000000000ffffffffcbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae0100000000ffffffff040b8e11e3b8904ac80caeb16af1c93053f8a11a963269bcefa96823d75b8640ae9408a337e7e0ecf24c121a17193623254c277a306e9fd39cd5aaf8b7d374f4011c65027fa518c54bb326d5ce3da5c2eb8a6521ab99df86b511477d0f5ebcd616f063ac220020c731ad44c00a2928d508ad82b05868cb42733a5b0d0b208f483307ce8c328d930b85bd6dc21b4919f6ebda7ab86ac8122c793be3fad19e44455945ddec8b59e9f6081271c10f0caf52a40e015e7d35966dbad39525a6c0691d4beeb3bfb22af5304d0302e71fc2fff37aeb6d2e2a7b7f2308d4ab7d4bf0a4cf9be7c06e89a66442b48322002058037c2d81d3122185c8704d4276e2629122c95b8ea68575c451628d37eea84501230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000001f400000b9991881df2ec384ff5616f6c03d45cf033ee64536297c3557f9fffec716c1fbe0970cb1dff96101101e24bed1a66fb0794d2fcb26aba11e7f2393edc1534df8a960252a4b012198c2131d70498b5939c401c01eb1178dfd58123b55766b03f008f7b220020cd4ed5f0db8c450e8b0be595b6410c1759c19f1f6926279095c83dade9862b6d00000000000002473044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801210334c307ad8142e7c8a6bf1ad3552b12fbb860885ea7f2d76c1f49f93a7c4bbbe700000002473044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa012103df8f51c053ba0dfb443cce9793b6dc3339ffb0ce97af4792dade3aae1eb890f6006302000359a33e8f3d0439eb7d60aa79255858269bc1011e4cd0d4aa753bc2793f9638fe70dda4a99191f08700047a8b66d9cf7a53bf70756013c8630419e3a0bf428158dd02ab6e16822f239df0a6f1b67b6e1335509a286b30c4b11a22dcea9f95d513fd4e1060330000000000000001efdfbc0022a6437ec10c672d76c513868f403f6b9706e09733d6624e3cda831c2c199dd4c5763054a1c219e079e8cf3ce0c00dc2f16516972e1e64d576adfd9f5d778675c8a3172450a4cc82d6e6c59f2b16dffddc902d0aaa647b750d6224cafca7239a4fa81219cf2ee89741ffc5b7dd7e47d332ca931cffb1d1d432935a6013207629118c965b7a5102e62c43ca9d06bca191307a476738548536809ff6b01c6b5b25d76ff2f67d99e20fdf7d2eff6fc248186d21d054196023c5e4f572ccf0f3aad8728c46f2ff6756ea39de46028610a3d26cd42978b09e0e29e0a8aa46e4fd39d28d028592560264cf1a794c27f6c95d382f486dfe900a81d9d92935c7e0e6306549b3e49b1f60182512ccb994338c3541a2956139b2ccb3dd156853105abf5fb394cb2c45915dfd4106c7472dc5d360ab5bca408203a3fef58b4dd33b0c11c367dde2f19c8af7682be067244bf49a2b8cd4685f5481cc31ba27fe2f3d7b7a353be9b41e4eee2342fd70b8408c91951c71c75dde8fbc03e3f28e6d3d3b41e0e963d3ba0c25b2eb50560c21221950b0699d2615f0128e6cb7fa1b04ac1a046e569a7e87df98c14360b8ffc43db5e17548c7ea5056f84ffd14f4cdfc68a4f10e9b391cfa63eef2c2d623e7cdcdfae2fc4d63496d81462174ff360809b7e3b4305979d9cb8e9ad5b0f012494d31ce51ee6489555b09dddb16641ed9e2534fc34db99d2a4fa736eeabacf2f8cdca97f9e84c964277c6f30f1af7fe2b51b39b487d56ebaf593a3f98e811cb09849c5b445d5b7c9ba37807bd0189c8bdb2709fa70c230f9aba41dd3c62384aea6e1ca098ffec26367aa65a09459fca074d1da0365cf7fc2d8310ae099b838ca78e62cee10f95ec549faac1ff0f8236fb8cf2c0f6654e471d3950ef45e0159c44f9e343d05b3af59b939cf76090d040376407c41661eeda7d2cb61cad0088a286948787dae0cc5abdcb97f7f42026c65a13e1df1357c25d376955942adc858e73876e1d8812969055d55decac9a689dcd11dffe5cf6e06088b93a11e153ffed104266bba472cebffb2b0cfc8ef132309bd7836071d3b6ed459a5950c64cccf230015c98f9210f2d57b7f3a07c382f3df09f055c88e1f312db0d60d471afdc0b780d319a6229babd8f45edecff8d1073fa850f755219a3ea14e7234cbc7590c60eba0ba0cc1afde6ce91c8e8835b1ca809926b3e7d8d7a0941425e5f08e884f12693eeea1b3651f53da90972aaa37d426f37db3edae4285db114cbad5964c269e03b15358ad2a7242e0af538a594fc779ec3c43c3d94fab2028310c6d0acf3efdf0acf028ee757c5c02bb5b8b691aa5eed1a62acbabd0d61faa478cdcd54c6db2cec6144d8d1185115097a7da79c16ad3118d12e36dbcb7a70b0ddb27bddfcb1c6e5426b7e411f607d22c3ac2b8d3e41f55faf5e2105bf3b943846cc4c33edc64f902c1eeda09c8110d4f3ed0a5e511156a3e368f02161b92126abf649341ddb8ed03d1d41b91fc34548c6d94dfb47c088ef27a3cbfe1c9cb05f2ab2f18b8746394c8080c4cd92e818e46f861614ab870cb7ae3446e376793f3a6568a2ccfc2ab0ed0365567671436fee6cf427b6410a046d80b9d88f094924ad370da363e8eb70355b711687e92d88a08ed811ff241c7a6dbbad9dcfc18e6a42493483b938e36c1edd2a1c6e078a17c5d145c9c058b4dd69afc44c345f1c88afb95c1deb5c4994161ba25783165d43b9e50a2d8333a8037cec2ae809a3dbe026d6ba40d60badd05bce73b0f9f36966c30b9c0cb5776544c1182024a96e746a3b01f9db10b45aaffd3b055b02b40bccd41e57c10719bedb0fba99a0f6b0868b186fca0397ab8c219f33190f81e4cce2fbcbc0975c394919c98fdfd7e25a33e5f31fefd06c8dc409cbd3e743f0f48dc90abe45b2e68948436caa37fe9932a77b7e0fe0819d8283964b0eee2249d9190f3eb0bb8178e10a287be1059f35cc1a153dda14def65f3c49cdc5186da86bd3e965446f914e3c9b4cbfcfd2c379f306c5ef8844c4fd398b3c6f96601e90d2dc8810875663939f63abe3ee2e1c8a9c2c2010a01d0dcaebb556a7c98421f8e6465cb0434c07dcea9db1a142f9684e50b06c545785f0dee4def1257e4bb22d87a2b37ca9eb53081eb8f1ea0439c4575abac435868a36552df569ccc63477594ccf7eadfed6adbb8e81800a2e2fdd7effdd1e2f09cf76c9e780f6f8eb8408a3fcc06cb8bcd28db7a37edb0232a6f0e509c684318f179d0c91a97718ce3956c266790361ea3a1bf70cdb8a2f2a59b06dee18075745c7302db9b13a452c188c5624964af2d5d4bbb1138dec59df5dfb077a0f62ac4db3de81f54365f2a4a6dee63a6092b4660d3f5dca3cc8de3bb5350f5dcebabd515c72c9114bc58d96e2e863106f0982c2632bbacf2fe5cf6a8df880c550f7008fd09227baff82d4eb031802fbe7d50f6174860c70fcd9f0356e34c0d45df66492dc309b260b7158adf678e2da66348ca84de3e721c6196e0c717f59cb802c6866defdd9032a4b7da82b816d9681e5eb9115fc2a572fbbe105f479ab339bfa5961aa1920346c9ae4185a74aa828da78a71e55876c657249e83f5812cfb055400da1db8bbb5ed3ce2ca4655b0c39b698ed7d235fb0ed4f29a7e8925cb873176efcd1c6981dd23865468c6e01ddf61fa3e40d6fed18d8e3dbd97a08c68bfb092e441e512d44089cf563509785dd58203949a1ca9b66a700db14060a760aa404e5e9f31eaac015f1527f6d760d8714c88040b87fc8a4d183230cfae35326947e28a7a37eefe1d77070f5232a0d67e278a45d649709a7398cbd43094c5001263671517f83e62e79fb75e6f9bc592fb3bbececa3f597dee71dda0fc909079ea49d81554d2fd79d1cf3cf25d1186efb83cf972b7426600d7d6eb6c48a5f0e26af640c733f3f771e0926e6b38b6f39d7882b0538dcf281d92a6bd361bb32e16f3988d6790fa0a45f549e983f4eb68ce5ff11647b37f8e4c444aae8bc0f7c49ce7215545a29215b55f37dc42aa6add6fd1fb45d9ae580434097e7a8686e23cdbdbf6f8b6b1e5579a7908bafd8878b004c7c94e045fdf2b94f8c1a75ccee7bfabd9bb6d0ea8a60dca61053636160c19f8f3fff3d0330fc95d20a1393629f33f281e5da80a5ff66aaa5eefcf495f8bf7e24744778841d7c633f01af2305a122ee093837998e87f060105ffbc083c0d71f68c2c63820d7a547d9af5618544efb9736af56736e73cb696f191c68970ea1deb587231c889672b3b5399b9b5e915e3c567474c3905ec5b6468da826f1a6438ec335da847db540a091ab311c6846f96a2f17befa2f29ea491a41d7630e42583ad1212e6c606dc258a49f756e2480f90775c04c5c533300e37f8bc7afe7b155fb95877252ce4a53f78491ebf9d8a4aa41da1848633816542901d56e66f126316c80efdaf4b457f9ce771edb012a0b3c27c717f5cb3cc99ffcc959a02289e30d5b1ff936320579c469bd55cba6e79a0c5f1bda59981b71840a8c1ca56863e91eb21fbaf84525d5f04e0f282d03bb56d6dc2352f163d8357b86bc6e4e621bb693db3565eb9ef5629af537874c1cb3459582463362dab3c6fed7e574ce9bffcc685b8eea61599292cc69860c4f9584818182f94d719dcc463e9a6f854405ca2deb3de29ffa1826f795b7e7ac2555c0ee576c75494cb832c59de8d9620927167bc136549b731ef79a39fbf8789831cc003a772fa00d4d699d089d47037e12e1c6eb8c20c5535225a33a1a787ba866ad481e9a4d689c83d75f1986405c82154e312ce8b3494ac5721b96193c025bb75b2cc974f9171297da058d2ed4f00d94e60737af29da660fc51fb9bb4d241e78c9d1815d7e3ea90aa541c4c512ab423ece93f9ff2f479f464b953b4171217b758b280c5d8acda32cced7bb0c92cd9b405afb3a8405602da914e1831fec5b6a291f90635afe82b9389a8b41d957f81be125de2f943b7cda9e873fcd74b446bacc00bdfcbe643053f6cc8162c0a98343242b489f59f7ebac016a7fbf620dafc15c8ecfe20b954153dba19eb81087673a1e847238864036e9a300239a00a5a03d8b39aae2bc201c04c477b1f2a37552670c06ea65551c5c88a42476d0d797af494b077737cb48050bd35f4980964b8b9b98bde84615e8fdca407230f5d15e97ae65d63a96f3d88518fde12d6a82881db5c8d4cd79e724312e88b394129de3569c5c99bf842a90f193c91fa55a82116e237c877dec2da6dc652cb33e33df47420c5238fb6ba5fd96cb77f0cf6c8a12be1a95186680d16a064d9b1a7c2461fdf5e0a512a5a3ed2f8dc0eeadb6c95a658aa1c2713fea473de51f65b13a40a2fe64e5227bc9248f59c2bd60dd2fc14918e333faab6e792ce2f0597be47cee70f5a8b788a50c9cd153bf24786aa80f631ad21926e3285f41c5125a15c12cc889112df0b1857020160122c2595ab3359bcab184ecb32f7cf8f38eea23f4f9135104629d8f1e8273c44f8afa129d3a74cf58ce494214629cd53b99a8489ddc5d339e317ce75dd6c5dbd098d811c56ec5f19c00fa00b5465e39f8f2022c71ab3ed0d5a24058c197719551985ab30a851390ab5e11420c521b1398bff0038d904e5879db37d60c623a0a82e191cd0b6bd20a9e956d41d5daef703bdedd6bd0e20fb096423dd39706e939e796aa8bdf071e44791d2e1ed4a81ffd018cb79c5b6bdfd6297cc6cd379845fd7ddfdb0b83d7b26c21e3edb58185e71472a79cb65322579bd5e0e7b1fe081dcae5447834d70459f8a96b341a26d8922a2b1412f95f3533e04b5f65be112cca03ca45ee0eca10adc7593c78c041281c880d879125e585e68f5c7fbf8686f245cd736ab5aadc57c032c637b753b49575acf4bbff46883382f408417438d7817097accae3fc54afc6015b84b3b05627d7c83c4627c87727bd24c4b4d96a08c64164ab8d4abe3fff5c3b09e8fd12498e3cc3627e799e4ef72a870cd89598d51ba396655b4de66e48997faa51d05d581c52f52852cffc9f89252f26d314d2fb8fcbce197f3a8f330339c2ec3c710710b74f0915da3bbb638b1f1a0cb0c176adc151da0ab52796d466b23e8a269c5b22b76fe7586cbc217621acc955a43571dc04f69deb50066cc587595cf0ca4e9a00a261ff2791ada8de04bcbbea249d2a7840bd8fd3ef98a248eacb7fea5318b2e207668e13ab4e5578c03315d44b478df5247d8afd0624d2a57adf85fd16d86ae54cca21f6c91d8cafb3b31e3f9c4e903c04f39d67c90560dd10b2d28c6ee937cae01e921c98ddd833a9b9247053110c0f29d2f35f8ea322a738636f17648b627db622a9cc891fc1d066d5fcabc168f1b492479b0578d0bd8de0298d4bb96a4351714a10a39de49d57ad66bd6b458ae0d799a19da54bf620c0e6979a95b61a83cd06e46d7d263d53d66f77557232983268f5fd01d10442af0c840ab09c6cc4ad77add6379eeaf98f7cdbd70fffcb035abae4efecdb7e6f63ed8acebd8449b3a910e5eb06b0ee6d80dd45026c9e6c2f978f813b2800386a4d7ad9d127d76c4286c1b2facccfd16e6a263ba3e2893ae5e42049d421e08a62ee9e9574a1f70f0add7b68344256592513cc15f4bc64c5a029f60d617c245c1c34d06c095b2d0a9647e65dadb33ea79e3e0ea62ce55347d24eaab7cf9fc33fd70c07363771f78a13d92941daf7970c97b43d2fbe3e789a52ae7bed64736e6ce59f95322d20f9d6dc00b5824a0ce9072dd051c66ac20d39bd953f567a831d75fa91fb4d49b200fc893489e60df95c2810f7fc57b7f6b7725ae600e1c2def6a943b8d111ff3e9a5ac80aa981fad8709e98ee1550005bb8f65dedffbfe3793abb46302000318eb22887126df9062243038440ef3fca2aa024fff8739db4930b314822b00cab172e83c33b7e5b959b0c3f27c714e447120833ef69bd634d1e011fc3c2585beaa882a29c2dabddfd31a48c0255d1ab57c6796aa4625a546a02cef51a9ee2e80fd4e1060330000000000000001cb6f1101e2b960c9a2fe480eb88fc76c63e58b57445c78d88e04f740580a36d6956006ef12ba606aaca89796dad5ff7cb4c4c7f4e65a07fea8a2ce3b58b265d4b3220013a09ecf4e01023aabca5586d61ecd5d7f2bedceb8b18a8e41451c97a192098b196add06a8a6b619e1e731fd9ae2973741aff6358c1ad45cc873a2d497271e3a20873a6f701d4c44ef670c8c7a9793079d9bdfe956bdc02a52d1de8b2de58b0f7d309240999f13985fa8c98e57fe1bb75219ae6330e9495b523e891dba7885a5302817d68a9891ae0c2597d4d7833b91b073c4f9b27be1cf81ca1c2c1014c57a4affe7b402c0e0c1862bd17bc1d43428671a106c26cab61d5e4ffd1c01f6af1c6e97f7a25ae8aaa8d2c91c57881df52bd5f242b127ec7aed5880101caa01783884dfe943ec9764473323f59b27a204f34aa1fe7fd4433fa606608b0f253247d149e3e269ae5445e917390be83d5650c05859e3a817a6c7e561e2b12baf6d4ca4221df0b7f29fa134269139afd9cee5c7d60149dfa23031705c6a8b72d00d659d7a085de8330de2e5c168ee3eba2180a9319f5e8e0806dadaf0fffbc2df839571360b8cd32300504a527cf914da7a1e788261c9cca2872ebec5a17cad33b15a7a7427c200b8746761359194520f0da1d7ae03f26190d07cf92d515e04815f514c66a98997320a028ad24e83182f213d991accf19a8a59003a2ca666ca505c0d8349e2cb22887efb7db9e4a4e3e2d8da0d5f032603e03f48fb967fd018fc99c6eb72acee4178edeb48703903a89e9462a2d1f447234c3373fff8b205848c7a9d6e45ccc31eeeb0105ed3af1188fb847cf6f03a7f0a646fa325b672796168dbbd9d1d19b2f41685b18c3c96f1cfb7ecb1dea132e8815b62647820ac4b12597d8e737a01a970704b03ba5ae68f8d64a1810db10427fbff1d74cfac91561484cfc8d3b23f74ba0f37e7db2f942c58fb1dd30f6a50c57b5eae720c6ed69b0fb81a6e0260c53028c732a544391e319987a24548230378f8f1ddf65a2d654c7b26951d5c6546cc8fda6003228e8913c9e3c5adf7b7b72f4ff5c4aedba6096097f9a4b58ea1e060609e8d1f0fb0e5dd905b29fec72b118d40c5f599a63f9a37041742a7f1af3ef951c31833621842ec212f9fc5cd3e8c08278ea192f8032ade447d2f35ab59810aff371f598b7dd57b3cde2ad854ecad0c786150748ac241ecd67cb868663a6fcbe9d68c3dc221d4fcec9b0ad89c337c1e10b91a38ab1357f260ca3a084da536e56262973e6c6cca838601fb2f335811375aed78295c4b17d3798d39d4cbf6254ce57680a102907e5c08b5c7ec0a1e73bf3d7b8babdc6156c6ca3f09c0423d6716ff4e6ee0338cfd778158202b5ffb60b74558dc6d0be9b5aed6892c4e0ad3e20de5b604b2b010af09ceaba7c0fba5a7fed39d31cb2769909a251ba5b0668330f734728f5c6786a8f1a35df77f3d739eec71d9268fb2a494a14bf7ab91c075023e76856d1745f5813d83878822934d0b4cc0538048c3f96cad7aef2bbc49bab139915dd4998ed3c6701973eb7913530b14c688f0b344ca9cb990de2a9b12fa7ad8b292234a33428b4d16813693964365bd412fb936c1461fdf8dfb0bba31202685f29addf95fc65f841e97042bc5d82f103e41017c6ac91d3d266e12db2dc195ac4f6d4353924270c7144cd96dcd07b9612e2bf1e0f7fc46ef83690648395c575a13c2b2df0fa04f740340e6b116b0866a401de22f68fa3f621d75b9f5f625cd5d5d7e12a5b0ff795749d742eb2648ddf068a451059390da566b3de84f9d528b2663de7dcc562eb014071e8277a054783d322fa67b9e5261b87e9c354ff58fc52bf9df404139311d6bf9650658fc94835a6220ca02a4bfbf46b2af4f30b1ba681c0de7c134d98dd52eb1e937c191cc9557aa73a343b99ae0b8954a3e929174984b574da75e90a9b71af1215317b04e4090770ab596091fc05c82235a324f86280f7fa081360ac758c1980c6a6763453e6b344611e46b05760941f9517ceb298ed7a2d6f96b11f5719ed0dec803c511dadb8d056d4ca06ca0ad090558a4fbf3a886f3ea9c33e1bb4bb5ddef4798cdfb384bea75a3794c42a53af60f12c95fe9b38d7f6a5d914ef100508091fc84756b596b9ba08d1dc42a7e253435b5481d1470ef00a1172cb036b5bdfaccaee02b15d099da17f9753846226325232e71ed9b48f57697bb3d1db75ed214310e6e3608ded6f188e37b21b96eefaa396db0df05a86416fe64aa950eea87e7af4407c828a8822b17be661269c9f9e365cdc79d20503e2d5e575c5387fa961206118dd379834aade7727a1b2477a24f05f6c2ba3156fe7f5b5ba6d7487b1a124f38e3ed3cda92a8edf05f28e3d699f0c12de9cfeb30ec8d4cd253287a6d3f596db0c06006a531e80083f5b41ee26c05d529e0a59ec151b4a9260a7ea8c1a175ca41b59f464adc122f448fc43e90dfa7b88f81caa7a84e3d6d4dbb85e5828b6ae7455dc2c87c8d9c706af2e62763675851b4ca449c9c0f95d953ce53c5327ba8981321a1cbfb76bafac7fa17c99567725d8e0ac288f3ccd3bad666e515156517281c97a3dbfbd5f345f8eb80bb3c4230301a38b7c920d74eb910d380f884a683f7d3e2738fabf9646138e8a32c35e43786e67925508e4cc7b1e7a36abdf6a497077704e216f1e730c20ecfcddfbdf2484d8eb0ef9b7478f77063fa90b8afbcd019d1a584df58c537b40b193f246598ae4c53958a947dd3916b14a5a4227f01bf543a8c5d6ab8eaefdfb959c8715b756a9c797fe39229dc56a86364cb367fa37e16e96cf8dca1fdc8b6a46ce88e3d29c75b6cc718ca8c28e9e1ae991b28c286107c1dced150814d6369cc8003b2976018941df7fb8eeb68be57adcf8a0e813d2fcd16dc390ce17dd0a91dd674d766d21b5de7f4678a548d75cc3de7d099b418fbdb66b2a2b12a56b1dd8b3f84a7b45e36db9bb63b3ef9fdadebc21c6a75364173925ffc69d481024e49076dca105795e7a64a3c82011889aacf0114a1bd31414e288cbb63eb47d399d0e025a54f11670c8ad4a793d0e7ebd3b0d8eb30b87cf62b131c61a4c55d2e56e47ae99fc543c57a1877ce44dac4c6f9fd99552701ade43858e0b4020230cb4d42d1990bfb509471a5c1c5557c29c00072c5cbbc056de6d465ea2ba2f4a1a5dd604dbf998e834b9200c59fdf90bec38af9218e47ea5ed5512cf8b0146126a15d49bf915eb893ad1ef83d8faf6c93f944ebce3704f930b6f69a1afe767ac2c9fdf092c804c7372ae1a64bca3a3b5a31f2ad430ba9e61dab3daa3be90a538cf0fba00796de511cddb5a594f14aa6d215bd0be19c0ca5f043403b7dc56c87b092d9436eb79509c3dbe367c2fcbc2b09f9818cf5a55d5ee0e477888166bbfece661b62812ffed3e4167ecc81dba148f89a8f2e7c27424a2ee091ac487e68fbbf9798e8caf46b35de8dde66a7cad6dc98a426ea7b8b930cf2d7d71fe71066dbe51e8a1c7151e97fecbeedef3d6f8e01cd5576dd58097b46153f9c3bcecf30bc82b4cdfb1bbfa826c7c5b217a023e4da02a35d0947b2c4d24d50a292e4c70fe854a420c54490d4850ee8c372756671fe130532f89878a64977ead60bf604b73859ae64ed62536423bb51b30c6fedbc819fdae05cb64b87b153f4252b832d6b866100a7b307d1e705643f96f0724858e6211802b2ce706d5424b99315db90c7d74fac66951251f6cb739ea008f839c7f62318f795337ca4ff05886a2640819873ae00b933081b64da1101d1b17451357921a2f4d4dc86c92a5eb346fd6cd3a63315768b94b90a15162aec91cea706b9221330db154d1fd71acac90be47055c725bce38710f1b4b4144f331cfa9fe15ebf6535747669e4aa1f0d72092ef395f16a4ec9014029b5c9d1b4bed9ec81a7568f8f1c87e0ce0f4ef9cf49e3fe4960b0b7904614772c63147f3c5463fffed182919c4973a8256346116be40b10a38cdea5bad5878760daaeda57476e86ec65e58030bc8ff99ebf017e9bf6383f981edc83b538e2bf4bb573637e6f4717d74a3ac71f5e151259b29c1b7226e3a8ab176baa2f27e3e385cd48c6f072bb6e8e9c92e35d7ff51177f4e3553555d967c04befc1847003a8592738c82eef231ce3d372372a19a01b27dc7916f986ff3f3ea8872d4986bc1ca649a92924c8f582ae2b44028e711e955d2563c33db3b7734aa246de553dab2c5268538f7c2b6dbe9a70657e2a26e52f5d216dfa9aa8e197a227c86a7d3b468880a721b804a0c51af1592043eee7fe3657b40c1832a858cfb4e037d208ee69c4fd697b929383a971b2a0864544505af2267e334db5f3f3f4ed88e2f6f2b3d7b96016ff92a120556e4d1e50440943893b00508c6242bcc41b6d06dc29ba20564b42257b9fa1b5f4f453e94e72501d31e8947e09a38261020400db4b8cf675b1854639a962a57905cbbee14ea0daa9bd281fd635c8f900fcabdcbcfb140f4f24b47731782ca899284fadfc9d0d6eff77045792e139afad34c7672bacfa22d85fcc05652178cc169bcf52ee3cef281d99935abf9c9910caa7994cfe33b9319d9854aa6e2590a86297f23b0cada7251a6ee1b2f3d2cb5a193cae8768d92f556994e416d4bcf5bba3a295d9e2215291237df74e3c493189bc5a27b3fec3e1a1329c6c6c75e0802b40fc74776476dd2d9e3453ec1709a8a2d162a936d9fe7dd4b6f7abdadfa429aed4cbd5896cfb24a2d91f1cee781d0ed73cf7306d6f9545fd3346c2232b8799553357a5a531d6085d04af5f183019dfd3483baf23b0ba5a6b58bba4b7a1eb0a32626bebb5cc0c4dad45c55d135be8b0a4dee787ed48b90a2a3fc120a753b52290c27ad0eb32b668a9540986ca0256c1676debc4d19b1b80bedd81e505154264a199ef1a54e1fff1b3589fbb6b2d87a1e04e67066571b68fe04f030d473f8d135585f8b7be91f0ae1a4fa2f44008c0f727f6aba9c5c60c3a9ff22911e267ffa2a5d1c71ff25f96ad257be29a2ec641e2055d785765cadd0c2fe513c44154e74f4b8cc4b24d9ee2f6cfe245549713f9dada1935247a2ac7ccc13c4a5c00c6ffe7ca33c0cde4c75c4fe2ea041a965e4c7385ebfdbc348da8c4216a02fa829892c827adbcbb87745120667cdc5a4aef28b190a54b422df45b8547c447765838dbf9f05de338ab672706b59b2f0644d6735d9316e64a1a15d3dfad893bb1bbcbe1b574a0b8ef5265e195a929148cc5e97c8bfb032d4528b523b6a6b29209428f38115cd102e3b4e268333e490140964278238e7ea9638ac34559e05300dad0c3f18e9228474cd3a7186102967c33fc14f086b4f1ec3957d87f2609d140dbb9e7ff793101d1cb90d004565c6a32924715b1bcab483e6389e2e824054edef350f328870f16412aca0fee39edcbd02a6a667aaaeabb6654c4762c639a26286a3c1730ab75defcd9451b4377f6acdc3b905684658c0844d904c47d313d85eb54963fd71a9a76dc8e345e479004f00e446b886ec41cf7bbb9311463e877aa4e357a0dd0b185a5cf12244296f5f8568e84cf6ac3b6125db6897e4e7c183cafc04f61b3263456f61a7880b446e3cffe986c3bf027c7deba490ec8544d2627e6596ef8f8a5cb577796e7c36ffc4f4346263b5d86ae1d7b8d04709367349d590047a8bfb34fbf6481adce60eddfdd1e148ab83874d70b5303fa0ce60c0ba7a047a477dc4c513d2218b0bb2bdf9b60be9a39e928976464e333ce0cb19aa21fda1c6851c6db9d5bbc6552e080f8e448637af711fed92e72c8d8530187de94603377dc387041a9eb42ac70b3923b9828de33bb337d55409cb419bf4089cb2bec79ffc3afc6dcc3cb82bc903d956d28e30000630200033fb971149dc9881cf31b7bd90de445f0ada69611016c5fde4af5bffe2b40a1a27d651a1d2127b0a95539b18fbb835f5145c1c4c7492866c6bd08ba260abb300720d2d42b729b72c6166f9ae0e4ac09a0f6851ca65444bed00b72b7f12befbbd0fd4e10603300000000000000018b6d2d00790f618171a9e8eb6051fc14dc27c502a54f5ccecacb4bcb350581a8f4b1a887a1e58865a21f51ef5098400c115cca84f489637718d8c3ca4350ad677374d40d2b64fe949ca34bd4ba845a87c7693421b70aa8d852e021aee329762883b9820bc0a47ea2fc6a8411ef773703632849094e51c73997c67f3e922d2801b6abc445375cd963a62c2bb28d733bf9274fe503081b51a56023a94200743e7d38865c190331449d19bf3d4eb7bf0b2a9b90696484aab906b9470e10946744838fc428f88461864d6601e93f10909e049a315fcc0ea7f4d71507fe5ed19b9ac2f55b0d3902b153ee27da9c55ab66debfb5ca440dfbb1a600cd8875049c4c13bbf242d26b10035002c7859f9c3ea631d955914adfa0817e4801e85b3f250cd9e7523db62c4ecb17a49028a02a1b61eb96a410643f1fec0ac664d96f99a1db4ac335c2bfec2946707c3c779a56373db197039af9a903e833af6f51de5cf8fc667dbf5416845d415dc98641e0984ebdfab88bbcdf305f605d36f7a472a516206d7ec722251e269800a00e8adb8f2ce161395c1c6ad4b406e1fda77bc7f0af07ea075011cee6cc5e7fd1b6e96e321171ca7d28a35595ddf0b0c831d28a88d30c7391c5832d90f906539aa49185fc6c0864e2d10b21160991fc19a1d084006d03fe3fb6f571f1ffd9f06ffbc0c076689373f9c2f8655758f7f44618345a6d5f8edae46e73a09c38157d5c39dd51a47756ea761e6320d6a91a1bb22d8dd35e4e7806b0242bcc4cae8720a953c6f933c0ee3216513cce6742a2cb4bf44553d8eaf175471dbc0f71c7c245fe99ab4240ccac637a16c82f0c60586f00d83ff852af48a239289d8b70a2638b0aff02572d6d2d68e22b87ba93f3db51bb27825265607ba4b6e9a194c7351f220b9e715a23237c40024fb7cfedaf7c8e0a1c4c6aebef8841fcf2609a3dd7f44dfd8895077df41f10790372eac8adff5ea7eeb28e371b4700d5044b41fd358dc4ba29158213e0f93711026fac8abfbe7cd80a939477ce545bc91cd1d32e8f2268563b0fe3e80855777d51cdf4835050a557d3c7b7f6905ba744ae5450d22837d2c2fa0c0755934654a78601a1fe236f11b6d72f368880ed938ff4a2e8d82c118493a1bb9a9ee95cf329f2d175d467aacc2c6cd73ed59ce64d508604db77942f9b7f3b0f86d913d3e1b489d2190a6da1ed997ab1eee356c885270e4e0192acc9c2b8702107c96aed654318bbb7724b913808dd2cfbbf6ace8db9c4cbf26f2c90a76eb967e365c58855b83550819cb5b28ea5e6ec1ea153ad3ee5e6292a174f7cab1b39e852194a6926bdc4d42326e17998cc057f614e91f6acab5a5bbedd93d9a13dc61977aa2accaf35370a3f1d3819c43c9430d0e767e92de96bb225007a7b6576ed7c4f05c984ce2e437d3b7f7f50c270caf90f8e5dbecb992be2972ef8d79c7674e025ee06b1302bcbd57fe5be9d9b4e38f17d9dca898ef3d71918550fd77a15c7aa2b66ee1a2f38b81040f3d6ec6693f54cc3fe39515275849e9e24b0af3e81705dea95e8f1bb1b4665cfdeb0630a5542a2857f2b58c36761d743299d77872d6894302123f4347702572f04d9876191d771e87655c071fbd29338eef0f9acb0a8ca3f0327ead8e875bc2e7ba38f249e6eda1fb74162e972ff523d20c6638b93297d406e9b2264187c06d0a78203d771f2525227d029b27b23192f747492b9774b12b039729ef75d11ce8d701e56fbb202f3e4bd68686f096f13680456529e5f132915595e0e0b4061b3014219f1fbef4d7403dbfcac01c701b7727c2463cb838d427e07706400be4fdd9140a800e47e7ac15a7a8a897187a38a0080726349d8b7566252076b1ae1366496b50e9a6d236837ffa0c4c3e61bb409a7d9faf8662109ef7213007a76a6d94cb79ad07183a33a4cdedd78896278a3b5531ec0efda9d77076d85a63536b426a6b58c3d0e8a46faf0fdf678e4964272e8410b346cc753edb94a61a2f309f8e753ff332f5b15215e0a20ef32e6a6faa044a431764e008e66b4af820bb6afe4d8dc1679219fe7614482517fdc523d4d7ce2bad9d59f7b9aed89b813e5b36b58a7c668e53181c0e1da45e4ba3851b46de8e056d63e440c471fbe23fbffc31ece7cd20658784f2d2fca3f730a1f8a90ea6995ccb490fca475b1441e38468433d1423c1d83a20b04f1216aff13c8e035c2ed389695c2bb0bedadc38c8a6222d687f0235bda3566c0865774bb6098acd674ff9091db1a6c4f0c2955c1759730b361f310d956f892089f500eae0084022e610ca4e758ce2c680d213bd1b5e00a6c991976e93189159bb98a1e4eff14f681d47694060126c0852ad52489c15d7302d82c66aa830208a9fd13da87a2aac3e44dddae632f2e4d56dc768ee6b3622c61e59aee27fee5aa0bfa9c56402ae3525f00634b11381d0b9637ac699e4c4b225c32bef9dc563e87cfc33bf07450c2cdd015bbd94df63697cdd9b6cf4169cfe1f626c126dbb588c57542662d02eeed561946ce94b46571f72ca3cf7fe52a8a6ea24fa216f01655dadbeb0f74e383e522da69db64b368cb155c2ba4c4fc8aea8745b1081223317003f0cd7ae620fc7d9a6c9c4f39a237d5d9d7f3e756c77daeccbd5d06ed28ac2f089db5449340872bc444aa4aecf6552621b84e4fabfd6baf0e1b61cab00e5c2050bfa38899e9840e2dac55c7d5e7105f65dc3afe3c35dd3e8ebb1a013d65fb0b9d76665f3c4eff5b766fbb0c03cc10c411987ef516405296437a91a67d7398d788e30f55bc1e6236b317784504c53800cc07f4eaf78bac03a025a7943573edcc67db3d5d5281f85ee993238fee3580cb846efae33b45ee2ee1ad640b1d068302504521269a31a166435e8fd964d2e15048f299a95ec1cbeb0c8d5d119e24670112d61d56ea120d7bc30fcd924fc7b812404ac45798af3fb590570a4d7a3f41639b879d1bdf2c72c979105460892fb41570cffee716679eb7b4124be188e28ca4c68d206c1cc9d49cd7489d63372853dbe83f874579238ecdd28c0dc265871d6dccf782b571f1004702121e8b15c9d8af9e6812dbbe742812c7e7cd1dafbdbe3d189f618936e270855700be8f6a7b528f271a936a2cae204b44d909ae3f6a8bcbfcda44b430397b1c96187e5a8362afe92bb9afb0a0a482cb6c8cac39a0fb1fe0034f8a965a3be425b4b34f67ff38a8ab30f8219a8933539c1d06d9b2997b6de743c568caea8b269642b8503b546c9e136d0e47775c8fef45d4489e6b4747c6accd6fad3d34fdd6cbafe07264e7ae1e025306c97d77a130093cc8d5ab8e4abe095787183a9084c569168011766b47dade4e3e1353a78f9f3464d8237b7de02da10c7a7b8951bafbaa898003ad9de997c89d8507393c6fb782b8f41aa99d5c92d5ed93e02a2e7550d42f178739898406badb6da850e305c10063b1a687a2b321a1f867ddfc7949d9764493af4f9681137101f87ec3c3733c0ee23a758a69dd5dbfccd20e0e7cc8543c213688ef9cc85bf9c539d3b6758e24befb3c1b617b7d59a17e915bb985df8229429430dd3057a8225d22afc2775e352a2d7c2f2f46786d4e6e984fb35ac6d7e1b57da82a6d1470895e56521c88c166f8124a4f0c5ada7d5e43174e319c21b9416735858ab50958def63c9a38e853d28a0f47b8e601beb0cdfb30d87070003f957ae347d5b03e80890311ded8018de0227c430f29ff20f0d0d1331dd5f22cff547847c0a26c1fdc272cd234b668823635f68e0797bf68fb1e531a423b1fae9b056fb8c0589908cd2774a7bea8da465248a438a22919d35e0ed8c5020f06824aa856c1a75e0d50d8e9c2dca471d249a97e8e8055d0927432577ef07e6658aa6ab3e9f5f4f50848b12dcdcd9594dae732864f9c6253cccf39922b5f1f8e16458a0c11db397017821de73a331400a76c2a5a29c7661405e9f244a92862a8ca13bc86a78a36744e52019c067573574f75e01b21c36e19a714e9cc0860e9df8e659cefab57002dc2b3d1a2918dc20ff25bc0d87023813abcbbe29defa514bd71fedf314a140508c7e8dd4ace82d56cfd6307fc8299a65c8b3b0719881dc06070d670729902ebfa1dc0b88050e5824cc186454ec2727d0fb2f95eb677f949375a0a31661c7f2bc452426a052b160b0654bffae35766a5317b845582176f1ec52e5bb7d814651781e268cfaefcf6da560810d84343dab8a8b2f2f7976334043498f529d75f9dec893bafdde0ebf003ea7d43f22d8e4eb3afea7be8bd22a9adb9334db2d6b05b8bfe72a96ca2c5ecc925333e4076bf5b7d9ed519ac3eb87c73d0c8121b1034424991561eccb669807a722bcd43141915c9db90f7a8a8e732054970645da1845b988f21cd5d2a89abd8e14c0e6532a3db89e43571b795d6f475b11c16cd7253a4538f4e73d0e3791e0c8f3e51ce3d9645062f249549d9165185fe6920659fe72ae01f69c6d5cef5a01cbbce0fcfd671e1a0aac35d541210a723d2fde91f37c130657d8825662bc46ca7780e07422ce2e7e5cbc1b15ad29b8473ffb832f45c480e960d620267561b3e3112c54359459c3f0235eb6eb2720dd5cf65f88267e099ae87ec7e35b3a915f18a4ab67583ccb4d907637812d797dfa51acc7b5cb13ab58934217a562b00a4a3d030bd9d3565a47c95396034bd65d39d39a6e7795f13e5031d148db16eddba996e1e70730eee02c47bd8b5c42812a12a2db5490fc3ad50d7d03c72c0e933ed8b43f8e34124e272cb39e06e628f18acfe4488dcced67a2c47008801e8d2db5dc7f7556d38020d53512993f3efeb4b07fd1e7b631deeeda74983011ca401ec7b86eb2a7a4d341f97337d37ada0dbbe124fe481ecac3e9b8e8f3b8b90ccf81ec028f2ee4e62934abcfcc2647966f6eea6563a0fc8fc75348f5fb3d2390db24d49858bbca822217fa81d240cacb7b2f6c2e4bad8a7a112b83a5d35ad68ec1cd599afee41fd4e860097f33afbc2cd790b2933f1194549c5aa3fe5c651a456c8ba7c8fa5ee5492233c21a80bd9216fcfccc03ecb76af3849711a0f69d5a261ce94484c30f4b74ca6cb4d7d5c4dcc0be1f0390c208e1e7e863700c6dce7ea5ab3831c00e586094a6a1f3b32dfbbf99a7581f90001dd558738804d0663a59d77407b6ab1ef3a82c156bc58d5a694a365b300a90ebbcddc49bbe5ba63c88e7a6e0faf5364ea17cabc602ddbf87a4c2f55b068ef296be5bb66befc1e37ad77f8e97c08f02d17dcdeb47959b0f46c2ae2c3d99a948f2a52c5793d53fe57876c38336a74786042abafb63c2154096eaed98598aed76da5a17ae179e79f848b237bdd6db63e5fbe77ee28b2bdcae462905ce1827800407317c2a42fc0dc234b2183db9097c0fae23da91aca6b1b7894537b0dc8524536573a34ef68596021cba863ece0de4a068f806d888aa03ed88ad92f375860f8885c5533c637a7a330c24aa0357f007ac3678e59cb1f6aa7c6979e15fd107a98ab42a635a3c3e70b58a19ec73b4bdc482000c3dfb4af84012ea3957d3d30b80857d9e06a2e677c84e5d9041ad4bf22afbdf0351f6d5c7a7a2ada3dd5ab4e48e37d51e5fad56cf9963715438c5f04b9772773893a59e2e46c6b7e19e9001650b66b469f4b1c4d188b286d5ce8b21269179e772147c7cb09eaee9b9de684ffc33068e5d346e79b710d82fd1278aee64ddd4ed37a944e6c745217c6a626444aa95b565c1f68a12cd2b86a61927896884bd5a76a9df4f6fe548bc16444272ec1e856334d64e0f32ba90daa77085b0683e3e010abf571dc564fc703a12998c72b6712386cfa4ccc802c850a3604bb0b2d5cd2eb6e788d475ff198f94a220c925a32ab6d69b037f1b9f0f4ce1d1b89cc0d").unwrap()).unwrap(); assert_eq!(tx, expected); @@ -1563,7 +1574,7 @@ mod tests { let mut psbt: Psbt = deserialize(&Vec::::from_hex("70736574ff01020402000000010401020105010401fb04020000000001017a0bab8c49f1fce77440be124c72ce22bb23b58c6f52baf4cdde1f656056cd6b96440980610bc88e4ab656c2e5ff6fe6c6a39967a1c0d386682240c5ff039148dc335d03b636cc4beba2967c418a9443e161cd0ac77bec5e44c4bf98e72fc28857abca331600142d2186719dc0c245e7b4a30f17834f371ca7377c22020334c307ad8142e7c8a6bf1ad3552b12fbb860885ea7f2d76c1f49f93a7c4bbbe7473044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801010e20cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae010f04000000000001017a0b90df52169792d13db9b7d074d091aaa3e83aff261b1cc19d291441b62e7a03190899a91403ca5cd8bded09945bc99c2f980fd27601cada66833a5f4bc108baf63902e8bed2778bf381d17241be029f228664c7d1522ced55379e275b83fe805b370216001403bb7619d51d2af2c5538d3908ead081a7ef2b2b220203df8f51c053ba0dfb443cce9793b6dc3339ffb0ce97af4792dade3aae1eb890f6473044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa01010e20cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae010f04010000000007fc0470736574012108a337e7e0ecf24c121a17193623254c277a306e9fd39cd5aaf8b7d374f4011c6507fc047073657403210b8e11e3b8904ac80caeb16af1c93053f8a11a963269bcefa96823d75b8640ae940104220020c731ad44c00a2928d508ad82b05868cb42733a5b0d0b208f483307ce8c328d9307fc047073657404fd4e1060330000000000000001efdfbc0022a6437ec10c672d76c513868f403f6b9706e09733d6624e3cda831c2c199dd4c5763054a1c219e079e8cf3ce0c00dc2f16516972e1e64d576adfd9f5d778675c8a3172450a4cc82d6e6c59f2b16dffddc902d0aaa647b750d6224cafca7239a4fa81219cf2ee89741ffc5b7dd7e47d332ca931cffb1d1d432935a6013207629118c965b7a5102e62c43ca9d06bca191307a476738548536809ff6b01c6b5b25d76ff2f67d99e20fdf7d2eff6fc248186d21d054196023c5e4f572ccf0f3aad8728c46f2ff6756ea39de46028610a3d26cd42978b09e0e29e0a8aa46e4fd39d28d028592560264cf1a794c27f6c95d382f486dfe900a81d9d92935c7e0e6306549b3e49b1f60182512ccb994338c3541a2956139b2ccb3dd156853105abf5fb394cb2c45915dfd4106c7472dc5d360ab5bca408203a3fef58b4dd33b0c11c367dde2f19c8af7682be067244bf49a2b8cd4685f5481cc31ba27fe2f3d7b7a353be9b41e4eee2342fd70b8408c91951c71c75dde8fbc03e3f28e6d3d3b41e0e963d3ba0c25b2eb50560c21221950b0699d2615f0128e6cb7fa1b04ac1a046e569a7e87df98c14360b8ffc43db5e17548c7ea5056f84ffd14f4cdfc68a4f10e9b391cfa63eef2c2d623e7cdcdfae2fc4d63496d81462174ff360809b7e3b4305979d9cb8e9ad5b0f012494d31ce51ee6489555b09dddb16641ed9e2534fc34db99d2a4fa736eeabacf2f8cdca97f9e84c964277c6f30f1af7fe2b51b39b487d56ebaf593a3f98e811cb09849c5b445d5b7c9ba37807bd0189c8bdb2709fa70c230f9aba41dd3c62384aea6e1ca098ffec26367aa65a09459fca074d1da0365cf7fc2d8310ae099b838ca78e62cee10f95ec549faac1ff0f8236fb8cf2c0f6654e471d3950ef45e0159c44f9e343d05b3af59b939cf76090d040376407c41661eeda7d2cb61cad0088a286948787dae0cc5abdcb97f7f42026c65a13e1df1357c25d376955942adc858e73876e1d8812969055d55decac9a689dcd11dffe5cf6e06088b93a11e153ffed104266bba472cebffb2b0cfc8ef132309bd7836071d3b6ed459a5950c64cccf230015c98f9210f2d57b7f3a07c382f3df09f055c88e1f312db0d60d471afdc0b780d319a6229babd8f45edecff8d1073fa850f755219a3ea14e7234cbc7590c60eba0ba0cc1afde6ce91c8e8835b1ca809926b3e7d8d7a0941425e5f08e884f12693eeea1b3651f53da90972aaa37d426f37db3edae4285db114cbad5964c269e03b15358ad2a7242e0af538a594fc779ec3c43c3d94fab2028310c6d0acf3efdf0acf028ee757c5c02bb5b8b691aa5eed1a62acbabd0d61faa478cdcd54c6db2cec6144d8d1185115097a7da79c16ad3118d12e36dbcb7a70b0ddb27bddfcb1c6e5426b7e411f607d22c3ac2b8d3e41f55faf5e2105bf3b943846cc4c33edc64f902c1eeda09c8110d4f3ed0a5e511156a3e368f02161b92126abf649341ddb8ed03d1d41b91fc34548c6d94dfb47c088ef27a3cbfe1c9cb05f2ab2f18b8746394c8080c4cd92e818e46f861614ab870cb7ae3446e376793f3a6568a2ccfc2ab0ed0365567671436fee6cf427b6410a046d80b9d88f094924ad370da363e8eb70355b711687e92d88a08ed811ff241c7a6dbbad9dcfc18e6a42493483b938e36c1edd2a1c6e078a17c5d145c9c058b4dd69afc44c345f1c88afb95c1deb5c4994161ba25783165d43b9e50a2d8333a8037cec2ae809a3dbe026d6ba40d60badd05bce73b0f9f36966c30b9c0cb5776544c1182024a96e746a3b01f9db10b45aaffd3b055b02b40bccd41e57c10719bedb0fba99a0f6b0868b186fca0397ab8c219f33190f81e4cce2fbcbc0975c394919c98fdfd7e25a33e5f31fefd06c8dc409cbd3e743f0f48dc90abe45b2e68948436caa37fe9932a77b7e0fe0819d8283964b0eee2249d9190f3eb0bb8178e10a287be1059f35cc1a153dda14def65f3c49cdc5186da86bd3e965446f914e3c9b4cbfcfd2c379f306c5ef8844c4fd398b3c6f96601e90d2dc8810875663939f63abe3ee2e1c8a9c2c2010a01d0dcaebb556a7c98421f8e6465cb0434c07dcea9db1a142f9684e50b06c545785f0dee4def1257e4bb22d87a2b37ca9eb53081eb8f1ea0439c4575abac435868a36552df569ccc63477594ccf7eadfed6adbb8e81800a2e2fdd7effdd1e2f09cf76c9e780f6f8eb8408a3fcc06cb8bcd28db7a37edb0232a6f0e509c684318f179d0c91a97718ce3956c266790361ea3a1bf70cdb8a2f2a59b06dee18075745c7302db9b13a452c188c5624964af2d5d4bbb1138dec59df5dfb077a0f62ac4db3de81f54365f2a4a6dee63a6092b4660d3f5dca3cc8de3bb5350f5dcebabd515c72c9114bc58d96e2e863106f0982c2632bbacf2fe5cf6a8df880c550f7008fd09227baff82d4eb031802fbe7d50f6174860c70fcd9f0356e34c0d45df66492dc309b260b7158adf678e2da66348ca84de3e721c6196e0c717f59cb802c6866defdd9032a4b7da82b816d9681e5eb9115fc2a572fbbe105f479ab339bfa5961aa1920346c9ae4185a74aa828da78a71e55876c657249e83f5812cfb055400da1db8bbb5ed3ce2ca4655b0c39b698ed7d235fb0ed4f29a7e8925cb873176efcd1c6981dd23865468c6e01ddf61fa3e40d6fed18d8e3dbd97a08c68bfb092e441e512d44089cf563509785dd58203949a1ca9b66a700db14060a760aa404e5e9f31eaac015f1527f6d760d8714c88040b87fc8a4d183230cfae35326947e28a7a37eefe1d77070f5232a0d67e278a45d649709a7398cbd43094c5001263671517f83e62e79fb75e6f9bc592fb3bbececa3f597dee71dda0fc909079ea49d81554d2fd79d1cf3cf25d1186efb83cf972b7426600d7d6eb6c48a5f0e26af640c733f3f771e0926e6b38b6f39d7882b0538dcf281d92a6bd361bb32e16f3988d6790fa0a45f549e983f4eb68ce5ff11647b37f8e4c444aae8bc0f7c49ce7215545a29215b55f37dc42aa6add6fd1fb45d9ae580434097e7a8686e23cdbdbf6f8b6b1e5579a7908bafd8878b004c7c94e045fdf2b94f8c1a75ccee7bfabd9bb6d0ea8a60dca61053636160c19f8f3fff3d0330fc95d20a1393629f33f281e5da80a5ff66aaa5eefcf495f8bf7e24744778841d7c633f01af2305a122ee093837998e87f060105ffbc083c0d71f68c2c63820d7a547d9af5618544efb9736af56736e73cb696f191c68970ea1deb587231c889672b3b5399b9b5e915e3c567474c3905ec5b6468da826f1a6438ec335da847db540a091ab311c6846f96a2f17befa2f29ea491a41d7630e42583ad1212e6c606dc258a49f756e2480f90775c04c5c533300e37f8bc7afe7b155fb95877252ce4a53f78491ebf9d8a4aa41da1848633816542901d56e66f126316c80efdaf4b457f9ce771edb012a0b3c27c717f5cb3cc99ffcc959a02289e30d5b1ff936320579c469bd55cba6e79a0c5f1bda59981b71840a8c1ca56863e91eb21fbaf84525d5f04e0f282d03bb56d6dc2352f163d8357b86bc6e4e621bb693db3565eb9ef5629af537874c1cb3459582463362dab3c6fed7e574ce9bffcc685b8eea61599292cc69860c4f9584818182f94d719dcc463e9a6f854405ca2deb3de29ffa1826f795b7e7ac2555c0ee576c75494cb832c59de8d9620927167bc136549b731ef79a39fbf8789831cc003a772fa00d4d699d089d47037e12e1c6eb8c20c5535225a33a1a787ba866ad481e9a4d689c83d75f1986405c82154e312ce8b3494ac5721b96193c025bb75b2cc974f9171297da058d2ed4f00d94e60737af29da660fc51fb9bb4d241e78c9d1815d7e3ea90aa541c4c512ab423ece93f9ff2f479f464b953b4171217b758b280c5d8acda32cced7bb0c92cd9b405afb3a8405602da914e1831fec5b6a291f90635afe82b9389a8b41d957f81be125de2f943b7cda9e873fcd74b446bacc00bdfcbe643053f6cc8162c0a98343242b489f59f7ebac016a7fbf620dafc15c8ecfe20b954153dba19eb81087673a1e847238864036e9a300239a00a5a03d8b39aae2bc201c04c477b1f2a37552670c06ea65551c5c88a42476d0d797af494b077737cb48050bd35f4980964b8b9b98bde84615e8fdca407230f5d15e97ae65d63a96f3d88518fde12d6a82881db5c8d4cd79e724312e88b394129de3569c5c99bf842a90f193c91fa55a82116e237c877dec2da6dc652cb33e33df47420c5238fb6ba5fd96cb77f0cf6c8a12be1a95186680d16a064d9b1a7c2461fdf5e0a512a5a3ed2f8dc0eeadb6c95a658aa1c2713fea473de51f65b13a40a2fe64e5227bc9248f59c2bd60dd2fc14918e333faab6e792ce2f0597be47cee70f5a8b788a50c9cd153bf24786aa80f631ad21926e3285f41c5125a15c12cc889112df0b1857020160122c2595ab3359bcab184ecb32f7cf8f38eea23f4f9135104629d8f1e8273c44f8afa129d3a74cf58ce494214629cd53b99a8489ddc5d339e317ce75dd6c5dbd098d811c56ec5f19c00fa00b5465e39f8f2022c71ab3ed0d5a24058c197719551985ab30a851390ab5e11420c521b1398bff0038d904e5879db37d60c623a0a82e191cd0b6bd20a9e956d41d5daef703bdedd6bd0e20fb096423dd39706e939e796aa8bdf071e44791d2e1ed4a81ffd018cb79c5b6bdfd6297cc6cd379845fd7ddfdb0b83d7b26c21e3edb58185e71472a79cb65322579bd5e0e7b1fe081dcae5447834d70459f8a96b341a26d8922a2b1412f95f3533e04b5f65be112cca03ca45ee0eca10adc7593c78c041281c880d879125e585e68f5c7fbf8686f245cd736ab5aadc57c032c637b753b49575acf4bbff46883382f408417438d7817097accae3fc54afc6015b84b3b05627d7c83c4627c87727bd24c4b4d96a08c64164ab8d4abe3fff5c3b09e8fd12498e3cc3627e799e4ef72a870cd89598d51ba396655b4de66e48997faa51d05d581c52f52852cffc9f89252f26d314d2fb8fcbce197f3a8f330339c2ec3c710710b74f0915da3bbb638b1f1a0cb0c176adc151da0ab52796d466b23e8a269c5b22b76fe7586cbc217621acc955a43571dc04f69deb50066cc587595cf0ca4e9a00a261ff2791ada8de04bcbbea249d2a7840bd8fd3ef98a248eacb7fea5318b2e207668e13ab4e5578c03315d44b478df5247d8afd0624d2a57adf85fd16d86ae54cca21f6c91d8cafb3b31e3f9c4e903c04f39d67c90560dd10b2d28c6ee937cae01e921c98ddd833a9b9247053110c0f29d2f35f8ea322a738636f17648b627db622a9cc891fc1d066d5fcabc168f1b492479b0578d0bd8de0298d4bb96a4351714a10a39de49d57ad66bd6b458ae0d799a19da54bf620c0e6979a95b61a83cd06e46d7d263d53d66f77557232983268f5fd01d10442af0c840ab09c6cc4ad77add6379eeaf98f7cdbd70fffcb035abae4efecdb7e6f63ed8acebd8449b3a910e5eb06b0ee6d80dd45026c9e6c2f978f813b2800386a4d7ad9d127d76c4286c1b2facccfd16e6a263ba3e2893ae5e42049d421e08a62ee9e9574a1f70f0add7b68344256592513cc15f4bc64c5a029f60d617c245c1c34d06c095b2d0a9647e65dadb33ea79e3e0ea62ce55347d24eaab7cf9fc33fd70c07363771f78a13d92941daf7970c97b43d2fbe3e789a52ae7bed64736e6ce59f95322d20f9d6dc00b5824a0ce9072dd051c66ac20d39bd953f567a831d75fa91fb4d49b200fc893489e60df95c2810f7fc57b7f6b7725ae600e1c2def6a943b8d111ff3e9a5ac80aa981fad8709e98ee1550005bb8f65dedffbfe3793abb407fc0470736574056302000359a33e8f3d0439eb7d60aa79255858269bc1011e4cd0d4aa753bc2793f9638fe70dda4a99191f08700047a8b66d9cf7a53bf70756013c8630419e3a0bf428158dd02ab6e16822f239df0a6f1b67b6e1335509a286b30c4b11a22dcea9f95d51307fc04707365740721027fa518c54bb326d5ce3da5c2eb8a6521ab99df86b511477d0f5ebcd616f063ac0007fc04707365740121081271c10f0caf52a40e015e7d35966dbad39525a6c0691d4beeb3bfb22af5304d07fc047073657403210b85bd6dc21b4919f6ebda7ab86ac8122c793be3fad19e44455945ddec8b59e9f6010422002058037c2d81d3122185c8704d4276e2629122c95b8ea68575c451628d37eea84507fc047073657404fd4e1060330000000000000001cb6f1101e2b960c9a2fe480eb88fc76c63e58b57445c78d88e04f740580a36d6956006ef12ba606aaca89796dad5ff7cb4c4c7f4e65a07fea8a2ce3b58b265d4b3220013a09ecf4e01023aabca5586d61ecd5d7f2bedceb8b18a8e41451c97a192098b196add06a8a6b619e1e731fd9ae2973741aff6358c1ad45cc873a2d497271e3a20873a6f701d4c44ef670c8c7a9793079d9bdfe956bdc02a52d1de8b2de58b0f7d309240999f13985fa8c98e57fe1bb75219ae6330e9495b523e891dba7885a5302817d68a9891ae0c2597d4d7833b91b073c4f9b27be1cf81ca1c2c1014c57a4affe7b402c0e0c1862bd17bc1d43428671a106c26cab61d5e4ffd1c01f6af1c6e97f7a25ae8aaa8d2c91c57881df52bd5f242b127ec7aed5880101caa01783884dfe943ec9764473323f59b27a204f34aa1fe7fd4433fa606608b0f253247d149e3e269ae5445e917390be83d5650c05859e3a817a6c7e561e2b12baf6d4ca4221df0b7f29fa134269139afd9cee5c7d60149dfa23031705c6a8b72d00d659d7a085de8330de2e5c168ee3eba2180a9319f5e8e0806dadaf0fffbc2df839571360b8cd32300504a527cf914da7a1e788261c9cca2872ebec5a17cad33b15a7a7427c200b8746761359194520f0da1d7ae03f26190d07cf92d515e04815f514c66a98997320a028ad24e83182f213d991accf19a8a59003a2ca666ca505c0d8349e2cb22887efb7db9e4a4e3e2d8da0d5f032603e03f48fb967fd018fc99c6eb72acee4178edeb48703903a89e9462a2d1f447234c3373fff8b205848c7a9d6e45ccc31eeeb0105ed3af1188fb847cf6f03a7f0a646fa325b672796168dbbd9d1d19b2f41685b18c3c96f1cfb7ecb1dea132e8815b62647820ac4b12597d8e737a01a970704b03ba5ae68f8d64a1810db10427fbff1d74cfac91561484cfc8d3b23f74ba0f37e7db2f942c58fb1dd30f6a50c57b5eae720c6ed69b0fb81a6e0260c53028c732a544391e319987a24548230378f8f1ddf65a2d654c7b26951d5c6546cc8fda6003228e8913c9e3c5adf7b7b72f4ff5c4aedba6096097f9a4b58ea1e060609e8d1f0fb0e5dd905b29fec72b118d40c5f599a63f9a37041742a7f1af3ef951c31833621842ec212f9fc5cd3e8c08278ea192f8032ade447d2f35ab59810aff371f598b7dd57b3cde2ad854ecad0c786150748ac241ecd67cb868663a6fcbe9d68c3dc221d4fcec9b0ad89c337c1e10b91a38ab1357f260ca3a084da536e56262973e6c6cca838601fb2f335811375aed78295c4b17d3798d39d4cbf6254ce57680a102907e5c08b5c7ec0a1e73bf3d7b8babdc6156c6ca3f09c0423d6716ff4e6ee0338cfd778158202b5ffb60b74558dc6d0be9b5aed6892c4e0ad3e20de5b604b2b010af09ceaba7c0fba5a7fed39d31cb2769909a251ba5b0668330f734728f5c6786a8f1a35df77f3d739eec71d9268fb2a494a14bf7ab91c075023e76856d1745f5813d83878822934d0b4cc0538048c3f96cad7aef2bbc49bab139915dd4998ed3c6701973eb7913530b14c688f0b344ca9cb990de2a9b12fa7ad8b292234a33428b4d16813693964365bd412fb936c1461fdf8dfb0bba31202685f29addf95fc65f841e97042bc5d82f103e41017c6ac91d3d266e12db2dc195ac4f6d4353924270c7144cd96dcd07b9612e2bf1e0f7fc46ef83690648395c575a13c2b2df0fa04f740340e6b116b0866a401de22f68fa3f621d75b9f5f625cd5d5d7e12a5b0ff795749d742eb2648ddf068a451059390da566b3de84f9d528b2663de7dcc562eb014071e8277a054783d322fa67b9e5261b87e9c354ff58fc52bf9df404139311d6bf9650658fc94835a6220ca02a4bfbf46b2af4f30b1ba681c0de7c134d98dd52eb1e937c191cc9557aa73a343b99ae0b8954a3e929174984b574da75e90a9b71af1215317b04e4090770ab596091fc05c82235a324f86280f7fa081360ac758c1980c6a6763453e6b344611e46b05760941f9517ceb298ed7a2d6f96b11f5719ed0dec803c511dadb8d056d4ca06ca0ad090558a4fbf3a886f3ea9c33e1bb4bb5ddef4798cdfb384bea75a3794c42a53af60f12c95fe9b38d7f6a5d914ef100508091fc84756b596b9ba08d1dc42a7e253435b5481d1470ef00a1172cb036b5bdfaccaee02b15d099da17f9753846226325232e71ed9b48f57697bb3d1db75ed214310e6e3608ded6f188e37b21b96eefaa396db0df05a86416fe64aa950eea87e7af4407c828a8822b17be661269c9f9e365cdc79d20503e2d5e575c5387fa961206118dd379834aade7727a1b2477a24f05f6c2ba3156fe7f5b5ba6d7487b1a124f38e3ed3cda92a8edf05f28e3d699f0c12de9cfeb30ec8d4cd253287a6d3f596db0c06006a531e80083f5b41ee26c05d529e0a59ec151b4a9260a7ea8c1a175ca41b59f464adc122f448fc43e90dfa7b88f81caa7a84e3d6d4dbb85e5828b6ae7455dc2c87c8d9c706af2e62763675851b4ca449c9c0f95d953ce53c5327ba8981321a1cbfb76bafac7fa17c99567725d8e0ac288f3ccd3bad666e515156517281c97a3dbfbd5f345f8eb80bb3c4230301a38b7c920d74eb910d380f884a683f7d3e2738fabf9646138e8a32c35e43786e67925508e4cc7b1e7a36abdf6a497077704e216f1e730c20ecfcddfbdf2484d8eb0ef9b7478f77063fa90b8afbcd019d1a584df58c537b40b193f246598ae4c53958a947dd3916b14a5a4227f01bf543a8c5d6ab8eaefdfb959c8715b756a9c797fe39229dc56a86364cb367fa37e16e96cf8dca1fdc8b6a46ce88e3d29c75b6cc718ca8c28e9e1ae991b28c286107c1dced150814d6369cc8003b2976018941df7fb8eeb68be57adcf8a0e813d2fcd16dc390ce17dd0a91dd674d766d21b5de7f4678a548d75cc3de7d099b418fbdb66b2a2b12a56b1dd8b3f84a7b45e36db9bb63b3ef9fdadebc21c6a75364173925ffc69d481024e49076dca105795e7a64a3c82011889aacf0114a1bd31414e288cbb63eb47d399d0e025a54f11670c8ad4a793d0e7ebd3b0d8eb30b87cf62b131c61a4c55d2e56e47ae99fc543c57a1877ce44dac4c6f9fd99552701ade43858e0b4020230cb4d42d1990bfb509471a5c1c5557c29c00072c5cbbc056de6d465ea2ba2f4a1a5dd604dbf998e834b9200c59fdf90bec38af9218e47ea5ed5512cf8b0146126a15d49bf915eb893ad1ef83d8faf6c93f944ebce3704f930b6f69a1afe767ac2c9fdf092c804c7372ae1a64bca3a3b5a31f2ad430ba9e61dab3daa3be90a538cf0fba00796de511cddb5a594f14aa6d215bd0be19c0ca5f043403b7dc56c87b092d9436eb79509c3dbe367c2fcbc2b09f9818cf5a55d5ee0e477888166bbfece661b62812ffed3e4167ecc81dba148f89a8f2e7c27424a2ee091ac487e68fbbf9798e8caf46b35de8dde66a7cad6dc98a426ea7b8b930cf2d7d71fe71066dbe51e8a1c7151e97fecbeedef3d6f8e01cd5576dd58097b46153f9c3bcecf30bc82b4cdfb1bbfa826c7c5b217a023e4da02a35d0947b2c4d24d50a292e4c70fe854a420c54490d4850ee8c372756671fe130532f89878a64977ead60bf604b73859ae64ed62536423bb51b30c6fedbc819fdae05cb64b87b153f4252b832d6b866100a7b307d1e705643f96f0724858e6211802b2ce706d5424b99315db90c7d74fac66951251f6cb739ea008f839c7f62318f795337ca4ff05886a2640819873ae00b933081b64da1101d1b17451357921a2f4d4dc86c92a5eb346fd6cd3a63315768b94b90a15162aec91cea706b9221330db154d1fd71acac90be47055c725bce38710f1b4b4144f331cfa9fe15ebf6535747669e4aa1f0d72092ef395f16a4ec9014029b5c9d1b4bed9ec81a7568f8f1c87e0ce0f4ef9cf49e3fe4960b0b7904614772c63147f3c5463fffed182919c4973a8256346116be40b10a38cdea5bad5878760daaeda57476e86ec65e58030bc8ff99ebf017e9bf6383f981edc83b538e2bf4bb573637e6f4717d74a3ac71f5e151259b29c1b7226e3a8ab176baa2f27e3e385cd48c6f072bb6e8e9c92e35d7ff51177f4e3553555d967c04befc1847003a8592738c82eef231ce3d372372a19a01b27dc7916f986ff3f3ea8872d4986bc1ca649a92924c8f582ae2b44028e711e955d2563c33db3b7734aa246de553dab2c5268538f7c2b6dbe9a70657e2a26e52f5d216dfa9aa8e197a227c86a7d3b468880a721b804a0c51af1592043eee7fe3657b40c1832a858cfb4e037d208ee69c4fd697b929383a971b2a0864544505af2267e334db5f3f3f4ed88e2f6f2b3d7b96016ff92a120556e4d1e50440943893b00508c6242bcc41b6d06dc29ba20564b42257b9fa1b5f4f453e94e72501d31e8947e09a38261020400db4b8cf675b1854639a962a57905cbbee14ea0daa9bd281fd635c8f900fcabdcbcfb140f4f24b47731782ca899284fadfc9d0d6eff77045792e139afad34c7672bacfa22d85fcc05652178cc169bcf52ee3cef281d99935abf9c9910caa7994cfe33b9319d9854aa6e2590a86297f23b0cada7251a6ee1b2f3d2cb5a193cae8768d92f556994e416d4bcf5bba3a295d9e2215291237df74e3c493189bc5a27b3fec3e1a1329c6c6c75e0802b40fc74776476dd2d9e3453ec1709a8a2d162a936d9fe7dd4b6f7abdadfa429aed4cbd5896cfb24a2d91f1cee781d0ed73cf7306d6f9545fd3346c2232b8799553357a5a531d6085d04af5f183019dfd3483baf23b0ba5a6b58bba4b7a1eb0a32626bebb5cc0c4dad45c55d135be8b0a4dee787ed48b90a2a3fc120a753b52290c27ad0eb32b668a9540986ca0256c1676debc4d19b1b80bedd81e505154264a199ef1a54e1fff1b3589fbb6b2d87a1e04e67066571b68fe04f030d473f8d135585f8b7be91f0ae1a4fa2f44008c0f727f6aba9c5c60c3a9ff22911e267ffa2a5d1c71ff25f96ad257be29a2ec641e2055d785765cadd0c2fe513c44154e74f4b8cc4b24d9ee2f6cfe245549713f9dada1935247a2ac7ccc13c4a5c00c6ffe7ca33c0cde4c75c4fe2ea041a965e4c7385ebfdbc348da8c4216a02fa829892c827adbcbb87745120667cdc5a4aef28b190a54b422df45b8547c447765838dbf9f05de338ab672706b59b2f0644d6735d9316e64a1a15d3dfad893bb1bbcbe1b574a0b8ef5265e195a929148cc5e97c8bfb032d4528b523b6a6b29209428f38115cd102e3b4e268333e490140964278238e7ea9638ac34559e05300dad0c3f18e9228474cd3a7186102967c33fc14f086b4f1ec3957d87f2609d140dbb9e7ff793101d1cb90d004565c6a32924715b1bcab483e6389e2e824054edef350f328870f16412aca0fee39edcbd02a6a667aaaeabb6654c4762c639a26286a3c1730ab75defcd9451b4377f6acdc3b905684658c0844d904c47d313d85eb54963fd71a9a76dc8e345e479004f00e446b886ec41cf7bbb9311463e877aa4e357a0dd0b185a5cf12244296f5f8568e84cf6ac3b6125db6897e4e7c183cafc04f61b3263456f61a7880b446e3cffe986c3bf027c7deba490ec8544d2627e6596ef8f8a5cb577796e7c36ffc4f4346263b5d86ae1d7b8d04709367349d590047a8bfb34fbf6481adce60eddfdd1e148ab83874d70b5303fa0ce60c0ba7a047a477dc4c513d2218b0bb2bdf9b60be9a39e928976464e333ce0cb19aa21fda1c6851c6db9d5bbc6552e080f8e448637af711fed92e72c8d8530187de94603377dc387041a9eb42ac70b3923b9828de33bb337d55409cb419bf4089cb2bec79ffc3afc6dcc3cb82bc903d956d28e307fc0470736574056302000318eb22887126df9062243038440ef3fca2aa024fff8739db4930b314822b00cab172e83c33b7e5b959b0c3f27c714e447120833ef69bd634d1e011fc3c2585beaa882a29c2dabddfd31a48c0255d1ab57c6796aa4625a546a02cef51a9ee2e8007fc047073657407210302e71fc2fff37aeb6d2e2a7b7f2308d4ab7d4bf0a4cf9be7c06e89a66442b48300010308f40100000000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20104000007fc047073657401210970cb1dff96101101e24bed1a66fb0794d2fcb26aba11e7f2393edc1534df8a9607fc047073657403210b9991881df2ec384ff5616f6c03d45cf033ee64536297c3557f9fffec716c1fbe0104220020cd4ed5f0db8c450e8b0be595b6410c1759c19f1f6926279095c83dade9862b6d07fc047073657404fd4e10603300000000000000018b6d2d00790f618171a9e8eb6051fc14dc27c502a54f5ccecacb4bcb350581a8f4b1a887a1e58865a21f51ef5098400c115cca84f489637718d8c3ca4350ad677374d40d2b64fe949ca34bd4ba845a87c7693421b70aa8d852e021aee329762883b9820bc0a47ea2fc6a8411ef773703632849094e51c73997c67f3e922d2801b6abc445375cd963a62c2bb28d733bf9274fe503081b51a56023a94200743e7d38865c190331449d19bf3d4eb7bf0b2a9b90696484aab906b9470e10946744838fc428f88461864d6601e93f10909e049a315fcc0ea7f4d71507fe5ed19b9ac2f55b0d3902b153ee27da9c55ab66debfb5ca440dfbb1a600cd8875049c4c13bbf242d26b10035002c7859f9c3ea631d955914adfa0817e4801e85b3f250cd9e7523db62c4ecb17a49028a02a1b61eb96a410643f1fec0ac664d96f99a1db4ac335c2bfec2946707c3c779a56373db197039af9a903e833af6f51de5cf8fc667dbf5416845d415dc98641e0984ebdfab88bbcdf305f605d36f7a472a516206d7ec722251e269800a00e8adb8f2ce161395c1c6ad4b406e1fda77bc7f0af07ea075011cee6cc5e7fd1b6e96e321171ca7d28a35595ddf0b0c831d28a88d30c7391c5832d90f906539aa49185fc6c0864e2d10b21160991fc19a1d084006d03fe3fb6f571f1ffd9f06ffbc0c076689373f9c2f8655758f7f44618345a6d5f8edae46e73a09c38157d5c39dd51a47756ea761e6320d6a91a1bb22d8dd35e4e7806b0242bcc4cae8720a953c6f933c0ee3216513cce6742a2cb4bf44553d8eaf175471dbc0f71c7c245fe99ab4240ccac637a16c82f0c60586f00d83ff852af48a239289d8b70a2638b0aff02572d6d2d68e22b87ba93f3db51bb27825265607ba4b6e9a194c7351f220b9e715a23237c40024fb7cfedaf7c8e0a1c4c6aebef8841fcf2609a3dd7f44dfd8895077df41f10790372eac8adff5ea7eeb28e371b4700d5044b41fd358dc4ba29158213e0f93711026fac8abfbe7cd80a939477ce545bc91cd1d32e8f2268563b0fe3e80855777d51cdf4835050a557d3c7b7f6905ba744ae5450d22837d2c2fa0c0755934654a78601a1fe236f11b6d72f368880ed938ff4a2e8d82c118493a1bb9a9ee95cf329f2d175d467aacc2c6cd73ed59ce64d508604db77942f9b7f3b0f86d913d3e1b489d2190a6da1ed997ab1eee356c885270e4e0192acc9c2b8702107c96aed654318bbb7724b913808dd2cfbbf6ace8db9c4cbf26f2c90a76eb967e365c58855b83550819cb5b28ea5e6ec1ea153ad3ee5e6292a174f7cab1b39e852194a6926bdc4d42326e17998cc057f614e91f6acab5a5bbedd93d9a13dc61977aa2accaf35370a3f1d3819c43c9430d0e767e92de96bb225007a7b6576ed7c4f05c984ce2e437d3b7f7f50c270caf90f8e5dbecb992be2972ef8d79c7674e025ee06b1302bcbd57fe5be9d9b4e38f17d9dca898ef3d71918550fd77a15c7aa2b66ee1a2f38b81040f3d6ec6693f54cc3fe39515275849e9e24b0af3e81705dea95e8f1bb1b4665cfdeb0630a5542a2857f2b58c36761d743299d77872d6894302123f4347702572f04d9876191d771e87655c071fbd29338eef0f9acb0a8ca3f0327ead8e875bc2e7ba38f249e6eda1fb74162e972ff523d20c6638b93297d406e9b2264187c06d0a78203d771f2525227d029b27b23192f747492b9774b12b039729ef75d11ce8d701e56fbb202f3e4bd68686f096f13680456529e5f132915595e0e0b4061b3014219f1fbef4d7403dbfcac01c701b7727c2463cb838d427e07706400be4fdd9140a800e47e7ac15a7a8a897187a38a0080726349d8b7566252076b1ae1366496b50e9a6d236837ffa0c4c3e61bb409a7d9faf8662109ef7213007a76a6d94cb79ad07183a33a4cdedd78896278a3b5531ec0efda9d77076d85a63536b426a6b58c3d0e8a46faf0fdf678e4964272e8410b346cc753edb94a61a2f309f8e753ff332f5b15215e0a20ef32e6a6faa044a431764e008e66b4af820bb6afe4d8dc1679219fe7614482517fdc523d4d7ce2bad9d59f7b9aed89b813e5b36b58a7c668e53181c0e1da45e4ba3851b46de8e056d63e440c471fbe23fbffc31ece7cd20658784f2d2fca3f730a1f8a90ea6995ccb490fca475b1441e38468433d1423c1d83a20b04f1216aff13c8e035c2ed389695c2bb0bedadc38c8a6222d687f0235bda3566c0865774bb6098acd674ff9091db1a6c4f0c2955c1759730b361f310d956f892089f500eae0084022e610ca4e758ce2c680d213bd1b5e00a6c991976e93189159bb98a1e4eff14f681d47694060126c0852ad52489c15d7302d82c66aa830208a9fd13da87a2aac3e44dddae632f2e4d56dc768ee6b3622c61e59aee27fee5aa0bfa9c56402ae3525f00634b11381d0b9637ac699e4c4b225c32bef9dc563e87cfc33bf07450c2cdd015bbd94df63697cdd9b6cf4169cfe1f626c126dbb588c57542662d02eeed561946ce94b46571f72ca3cf7fe52a8a6ea24fa216f01655dadbeb0f74e383e522da69db64b368cb155c2ba4c4fc8aea8745b1081223317003f0cd7ae620fc7d9a6c9c4f39a237d5d9d7f3e756c77daeccbd5d06ed28ac2f089db5449340872bc444aa4aecf6552621b84e4fabfd6baf0e1b61cab00e5c2050bfa38899e9840e2dac55c7d5e7105f65dc3afe3c35dd3e8ebb1a013d65fb0b9d76665f3c4eff5b766fbb0c03cc10c411987ef516405296437a91a67d7398d788e30f55bc1e6236b317784504c53800cc07f4eaf78bac03a025a7943573edcc67db3d5d5281f85ee993238fee3580cb846efae33b45ee2ee1ad640b1d068302504521269a31a166435e8fd964d2e15048f299a95ec1cbeb0c8d5d119e24670112d61d56ea120d7bc30fcd924fc7b812404ac45798af3fb590570a4d7a3f41639b879d1bdf2c72c979105460892fb41570cffee716679eb7b4124be188e28ca4c68d206c1cc9d49cd7489d63372853dbe83f874579238ecdd28c0dc265871d6dccf782b571f1004702121e8b15c9d8af9e6812dbbe742812c7e7cd1dafbdbe3d189f618936e270855700be8f6a7b528f271a936a2cae204b44d909ae3f6a8bcbfcda44b430397b1c96187e5a8362afe92bb9afb0a0a482cb6c8cac39a0fb1fe0034f8a965a3be425b4b34f67ff38a8ab30f8219a8933539c1d06d9b2997b6de743c568caea8b269642b8503b546c9e136d0e47775c8fef45d4489e6b4747c6accd6fad3d34fdd6cbafe07264e7ae1e025306c97d77a130093cc8d5ab8e4abe095787183a9084c569168011766b47dade4e3e1353a78f9f3464d8237b7de02da10c7a7b8951bafbaa898003ad9de997c89d8507393c6fb782b8f41aa99d5c92d5ed93e02a2e7550d42f178739898406badb6da850e305c10063b1a687a2b321a1f867ddfc7949d9764493af4f9681137101f87ec3c3733c0ee23a758a69dd5dbfccd20e0e7cc8543c213688ef9cc85bf9c539d3b6758e24befb3c1b617b7d59a17e915bb985df8229429430dd3057a8225d22afc2775e352a2d7c2f2f46786d4e6e984fb35ac6d7e1b57da82a6d1470895e56521c88c166f8124a4f0c5ada7d5e43174e319c21b9416735858ab50958def63c9a38e853d28a0f47b8e601beb0cdfb30d87070003f957ae347d5b03e80890311ded8018de0227c430f29ff20f0d0d1331dd5f22cff547847c0a26c1fdc272cd234b668823635f68e0797bf68fb1e531a423b1fae9b056fb8c0589908cd2774a7bea8da465248a438a22919d35e0ed8c5020f06824aa856c1a75e0d50d8e9c2dca471d249a97e8e8055d0927432577ef07e6658aa6ab3e9f5f4f50848b12dcdcd9594dae732864f9c6253cccf39922b5f1f8e16458a0c11db397017821de73a331400a76c2a5a29c7661405e9f244a92862a8ca13bc86a78a36744e52019c067573574f75e01b21c36e19a714e9cc0860e9df8e659cefab57002dc2b3d1a2918dc20ff25bc0d87023813abcbbe29defa514bd71fedf314a140508c7e8dd4ace82d56cfd6307fc8299a65c8b3b0719881dc06070d670729902ebfa1dc0b88050e5824cc186454ec2727d0fb2f95eb677f949375a0a31661c7f2bc452426a052b160b0654bffae35766a5317b845582176f1ec52e5bb7d814651781e268cfaefcf6da560810d84343dab8a8b2f2f7976334043498f529d75f9dec893bafdde0ebf003ea7d43f22d8e4eb3afea7be8bd22a9adb9334db2d6b05b8bfe72a96ca2c5ecc925333e4076bf5b7d9ed519ac3eb87c73d0c8121b1034424991561eccb669807a722bcd43141915c9db90f7a8a8e732054970645da1845b988f21cd5d2a89abd8e14c0e6532a3db89e43571b795d6f475b11c16cd7253a4538f4e73d0e3791e0c8f3e51ce3d9645062f249549d9165185fe6920659fe72ae01f69c6d5cef5a01cbbce0fcfd671e1a0aac35d541210a723d2fde91f37c130657d8825662bc46ca7780e07422ce2e7e5cbc1b15ad29b8473ffb832f45c480e960d620267561b3e3112c54359459c3f0235eb6eb2720dd5cf65f88267e099ae87ec7e35b3a915f18a4ab67583ccb4d907637812d797dfa51acc7b5cb13ab58934217a562b00a4a3d030bd9d3565a47c95396034bd65d39d39a6e7795f13e5031d148db16eddba996e1e70730eee02c47bd8b5c42812a12a2db5490fc3ad50d7d03c72c0e933ed8b43f8e34124e272cb39e06e628f18acfe4488dcced67a2c47008801e8d2db5dc7f7556d38020d53512993f3efeb4b07fd1e7b631deeeda74983011ca401ec7b86eb2a7a4d341f97337d37ada0dbbe124fe481ecac3e9b8e8f3b8b90ccf81ec028f2ee4e62934abcfcc2647966f6eea6563a0fc8fc75348f5fb3d2390db24d49858bbca822217fa81d240cacb7b2f6c2e4bad8a7a112b83a5d35ad68ec1cd599afee41fd4e860097f33afbc2cd790b2933f1194549c5aa3fe5c651a456c8ba7c8fa5ee5492233c21a80bd9216fcfccc03ecb76af3849711a0f69d5a261ce94484c30f4b74ca6cb4d7d5c4dcc0be1f0390c208e1e7e863700c6dce7ea5ab3831c00e586094a6a1f3b32dfbbf99a7581f90001dd558738804d0663a59d77407b6ab1ef3a82c156bc58d5a694a365b300a90ebbcddc49bbe5ba63c88e7a6e0faf5364ea17cabc602ddbf87a4c2f55b068ef296be5bb66befc1e37ad77f8e97c08f02d17dcdeb47959b0f46c2ae2c3d99a948f2a52c5793d53fe57876c38336a74786042abafb63c2154096eaed98598aed76da5a17ae179e79f848b237bdd6db63e5fbe77ee28b2bdcae462905ce1827800407317c2a42fc0dc234b2183db9097c0fae23da91aca6b1b7894537b0dc8524536573a34ef68596021cba863ece0de4a068f806d888aa03ed88ad92f375860f8885c5533c637a7a330c24aa0357f007ac3678e59cb1f6aa7c6979e15fd107a98ab42a635a3c3e70b58a19ec73b4bdc482000c3dfb4af84012ea3957d3d30b80857d9e06a2e677c84e5d9041ad4bf22afbdf0351f6d5c7a7a2ada3dd5ab4e48e37d51e5fad56cf9963715438c5f04b9772773893a59e2e46c6b7e19e9001650b66b469f4b1c4d188b286d5ce8b21269179e772147c7cb09eaee9b9de684ffc33068e5d346e79b710d82fd1278aee64ddd4ed37a944e6c745217c6a626444aa95b565c1f68a12cd2b86a61927896884bd5a76a9df4f6fe548bc16444272ec1e856334d64e0f32ba90daa77085b0683e3e010abf571dc564fc703a12998c72b6712386cfa4ccc802c850a3604bb0b2d5cd2eb6e788d475ff198f94a220c925a32ab6d69b037f1b9f0f4ce1d1b89cc0d07fc047073657405630200033fb971149dc9881cf31b7bd90de445f0ada69611016c5fde4af5bffe2b40a1a27d651a1d2127b0a95539b18fbb835f5145c1c4c7492866c6bd08ba260abb300720d2d42b729b72c6166f9ae0e4ac09a0f6851ca65444bed00b72b7f12befbbd007fc047073657407210252a4b012198c2131d70498b5939c401c01eb1178dfd58123b55766b03f008f7b00").unwrap()).unwrap(); let secp = Secp256k1::verification_only(); - let dummy_hash = elements::BlockHash::all_zeros(); + let dummy_hash = BlockHash::GENESIS_PREVIOUS_BLOCK_HASH; finalize(&mut psbt, &secp, dummy_hash).unwrap(); let expected = "70736574ff01020402000000010401020105010401fb04020000000001017a0bab8c49f1fce77440be124c72ce22bb23b58c6f52baf4cdde1f656056cd6b96440980610bc88e4ab656c2e5ff6fe6c6a39967a1c0d386682240c5ff039148dc335d03b636cc4beba2967c418a9443e161cd0ac77bec5e44c4bf98e72fc28857abca331600142d2186719dc0c245e7b4a30f17834f371ca7377c01086b02473044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801210334c307ad8142e7c8a6bf1ad3552b12fbb860885ea7f2d76c1f49f93a7c4bbbe7010e20cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae010f04000000000001017a0b90df52169792d13db9b7d074d091aaa3e83aff261b1cc19d291441b62e7a03190899a91403ca5cd8bded09945bc99c2f980fd27601cada66833a5f4bc108baf63902e8bed2778bf381d17241be029f228664c7d1522ced55379e275b83fe805b370216001403bb7619d51d2af2c5538d3908ead081a7ef2b2b01086b02473044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa012103df8f51c053ba0dfb443cce9793b6dc3339ffb0ce97af4792dade3aae1eb890f6010e20cbbe4671915035276d8df41a7ef0b6a36dd101de48a4076046fdba3b0bec20ae010f04010000000007fc0470736574012108a337e7e0ecf24c121a17193623254c277a306e9fd39cd5aaf8b7d374f4011c6507fc047073657403210b8e11e3b8904ac80caeb16af1c93053f8a11a963269bcefa96823d75b8640ae940104220020c731ad44c00a2928d508ad82b05868cb42733a5b0d0b208f483307ce8c328d9307fc047073657404fd4e1060330000000000000001efdfbc0022a6437ec10c672d76c513868f403f6b9706e09733d6624e3cda831c2c199dd4c5763054a1c219e079e8cf3ce0c00dc2f16516972e1e64d576adfd9f5d778675c8a3172450a4cc82d6e6c59f2b16dffddc902d0aaa647b750d6224cafca7239a4fa81219cf2ee89741ffc5b7dd7e47d332ca931cffb1d1d432935a6013207629118c965b7a5102e62c43ca9d06bca191307a476738548536809ff6b01c6b5b25d76ff2f67d99e20fdf7d2eff6fc248186d21d054196023c5e4f572ccf0f3aad8728c46f2ff6756ea39de46028610a3d26cd42978b09e0e29e0a8aa46e4fd39d28d028592560264cf1a794c27f6c95d382f486dfe900a81d9d92935c7e0e6306549b3e49b1f60182512ccb994338c3541a2956139b2ccb3dd156853105abf5fb394cb2c45915dfd4106c7472dc5d360ab5bca408203a3fef58b4dd33b0c11c367dde2f19c8af7682be067244bf49a2b8cd4685f5481cc31ba27fe2f3d7b7a353be9b41e4eee2342fd70b8408c91951c71c75dde8fbc03e3f28e6d3d3b41e0e963d3ba0c25b2eb50560c21221950b0699d2615f0128e6cb7fa1b04ac1a046e569a7e87df98c14360b8ffc43db5e17548c7ea5056f84ffd14f4cdfc68a4f10e9b391cfa63eef2c2d623e7cdcdfae2fc4d63496d81462174ff360809b7e3b4305979d9cb8e9ad5b0f012494d31ce51ee6489555b09dddb16641ed9e2534fc34db99d2a4fa736eeabacf2f8cdca97f9e84c964277c6f30f1af7fe2b51b39b487d56ebaf593a3f98e811cb09849c5b445d5b7c9ba37807bd0189c8bdb2709fa70c230f9aba41dd3c62384aea6e1ca098ffec26367aa65a09459fca074d1da0365cf7fc2d8310ae099b838ca78e62cee10f95ec549faac1ff0f8236fb8cf2c0f6654e471d3950ef45e0159c44f9e343d05b3af59b939cf76090d040376407c41661eeda7d2cb61cad0088a286948787dae0cc5abdcb97f7f42026c65a13e1df1357c25d376955942adc858e73876e1d8812969055d55decac9a689dcd11dffe5cf6e06088b93a11e153ffed104266bba472cebffb2b0cfc8ef132309bd7836071d3b6ed459a5950c64cccf230015c98f9210f2d57b7f3a07c382f3df09f055c88e1f312db0d60d471afdc0b780d319a6229babd8f45edecff8d1073fa850f755219a3ea14e7234cbc7590c60eba0ba0cc1afde6ce91c8e8835b1ca809926b3e7d8d7a0941425e5f08e884f12693eeea1b3651f53da90972aaa37d426f37db3edae4285db114cbad5964c269e03b15358ad2a7242e0af538a594fc779ec3c43c3d94fab2028310c6d0acf3efdf0acf028ee757c5c02bb5b8b691aa5eed1a62acbabd0d61faa478cdcd54c6db2cec6144d8d1185115097a7da79c16ad3118d12e36dbcb7a70b0ddb27bddfcb1c6e5426b7e411f607d22c3ac2b8d3e41f55faf5e2105bf3b943846cc4c33edc64f902c1eeda09c8110d4f3ed0a5e511156a3e368f02161b92126abf649341ddb8ed03d1d41b91fc34548c6d94dfb47c088ef27a3cbfe1c9cb05f2ab2f18b8746394c8080c4cd92e818e46f861614ab870cb7ae3446e376793f3a6568a2ccfc2ab0ed0365567671436fee6cf427b6410a046d80b9d88f094924ad370da363e8eb70355b711687e92d88a08ed811ff241c7a6dbbad9dcfc18e6a42493483b938e36c1edd2a1c6e078a17c5d145c9c058b4dd69afc44c345f1c88afb95c1deb5c4994161ba25783165d43b9e50a2d8333a8037cec2ae809a3dbe026d6ba40d60badd05bce73b0f9f36966c30b9c0cb5776544c1182024a96e746a3b01f9db10b45aaffd3b055b02b40bccd41e57c10719bedb0fba99a0f6b0868b186fca0397ab8c219f33190f81e4cce2fbcbc0975c394919c98fdfd7e25a33e5f31fefd06c8dc409cbd3e743f0f48dc90abe45b2e68948436caa37fe9932a77b7e0fe0819d8283964b0eee2249d9190f3eb0bb8178e10a287be1059f35cc1a153dda14def65f3c49cdc5186da86bd3e965446f914e3c9b4cbfcfd2c379f306c5ef8844c4fd398b3c6f96601e90d2dc8810875663939f63abe3ee2e1c8a9c2c2010a01d0dcaebb556a7c98421f8e6465cb0434c07dcea9db1a142f9684e50b06c545785f0dee4def1257e4bb22d87a2b37ca9eb53081eb8f1ea0439c4575abac435868a36552df569ccc63477594ccf7eadfed6adbb8e81800a2e2fdd7effdd1e2f09cf76c9e780f6f8eb8408a3fcc06cb8bcd28db7a37edb0232a6f0e509c684318f179d0c91a97718ce3956c266790361ea3a1bf70cdb8a2f2a59b06dee18075745c7302db9b13a452c188c5624964af2d5d4bbb1138dec59df5dfb077a0f62ac4db3de81f54365f2a4a6dee63a6092b4660d3f5dca3cc8de3bb5350f5dcebabd515c72c9114bc58d96e2e863106f0982c2632bbacf2fe5cf6a8df880c550f7008fd09227baff82d4eb031802fbe7d50f6174860c70fcd9f0356e34c0d45df66492dc309b260b7158adf678e2da66348ca84de3e721c6196e0c717f59cb802c6866defdd9032a4b7da82b816d9681e5eb9115fc2a572fbbe105f479ab339bfa5961aa1920346c9ae4185a74aa828da78a71e55876c657249e83f5812cfb055400da1db8bbb5ed3ce2ca4655b0c39b698ed7d235fb0ed4f29a7e8925cb873176efcd1c6981dd23865468c6e01ddf61fa3e40d6fed18d8e3dbd97a08c68bfb092e441e512d44089cf563509785dd58203949a1ca9b66a700db14060a760aa404e5e9f31eaac015f1527f6d760d8714c88040b87fc8a4d183230cfae35326947e28a7a37eefe1d77070f5232a0d67e278a45d649709a7398cbd43094c5001263671517f83e62e79fb75e6f9bc592fb3bbececa3f597dee71dda0fc909079ea49d81554d2fd79d1cf3cf25d1186efb83cf972b7426600d7d6eb6c48a5f0e26af640c733f3f771e0926e6b38b6f39d7882b0538dcf281d92a6bd361bb32e16f3988d6790fa0a45f549e983f4eb68ce5ff11647b37f8e4c444aae8bc0f7c49ce7215545a29215b55f37dc42aa6add6fd1fb45d9ae580434097e7a8686e23cdbdbf6f8b6b1e5579a7908bafd8878b004c7c94e045fdf2b94f8c1a75ccee7bfabd9bb6d0ea8a60dca61053636160c19f8f3fff3d0330fc95d20a1393629f33f281e5da80a5ff66aaa5eefcf495f8bf7e24744778841d7c633f01af2305a122ee093837998e87f060105ffbc083c0d71f68c2c63820d7a547d9af5618544efb9736af56736e73cb696f191c68970ea1deb587231c889672b3b5399b9b5e915e3c567474c3905ec5b6468da826f1a6438ec335da847db540a091ab311c6846f96a2f17befa2f29ea491a41d7630e42583ad1212e6c606dc258a49f756e2480f90775c04c5c533300e37f8bc7afe7b155fb95877252ce4a53f78491ebf9d8a4aa41da1848633816542901d56e66f126316c80efdaf4b457f9ce771edb012a0b3c27c717f5cb3cc99ffcc959a02289e30d5b1ff936320579c469bd55cba6e79a0c5f1bda59981b71840a8c1ca56863e91eb21fbaf84525d5f04e0f282d03bb56d6dc2352f163d8357b86bc6e4e621bb693db3565eb9ef5629af537874c1cb3459582463362dab3c6fed7e574ce9bffcc685b8eea61599292cc69860c4f9584818182f94d719dcc463e9a6f854405ca2deb3de29ffa1826f795b7e7ac2555c0ee576c75494cb832c59de8d9620927167bc136549b731ef79a39fbf8789831cc003a772fa00d4d699d089d47037e12e1c6eb8c20c5535225a33a1a787ba866ad481e9a4d689c83d75f1986405c82154e312ce8b3494ac5721b96193c025bb75b2cc974f9171297da058d2ed4f00d94e60737af29da660fc51fb9bb4d241e78c9d1815d7e3ea90aa541c4c512ab423ece93f9ff2f479f464b953b4171217b758b280c5d8acda32cced7bb0c92cd9b405afb3a8405602da914e1831fec5b6a291f90635afe82b9389a8b41d957f81be125de2f943b7cda9e873fcd74b446bacc00bdfcbe643053f6cc8162c0a98343242b489f59f7ebac016a7fbf620dafc15c8ecfe20b954153dba19eb81087673a1e847238864036e9a300239a00a5a03d8b39aae2bc201c04c477b1f2a37552670c06ea65551c5c88a42476d0d797af494b077737cb48050bd35f4980964b8b9b98bde84615e8fdca407230f5d15e97ae65d63a96f3d88518fde12d6a82881db5c8d4cd79e724312e88b394129de3569c5c99bf842a90f193c91fa55a82116e237c877dec2da6dc652cb33e33df47420c5238fb6ba5fd96cb77f0cf6c8a12be1a95186680d16a064d9b1a7c2461fdf5e0a512a5a3ed2f8dc0eeadb6c95a658aa1c2713fea473de51f65b13a40a2fe64e5227bc9248f59c2bd60dd2fc14918e333faab6e792ce2f0597be47cee70f5a8b788a50c9cd153bf24786aa80f631ad21926e3285f41c5125a15c12cc889112df0b1857020160122c2595ab3359bcab184ecb32f7cf8f38eea23f4f9135104629d8f1e8273c44f8afa129d3a74cf58ce494214629cd53b99a8489ddc5d339e317ce75dd6c5dbd098d811c56ec5f19c00fa00b5465e39f8f2022c71ab3ed0d5a24058c197719551985ab30a851390ab5e11420c521b1398bff0038d904e5879db37d60c623a0a82e191cd0b6bd20a9e956d41d5daef703bdedd6bd0e20fb096423dd39706e939e796aa8bdf071e44791d2e1ed4a81ffd018cb79c5b6bdfd6297cc6cd379845fd7ddfdb0b83d7b26c21e3edb58185e71472a79cb65322579bd5e0e7b1fe081dcae5447834d70459f8a96b341a26d8922a2b1412f95f3533e04b5f65be112cca03ca45ee0eca10adc7593c78c041281c880d879125e585e68f5c7fbf8686f245cd736ab5aadc57c032c637b753b49575acf4bbff46883382f408417438d7817097accae3fc54afc6015b84b3b05627d7c83c4627c87727bd24c4b4d96a08c64164ab8d4abe3fff5c3b09e8fd12498e3cc3627e799e4ef72a870cd89598d51ba396655b4de66e48997faa51d05d581c52f52852cffc9f89252f26d314d2fb8fcbce197f3a8f330339c2ec3c710710b74f0915da3bbb638b1f1a0cb0c176adc151da0ab52796d466b23e8a269c5b22b76fe7586cbc217621acc955a43571dc04f69deb50066cc587595cf0ca4e9a00a261ff2791ada8de04bcbbea249d2a7840bd8fd3ef98a248eacb7fea5318b2e207668e13ab4e5578c03315d44b478df5247d8afd0624d2a57adf85fd16d86ae54cca21f6c91d8cafb3b31e3f9c4e903c04f39d67c90560dd10b2d28c6ee937cae01e921c98ddd833a9b9247053110c0f29d2f35f8ea322a738636f17648b627db622a9cc891fc1d066d5fcabc168f1b492479b0578d0bd8de0298d4bb96a4351714a10a39de49d57ad66bd6b458ae0d799a19da54bf620c0e6979a95b61a83cd06e46d7d263d53d66f77557232983268f5fd01d10442af0c840ab09c6cc4ad77add6379eeaf98f7cdbd70fffcb035abae4efecdb7e6f63ed8acebd8449b3a910e5eb06b0ee6d80dd45026c9e6c2f978f813b2800386a4d7ad9d127d76c4286c1b2facccfd16e6a263ba3e2893ae5e42049d421e08a62ee9e9574a1f70f0add7b68344256592513cc15f4bc64c5a029f60d617c245c1c34d06c095b2d0a9647e65dadb33ea79e3e0ea62ce55347d24eaab7cf9fc33fd70c07363771f78a13d92941daf7970c97b43d2fbe3e789a52ae7bed64736e6ce59f95322d20f9d6dc00b5824a0ce9072dd051c66ac20d39bd953f567a831d75fa91fb4d49b200fc893489e60df95c2810f7fc57b7f6b7725ae600e1c2def6a943b8d111ff3e9a5ac80aa981fad8709e98ee1550005bb8f65dedffbfe3793abb407fc0470736574056302000359a33e8f3d0439eb7d60aa79255858269bc1011e4cd0d4aa753bc2793f9638fe70dda4a99191f08700047a8b66d9cf7a53bf70756013c8630419e3a0bf428158dd02ab6e16822f239df0a6f1b67b6e1335509a286b30c4b11a22dcea9f95d51307fc04707365740721027fa518c54bb326d5ce3da5c2eb8a6521ab99df86b511477d0f5ebcd616f063ac0007fc04707365740121081271c10f0caf52a40e015e7d35966dbad39525a6c0691d4beeb3bfb22af5304d07fc047073657403210b85bd6dc21b4919f6ebda7ab86ac8122c793be3fad19e44455945ddec8b59e9f6010422002058037c2d81d3122185c8704d4276e2629122c95b8ea68575c451628d37eea84507fc047073657404fd4e1060330000000000000001cb6f1101e2b960c9a2fe480eb88fc76c63e58b57445c78d88e04f740580a36d6956006ef12ba606aaca89796dad5ff7cb4c4c7f4e65a07fea8a2ce3b58b265d4b3220013a09ecf4e01023aabca5586d61ecd5d7f2bedceb8b18a8e41451c97a192098b196add06a8a6b619e1e731fd9ae2973741aff6358c1ad45cc873a2d497271e3a20873a6f701d4c44ef670c8c7a9793079d9bdfe956bdc02a52d1de8b2de58b0f7d309240999f13985fa8c98e57fe1bb75219ae6330e9495b523e891dba7885a5302817d68a9891ae0c2597d4d7833b91b073c4f9b27be1cf81ca1c2c1014c57a4affe7b402c0e0c1862bd17bc1d43428671a106c26cab61d5e4ffd1c01f6af1c6e97f7a25ae8aaa8d2c91c57881df52bd5f242b127ec7aed5880101caa01783884dfe943ec9764473323f59b27a204f34aa1fe7fd4433fa606608b0f253247d149e3e269ae5445e917390be83d5650c05859e3a817a6c7e561e2b12baf6d4ca4221df0b7f29fa134269139afd9cee5c7d60149dfa23031705c6a8b72d00d659d7a085de8330de2e5c168ee3eba2180a9319f5e8e0806dadaf0fffbc2df839571360b8cd32300504a527cf914da7a1e788261c9cca2872ebec5a17cad33b15a7a7427c200b8746761359194520f0da1d7ae03f26190d07cf92d515e04815f514c66a98997320a028ad24e83182f213d991accf19a8a59003a2ca666ca505c0d8349e2cb22887efb7db9e4a4e3e2d8da0d5f032603e03f48fb967fd018fc99c6eb72acee4178edeb48703903a89e9462a2d1f447234c3373fff8b205848c7a9d6e45ccc31eeeb0105ed3af1188fb847cf6f03a7f0a646fa325b672796168dbbd9d1d19b2f41685b18c3c96f1cfb7ecb1dea132e8815b62647820ac4b12597d8e737a01a970704b03ba5ae68f8d64a1810db10427fbff1d74cfac91561484cfc8d3b23f74ba0f37e7db2f942c58fb1dd30f6a50c57b5eae720c6ed69b0fb81a6e0260c53028c732a544391e319987a24548230378f8f1ddf65a2d654c7b26951d5c6546cc8fda6003228e8913c9e3c5adf7b7b72f4ff5c4aedba6096097f9a4b58ea1e060609e8d1f0fb0e5dd905b29fec72b118d40c5f599a63f9a37041742a7f1af3ef951c31833621842ec212f9fc5cd3e8c08278ea192f8032ade447d2f35ab59810aff371f598b7dd57b3cde2ad854ecad0c786150748ac241ecd67cb868663a6fcbe9d68c3dc221d4fcec9b0ad89c337c1e10b91a38ab1357f260ca3a084da536e56262973e6c6cca838601fb2f335811375aed78295c4b17d3798d39d4cbf6254ce57680a102907e5c08b5c7ec0a1e73bf3d7b8babdc6156c6ca3f09c0423d6716ff4e6ee0338cfd778158202b5ffb60b74558dc6d0be9b5aed6892c4e0ad3e20de5b604b2b010af09ceaba7c0fba5a7fed39d31cb2769909a251ba5b0668330f734728f5c6786a8f1a35df77f3d739eec71d9268fb2a494a14bf7ab91c075023e76856d1745f5813d83878822934d0b4cc0538048c3f96cad7aef2bbc49bab139915dd4998ed3c6701973eb7913530b14c688f0b344ca9cb990de2a9b12fa7ad8b292234a33428b4d16813693964365bd412fb936c1461fdf8dfb0bba31202685f29addf95fc65f841e97042bc5d82f103e41017c6ac91d3d266e12db2dc195ac4f6d4353924270c7144cd96dcd07b9612e2bf1e0f7fc46ef83690648395c575a13c2b2df0fa04f740340e6b116b0866a401de22f68fa3f621d75b9f5f625cd5d5d7e12a5b0ff795749d742eb2648ddf068a451059390da566b3de84f9d528b2663de7dcc562eb014071e8277a054783d322fa67b9e5261b87e9c354ff58fc52bf9df404139311d6bf9650658fc94835a6220ca02a4bfbf46b2af4f30b1ba681c0de7c134d98dd52eb1e937c191cc9557aa73a343b99ae0b8954a3e929174984b574da75e90a9b71af1215317b04e4090770ab596091fc05c82235a324f86280f7fa081360ac758c1980c6a6763453e6b344611e46b05760941f9517ceb298ed7a2d6f96b11f5719ed0dec803c511dadb8d056d4ca06ca0ad090558a4fbf3a886f3ea9c33e1bb4bb5ddef4798cdfb384bea75a3794c42a53af60f12c95fe9b38d7f6a5d914ef100508091fc84756b596b9ba08d1dc42a7e253435b5481d1470ef00a1172cb036b5bdfaccaee02b15d099da17f9753846226325232e71ed9b48f57697bb3d1db75ed214310e6e3608ded6f188e37b21b96eefaa396db0df05a86416fe64aa950eea87e7af4407c828a8822b17be661269c9f9e365cdc79d20503e2d5e575c5387fa961206118dd379834aade7727a1b2477a24f05f6c2ba3156fe7f5b5ba6d7487b1a124f38e3ed3cda92a8edf05f28e3d699f0c12de9cfeb30ec8d4cd253287a6d3f596db0c06006a531e80083f5b41ee26c05d529e0a59ec151b4a9260a7ea8c1a175ca41b59f464adc122f448fc43e90dfa7b88f81caa7a84e3d6d4dbb85e5828b6ae7455dc2c87c8d9c706af2e62763675851b4ca449c9c0f95d953ce53c5327ba8981321a1cbfb76bafac7fa17c99567725d8e0ac288f3ccd3bad666e515156517281c97a3dbfbd5f345f8eb80bb3c4230301a38b7c920d74eb910d380f884a683f7d3e2738fabf9646138e8a32c35e43786e67925508e4cc7b1e7a36abdf6a497077704e216f1e730c20ecfcddfbdf2484d8eb0ef9b7478f77063fa90b8afbcd019d1a584df58c537b40b193f246598ae4c53958a947dd3916b14a5a4227f01bf543a8c5d6ab8eaefdfb959c8715b756a9c797fe39229dc56a86364cb367fa37e16e96cf8dca1fdc8b6a46ce88e3d29c75b6cc718ca8c28e9e1ae991b28c286107c1dced150814d6369cc8003b2976018941df7fb8eeb68be57adcf8a0e813d2fcd16dc390ce17dd0a91dd674d766d21b5de7f4678a548d75cc3de7d099b418fbdb66b2a2b12a56b1dd8b3f84a7b45e36db9bb63b3ef9fdadebc21c6a75364173925ffc69d481024e49076dca105795e7a64a3c82011889aacf0114a1bd31414e288cbb63eb47d399d0e025a54f11670c8ad4a793d0e7ebd3b0d8eb30b87cf62b131c61a4c55d2e56e47ae99fc543c57a1877ce44dac4c6f9fd99552701ade43858e0b4020230cb4d42d1990bfb509471a5c1c5557c29c00072c5cbbc056de6d465ea2ba2f4a1a5dd604dbf998e834b9200c59fdf90bec38af9218e47ea5ed5512cf8b0146126a15d49bf915eb893ad1ef83d8faf6c93f944ebce3704f930b6f69a1afe767ac2c9fdf092c804c7372ae1a64bca3a3b5a31f2ad430ba9e61dab3daa3be90a538cf0fba00796de511cddb5a594f14aa6d215bd0be19c0ca5f043403b7dc56c87b092d9436eb79509c3dbe367c2fcbc2b09f9818cf5a55d5ee0e477888166bbfece661b62812ffed3e4167ecc81dba148f89a8f2e7c27424a2ee091ac487e68fbbf9798e8caf46b35de8dde66a7cad6dc98a426ea7b8b930cf2d7d71fe71066dbe51e8a1c7151e97fecbeedef3d6f8e01cd5576dd58097b46153f9c3bcecf30bc82b4cdfb1bbfa826c7c5b217a023e4da02a35d0947b2c4d24d50a292e4c70fe854a420c54490d4850ee8c372756671fe130532f89878a64977ead60bf604b73859ae64ed62536423bb51b30c6fedbc819fdae05cb64b87b153f4252b832d6b866100a7b307d1e705643f96f0724858e6211802b2ce706d5424b99315db90c7d74fac66951251f6cb739ea008f839c7f62318f795337ca4ff05886a2640819873ae00b933081b64da1101d1b17451357921a2f4d4dc86c92a5eb346fd6cd3a63315768b94b90a15162aec91cea706b9221330db154d1fd71acac90be47055c725bce38710f1b4b4144f331cfa9fe15ebf6535747669e4aa1f0d72092ef395f16a4ec9014029b5c9d1b4bed9ec81a7568f8f1c87e0ce0f4ef9cf49e3fe4960b0b7904614772c63147f3c5463fffed182919c4973a8256346116be40b10a38cdea5bad5878760daaeda57476e86ec65e58030bc8ff99ebf017e9bf6383f981edc83b538e2bf4bb573637e6f4717d74a3ac71f5e151259b29c1b7226e3a8ab176baa2f27e3e385cd48c6f072bb6e8e9c92e35d7ff51177f4e3553555d967c04befc1847003a8592738c82eef231ce3d372372a19a01b27dc7916f986ff3f3ea8872d4986bc1ca649a92924c8f582ae2b44028e711e955d2563c33db3b7734aa246de553dab2c5268538f7c2b6dbe9a70657e2a26e52f5d216dfa9aa8e197a227c86a7d3b468880a721b804a0c51af1592043eee7fe3657b40c1832a858cfb4e037d208ee69c4fd697b929383a971b2a0864544505af2267e334db5f3f3f4ed88e2f6f2b3d7b96016ff92a120556e4d1e50440943893b00508c6242bcc41b6d06dc29ba20564b42257b9fa1b5f4f453e94e72501d31e8947e09a38261020400db4b8cf675b1854639a962a57905cbbee14ea0daa9bd281fd635c8f900fcabdcbcfb140f4f24b47731782ca899284fadfc9d0d6eff77045792e139afad34c7672bacfa22d85fcc05652178cc169bcf52ee3cef281d99935abf9c9910caa7994cfe33b9319d9854aa6e2590a86297f23b0cada7251a6ee1b2f3d2cb5a193cae8768d92f556994e416d4bcf5bba3a295d9e2215291237df74e3c493189bc5a27b3fec3e1a1329c6c6c75e0802b40fc74776476dd2d9e3453ec1709a8a2d162a936d9fe7dd4b6f7abdadfa429aed4cbd5896cfb24a2d91f1cee781d0ed73cf7306d6f9545fd3346c2232b8799553357a5a531d6085d04af5f183019dfd3483baf23b0ba5a6b58bba4b7a1eb0a32626bebb5cc0c4dad45c55d135be8b0a4dee787ed48b90a2a3fc120a753b52290c27ad0eb32b668a9540986ca0256c1676debc4d19b1b80bedd81e505154264a199ef1a54e1fff1b3589fbb6b2d87a1e04e67066571b68fe04f030d473f8d135585f8b7be91f0ae1a4fa2f44008c0f727f6aba9c5c60c3a9ff22911e267ffa2a5d1c71ff25f96ad257be29a2ec641e2055d785765cadd0c2fe513c44154e74f4b8cc4b24d9ee2f6cfe245549713f9dada1935247a2ac7ccc13c4a5c00c6ffe7ca33c0cde4c75c4fe2ea041a965e4c7385ebfdbc348da8c4216a02fa829892c827adbcbb87745120667cdc5a4aef28b190a54b422df45b8547c447765838dbf9f05de338ab672706b59b2f0644d6735d9316e64a1a15d3dfad893bb1bbcbe1b574a0b8ef5265e195a929148cc5e97c8bfb032d4528b523b6a6b29209428f38115cd102e3b4e268333e490140964278238e7ea9638ac34559e05300dad0c3f18e9228474cd3a7186102967c33fc14f086b4f1ec3957d87f2609d140dbb9e7ff793101d1cb90d004565c6a32924715b1bcab483e6389e2e824054edef350f328870f16412aca0fee39edcbd02a6a667aaaeabb6654c4762c639a26286a3c1730ab75defcd9451b4377f6acdc3b905684658c0844d904c47d313d85eb54963fd71a9a76dc8e345e479004f00e446b886ec41cf7bbb9311463e877aa4e357a0dd0b185a5cf12244296f5f8568e84cf6ac3b6125db6897e4e7c183cafc04f61b3263456f61a7880b446e3cffe986c3bf027c7deba490ec8544d2627e6596ef8f8a5cb577796e7c36ffc4f4346263b5d86ae1d7b8d04709367349d590047a8bfb34fbf6481adce60eddfdd1e148ab83874d70b5303fa0ce60c0ba7a047a477dc4c513d2218b0bb2bdf9b60be9a39e928976464e333ce0cb19aa21fda1c6851c6db9d5bbc6552e080f8e448637af711fed92e72c8d8530187de94603377dc387041a9eb42ac70b3923b9828de33bb337d55409cb419bf4089cb2bec79ffc3afc6dcc3cb82bc903d956d28e307fc0470736574056302000318eb22887126df9062243038440ef3fca2aa024fff8739db4930b314822b00cab172e83c33b7e5b959b0c3f27c714e447120833ef69bd634d1e011fc3c2585beaa882a29c2dabddfd31a48c0255d1ab57c6796aa4625a546a02cef51a9ee2e8007fc047073657407210302e71fc2fff37aeb6d2e2a7b7f2308d4ab7d4bf0a4cf9be7c06e89a66442b48300010308f40100000000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20104000007fc047073657401210970cb1dff96101101e24bed1a66fb0794d2fcb26aba11e7f2393edc1534df8a9607fc047073657403210b9991881df2ec384ff5616f6c03d45cf033ee64536297c3557f9fffec716c1fbe0104220020cd4ed5f0db8c450e8b0be595b6410c1759c19f1f6926279095c83dade9862b6d07fc047073657404fd4e10603300000000000000018b6d2d00790f618171a9e8eb6051fc14dc27c502a54f5ccecacb4bcb350581a8f4b1a887a1e58865a21f51ef5098400c115cca84f489637718d8c3ca4350ad677374d40d2b64fe949ca34bd4ba845a87c7693421b70aa8d852e021aee329762883b9820bc0a47ea2fc6a8411ef773703632849094e51c73997c67f3e922d2801b6abc445375cd963a62c2bb28d733bf9274fe503081b51a56023a94200743e7d38865c190331449d19bf3d4eb7bf0b2a9b90696484aab906b9470e10946744838fc428f88461864d6601e93f10909e049a315fcc0ea7f4d71507fe5ed19b9ac2f55b0d3902b153ee27da9c55ab66debfb5ca440dfbb1a600cd8875049c4c13bbf242d26b10035002c7859f9c3ea631d955914adfa0817e4801e85b3f250cd9e7523db62c4ecb17a49028a02a1b61eb96a410643f1fec0ac664d96f99a1db4ac335c2bfec2946707c3c779a56373db197039af9a903e833af6f51de5cf8fc667dbf5416845d415dc98641e0984ebdfab88bbcdf305f605d36f7a472a516206d7ec722251e269800a00e8adb8f2ce161395c1c6ad4b406e1fda77bc7f0af07ea075011cee6cc5e7fd1b6e96e321171ca7d28a35595ddf0b0c831d28a88d30c7391c5832d90f906539aa49185fc6c0864e2d10b21160991fc19a1d084006d03fe3fb6f571f1ffd9f06ffbc0c076689373f9c2f8655758f7f44618345a6d5f8edae46e73a09c38157d5c39dd51a47756ea761e6320d6a91a1bb22d8dd35e4e7806b0242bcc4cae8720a953c6f933c0ee3216513cce6742a2cb4bf44553d8eaf175471dbc0f71c7c245fe99ab4240ccac637a16c82f0c60586f00d83ff852af48a239289d8b70a2638b0aff02572d6d2d68e22b87ba93f3db51bb27825265607ba4b6e9a194c7351f220b9e715a23237c40024fb7cfedaf7c8e0a1c4c6aebef8841fcf2609a3dd7f44dfd8895077df41f10790372eac8adff5ea7eeb28e371b4700d5044b41fd358dc4ba29158213e0f93711026fac8abfbe7cd80a939477ce545bc91cd1d32e8f2268563b0fe3e80855777d51cdf4835050a557d3c7b7f6905ba744ae5450d22837d2c2fa0c0755934654a78601a1fe236f11b6d72f368880ed938ff4a2e8d82c118493a1bb9a9ee95cf329f2d175d467aacc2c6cd73ed59ce64d508604db77942f9b7f3b0f86d913d3e1b489d2190a6da1ed997ab1eee356c885270e4e0192acc9c2b8702107c96aed654318bbb7724b913808dd2cfbbf6ace8db9c4cbf26f2c90a76eb967e365c58855b83550819cb5b28ea5e6ec1ea153ad3ee5e6292a174f7cab1b39e852194a6926bdc4d42326e17998cc057f614e91f6acab5a5bbedd93d9a13dc61977aa2accaf35370a3f1d3819c43c9430d0e767e92de96bb225007a7b6576ed7c4f05c984ce2e437d3b7f7f50c270caf90f8e5dbecb992be2972ef8d79c7674e025ee06b1302bcbd57fe5be9d9b4e38f17d9dca898ef3d71918550fd77a15c7aa2b66ee1a2f38b81040f3d6ec6693f54cc3fe39515275849e9e24b0af3e81705dea95e8f1bb1b4665cfdeb0630a5542a2857f2b58c36761d743299d77872d6894302123f4347702572f04d9876191d771e87655c071fbd29338eef0f9acb0a8ca3f0327ead8e875bc2e7ba38f249e6eda1fb74162e972ff523d20c6638b93297d406e9b2264187c06d0a78203d771f2525227d029b27b23192f747492b9774b12b039729ef75d11ce8d701e56fbb202f3e4bd68686f096f13680456529e5f132915595e0e0b4061b3014219f1fbef4d7403dbfcac01c701b7727c2463cb838d427e07706400be4fdd9140a800e47e7ac15a7a8a897187a38a0080726349d8b7566252076b1ae1366496b50e9a6d236837ffa0c4c3e61bb409a7d9faf8662109ef7213007a76a6d94cb79ad07183a33a4cdedd78896278a3b5531ec0efda9d77076d85a63536b426a6b58c3d0e8a46faf0fdf678e4964272e8410b346cc753edb94a61a2f309f8e753ff332f5b15215e0a20ef32e6a6faa044a431764e008e66b4af820bb6afe4d8dc1679219fe7614482517fdc523d4d7ce2bad9d59f7b9aed89b813e5b36b58a7c668e53181c0e1da45e4ba3851b46de8e056d63e440c471fbe23fbffc31ece7cd20658784f2d2fca3f730a1f8a90ea6995ccb490fca475b1441e38468433d1423c1d83a20b04f1216aff13c8e035c2ed389695c2bb0bedadc38c8a6222d687f0235bda3566c0865774bb6098acd674ff9091db1a6c4f0c2955c1759730b361f310d956f892089f500eae0084022e610ca4e758ce2c680d213bd1b5e00a6c991976e93189159bb98a1e4eff14f681d47694060126c0852ad52489c15d7302d82c66aa830208a9fd13da87a2aac3e44dddae632f2e4d56dc768ee6b3622c61e59aee27fee5aa0bfa9c56402ae3525f00634b11381d0b9637ac699e4c4b225c32bef9dc563e87cfc33bf07450c2cdd015bbd94df63697cdd9b6cf4169cfe1f626c126dbb588c57542662d02eeed561946ce94b46571f72ca3cf7fe52a8a6ea24fa216f01655dadbeb0f74e383e522da69db64b368cb155c2ba4c4fc8aea8745b1081223317003f0cd7ae620fc7d9a6c9c4f39a237d5d9d7f3e756c77daeccbd5d06ed28ac2f089db5449340872bc444aa4aecf6552621b84e4fabfd6baf0e1b61cab00e5c2050bfa38899e9840e2dac55c7d5e7105f65dc3afe3c35dd3e8ebb1a013d65fb0b9d76665f3c4eff5b766fbb0c03cc10c411987ef516405296437a91a67d7398d788e30f55bc1e6236b317784504c53800cc07f4eaf78bac03a025a7943573edcc67db3d5d5281f85ee993238fee3580cb846efae33b45ee2ee1ad640b1d068302504521269a31a166435e8fd964d2e15048f299a95ec1cbeb0c8d5d119e24670112d61d56ea120d7bc30fcd924fc7b812404ac45798af3fb590570a4d7a3f41639b879d1bdf2c72c979105460892fb41570cffee716679eb7b4124be188e28ca4c68d206c1cc9d49cd7489d63372853dbe83f874579238ecdd28c0dc265871d6dccf782b571f1004702121e8b15c9d8af9e6812dbbe742812c7e7cd1dafbdbe3d189f618936e270855700be8f6a7b528f271a936a2cae204b44d909ae3f6a8bcbfcda44b430397b1c96187e5a8362afe92bb9afb0a0a482cb6c8cac39a0fb1fe0034f8a965a3be425b4b34f67ff38a8ab30f8219a8933539c1d06d9b2997b6de743c568caea8b269642b8503b546c9e136d0e47775c8fef45d4489e6b4747c6accd6fad3d34fdd6cbafe07264e7ae1e025306c97d77a130093cc8d5ab8e4abe095787183a9084c569168011766b47dade4e3e1353a78f9f3464d8237b7de02da10c7a7b8951bafbaa898003ad9de997c89d8507393c6fb782b8f41aa99d5c92d5ed93e02a2e7550d42f178739898406badb6da850e305c10063b1a687a2b321a1f867ddfc7949d9764493af4f9681137101f87ec3c3733c0ee23a758a69dd5dbfccd20e0e7cc8543c213688ef9cc85bf9c539d3b6758e24befb3c1b617b7d59a17e915bb985df8229429430dd3057a8225d22afc2775e352a2d7c2f2f46786d4e6e984fb35ac6d7e1b57da82a6d1470895e56521c88c166f8124a4f0c5ada7d5e43174e319c21b9416735858ab50958def63c9a38e853d28a0f47b8e601beb0cdfb30d87070003f957ae347d5b03e80890311ded8018de0227c430f29ff20f0d0d1331dd5f22cff547847c0a26c1fdc272cd234b668823635f68e0797bf68fb1e531a423b1fae9b056fb8c0589908cd2774a7bea8da465248a438a22919d35e0ed8c5020f06824aa856c1a75e0d50d8e9c2dca471d249a97e8e8055d0927432577ef07e6658aa6ab3e9f5f4f50848b12dcdcd9594dae732864f9c6253cccf39922b5f1f8e16458a0c11db397017821de73a331400a76c2a5a29c7661405e9f244a92862a8ca13bc86a78a36744e52019c067573574f75e01b21c36e19a714e9cc0860e9df8e659cefab57002dc2b3d1a2918dc20ff25bc0d87023813abcbbe29defa514bd71fedf314a140508c7e8dd4ace82d56cfd6307fc8299a65c8b3b0719881dc06070d670729902ebfa1dc0b88050e5824cc186454ec2727d0fb2f95eb677f949375a0a31661c7f2bc452426a052b160b0654bffae35766a5317b845582176f1ec52e5bb7d814651781e268cfaefcf6da560810d84343dab8a8b2f2f7976334043498f529d75f9dec893bafdde0ebf003ea7d43f22d8e4eb3afea7be8bd22a9adb9334db2d6b05b8bfe72a96ca2c5ecc925333e4076bf5b7d9ed519ac3eb87c73d0c8121b1034424991561eccb669807a722bcd43141915c9db90f7a8a8e732054970645da1845b988f21cd5d2a89abd8e14c0e6532a3db89e43571b795d6f475b11c16cd7253a4538f4e73d0e3791e0c8f3e51ce3d9645062f249549d9165185fe6920659fe72ae01f69c6d5cef5a01cbbce0fcfd671e1a0aac35d541210a723d2fde91f37c130657d8825662bc46ca7780e07422ce2e7e5cbc1b15ad29b8473ffb832f45c480e960d620267561b3e3112c54359459c3f0235eb6eb2720dd5cf65f88267e099ae87ec7e35b3a915f18a4ab67583ccb4d907637812d797dfa51acc7b5cb13ab58934217a562b00a4a3d030bd9d3565a47c95396034bd65d39d39a6e7795f13e5031d148db16eddba996e1e70730eee02c47bd8b5c42812a12a2db5490fc3ad50d7d03c72c0e933ed8b43f8e34124e272cb39e06e628f18acfe4488dcced67a2c47008801e8d2db5dc7f7556d38020d53512993f3efeb4b07fd1e7b631deeeda74983011ca401ec7b86eb2a7a4d341f97337d37ada0dbbe124fe481ecac3e9b8e8f3b8b90ccf81ec028f2ee4e62934abcfcc2647966f6eea6563a0fc8fc75348f5fb3d2390db24d49858bbca822217fa81d240cacb7b2f6c2e4bad8a7a112b83a5d35ad68ec1cd599afee41fd4e860097f33afbc2cd790b2933f1194549c5aa3fe5c651a456c8ba7c8fa5ee5492233c21a80bd9216fcfccc03ecb76af3849711a0f69d5a261ce94484c30f4b74ca6cb4d7d5c4dcc0be1f0390c208e1e7e863700c6dce7ea5ab3831c00e586094a6a1f3b32dfbbf99a7581f90001dd558738804d0663a59d77407b6ab1ef3a82c156bc58d5a694a365b300a90ebbcddc49bbe5ba63c88e7a6e0faf5364ea17cabc602ddbf87a4c2f55b068ef296be5bb66befc1e37ad77f8e97c08f02d17dcdeb47959b0f46c2ae2c3d99a948f2a52c5793d53fe57876c38336a74786042abafb63c2154096eaed98598aed76da5a17ae179e79f848b237bdd6db63e5fbe77ee28b2bdcae462905ce1827800407317c2a42fc0dc234b2183db9097c0fae23da91aca6b1b7894537b0dc8524536573a34ef68596021cba863ece0de4a068f806d888aa03ed88ad92f375860f8885c5533c637a7a330c24aa0357f007ac3678e59cb1f6aa7c6979e15fd107a98ab42a635a3c3e70b58a19ec73b4bdc482000c3dfb4af84012ea3957d3d30b80857d9e06a2e677c84e5d9041ad4bf22afbdf0351f6d5c7a7a2ada3dd5ab4e48e37d51e5fad56cf9963715438c5f04b9772773893a59e2e46c6b7e19e9001650b66b469f4b1c4d188b286d5ce8b21269179e772147c7cb09eaee9b9de684ffc33068e5d346e79b710d82fd1278aee64ddd4ed37a944e6c745217c6a626444aa95b565c1f68a12cd2b86a61927896884bd5a76a9df4f6fe548bc16444272ec1e856334d64e0f32ba90daa77085b0683e3e010abf571dc564fc703a12998c72b6712386cfa4ccc802c850a3604bb0b2d5cd2eb6e788d475ff198f94a220c925a32ab6d69b037f1b9f0f4ce1d1b89cc0d07fc047073657405630200033fb971149dc9881cf31b7bd90de445f0ada69611016c5fde4af5bffe2b40a1a27d651a1d2127b0a95539b18fbb835f5145c1c4c7492866c6bd08ba260abb300720d2d42b729b72c6166f9ae0e4ac09a0f6851ca65444bed00b72b7f12befbbd007fc047073657407210252a4b012198c2131d70498b5939c401c01eb1178dfd58123b55766b03f008f7b00"; assert_eq!(elements::encode::serialize_hex(&psbt), expected); @@ -1774,7 +1785,7 @@ mod tests { input: vec![], output: vec![TxOut { value: elements::confidential::Value::Explicit(1_000), - script_pubkey: Script::from_str( + script_pubkey: Script::from_hex_no_prefix( "5120f370a017453c8a22123a43f83f7efced972ba1ef8320ae58e3997a94a64bb7ff", ) .unwrap(), @@ -1850,7 +1861,7 @@ mod tests { input: vec![], output: vec![TxOut { value: confidential::Value::Explicit(1_000), - script_pubkey: Script::from_str( + script_pubkey: Script::from_hex_no_prefix( "5120f370a017453c8a22123a43f83f7efced972ba1ef8320ae58e3997a94a64bb7ff", // spk calculatations are differnet in elements because of different tagged hashes ) .unwrap(), diff --git a/src/simplicity.rs b/src/simplicity.rs index 8068f3e8..2871a1a1 100644 --- a/src/simplicity.rs +++ b/src/simplicity.rs @@ -1,13 +1,9 @@ // SPDX-License-Identifier: CC0-1.0 use std::fmt; -use std::marker::PhantomData; use std::str::FromStr; use std::sync::Arc; -use bitcoin_miniscript::ToPublicKey; -use elements::{LockTime, SchnorrSig, Sequence}; -use elements::taproot::TapLeafHash; -use simplicity::{Policy, FailEntropy, Preimage32}; +use simplicity::{FailEntropy, Policy}; use crate::policy::concrete::PolicyError; use crate::{expression, Error, MiniscriptKey}; @@ -123,37 +119,6 @@ pub fn for_each_key<'a, Pk: MiniscriptKey + 'a, F: FnMut(&'a Pk) -> bool>(policy true } -// We could make crate::Satisfier a subtrait of simplicity::Satisfier, -// but then we would have to implement simplicity::Satisfier for all the blanket implementations -// of crate::Satisfier, such as HashMap, which is annoying -// We might choose to do so in the future, but for now a crate-local wrapper is easier -// This wrapper is internally used by `Tr` and is never encountered by users -pub(crate) struct SatisfierWrapper>(S, PhantomData); - -impl> SatisfierWrapper { - pub fn new(satisfier: S) -> Self { - Self(satisfier, PhantomData) - } -} - -impl> simplicity::Satisfier for SatisfierWrapper { - fn lookup_tap_leaf_script_sig(&self, pk: &Pk, hash: &TapLeafHash) -> Option { - self.0.lookup_tap_leaf_script_sig(pk, hash) - } - - fn lookup_sha256(&self, hash: &Pk::Sha256) -> Option { - self.0.lookup_sha256(hash) - } - - fn check_older(&self, sequence: Sequence) -> bool { - self.0.check_older(sequence) - } - - fn check_after(&self, locktime: LockTime) -> bool { - self.0.check_after(locktime) - } -} - #[cfg(test)] mod tests { use secp256k1::XOnlyPublicKey;