diff --git a/Cargo.toml b/Cargo.toml index a45707ba7..2853f3d81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,16 +23,17 @@ rand = ["bitcoin/rand"] base64 = ["bitcoin/base64"] [dependencies] -bitcoin = { version = "0.29.1", default-features = false } +bitcoin = { version = "0.30.0", default-features = false } hashbrown = { version = "0.11", optional = true } +internals = { package = "bitcoin-private", version = "0.1.0", default_features = false } # Do NOT use this as a feature! Use the `serde` feature instead. actual-serde = { package = "serde", version = "1.0.103", optional = true } [dev-dependencies] serde_test = "1.0.147" -bitcoin = { version = "0.29.2", features = ["base64"] } -secp256k1 = {version = "0.24.0", features = ["rand-std"]} +bitcoin = { version = "0.30.0", features = ["base64"] } +secp256k1 = {version = "0.27.0", features = ["rand-std"]} actual-base64 = { package = "base64", version = "0.13.0" } [[example]] diff --git a/bitcoind-tests/Cargo.toml b/bitcoind-tests/Cargo.toml index f91767896..57eb1c530 100644 --- a/bitcoind-tests/Cargo.toml +++ b/bitcoind-tests/Cargo.toml @@ -9,6 +9,7 @@ publish = false [dependencies] miniscript = {path = "../"} -bitcoind = { version = "0.29.3" } +bitcoind = { version = "0.30.0" } actual-rand = { package = "rand", version = "0.8.4"} secp256k1 = {version = "0.27.0", features = ["rand-std"]} +internals = { package = "bitcoin-private", version = "0.1.0", default_features = false } \ No newline at end of file diff --git a/bitcoind-tests/tests/setup/mod.rs b/bitcoind-tests/tests/setup/mod.rs index c97187d72..294b564ca 100644 --- a/bitcoind-tests/tests/setup/mod.rs +++ b/bitcoind-tests/tests/setup/mod.rs @@ -29,7 +29,7 @@ pub fn setup() -> BitcoinD { let bitcoind = bitcoind::BitcoinD::new(exe_path).unwrap(); let cl = &bitcoind.client; // generate to an address by the wallet. And wait for funds to mature - let addr = cl.get_new_address(None, None).unwrap(); + let addr = cl.get_new_address(None, None).unwrap().assume_checked(); let blks = cl.generate_to_address(101, &addr).unwrap(); assert_eq!(blks.len(), 101); diff --git a/bitcoind-tests/tests/setup/test_util.rs b/bitcoind-tests/tests/setup/test_util.rs index 7af2114b3..7542d1c3d 100644 --- a/bitcoind-tests/tests/setup/test_util.rs +++ b/bitcoind-tests/tests/setup/test_util.rs @@ -20,20 +20,21 @@ use std::str::FromStr; use actual_rand as rand; -use bitcoin::hashes::hex::ToHex; use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; use bitcoin::secp256k1; +use internals::hex::exts::DisplayHex; use miniscript::descriptor::{SinglePub, SinglePubKey}; use miniscript::{ bitcoin, hash256, Descriptor, DescriptorPublicKey, Error, Miniscript, ScriptContext, TranslatePk, Translator, }; use rand::RngCore; +use secp256k1::XOnlyPublicKey; #[derive(Clone, Debug)] pub struct PubData { pub pks: Vec, - pub x_only_pks: Vec, + pub x_only_pks: Vec, pub sha256: sha256::Hash, pub hash256: hash256::Hash, pub ripemd160: ripemd160::Hash, @@ -43,7 +44,7 @@ pub struct PubData { #[derive(Debug, Clone)] pub struct SecretData { pub sks: Vec, - pub x_only_keypairs: Vec, + pub x_only_keypairs: Vec, pub sha256_pre: [u8; 32], pub hash256_pre: [u8; 32], pub ripemd160_pre: [u8; 32], @@ -61,8 +62,8 @@ fn setup_keys( ) -> ( Vec, Vec, - Vec, - Vec, + Vec, + Vec, ) { let secp_sign = secp256k1::Secp256k1::signing_only(); let mut sk = [0; 32]; @@ -86,8 +87,8 @@ fn setup_keys( let mut x_only_pks = vec![]; for i in 0..n { - let keypair = bitcoin::KeyPair::from_secret_key(&secp_sign, &sks[i]); - let (xpk, _parity) = bitcoin::XOnlyPublicKey::from_keypair(&keypair); + let keypair = bitcoin::secp256k1::KeyPair::from_secret_key(&secp_sign, &sks[i]); + let (xpk, _parity) = XOnlyPublicKey::from_keypair(&keypair); x_only_keypairs.push(keypair); x_only_pks.push(xpk); } @@ -286,19 +287,19 @@ pub fn parse_test_desc( fn subs_hash_frag(ms: &str, pubdata: &PubData) -> String { let ms = ms.replace( "sha256(H)", - &format!("sha256({})", &pubdata.sha256.to_hex()), + &format!("sha256({})", &pubdata.sha256.to_string()), ); let ms = ms.replace( "hash256(H)", - &format!("hash256({})", &pubdata.hash256.into_inner().to_hex()), + &format!("hash256({})", &pubdata.hash256.to_string()), ); let ms = ms.replace( "ripemd160(H)", - &format!("ripemd160({})", &pubdata.ripemd160.to_hex()), + &format!("ripemd160({})", &pubdata.ripemd160.to_string()), ); let ms = ms.replace( "hash160(H)", - &format!("hash160({})", &pubdata.hash160.to_hex()), + &format!("hash160({})", &pubdata.hash160.to_string()), ); let mut rand_hash32 = [0u8; 32]; @@ -306,12 +307,21 @@ fn subs_hash_frag(ms: &str, pubdata: &PubData) -> String { 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.to_lower_hex_string()), + ); + let ms = ms.replace( + "hash256(H!)", + &format!("hash256({})", rand_hash32.to_lower_hex_string()), + ); let ms = ms.replace( "ripemd160(H!)", - &format!("ripemd160({})", rand_hash20.to_hex()), + &format!("ripemd160({})", rand_hash20.to_lower_hex_string()), + ); + let ms = ms.replace( + "hash160(H!)", + &format!("hash160({})", rand_hash20.to_lower_hex_string()), ); - let ms = ms.replace("hash160(H!)", &format!("hash160({})", rand_hash20.to_hex())); ms } diff --git a/bitcoind-tests/tests/test_cpp.rs b/bitcoind-tests/tests/test_cpp.rs index 876f891bc..8e682386d 100644 --- a/bitcoind-tests/tests/test_cpp.rs +++ b/bitcoind-tests/tests/test_cpp.rs @@ -10,11 +10,11 @@ use std::io::{self, BufRead}; use std::path::Path; use bitcoin::hashes::{sha256d, Hash}; +use bitcoin::psbt::Psbt; use bitcoin::secp256k1::{self, Secp256k1}; -use bitcoin::util::psbt; -use bitcoin::util::psbt::PartiallySignedTransaction as Psbt; -use bitcoin::{Amount, LockTime, OutPoint, Sequence, Transaction, TxIn, TxOut, Txid}; +use bitcoin::{psbt, Amount, OutPoint, Sequence, Transaction, TxIn, TxOut, Txid}; use bitcoind::bitcoincore_rpc::{json, Client, RpcApi}; +use miniscript::bitcoin::absolute; use miniscript::psbt::PsbtExt; use miniscript::{bitcoin, Descriptor}; @@ -76,7 +76,10 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { let pks = &testdata.pubdata.pks; // Generate some blocks let blocks = cl - .generate_to_address(500, &cl.get_new_address(None, None).unwrap()) + .generate_to_address( + 500, + &cl.get_new_address(None, None).unwrap().assume_checked(), + ) .unwrap(); assert_eq!(blocks.len(), 500); @@ -99,7 +102,10 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { } // Wait for the funds to mature. let blocks = cl - .generate_to_address(50, &cl.get_new_address(None, None).unwrap()) + .generate_to_address( + 50, + &cl.get_new_address(None, None).unwrap().assume_checked(), + ) .unwrap(); assert_eq!(blocks.len(), 50); // Create a PSBT for each transaction. @@ -109,7 +115,7 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { let mut psbt = Psbt { unsigned_tx: Transaction { version: 2, - lock_time: LockTime::from_time(1_603_866_330) + lock_time: absolute::LockTime::from_time(1_603_866_330) .expect("valid timestamp") .into(), // 10/28/2020 @ 6:25am (UTC) input: vec![], @@ -136,7 +142,8 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { // and we can check it by gettransaction RPC. let addr = cl .get_new_address(None, Some(json::AddressType::Bech32)) - .unwrap(); + .unwrap() + .assume_checked(); psbt.unsigned_tx.output.push(TxOut { value: 99_999_000, script_pubkey: addr.script_pubkey(), @@ -168,8 +175,8 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { .collect(); // Get the required sighash message let amt = btc(1).to_sat(); - let mut sighash_cache = bitcoin::util::sighash::SighashCache::new(&psbts[i].unsigned_tx); - let sighash_ty = bitcoin::EcdsaSighashType::All; + let mut sighash_cache = bitcoin::sighash::SighashCache::new(&psbts[i].unsigned_tx); + let sighash_ty = bitcoin::sighash::EcdsaSighashType::All; let sighash = sighash_cache .segwit_signature_hash(0, &ms.encode(), amt, sighash_ty) .unwrap(); @@ -184,7 +191,7 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { let pk = pks[sks.iter().position(|&x| x == sk).unwrap()]; psbts[i].inputs[0].partial_sigs.insert( pk, - bitcoin::EcdsaSig { + bitcoin::ecdsa::Signature { sig, hash_ty: sighash_ty, }, @@ -196,7 +203,7 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { testdata.secretdata.sha256_pre.to_vec(), ); psbts[i].inputs[0].hash256_preimages.insert( - sha256d::Hash::from_inner(testdata.pubdata.hash256.into_inner()), + sha256d::Hash::from_byte_array(testdata.pubdata.hash256.to_byte_array()), testdata.secretdata.hash256_pre.to_vec(), ); println!("{}", ms); @@ -227,7 +234,10 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { } // Finally mine the blocks and await confirmations let _blocks = cl - .generate_to_address(10, &cl.get_new_address(None, None).unwrap()) + .generate_to_address( + 10, + &cl.get_new_address(None, None).unwrap().assume_checked(), + ) .unwrap(); // Get the required transactions from the node mined in the blocks. for txid in spend_txids { diff --git a/bitcoind-tests/tests/test_desc.rs b/bitcoind-tests/tests/test_desc.rs index 6c4a5246e..06c8e8f82 100644 --- a/bitcoind-tests/tests/test_desc.rs +++ b/bitcoind-tests/tests/test_desc.rs @@ -10,17 +10,16 @@ use std::{error, fmt}; use actual_rand as rand; use bitcoin::blockdata::witness::Witness; use bitcoin::hashes::{sha256d, Hash}; -use bitcoin::util::psbt::PartiallySignedTransaction as Psbt; -use bitcoin::util::sighash::SighashCache; -use bitcoin::util::taproot::{LeafVersion, TapLeafHash}; -use bitcoin::util::{psbt, sighash}; +use bitcoin::psbt::Psbt; +use bitcoin::sighash::SighashCache; +use bitcoin::taproot::{LeafVersion, TapLeafHash}; use bitcoin::{ - secp256k1, Amount, LockTime, OutPoint, SchnorrSig, Script, Sequence, Transaction, TxIn, TxOut, - Txid, + absolute, psbt, secp256k1, sighash, Amount, OutPoint, Sequence, Transaction, TxIn, TxOut, Txid, }; use bitcoind::bitcoincore_rpc::{json, Client, RpcApi}; +use miniscript::bitcoin::{self, ecdsa, taproot, ScriptBuf}; use miniscript::psbt::{PsbtExt, PsbtInputExt}; -use miniscript::{bitcoin, Descriptor, Miniscript, ScriptContext, ToPublicKey}; +use miniscript::{Descriptor, Miniscript, ScriptContext, ToPublicKey}; mod setup; use rand::RngCore; @@ -31,7 +30,7 @@ fn btc>(btc: F) -> Amount { } // Find the Outpoint by spk -fn get_vout(cl: &Client, txid: Txid, value: u64, spk: Script) -> (OutPoint, TxOut) { +fn get_vout(cl: &Client, txid: Txid, value: u64, spk: ScriptBuf) -> (OutPoint, TxOut) { let tx = cl .get_transaction(&txid, None) .unwrap() @@ -79,7 +78,7 @@ pub fn test_desc_satisfy( let x_only_pks = &testdata.pubdata.x_only_pks; // Generate some blocks let blocks = cl - .generate_to_address(1, &cl.get_new_address(None, None).unwrap()) + .generate_to_address(1, &cl.get_new_address(None, None).unwrap().assume_checked()) .unwrap(); assert_eq!(blocks.len(), 1); @@ -98,7 +97,7 @@ pub fn test_desc_satisfy( .unwrap(); // Wait for the funds to mature. let blocks = cl - .generate_to_address(2, &cl.get_new_address(None, None).unwrap()) + .generate_to_address(2, &cl.get_new_address(None, None).unwrap().assume_checked()) .unwrap(); assert_eq!(blocks.len(), 2); // Create a PSBT for each transaction. @@ -106,7 +105,7 @@ pub fn test_desc_satisfy( let mut psbt = Psbt { unsigned_tx: Transaction { version: 2, - lock_time: LockTime::from_time(1_603_866_330) + lock_time: absolute::LockTime::from_time(1_603_866_330) .expect("valid timestamp") .into(), // 10/28/2020 @ 6:25am (UTC) input: vec![], @@ -134,7 +133,8 @@ pub fn test_desc_satisfy( // and we can check it by gettransaction RPC. let addr = cl .get_new_address(None, Some(json::AddressType::Bech32)) - .unwrap(); + .unwrap() + .assume_checked(); // Had to decrease 'value', so that fees can be increased // (Was getting insufficient fees error, for deep script trees) psbt.unsigned_tx.output.push(TxOut { @@ -158,7 +158,7 @@ pub fn test_desc_satisfy( match derived_desc { Descriptor::Tr(ref tr) => { // Fixme: take a parameter - let hash_ty = sighash::SchnorrSighashType::Default; + let hash_ty = sighash::TapSighashType::Default; let internal_key_present = x_only_pks .iter() @@ -180,7 +180,7 @@ pub fn test_desc_satisfy( rand::thread_rng().fill_bytes(&mut aux_rand); let schnorr_sig = secp.sign_schnorr_with_aux_rand(&msg, &internal_keypair, &aux_rand); - psbt.inputs[0].tap_key_sig = Some(SchnorrSig { + psbt.inputs[0].tap_key_sig = Some(taproot::Signature { sig: schnorr_sig, hash_ty: hash_ty, }); @@ -206,13 +206,11 @@ pub fn test_desc_satisfy( 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); - // FIXME: uncomment when == is supported for secp256k1::KeyPair. (next major release) - // let x_only_pk = pks[xonly_keypairs.iter().position(|&x| x == keypair).unwrap()]; - // Just recalc public key - let (x_only_pk, _parity) = secp256k1::XOnlyPublicKey::from_keypair(&keypair); + let x_only_pk = + x_only_pks[xonly_keypairs.iter().position(|&x| x == keypair).unwrap()]; psbt.inputs[0].tap_script_sigs.insert( (x_only_pk, leaf_hash), - bitcoin::SchnorrSig { + taproot::Signature { sig, hash_ty: hash_ty, }, @@ -258,7 +256,7 @@ pub fn test_desc_satisfy( .to_secp_msg(); // Fixme: Take a parameter - let hash_ty = bitcoin::EcdsaSighashType::All; + let hash_ty = sighash::EcdsaSighashType::All; // Finally construct the signature and add to psbt for sk in sks_reqd { @@ -267,7 +265,7 @@ pub fn test_desc_satisfy( assert!(secp.verify_ecdsa(&msg, &sig, &pk.inner).is_ok()); psbt.inputs[0].partial_sigs.insert( pk, - bitcoin::EcdsaSig { + ecdsa::Signature { sig, hash_ty: hash_ty, }, @@ -281,7 +279,7 @@ pub fn test_desc_satisfy( testdata.secretdata.sha256_pre.to_vec(), ); psbt.inputs[0].hash256_preimages.insert( - sha256d::Hash::from_inner(testdata.pubdata.hash256.into_inner()), + sha256d::Hash::from_byte_array(testdata.pubdata.hash256.to_byte_array()), testdata.secretdata.hash256_pre.to_vec(), ); psbt.inputs[0].hash160_preimages.insert( @@ -309,7 +307,7 @@ pub fn test_desc_satisfy( // Finally mine the blocks and await confirmations let _blocks = cl - .generate_to_address(1, &cl.get_new_address(None, None).unwrap()) + .generate_to_address(1, &cl.get_new_address(None, None).unwrap().assume_checked()) .unwrap(); // Get the required transactions from the node mined in the blocks. // Check whether the transaction is mined in blocks diff --git a/examples/psbt.rs b/examples/psbt.rs index cb567de08..b0fcad06c 100644 --- a/examples/psbt.rs +++ b/examples/psbt.rs @@ -1,14 +1,15 @@ use bitcoin::consensus::encode::deserialize; use bitcoin::hashes::hex::FromHex; +use bitcoin::psbt::Psbt; use miniscript::psbt::PsbtExt; fn main() { // Test vectors from BIP 174 - let mut psbt: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); + let mut psbt = Psbt::deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); // println!("{:?}", psbt); - let expected_finalized_psbt: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); + let expected_finalized_psbt = Psbt::deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); // Construct a secp context for transaction signature verification let secp = bitcoin::secp256k1::Secp256k1::verification_only(); diff --git a/examples/psbt_sign_finalize.rs b/examples/psbt_sign_finalize.rs index a8822090e..44c397582 100644 --- a/examples/psbt_sign_finalize.rs +++ b/examples/psbt_sign_finalize.rs @@ -2,15 +2,13 @@ use std::collections::BTreeMap; use std::str::FromStr; use actual_base64 as base64; -use bitcoin::consensus::serialize; -use bitcoin::util::sighash::SighashCache; -use bitcoin::{PackedLockTime, PrivateKey}; +use bitcoin::sighash::SighashCache; +use bitcoin::PrivateKey; use miniscript::bitcoin::consensus::encode::deserialize; use miniscript::bitcoin::hashes::hex::FromHex; -use miniscript::bitcoin::util::psbt; -use miniscript::bitcoin::util::psbt::PartiallySignedTransaction as Psbt; +use miniscript::bitcoin::psbt::PartiallySignedTransaction as Psbt; use miniscript::bitcoin::{ - self, secp256k1, Address, Network, OutPoint, Script, Sequence, Transaction, TxIn, TxOut, + self, psbt, secp256k1, Address, Network, OutPoint, Script, Sequence, Transaction, TxIn, TxOut, }; use miniscript::psbt::{PsbtExt, PsbtInputExt}; use miniscript::Descriptor; @@ -72,7 +70,7 @@ fn main() { let spend_tx = Transaction { version: 2, - lock_time: PackedLockTime(5000), + lock_time: bitcoin::absolute::LockTime::from_consensus(5000), input: vec![], output: vec![], }; @@ -91,11 +89,13 @@ fn main() { let hex_tx = "020000000001018ff27041f3d738f5f84fd5ee62f1c5b36afebfb15f6da0c9d1382ddd0eaaa23c0000000000feffffff02b3884703010000001600142ca3b4e53f17991582d47b15a053b3201891df5200e1f50500000000220020c0ebf552acd2a6f5dee4e067daaef17b3521e283aeaa44a475278617e3d2238a0247304402207b820860a9d425833f729775880b0ed59dd12b64b9a3d1ab677e27e4d6b370700220576003163f8420fe0b9dc8df726cff22cbc191104a2d4ae4f9dfedb087fcec72012103817e1da42a7701df4db94db8576f0e3605f3ab3701608b7e56f92321e4d8999100000000"; let depo_tx: Transaction = deserialize(&Vec::::from_hex(hex_tx).unwrap()).unwrap(); - let receiver = Address::from_str("bcrt1qsdks5za4t6sevaph6tz9ddfjzvhkdkxe9tfrcy").unwrap(); + let receiver = Address::from_str("bcrt1qsdks5za4t6sevaph6tz9ddfjzvhkdkxe9tfrcy") + .unwrap() + .assume_checked(); let amount = 100000000; - let (outpoint, witness_utxo) = get_vout(&depo_tx, bridge_descriptor.script_pubkey()); + let (outpoint, witness_utxo) = get_vout(&depo_tx, &bridge_descriptor.script_pubkey()); let mut txin = TxIn::default(); txin.previous_output = outpoint; @@ -132,7 +132,7 @@ fn main() { .to_secp_msg(); // Fixme: Take a parameter - let hash_ty = bitcoin::EcdsaSighashType::All; + let hash_ty = bitcoin::sighash::EcdsaSighashType::All; let sk1 = backup1_private.inner; let sk2 = backup2_private.inner; @@ -149,7 +149,7 @@ fn main() { psbt.inputs[0].partial_sigs.insert( pk1, - bitcoin::EcdsaSig { + bitcoin::ecdsa::Signature { sig: sig1, hash_ty: hash_ty, }, @@ -157,7 +157,7 @@ fn main() { println!("{:#?}", psbt); - let serialized = serialize(&psbt); + let serialized = psbt.serialize(); println!("{}", base64::encode(&serialized)); psbt.finalize_mut(&secp256k1).unwrap(); @@ -168,9 +168,9 @@ fn main() { } // Find the Outpoint by spk -fn get_vout(tx: &Transaction, spk: Script) -> (OutPoint, TxOut) { +fn get_vout(tx: &Transaction, spk: &Script) -> (OutPoint, TxOut) { for (i, txout) in tx.clone().output.into_iter().enumerate() { - if spk == txout.script_pubkey { + if spk == &txout.script_pubkey { return (OutPoint::new(tx.txid(), i as u32), txout); } } diff --git a/examples/sign_multisig.rs b/examples/sign_multisig.rs index 15838548f..e4b1cac33 100644 --- a/examples/sign_multisig.rs +++ b/examples/sign_multisig.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use std::str::FromStr; use bitcoin::blockdata::witness::Witness; -use bitcoin::{secp256k1, PackedLockTime, Sequence}; +use bitcoin::{absolute, ecdsa, secp256k1, Sequence}; fn main() { let mut tx = spending_transaction(); @@ -63,7 +63,7 @@ fn main() { // Attempt to satisfy at age 0, height 0. let original_txin = tx.input[0].clone(); - let mut sigs = HashMap::::new(); + let mut sigs = HashMap::::new(); // Doesn't work with no signatures. assert!(descriptor.satisfy(&mut tx.input[0], &sigs).is_err()); @@ -91,15 +91,15 @@ fn main() { fn spending_transaction() -> bitcoin::Transaction { bitcoin::Transaction { version: 2, - lock_time: PackedLockTime::ZERO, + lock_time: absolute::LockTime::ZERO, input: vec![bitcoin::TxIn { previous_output: Default::default(), - script_sig: bitcoin::Script::new(), + script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::MAX, witness: Witness::default(), }], output: vec![bitcoin::TxOut { - script_pubkey: bitcoin::Script::new(), + script_pubkey: bitcoin::ScriptBuf::new(), value: 100_000_000, }], } @@ -128,8 +128,8 @@ fn list_of_three_arbitrary_public_keys() -> Vec { // Returns a signature copied at random off the blockchain; this is not actually // a valid signature for this transaction; Miniscript does not verify the validity. -fn random_signature_from_the_blockchain() -> bitcoin::EcdsaSig { - bitcoin::EcdsaSig { +fn random_signature_from_the_blockchain() -> ecdsa::Signature { + ecdsa::Signature { sig: secp256k1::ecdsa::Signature::from_str( "3045\ 0221\ @@ -138,6 +138,6 @@ fn random_signature_from_the_blockchain() -> bitcoin::EcdsaSig { 531d75c136272f127a5dc14acc0722301cbddc222262934151f140da345af177", ) .unwrap(), - hash_ty: bitcoin::EcdsaSighashType::All, + hash_ty: bitcoin::sighash::EcdsaSighashType::All, } } diff --git a/examples/taproot.rs b/examples/taproot.rs index b30b1c9dc..0d64ebeff 100644 --- a/examples/taproot.rs +++ b/examples/taproot.rs @@ -1,8 +1,9 @@ use std::collections::HashMap; use std::str::FromStr; +use bitcoin::address::WitnessVersion; +use bitcoin::key::XOnlyPublicKey; use bitcoin::secp256k1::{rand, KeyPair}; -use bitcoin::util::address::WitnessVersion; use bitcoin::Network; use miniscript::descriptor::DescriptorType; use miniscript::policy::Concrete; @@ -12,18 +13,18 @@ use miniscript::{translate_hash_fail, Descriptor, Miniscript, Tap, TranslatePk, // for a detailed explanation of the policy and it's compilation struct StrPkTranslator { - pk_map: HashMap, + pk_map: HashMap, } -impl Translator for StrPkTranslator { - fn pk(&mut self, pk: &String) -> Result { +impl Translator for StrPkTranslator { + fn pk(&mut self, pk: &String) -> Result { self.pk_map.get(pk).copied().ok_or(()) } // We don't need to implement these methods as we are not using them in the policy // Fail if we encounter any hash fragments. // See also translate_hash_clone! macro - translate_hash_fail!(String, bitcoin::XOnlyPublicKey, ()); + translate_hash_fail!(String, XOnlyPublicKey, ()); } fn main() { @@ -86,7 +87,7 @@ fn main() { let secp = secp256k1::Secp256k1::new(); let key_pair = KeyPair::new(&secp, &mut rand::thread_rng()); // Random unspendable XOnlyPublicKey provided for compilation to Taproot Descriptor - let (unspendable_pubkey, _parity) = bitcoin::XOnlyPublicKey::from_keypair(&key_pair); + let (unspendable_pubkey, _parity) = XOnlyPublicKey::from_keypair(&key_pair); pk_map.insert("UNSPENDABLE_KEY".to_string(), unspendable_pubkey); let pubkeys = hardcoded_xonlypubkeys(); @@ -112,11 +113,12 @@ fn main() { let expected_addr = bitcoin::Address::from_str( "bc1pcc8ku64slu3wu04a6g376d2s8ck9y5alw5sus4zddvn8xgpdqw2swrghwx", ) - .unwrap(); + .unwrap() + .assume_checked(); assert_eq!(addr, expected_addr); } -fn hardcoded_xonlypubkeys() -> Vec { +fn hardcoded_xonlypubkeys() -> Vec { let serialized_keys: [[u8; 32]; 4] = [ [ 22, 37, 41, 4, 57, 254, 191, 38, 14, 184, 200, 133, 111, 226, 145, 183, 245, 112, 100, @@ -135,9 +137,9 @@ fn hardcoded_xonlypubkeys() -> Vec { 168, 39, 134, 58, 19, 181, 3, 63, 235, 103, 155, 213, ], ]; - let mut keys: Vec = vec![]; + let mut keys: Vec = vec![]; for idx in 0..4 { - keys.push(bitcoin::XOnlyPublicKey::from_slice(&serialized_keys[idx][..]).unwrap()); + keys.push(XOnlyPublicKey::from_slice(&serialized_keys[idx][..]).unwrap()); } keys } diff --git a/examples/verify_tx.rs b/examples/verify_tx.rs index 9b0e9731b..9f2387a2f 100644 --- a/examples/verify_tx.rs +++ b/examples/verify_tx.rs @@ -18,8 +18,7 @@ use std::str::FromStr; use bitcoin::consensus::Decodable; use bitcoin::secp256k1::{self, Secp256k1}; -use bitcoin::util::sighash; -use bitcoin::{LockTime, Sequence}; +use bitcoin::{absolute, sighash, Sequence}; use miniscript::interpreter::KeySigPair; fn main() { @@ -35,7 +34,7 @@ fn main() { &tx.input[0].script_sig, &tx.input[0].witness, Sequence::ZERO, - LockTime::ZERO, + absolute::LockTime::ZERO, ) .unwrap(); @@ -102,7 +101,7 @@ fn main() { let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| { let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig"); - ecdsa_sig.hash_ty == bitcoin::EcdsaSighashType::All + ecdsa_sig.hash_ty == bitcoin::sighash::EcdsaSighashType::All && secp .verify_ecdsa(&message, &ecdsa_sig.sig, &pk.inner) .is_ok() @@ -176,8 +175,8 @@ fn hard_coded_transaction() -> bitcoin::Transaction { bitcoin::Transaction::consensus_decode(&mut &tx_bytes[..]).expect("decode transaction") } -fn hard_coded_script_pubkey() -> bitcoin::Script { - bitcoin::Script::from(vec![ +fn hard_coded_script_pubkey() -> bitcoin::ScriptBuf { + bitcoin::ScriptBuf::from(vec![ 0xa9, 0x14, 0x92, 0x09, 0xa8, 0xf9, 0x0c, 0x58, 0x4b, 0xb5, 0x97, 0x4d, 0x58, 0x68, 0x72, 0x49, 0xe5, 0x32, 0xde, 0x59, 0xf4, 0xbc, 0x87, ]) diff --git a/examples/xpub_descriptors.rs b/examples/xpub_descriptors.rs index 64f7d718b..f640fad35 100644 --- a/examples/xpub_descriptors.rs +++ b/examples/xpub_descriptors.rs @@ -50,6 +50,8 @@ fn p2wsh(secp: &Secp256k1) -> Address { let expected = bitcoin::Address::from_str( "bc1qpq2cfgz5lktxzr5zqv7nrzz46hsvq3492ump9pz8rzcl8wqtwqcspx5y6a", ) + .unwrap() + .require_network(Network::Bitcoin) .unwrap(); assert_eq!(address, expected); address @@ -68,7 +70,10 @@ fn p2sh_p2wsh(secp: &Secp256k1) -> Address { .address(Network::Bitcoin) .unwrap(); - let expected = Address::from_str("325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s").unwrap(); + let expected = Address::from_str("325zcVBN5o2eqqqtGwPjmtDd8dJRyYP82s") + .unwrap() + .require_network(Network::Bitcoin) + .unwrap(); assert_eq!(address, expected); address } diff --git a/fuzz/fuzz_targets/roundtrip_miniscript_script.rs b/fuzz/fuzz_targets/roundtrip_miniscript_script.rs index 58b6c0fe8..d825be31d 100644 --- a/fuzz/fuzz_targets/roundtrip_miniscript_script.rs +++ b/fuzz/fuzz_targets/roundtrip_miniscript_script.rs @@ -5,12 +5,12 @@ use miniscript::{Miniscript, Segwitv0}; fn do_test(data: &[u8]) { // Try round-tripping as a script - let script = script::Script::from(data.to_owned()); + let script = script::Script::from_bytes(data); if let Ok(pt) = Miniscript::::parse(&script) { let output = pt.encode(); assert_eq!(pt.script_size(), output.len()); - assert_eq!(output, script); + assert_eq!(&output, script); } } diff --git a/src/descriptor/bare.rs b/src/descriptor/bare.rs index f44c33b2f..d9555be69 100644 --- a/src/descriptor/bare.rs +++ b/src/descriptor/bare.rs @@ -10,8 +10,8 @@ use core::fmt; -use bitcoin::blockdata::script; -use bitcoin::{Address, Network, Script}; +use bitcoin::script::{self, PushBytes}; +use bitcoin::{Address, Network, ScriptBuf}; use super::checksum::{self, verify_checksum}; use crate::expression::{self, FromTree}; @@ -94,24 +94,24 @@ impl Bare { impl Bare { /// Obtains the corresponding script pubkey for this descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { self.ms.encode() } /// Obtains the underlying miniscript for this descriptor. - pub fn inner_script(&self) -> Script { + pub fn inner_script(&self) -> ScriptBuf { self.script_pubkey() } /// Obtains the pre bip-340 signature script code for this descriptor. - pub fn ecdsa_sighash_script_code(&self) -> Script { + pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf { self.script_pubkey() } /// Returns satisfying non-malleable witness and scriptSig with minimum /// weight to spend an output controlled by the given descriptor if it is /// possible to construct one using the `satisfier`. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -124,7 +124,7 @@ impl Bare { /// Returns satisfying, possibly malleable, witness and scriptSig with /// minimum weight to spend an output controlled by the given descriptor if /// it is possible to construct one using the `satisfier`. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -257,7 +257,7 @@ impl Pkh { impl Pkh { /// Obtains the corresponding script pubkey for this descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { // Fine to hard code the `Network` here because we immediately call // `script_pubkey` which does not use the `network` field of `Address`. let addr = self.address(Network::Bitcoin); @@ -270,26 +270,28 @@ impl Pkh { } /// Obtains the underlying miniscript for this descriptor. - pub fn inner_script(&self) -> Script { + pub fn inner_script(&self) -> ScriptBuf { self.script_pubkey() } /// Obtains the pre bip-340 signature script code for this descriptor. - pub fn ecdsa_sighash_script_code(&self) -> Script { + pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf { self.script_pubkey() } /// Returns satisfying non-malleable witness and scriptSig with minimum /// weight to spend an output controlled by the given descriptor if it is /// possible to construct one using the `satisfier`. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) { - let sig_vec = sig.to_vec(); let script_sig = script::Builder::new() - .push_slice(&sig_vec[..]) + .push_slice::<&PushBytes>( + // serialize() does not allocate here + sig.serialize().as_ref(), + ) .push_key(&self.pk.to_public_key()) .into_script(); let witness = vec![]; @@ -302,7 +304,7 @@ impl Pkh { /// Returns satisfying, possibly malleable, witness and scriptSig with /// minimum weight to spend an output controlled by the given descriptor if /// it is possible to construct one using the `satisfier`. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index 60b5a5cca..7bad264d7 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -1,15 +1,17 @@ // SPDX-License-Identifier: CC0-1.0 +use core::convert::TryInto; use core::fmt; use core::str::FromStr; #[cfg(feature = "std")] use std::error; +use bitcoin::bip32; +use bitcoin::hash_types::XpubIdentifier; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, ripemd160, sha256, Hash, HashEngine}; +use bitcoin::key::XOnlyPublicKey; use bitcoin::secp256k1::{Secp256k1, Signing, Verification}; -use bitcoin::util::bip32; -use bitcoin::{self, XOnlyPublicKey, XpubIdentifier}; use crate::prelude::*; #[cfg(feature = "serde")] @@ -391,7 +393,7 @@ fn maybe_fmt_master_id( ) -> fmt::Result { if let Some((ref master_id, ref master_deriv)) = *origin { fmt::Formatter::write_str(f, "[")?; - for byte in master_id.into_bytes().iter() { + for byte in master_id.as_bytes().iter() { write!(f, "{:02x}", byte)?; } fmt_derivation_path(f, master_deriv)?; @@ -552,7 +554,11 @@ impl DescriptorPublicKey { } SinglePubKey::XOnly(x_only_pk) => engine.input(&x_only_pk.serialize()), }; - bip32::Fingerprint::from(&XpubIdentifier::from_engine(engine)[..4]) + bip32::Fingerprint::from( + &XpubIdentifier::from_engine(engine)[..4] + .try_into() + .expect("4 byte slice"), + ) } } } @@ -899,7 +905,7 @@ impl DescriptorXKey { /// ``` /// # use std::str::FromStr; /// # fn body() -> Result<(), ()> { - /// use miniscript::bitcoin::util::bip32; + /// use miniscript::bitcoin::bip32; /// use miniscript::descriptor::DescriptorPublicKey; /// /// let ctx = miniscript::bitcoin::secp256k1::Secp256k1::signing_only(); @@ -1176,8 +1182,7 @@ impl Serialize for DescriptorPublicKey { mod test { use core::str::FromStr; - use bitcoin::secp256k1; - use bitcoin::util::bip32; + use bitcoin::{bip32, secp256k1}; #[cfg(feature = "serde")] use serde_test::{assert_tokens, Token}; diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index e4e198671..7fb0f0ed6 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -16,10 +16,9 @@ use core::fmt; use core::ops::Range; use core::str::{self, FromStr}; -use bitcoin::blockdata::witness::Witness; +use bitcoin::address::WitnessVersion; use bitcoin::hashes::{hash160, ripemd160, sha256}; -use bitcoin::util::address::WitnessVersion; -use bitcoin::{self, secp256k1, Address, Network, Script, TxIn}; +use bitcoin::{secp256k1, Address, Network, Script, ScriptBuf, TxIn, Witness}; use sync::Arc; use self::checksum::verify_checksum; @@ -400,7 +399,7 @@ impl Descriptor { } /// Computes the scriptpubkey of the descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { match *self { Descriptor::Bare(ref bare) => bare.script_pubkey(), Descriptor::Pkh(ref pkh) => pkh.script_pubkey(), @@ -418,14 +417,14 @@ impl Descriptor { /// This is used in Segwit transactions to produce an unsigned transaction /// whose txid will not change during signing (since only the witness data /// will change). - pub fn unsigned_script_sig(&self) -> Script { + pub fn unsigned_script_sig(&self) -> ScriptBuf { match *self { - Descriptor::Bare(_) => Script::new(), - Descriptor::Pkh(_) => Script::new(), - Descriptor::Wpkh(_) => Script::new(), - Descriptor::Wsh(_) => Script::new(), + Descriptor::Bare(_) => ScriptBuf::new(), + Descriptor::Pkh(_) => ScriptBuf::new(), + Descriptor::Wpkh(_) => ScriptBuf::new(), + Descriptor::Wsh(_) => ScriptBuf::new(), Descriptor::Sh(ref sh) => sh.unsigned_script_sig(), - Descriptor::Tr(_) => Script::new(), + Descriptor::Tr(_) => ScriptBuf::new(), } } @@ -435,7 +434,7 @@ impl Descriptor { /// /// # Errors /// If the descriptor is a taproot descriptor. - pub fn explicit_script(&self) -> Result { + pub fn explicit_script(&self) -> Result { match *self { Descriptor::Bare(ref bare) => Ok(bare.script_pubkey()), Descriptor::Pkh(ref pkh) => Ok(pkh.script_pubkey()), @@ -453,7 +452,7 @@ impl Descriptor { /// /// # Errors /// If the descriptor is a taproot descriptor. - pub fn script_code(&self) -> Result { + pub fn script_code(&self) -> Result { match *self { Descriptor::Bare(ref bare) => Ok(bare.ecdsa_sighash_script_code()), Descriptor::Pkh(ref pkh) => Ok(pkh.ecdsa_sighash_script_code()), @@ -467,7 +466,7 @@ impl Descriptor { /// Returns satisfying non-malleable witness and scriptSig to spend an /// output controlled by the given descriptor if it possible to /// construct one using the satisfier S. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -484,7 +483,7 @@ impl Descriptor { /// Returns a possilbly mallable satisfying non-malleable witness and scriptSig to spend an /// output controlled by the given descriptor if it possible to /// construct one using the satisfier S. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -506,7 +505,7 @@ impl Descriptor { S: Satisfier, { let (witness, script_sig) = self.get_satisfaction(satisfier)?; - txin.witness = Witness::from_vec(witness); + txin.witness = Witness::from_slice(&witness); txin.script_sig = script_sig; Ok(()) } @@ -595,7 +594,7 @@ impl Descriptor { } /// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or - /// otherwise converting them. All [`bitcoin::XOnlyPublicKey`]s are converted to by adding a + /// otherwise converting them. All [`bitcoin::secp256k1::XOnlyPublicKey`]s are converted to by adding a /// default(0x02) y-coordinate. /// /// This is a shorthand for: @@ -872,7 +871,7 @@ impl Descriptor { impl Descriptor { /// Convert all the public keys in the descriptor to [`bitcoin::PublicKey`] by deriving them or - /// otherwise converting them. All [`bitcoin::XOnlyPublicKey`]s are converted to by adding a + /// otherwise converting them. All [`bitcoin::secp256k1::XOnlyPublicKey`]s are converted to by adding a /// default(0x02) y-coordinate. /// /// # Examples @@ -986,15 +985,17 @@ serde_string_impl_pk!(Descriptor, "a script descriptor"); #[cfg(test)] mod tests { + use core::convert::TryFrom; use core::str::FromStr; use bitcoin::blockdata::opcodes::all::{OP_CLTV, OP_CSV}; use bitcoin::blockdata::script::Instruction; use bitcoin::blockdata::{opcodes, script}; - use bitcoin::hashes::hex::{FromHex, ToHex}; - use bitcoin::hashes::{hash160, sha256}; - use bitcoin::util::bip32; - use bitcoin::{self, secp256k1, EcdsaSighashType, PublicKey, Sequence}; + use bitcoin::hashes::hex::FromHex; + use bitcoin::hashes::{hash160, sha256, Hash}; + use bitcoin::script::PushBytes; + use bitcoin::sighash::EcdsaSighashType; + use bitcoin::{self, bip32, secp256k1, PublicKey, Sequence}; use super::checksum::desc_checksum; use super::tr::Tr; @@ -1090,7 +1091,7 @@ mod tests { let pk = StdDescriptor::from_str(TEST_PK).unwrap(); assert_eq!( pk.script_pubkey(), - Script::from(vec![ + ScriptBuf::from(vec![ 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xac, @@ -1109,8 +1110,9 @@ mod tests { .push_opcode(opcodes::all::OP_DUP) .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_hex("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap() - [..] + &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",) + .unwrap() + .to_byte_array() ) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_CHECKSIG) @@ -1132,8 +1134,9 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice( - &hash160::Hash::from_hex("84e9ed95a38613f0527ff685a9928abe2d4754d4",).unwrap() - [..] + &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",) + .unwrap() + .to_byte_array() ) .into_script() ); @@ -1153,8 +1156,9 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_hex("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",).unwrap() - [..] + &hash160::Hash::from_str("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",) + .unwrap() + .to_byte_array() ) .push_opcode(opcodes::all::OP_EQUAL) .into_script() @@ -1175,8 +1179,9 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_hex("aa5282151694d3f2f32ace7d00ad38f927a33ac8",).unwrap() - [..] + &hash160::Hash::from_str("aa5282151694d3f2f32ace7d00ad38f927a33ac8",) + .unwrap() + .to_byte_array() ) .push_opcode(opcodes::all::OP_EQUAL) .into_script() @@ -1197,13 +1202,14 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice( - &sha256::Hash::from_hex( + &sha256::Hash::from_str( "\ f9379edc8983152dc781747830075bd5\ 3896e4b0ce5bff73777fd77d124ba085\ " ) - .unwrap()[..] + .unwrap() + .to_byte_array() ) .into_script() ); @@ -1223,8 +1229,9 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_hex("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",).unwrap() - [..] + &hash160::Hash::from_str("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",) + .unwrap() + .to_byte_array() ) .push_opcode(opcodes::all::OP_EQUAL) .into_script() @@ -1253,11 +1260,14 @@ mod tests { } impl Satisfier for SimpleSat { - fn lookup_ecdsa_sig(&self, pk: &bitcoin::PublicKey) -> Option { + fn lookup_ecdsa_sig( + &self, + pk: &bitcoin::PublicKey, + ) -> Option { if *pk == self.pk { - Some(bitcoin::EcdsaSig { + Some(bitcoin::ecdsa::Signature { sig: self.sig, - hash_ty: bitcoin::EcdsaSighashType::All, + hash_ty: bitcoin::sighash::EcdsaSighashType::All, }) } else { None @@ -1270,7 +1280,7 @@ mod tests { let mut txin = bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), - script_sig: bitcoin::Script::new(), + script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::from_height(100), witness: Witness::default(), }; @@ -1281,12 +1291,14 @@ mod tests { txin, bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), - script_sig: script::Builder::new().push_slice(&sigser[..]).into_script(), + script_sig: script::Builder::new() + .push_slice(<&PushBytes>::try_from(sigser.as_slice()).unwrap()) + .into_script(), sequence: Sequence::from_height(100), witness: Witness::default(), } ); - assert_eq!(bare.unsigned_script_sig(), bitcoin::Script::new()); + assert_eq!(bare.unsigned_script_sig(), bitcoin::ScriptBuf::new()); let pkh = Descriptor::new_pkh(pk); pkh.satisfy(&mut txin, &satisfier).expect("satisfaction"); @@ -1295,14 +1307,14 @@ mod tests { bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), script_sig: script::Builder::new() - .push_slice(&sigser[..]) + .push_slice(<&PushBytes>::try_from(sigser.as_slice()).unwrap()) .push_key(&pk) .into_script(), sequence: Sequence::from_height(100), witness: Witness::default(), } ); - assert_eq!(pkh.unsigned_script_sig(), bitcoin::Script::new()); + assert_eq!(pkh.unsigned_script_sig(), bitcoin::ScriptBuf::new()); let wpkh = Descriptor::new_wpkh(pk).unwrap(); wpkh.satisfy(&mut txin, &satisfier).expect("satisfaction"); @@ -1310,19 +1322,21 @@ mod tests { txin, bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), - script_sig: bitcoin::Script::new(), + script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::from_height(100), - witness: Witness::from_vec(vec![sigser.clone(), pk.to_bytes(),]), + witness: Witness::from_slice(&vec![sigser.clone(), pk.to_bytes(),]), } ); - assert_eq!(wpkh.unsigned_script_sig(), bitcoin::Script::new()); + assert_eq!(wpkh.unsigned_script_sig(), bitcoin::ScriptBuf::new()); let shwpkh = Descriptor::new_sh_wpkh(pk).unwrap(); shwpkh.satisfy(&mut txin, &satisfier).expect("satisfaction"); let redeem_script = script::Builder::new() .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice( - &hash160::Hash::from_hex("d1b2a1faf62e73460af885c687dee3b7189cd8ab").unwrap()[..], + &hash160::Hash::from_str("d1b2a1faf62e73460af885c687dee3b7189cd8ab") + .unwrap() + .to_byte_array(), ) .into_script(); assert_eq!( @@ -1330,16 +1344,16 @@ mod tests { bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), script_sig: script::Builder::new() - .push_slice(&redeem_script[..]) + .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap()) .into_script(), sequence: Sequence::from_height(100), - witness: Witness::from_vec(vec![sigser.clone(), pk.to_bytes(),]), + witness: Witness::from_slice(&vec![sigser.clone(), pk.to_bytes(),]), } ); assert_eq!( shwpkh.unsigned_script_sig(), script::Builder::new() - .push_slice(&redeem_script[..]) + .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap()) .into_script() ); @@ -1351,14 +1365,14 @@ mod tests { bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), script_sig: script::Builder::new() - .push_slice(&sigser[..]) - .push_slice(&ms.encode()[..]) + .push_slice(<&PushBytes>::try_from(sigser.as_slice()).unwrap()) + .push_slice(<&PushBytes>::try_from(ms.encode().as_bytes()).unwrap()) .into_script(), sequence: Sequence::from_height(100), witness: Witness::default(), } ); - assert_eq!(sh.unsigned_script_sig(), bitcoin::Script::new()); + assert_eq!(sh.unsigned_script_sig(), bitcoin::ScriptBuf::new()); let ms = ms_str!("c:pk_k({})", pk); @@ -1368,12 +1382,12 @@ mod tests { txin, bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), - script_sig: bitcoin::Script::new(), + script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::from_height(100), - witness: Witness::from_vec(vec![sigser.clone(), ms.encode().into_bytes(),]), + witness: Witness::from_slice(&vec![sigser.clone(), ms.encode().into_bytes(),]), } ); - assert_eq!(wsh.unsigned_script_sig(), bitcoin::Script::new()); + assert_eq!(wsh.unsigned_script_sig(), bitcoin::ScriptBuf::new()); let shwsh = Descriptor::new_sh_wsh(ms.clone()).unwrap(); shwsh.satisfy(&mut txin, &satisfier).expect("satisfaction"); @@ -1382,16 +1396,18 @@ mod tests { bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), script_sig: script::Builder::new() - .push_slice(&ms.encode().to_v0_p2wsh()[..]) + .push_slice( + <&PushBytes>::try_from(ms.encode().to_v0_p2wsh().as_bytes()).unwrap() + ) .into_script(), sequence: Sequence::from_height(100), - witness: Witness::from_vec(vec![sigser.clone(), ms.encode().into_bytes(),]), + witness: Witness::from_slice(&vec![sigser.clone(), ms.encode().into_bytes(),]), } ); assert_eq!( shwsh.unsigned_script_sig(), script::Builder::new() - .push_slice(&ms.encode().to_v0_p2wsh()[..]) + .push_slice(<&PushBytes>::try_from(ms.encode().to_v0_p2wsh().as_bytes()).unwrap()) .into_script() ); } @@ -1469,7 +1485,7 @@ mod tests { ) .unwrap(); assert_eq!( - key.script_pubkey().to_hex(), + key.script_pubkey().to_hex_string(), "51209c19294f03757da3dc235a5960631e3c55751632f5889b06b7a053bdc0bcfbcb" ) } @@ -1516,7 +1532,7 @@ mod tests { let mut txin = bitcoin::TxIn { previous_output: bitcoin::OutPoint::default(), - script_sig: bitcoin::Script::new(), + script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::ZERO, witness: Witness::default(), }; @@ -1525,14 +1541,14 @@ mod tests { satisfier.insert( a, - bitcoin::EcdsaSig { + bitcoin::ecdsa::Signature { sig: sig_a, hash_ty: EcdsaSighashType::All, }, ); satisfier.insert( b, - bitcoin::EcdsaSig { + bitcoin::ecdsa::Signature { sig: sig_b, hash_ty: EcdsaSighashType::All, }, @@ -1611,7 +1627,7 @@ mod tests { let key = "[78412e3a/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*"; let expected = DescriptorPublicKey::XPub(DescriptorXKey { origin: Some(( - bip32::Fingerprint::from(&[0x78, 0x41, 0x2e, 0x3a][..]), + bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]), (&[ bip32::ChildNumber::from_hardened_idx(44).unwrap(), bip32::ChildNumber::from_hardened_idx(0).unwrap(), @@ -1696,7 +1712,7 @@ mod tests { .unwrap(), ), origin: Some(( - bip32::Fingerprint::from(&[0x78, 0x41, 0x2e, 0x3a][..]), + bip32::Fingerprint::from([0x78, 0x41, 0x2e, 0x3a]), (&[ bip32::ChildNumber::from_hardened_idx(0).unwrap(), bip32::ChildNumber::from_normal_idx(42).unwrap(), @@ -1738,7 +1754,9 @@ mod tests { .unwrap() .address(bitcoin::Network::Bitcoin) .unwrap(); - let addr_expected = bitcoin::Address::from_str(raw_addr_expected).unwrap(); + let addr_expected = bitcoin::Address::from_str(raw_addr_expected) + .unwrap() + .assume_checked(); assert_eq!(addr_one, addr_expected); assert_eq!(addr_two, addr_expected); } @@ -1869,7 +1887,7 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))"; fn test_find_derivation_index_for_spk() { let secp = secp256k1::Secp256k1::verification_only(); let descriptor = Descriptor::from_str("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap(); - let script_at_0_1 = Script::from_str( + let script_at_0_1 = ScriptBuf::from_hex( "5120a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb", ) .unwrap(); diff --git a/src/descriptor/segwitv0.rs b/src/descriptor/segwitv0.rs index 1a8585e0c..88b875b6a 100644 --- a/src/descriptor/segwitv0.rs +++ b/src/descriptor/segwitv0.rs @@ -8,7 +8,7 @@ use core::fmt; -use bitcoin::{self, Address, Network, Script}; +use bitcoin::{Address, Network, ScriptBuf}; use super::checksum::{self, verify_checksum}; use super::SortedMultiVec; @@ -133,7 +133,7 @@ impl Wsh { impl Wsh { /// Obtains the corresponding script pubkey for this descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { self.inner_script().to_v0_p2wsh() } @@ -146,7 +146,7 @@ impl Wsh { } /// Obtains the underlying miniscript for this descriptor. - pub fn inner_script(&self) -> Script { + pub fn inner_script(&self) -> ScriptBuf { match self.inner { WshInner::SortedMulti(ref smv) => smv.encode(), WshInner::Ms(ref ms) => ms.encode(), @@ -154,14 +154,14 @@ impl Wsh { } /// Obtains the pre bip-340 signature script code for this descriptor. - pub fn ecdsa_sighash_script_code(&self) -> Script { + pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf { self.inner_script() } /// Returns satisfying non-malleable witness and scriptSig with minimum /// weight to spend an output controlled by the given descriptor if it is /// possible to construct one using the `satisfier`. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -171,14 +171,14 @@ impl Wsh { }; let witness_script = self.inner_script(); witness.push(witness_script.into_bytes()); - let script_sig = Script::new(); + let script_sig = ScriptBuf::new(); Ok((witness, script_sig)) } /// Returns satisfying, possibly malleable, witness and scriptSig with /// minimum weight to spend an output controlled by the given descriptor if /// it is possible to construct one using the `satisfier`. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -187,7 +187,7 @@ impl Wsh { WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?, }; witness.push(self.inner_script().into_bytes()); - let script_sig = Script::new(); + let script_sig = ScriptBuf::new(); Ok((witness, script_sig)) } } @@ -370,7 +370,7 @@ impl Wpkh { impl Wpkh { /// Obtains the corresponding script pubkey for this descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { let addr = Address::p2wpkh(&self.pk.to_public_key(), Network::Bitcoin) .expect("wpkh descriptors have compressed keys"); addr.script_pubkey() @@ -383,12 +383,12 @@ impl Wpkh { } /// Obtains the underlying miniscript for this descriptor. - pub fn inner_script(&self) -> Script { + pub fn inner_script(&self) -> ScriptBuf { self.script_pubkey() } /// Obtains the pre bip-340 signature script code for this descriptor. - pub fn ecdsa_sighash_script_code(&self) -> Script { + pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf { // For SegWit outputs, it is defined by bip-0143 (quoted below) and is different from // the previous txo's scriptPubKey. // The item 5: @@ -400,13 +400,13 @@ impl Wpkh { /// Returns satisfying non-malleable witness and scriptSig with minimum /// weight to spend an output controlled by the given descriptor if it is /// possible to construct one using the `satisfier`. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) { let sig_vec = sig.to_vec(); - let script_sig = Script::new(); + let script_sig = ScriptBuf::new(); let witness = vec![sig_vec, self.pk.to_public_key().to_bytes()]; Ok((witness, script_sig)) } else { @@ -417,7 +417,7 @@ impl Wpkh { /// Returns satisfying, possibly malleable, witness and scriptSig with /// minimum weight to spend an output controlled by the given descriptor if /// it is possible to construct one using the `satisfier`. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { diff --git a/src/descriptor/sh.rs b/src/descriptor/sh.rs index 002e6be5e..9916e4f87 100644 --- a/src/descriptor/sh.rs +++ b/src/descriptor/sh.rs @@ -8,10 +8,11 @@ //! sh(miniscript), and sh(wpkh) //! +use core::convert::TryFrom; use core::fmt; -use bitcoin::blockdata::script; -use bitcoin::{Address, Network, Script}; +use bitcoin::script::PushBytes; +use bitcoin::{script, Address, Network, ScriptBuf}; use super::checksum::{self, verify_checksum}; use super::{SortedMultiVec, Wpkh, Wsh}; @@ -280,7 +281,7 @@ impl Sh { impl Sh { /// Obtains the corresponding script pubkey for this descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { match self.inner { ShInner::Wsh(ref wsh) => wsh.script_pubkey().to_p2sh(), ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey().to_p2sh(), @@ -311,7 +312,7 @@ impl Sh { } /// Obtain the underlying miniscript for this descriptor - pub fn inner_script(&self) -> Script { + pub fn inner_script(&self) -> ScriptBuf { match self.inner { ShInner::Wsh(ref wsh) => wsh.inner_script(), ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(), @@ -321,7 +322,7 @@ impl Sh { } /// Obtains the pre bip-340 signature script code for this descriptor. - pub fn ecdsa_sighash_script_code(&self) -> Script { + pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf { match self.inner { // - For P2WSH witness program, if the witnessScript does not contain any `OP_CODESEPARATOR`, // the `scriptCode` is the `witnessScript` serialized as scripts inside CTxOut. @@ -340,29 +341,29 @@ impl Sh { /// This is used in Segwit transactions to produce an unsigned transaction /// whose txid will not change during signing (since only the witness data /// will change). - pub fn unsigned_script_sig(&self) -> Script { + pub fn unsigned_script_sig(&self) -> ScriptBuf { match self.inner { ShInner::Wsh(ref wsh) => { // wsh explicit must contain exactly 1 element - let witness_script = wsh.inner_script(); - script::Builder::new() - .push_slice(&witness_script.to_v0_p2wsh()[..]) - .into_script() + let witness_script = wsh.inner_script().to_v0_p2wsh(); + let push_bytes = <&PushBytes>::try_from(witness_script.as_bytes()) + .expect("Witness script is not too large"); + script::Builder::new().push_slice(&push_bytes).into_script() } ShInner::Wpkh(ref wpkh) => { let redeem_script = wpkh.script_pubkey(); - script::Builder::new() - .push_slice(&redeem_script[..]) - .into_script() + let push_bytes: &PushBytes = + <&PushBytes>::try_from(redeem_script.as_bytes()).expect("Script not too large"); + script::Builder::new().push_slice(&push_bytes).into_script() } - ShInner::SortedMulti(..) | ShInner::Ms(..) => Script::new(), + ShInner::SortedMulti(..) | ShInner::Ms(..) => ScriptBuf::new(), } } /// Returns satisfying non-malleable witness and scriptSig with minimum /// weight to spend an output controlled by the given descriptor if it is /// possible to construct one using the `satisfier`. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -396,7 +397,7 @@ impl Sh { /// Returns satisfying, possibly malleable, witness and scriptSig with /// minimum weight to spend an output controlled by the given descriptor if /// it is possible to construct one using the `satisfier`. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { diff --git a/src/descriptor/sortedmulti.rs b/src/descriptor/sortedmulti.rs index 303bd7a57..921d7b4b0 100644 --- a/src/descriptor/sortedmulti.rs +++ b/src/descriptor/sortedmulti.rs @@ -10,7 +10,7 @@ use core::fmt; use core::marker::PhantomData; use core::str::FromStr; -use bitcoin::blockdata::script; +use bitcoin::script; use crate::miniscript::context::ScriptContext; use crate::miniscript::decode::Terminal; @@ -141,7 +141,7 @@ impl SortedMultiVec { } /// Encode as a Bitcoin script - pub fn encode(&self) -> script::Script + pub fn encode(&self) -> script::ScriptBuf where Pk: ToPublicKey, { diff --git a/src/descriptor/tr.rs b/src/descriptor/tr.rs index 20d0880d8..cb204306e 100644 --- a/src/descriptor/tr.rs +++ b/src/descriptor/tr.rs @@ -4,12 +4,11 @@ use core::cmp::{self, max}; use core::str::FromStr; use core::{fmt, hash}; -use bitcoin::blockdata::opcodes; -use bitcoin::util::taproot::{ +use bitcoin::taproot::{ LeafVersion, TaprootBuilder, TaprootSpendInfo, TAPROOT_CONTROL_BASE_SIZE, TAPROOT_CONTROL_MAX_NODE_COUNT, TAPROOT_CONTROL_NODE_SIZE, }; -use bitcoin::{secp256k1, Address, Network, Script}; +use bitcoin::{opcodes, secp256k1, Address, Network, ScriptBuf}; use sync::Arc; use super::checksum::{self, verify_checksum}; @@ -344,7 +343,7 @@ impl Tr { impl Tr { /// Obtains the corresponding script pubkey for this descriptor. - pub fn script_pubkey(&self) -> Script { + pub fn script_pubkey(&self) -> ScriptBuf { let output_key = self.spend_info().output_key(); let builder = bitcoin::blockdata::script::Builder::new(); builder @@ -362,7 +361,7 @@ impl Tr { /// Returns satisfying non-malleable witness and scriptSig with minimum /// weight to spend an output controlled by the given descriptor if it is /// possible to construct one using the `satisfier`. - pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -372,7 +371,7 @@ impl Tr { /// Returns satisfying, possibly malleable, witness and scriptSig with /// minimum weight to spend an output controlled by the given descriptor if /// it is possible to construct one using the `satisfier`. - pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, Script), Error> + pub fn get_satisfaction_mall(&self, satisfier: S) -> Result<(Vec>, ScriptBuf), Error> where S: Satisfier, { @@ -658,7 +657,7 @@ fn best_tap_spend( desc: &Tr, satisfier: S, allow_mall: bool, -) -> Result<(Vec>, Script), Error> +) -> Result<(Vec>, ScriptBuf), Error> where Pk: ToPublicKey, S: Satisfier, @@ -666,7 +665,7 @@ where let spend_info = desc.spend_info(); // First try the key spend path if let Some(sig) = satisfier.lookup_tap_key_spend_sig() { - Ok((vec![sig.to_vec()], Script::new())) + Ok((vec![sig.to_vec()], ScriptBuf::new())) } else { // Since we have the complete descriptor we can ignore the satisfier. We don't use the control block // map (lookup_control_block) from the satisfier here. @@ -707,7 +706,7 @@ where } } match min_wit { - Some(wit) => Ok((wit, Script::new())), + Some(wit) => Ok((wit, ScriptBuf::new())), None => Err(Error::CouldNotSatisfy), // Could not satisfy all miniscripts inside Tr } } diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs index c8f16568e..ea241776f 100644 --- a/src/interpreter/error.rs +++ b/src/interpreter/error.rs @@ -6,9 +6,8 @@ use core::fmt; use std::error; use bitcoin::hashes::hash160; -use bitcoin::hashes::hex::ToHex; -use bitcoin::util::taproot; -use bitcoin::{self, secp256k1}; +use bitcoin::{secp256k1, taproot}; +use internals::hex::display::DisplayHex; use super::BitcoinKey; use crate::prelude::*; @@ -31,8 +30,8 @@ pub enum Error { ControlBlockVerificationError, /// General Interpreter error. CouldNotEvaluate, - /// EcdsaSig related error - EcdsaSig(bitcoin::EcdsaSigError), + /// ECDSA Signature related error + EcdsaSig(bitcoin::ecdsa::Error), /// We expected a push (including a `OP_1` but no other numeric pushes) ExpectedPush, /// The preimage to the hash function must be exactly 32 bytes. @@ -52,7 +51,7 @@ pub enum Error { /// ecdsa Signature failed to verify InvalidEcdsaSignature(bitcoin::PublicKey), /// Signature failed to verify - InvalidSchnorrSignature(bitcoin::XOnlyPublicKey), + InvalidSchnorrSignature(bitcoin::key::XOnlyPublicKey), /// Last byte of this signature isn't a standard sighash type NonStandardSighash(Vec), /// Miniscript error @@ -90,9 +89,9 @@ pub enum Error { /// Miniscript requires the entire top level script to be satisfied. ScriptSatisfactionError, /// Schnorr Signature error - SchnorrSig(bitcoin::SchnorrSigError), + SchnorrSig(bitcoin::taproot::Error), /// Errors in signature hash calculations - SighashError(bitcoin::util::sighash::Error), + SighashError(bitcoin::sighash::Error), /// Taproot Annex Unsupported TapAnnexUnsupported, /// An uncompressed public key was encountered in a context where it is @@ -143,15 +142,15 @@ impl fmt::Display for Error { Error::InsufficientSignaturesMultiSig => f.write_str("Insufficient signatures for CMS"), Error::InvalidSchnorrSighashType(ref sig) => write!( f, - "Invalid sighash type for schnorr signature '{}'", - sig.to_hex() + "Invalid sighash type for schnorr signature '{:x}'", + 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() + "Non standard sighash type for signature '{:x}'", + sig.as_hex() ), Error::NonEmptyWitness => f.write_str("legacy spend had nonempty witness"), Error::NonEmptyScriptSig => f.write_str("segwit spend had nonempty scriptsig"), @@ -243,22 +242,22 @@ impl From for Error { } #[doc(hidden)] -impl From for Error { - fn from(e: bitcoin::util::sighash::Error) -> Error { +impl From for Error { + fn from(e: bitcoin::sighash::Error) -> Error { Error::SighashError(e) } } #[doc(hidden)] -impl From for Error { - fn from(e: bitcoin::EcdsaSigError) -> Error { +impl From for Error { + fn from(e: bitcoin::ecdsa::Error) -> Error { Error::EcdsaSig(e) } } #[doc(hidden)] -impl From for Error { - fn from(e: bitcoin::SchnorrSigError) -> Error { +impl From for Error { + fn from(e: bitcoin::taproot::Error) -> Error { Error::SchnorrSig(e) } } @@ -277,7 +276,7 @@ pub enum PkEvalErrInner { /// Full Key FullKey(bitcoin::PublicKey), /// XOnly Key - XOnlyKey(bitcoin::XOnlyPublicKey), + XOnlyKey(bitcoin::key::XOnlyPublicKey), } impl From for PkEvalErrInner { diff --git a/src/interpreter/inner.rs b/src/interpreter/inner.rs index a307d059c..538cacb7e 100644 --- a/src/interpreter/inner.rs +++ b/src/interpreter/inner.rs @@ -1,10 +1,9 @@ // Written in 2019 by Sanket Kanjular and Andrew Poelstra // SPDX-License-Identifier: CC0-1.0 -use bitcoin; -use bitcoin::blockdata::witness::Witness; use bitcoin::hashes::{hash160, sha256, Hash}; -use bitcoin::util::taproot::{ControlBlock, TAPROOT_ANNEX_PREFIX}; +use bitcoin::taproot::{ControlBlock, TAPROOT_ANNEX_PREFIX}; +use bitcoin::Witness; use super::{stack, BitcoinKey, Error, Stack}; use crate::miniscript::context::{NoChecks, ScriptContext, SigType}; @@ -43,11 +42,10 @@ fn script_from_stack_elem( elem: &stack::Element<'_>, ) -> Result, Error> { match *elem { - stack::Element::Push(sl) => Miniscript::parse_with_ext( - &bitcoin::Script::from(sl.to_owned()), - &ExtParams::allow_all(), - ) - .map_err(Error::from), + stack::Element::Push(sl) => { + Miniscript::parse_with_ext(&bitcoin::Script::from_bytes(sl), &ExtParams::allow_all()) + .map_err(Error::from) + } stack::Element::Satisfied => { Miniscript::from_ast(crate::Terminal::True).map_err(Error::from) } @@ -101,7 +99,7 @@ pub(super) fn from_txdata<'txin>( spk: &bitcoin::Script, script_sig: &'txin bitcoin::Script, witness: &'txin Witness, -) -> Result<(Inner, Stack<'txin>, Option), Error> { +) -> Result<(Inner, Stack<'txin>, Option), Error> { let mut ssig_stack: Stack = script_sig .instructions_minimal() .map(stack::Element::from_instruction) @@ -120,11 +118,11 @@ pub(super) fn from_txdata<'txin>( } else { Ok(( Inner::PublicKey( - pk_from_slice(&spk[1..spk.len() - 1], false)?.into(), + pk_from_slice(spk[1..spk.len() - 1].as_bytes(), false)?.into(), PubkeyType::Pk, ), ssig_stack, - Some(spk.clone()), + Some(spk.to_owned()), )) } // ** pay to pubkeyhash ** @@ -135,12 +133,13 @@ pub(super) fn from_txdata<'txin>( match ssig_stack.pop() { Some(elem) => { let pk = pk_from_stack_elem(&elem, false)?; - if *spk == bitcoin::Script::new_p2pkh(&pk.to_pubkeyhash(SigType::Ecdsa).into()) + if *spk + == bitcoin::ScriptBuf::new_p2pkh(&pk.to_pubkeyhash(SigType::Ecdsa).into()) { Ok(( Inner::PublicKey(pk.into(), PubkeyType::Pkh), ssig_stack, - Some(spk.clone()), + Some(spk.to_owned()), )) } else { Err(Error::IncorrectPubkeyHash) @@ -158,11 +157,11 @@ pub(super) fn from_txdata<'txin>( Some(elem) => { let pk = pk_from_stack_elem(&elem, true)?; let hash160 = pk.to_pubkeyhash(SigType::Ecdsa); - if *spk == bitcoin::Script::new_v0_p2wpkh(&hash160.into()) { + if *spk == bitcoin::ScriptBuf::new_v0_p2wpkh(&hash160.into()) { Ok(( Inner::PublicKey(pk.into(), PubkeyType::Wpkh), wit_stack, - Some(bitcoin::Script::new_p2pkh(&hash160.into())), // bip143, why.. + Some(bitcoin::ScriptBuf::new_p2pkh(&hash160.into())), // bip143, why.. )) } else { Err(Error::IncorrectWPubkeyHash) @@ -181,8 +180,8 @@ pub(super) fn from_txdata<'txin>( let miniscript = script_from_stack_elem::(&elem)?; let script = miniscript.encode(); let miniscript = miniscript.to_no_checks_ms(); - let scripthash = sha256::Hash::hash(&script[..]); - if *spk == bitcoin::Script::new_v0_p2wsh(&scripthash.into()) { + let scripthash = sha256::Hash::hash(script.as_bytes()); + if *spk == bitcoin::ScriptBuf::new_v0_p2wsh(&scripthash.into()) { Ok(( Inner::Script(miniscript, ScriptType::Wsh), wit_stack, @@ -200,7 +199,7 @@ pub(super) fn from_txdata<'txin>( if !ssig_stack.is_empty() { Err(Error::NonEmptyScriptSig) } else { - let output_key = bitcoin::XOnlyPublicKey::from_slice(&spk[2..]) + let output_key = bitcoin::key::XOnlyPublicKey::from_slice(spk[2..].as_bytes()) .map_err(|_| Error::XOnlyPublicKeyParseError)?; let has_annex = wit_stack .last() @@ -227,7 +226,7 @@ pub(super) fn from_txdata<'txin>( let ctrl_blk = ctrl_blk.as_push()?; let tap_script = wit_stack.pop().ok_or(Error::UnexpectedStackEnd)?; let ctrl_blk = - ControlBlock::from_slice(ctrl_blk).map_err(Error::ControlBlockParse)?; + ControlBlock::decode(ctrl_blk).map_err(Error::ControlBlockParse)?; let tap_script = script_from_stack_elem::(&tap_script)?; let ms = tap_script.to_no_checks_ms(); // Creating new contexts is cheap @@ -257,7 +256,7 @@ pub(super) fn from_txdata<'txin>( Some(elem) => { if let stack::Element::Push(slice) = elem { let scripthash = hash160::Hash::hash(slice); - if *spk != bitcoin::Script::new_p2sh(&scripthash.into()) { + if *spk != bitcoin::ScriptBuf::new_p2sh(&scripthash.into()) { return Err(Error::IncorrectScriptHash); } // ** p2sh-wrapped wpkh ** @@ -269,12 +268,14 @@ pub(super) fn from_txdata<'txin>( } else { let pk = pk_from_stack_elem(&elem, true)?; let hash160 = pk.to_pubkeyhash(SigType::Ecdsa); - if slice == &bitcoin::Script::new_v0_p2wpkh(&hash160.into())[..] + if slice + == bitcoin::ScriptBuf::new_v0_p2wpkh(&hash160.into()) + .as_bytes() { Ok(( Inner::PublicKey(pk.into(), PubkeyType::ShWpkh), wit_stack, - Some(bitcoin::Script::new_p2pkh(&hash160.into())), // bip143, why.. + Some(bitcoin::ScriptBuf::new_p2pkh(&hash160.into())), // bip143, why.. )) } else { Err(Error::IncorrectWScriptHash) @@ -294,9 +295,10 @@ pub(super) fn from_txdata<'txin>( let miniscript = script_from_stack_elem::(&elem)?; let script = miniscript.encode(); let miniscript = miniscript.to_no_checks_ms(); - let scripthash = sha256::Hash::hash(&script[..]); + let scripthash = sha256::Hash::hash(script.as_bytes()); if slice - == &bitcoin::Script::new_v0_p2wsh(&scripthash.into())[..] + == bitcoin::ScriptBuf::new_v0_p2wsh(&scripthash.into()) + .as_bytes() { Ok(( Inner::Script(miniscript, ScriptType::ShWsh), @@ -317,8 +319,8 @@ pub(super) fn from_txdata<'txin>( let script = miniscript.encode(); let miniscript = miniscript.to_no_checks_ms(); if wit_stack.is_empty() { - let scripthash = hash160::Hash::hash(&script[..]); - if *spk == bitcoin::Script::new_p2sh(&scripthash.into()) { + let scripthash = hash160::Hash::hash(script.as_bytes()); + if *spk == bitcoin::ScriptBuf::new_p2sh(&scripthash.into()) { Ok(( Inner::Script(miniscript, ScriptType::Sh), ssig_stack, @@ -345,7 +347,7 @@ pub(super) fn from_txdata<'txin>( Ok(( Inner::Script(miniscript, ScriptType::Bare), ssig_stack, - Some(spk.clone()), + Some(spk.to_owned()), )) } else { Err(Error::NonEmptyWitness) @@ -383,17 +385,17 @@ impl ToNoChecks for Miniscript { } } -impl ToNoChecks for Miniscript { +impl ToNoChecks for Miniscript { fn to_no_checks_ms(&self) -> Miniscript { // specify the () error type as this cannot error struct TranslateXOnlyPk; - impl Translator for TranslateXOnlyPk { - fn pk(&mut self, pk: &bitcoin::XOnlyPublicKey) -> Result { + impl Translator for TranslateXOnlyPk { + fn pk(&mut self, pk: &bitcoin::key::XOnlyPublicKey) -> Result { Ok(BitcoinKey::XOnlyPublicKey(*pk)) } - translate_hash_clone!(bitcoin::XOnlyPublicKey, BitcoinKey, ()); + translate_hash_clone!(bitcoin::key::XOnlyPublicKey, BitcoinKey, ()); } self.real_translate_pk(&mut TranslateXOnlyPk) .expect("Translation should succeed") @@ -403,27 +405,29 @@ impl ToNoChecks for Miniscript #[cfg(test)] mod tests { + use core::convert::TryFrom; use core::str::FromStr; use bitcoin::blockdata::script; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, sha256, Hash}; - use bitcoin::{self, Script}; + use bitcoin::script::PushBytes; + use bitcoin::{self, ScriptBuf}; use super::*; use crate::miniscript::analyzable::ExtParams; struct KeyTestData { - pk_spk: bitcoin::Script, - pk_sig: bitcoin::Script, - pkh_spk: bitcoin::Script, - pkh_sig: bitcoin::Script, - pkh_sig_justkey: bitcoin::Script, - wpkh_spk: bitcoin::Script, + pk_spk: bitcoin::ScriptBuf, + pk_sig: bitcoin::ScriptBuf, + pkh_spk: bitcoin::ScriptBuf, + pkh_sig: bitcoin::ScriptBuf, + pkh_sig_justkey: bitcoin::ScriptBuf, + wpkh_spk: bitcoin::ScriptBuf, wpkh_stack: Witness, wpkh_stack_justkey: Witness, - sh_wpkh_spk: bitcoin::Script, - sh_wpkh_sig: bitcoin::Script, + sh_wpkh_spk: bitcoin::ScriptBuf, + sh_wpkh_sig: bitcoin::ScriptBuf, sh_wpkh_stack: Witness, sh_wpkh_stack_justkey: Witness, } @@ -431,22 +435,24 @@ mod tests { impl KeyTestData { fn from_key(key: bitcoin::PublicKey) -> KeyTestData { // what a funny looking signature.. - let dummy_sig = Vec::from_hex( + let dummy_sig_vec = Vec::from_hex( "\ 302e02153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63\ 02153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c65\ ", ) .unwrap(); + let mut dummy_sig = [0u8; 48]; + dummy_sig.copy_from_slice(&dummy_sig_vec[..]); let pkhash = key.to_pubkeyhash(SigType::Ecdsa).into(); let wpkhash = key.to_pubkeyhash(SigType::Ecdsa).into(); - let wpkh_spk = bitcoin::Script::new_v0_p2wpkh(&wpkhash); - let wpkh_scripthash = hash160::Hash::hash(&wpkh_spk[..]).into(); + let wpkh_spk = bitcoin::ScriptBuf::new_v0_p2wpkh(&wpkhash); + let wpkh_scripthash = hash160::Hash::hash(wpkh_spk.as_bytes()).into(); KeyTestData { - pk_spk: bitcoin::Script::new_p2pk(&key), - pkh_spk: bitcoin::Script::new_p2pkh(&pkhash), + pk_spk: bitcoin::ScriptBuf::new_p2pk(&key), + pkh_spk: bitcoin::ScriptBuf::new_p2pkh(&pkhash), pk_sig: script::Builder::new().push_slice(&dummy_sig).into_script(), pkh_sig: script::Builder::new() .push_slice(&dummy_sig) @@ -454,14 +460,14 @@ mod tests { .into_script(), pkh_sig_justkey: script::Builder::new().push_key(&key).into_script(), wpkh_spk: wpkh_spk.clone(), - wpkh_stack: Witness::from_vec(vec![dummy_sig.clone(), key.to_bytes()]), - wpkh_stack_justkey: Witness::from_vec(vec![key.to_bytes()]), - sh_wpkh_spk: bitcoin::Script::new_p2sh(&wpkh_scripthash), + wpkh_stack: Witness::from_slice(&vec![dummy_sig_vec.clone(), key.to_bytes()]), + wpkh_stack_justkey: Witness::from_slice(&vec![key.to_bytes()]), + sh_wpkh_spk: bitcoin::ScriptBuf::new_p2sh(&wpkh_scripthash), sh_wpkh_sig: script::Builder::new() - .push_slice(&wpkh_spk[..]) + .push_slice(<&PushBytes>::try_from(wpkh_spk[..].as_bytes()).unwrap()) .into_script(), - sh_wpkh_stack: Witness::from_vec(vec![dummy_sig, key.to_bytes()]), - sh_wpkh_stack_justkey: Witness::from_vec(vec![key.to_bytes()]), + sh_wpkh_stack: Witness::from_slice(&vec![dummy_sig_vec, key.to_bytes()]), + sh_wpkh_stack_justkey: Witness::from_slice(&vec![key.to_bytes()]), } } } @@ -494,7 +500,7 @@ mod tests { let fixed = fixed_test_data(); let comp = KeyTestData::from_key(fixed.pk_comp); let uncomp = KeyTestData::from_key(fixed.pk_uncomp); - let blank_script = bitcoin::Script::new(); + let blank_script = bitcoin::ScriptBuf::new(); let empty_wit = Witness::default(); // Compressed pk, empty scriptsig @@ -524,7 +530,7 @@ mod tests { inner, Inner::PublicKey(fixed.pk_comp.into(), PubkeyType::Pk) ); - assert_eq!(stack, Stack::from(vec![comp.pk_sig[1..].into()])); + assert_eq!(stack, Stack::from(vec![comp.pk_sig[1..].as_bytes().into()])); assert_eq!(script_code, Some(comp.pk_spk.clone())); // Uncompressed pk, correct scriptsig @@ -534,25 +540,28 @@ mod tests { inner, Inner::PublicKey(fixed.pk_uncomp.into(), PubkeyType::Pk) ); - assert_eq!(stack, Stack::from(vec![uncomp.pk_sig[1..].into()])); + assert_eq!( + stack, + Stack::from(vec![uncomp.pk_sig[1..].as_bytes().into()]) + ); assert_eq!(script_code, Some(uncomp.pk_spk)); // Scriptpubkey has invalid key let mut spk = comp.pk_spk.to_bytes(); spk[1] = 5; - let spk = bitcoin::Script::from(spk); - let err = from_txdata(&spk, &bitcoin::Script::new(), &empty_wit).unwrap_err(); + let spk = bitcoin::ScriptBuf::from(spk); + let err = from_txdata(&spk, &bitcoin::ScriptBuf::new(), &empty_wit).unwrap_err(); assert_eq!(err.to_string(), "could not parse pubkey"); // Scriptpubkey has invalid script let mut spk = comp.pk_spk.to_bytes(); spk[0] = 100; - let spk = bitcoin::Script::from(spk); - let err = from_txdata(&spk, &bitcoin::Script::new(), &empty_wit).unwrap_err(); + let spk = bitcoin::ScriptBuf::from(spk); + let err = from_txdata(&spk, &bitcoin::ScriptBuf::new(), &empty_wit).unwrap_err(); assert_eq!(&err.to_string()[0..12], "parse error:"); // Witness is nonempty - let wit = Witness::from_vec(vec![vec![]]); + let wit = Witness::from_slice(&vec![vec![]]); let err = from_txdata(&comp.pk_spk, &comp.pk_sig, &wit).unwrap_err(); assert_eq!(err.to_string(), "legacy spend had nonempty witness"); } @@ -565,7 +574,7 @@ mod tests { let empty_wit = Witness::default(); // pkh, empty scriptsig; this time it errors out - let err = from_txdata(&comp.pkh_spk, &bitcoin::Script::new(), &empty_wit).unwrap_err(); + let err = from_txdata(&comp.pkh_spk, &bitcoin::ScriptBuf::new(), &empty_wit).unwrap_err(); assert_eq!(err.to_string(), "unexpected end of stack"); // pkh, wrong pubkey @@ -613,7 +622,7 @@ mod tests { assert_eq!(script_code, Some(uncomp.pkh_spk.clone())); // Witness is nonempty - let wit = Witness::from_vec(vec![vec![]]); + let wit = Witness::from_slice(&vec![vec![]]); let err = from_txdata(&comp.pkh_spk, &comp.pkh_sig, &wit).unwrap_err(); assert_eq!(err.to_string(), "legacy spend had nonempty witness"); } @@ -623,7 +632,7 @@ mod tests { let fixed = fixed_test_data(); let comp = KeyTestData::from_key(fixed.pk_comp); let uncomp = KeyTestData::from_key(fixed.pk_uncomp); - let blank_script = bitcoin::Script::new(); + let blank_script = bitcoin::ScriptBuf::new(); // wpkh, empty witness; this time it errors out let err = from_txdata(&comp.wpkh_spk, &blank_script, &Witness::default()).unwrap_err(); @@ -679,7 +688,7 @@ mod tests { let fixed = fixed_test_data(); let comp = KeyTestData::from_key(fixed.pk_comp); let uncomp = KeyTestData::from_key(fixed.pk_uncomp); - let blank_script = bitcoin::Script::new(); + let blank_script = bitcoin::ScriptBuf::new(); // sh_wpkh, missing witness or scriptsig let err = from_txdata(&comp.sh_wpkh_spk, &blank_script, &Witness::default()).unwrap_err(); @@ -749,7 +758,7 @@ mod tests { assert_eq!(script_code, Some(comp.pkh_spk.clone())); } - fn ms_inner_script(ms: &str) -> (Miniscript, bitcoin::Script) { + fn ms_inner_script(ms: &str) -> (Miniscript, bitcoin::ScriptBuf) { let ms = Miniscript::::from_str_ext(ms, &ExtParams::insane()) .unwrap(); let spk = ms.encode(); @@ -761,7 +770,7 @@ mod tests { fn script_bare() { let preimage = b"12345678----____12345678----____"; let hash = hash160::Hash::hash(&preimage[..]); - let blank_script = bitcoin::Script::new(); + let blank_script = bitcoin::ScriptBuf::new(); let empty_wit = Witness::default(); let (miniscript, spk) = ms_inner_script(&format!("hash160({})", hash)); @@ -776,7 +785,7 @@ mod tests { assert_eq!(&err.to_string()[0..12], "parse error:"); // nonempty witness - let wit = Witness::from_vec(vec![vec![]]); + let wit = Witness::from_slice(&vec![vec![]]); let err = from_txdata(&spk, &blank_script, &wit).unwrap_err(); assert_eq!(&err.to_string(), "legacy spend had nonempty witness"); } @@ -787,13 +796,13 @@ mod tests { 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 = hash160::Hash::hash(redeem_script.as_bytes()).into(); - let spk = Script::new_p2sh(&rs_hash); + let spk = ScriptBuf::new_p2sh(&rs_hash); let script_sig = script::Builder::new() - .push_slice(&redeem_script[..]) + .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap()) .into_script(); - let blank_script = bitcoin::Script::new(); + let blank_script = bitcoin::ScriptBuf::new(); let empty_wit = Witness::default(); // sh without scriptsig @@ -812,7 +821,7 @@ mod tests { assert_eq!(script_code, Some(redeem_script)); // nonempty witness - let wit = Witness::from_vec(vec![vec![]]); + let wit = Witness::from_slice(&vec![vec![]]); let err = from_txdata(&spk, &script_sig, &wit).unwrap_err(); assert_eq!(&err.to_string(), "legacy spend had nonempty witness"); } @@ -822,18 +831,18 @@ mod tests { let preimage = b"12345678----____12345678----____"; let hash = hash160::Hash::hash(&preimage[..]); let (miniscript, witness_script) = ms_inner_script(&format!("hash160({})", hash)); - let wit_hash = sha256::Hash::hash(&witness_script[..]).into(); - let wit_stack = Witness::from_vec(vec![witness_script.to_bytes()]); + let wit_hash = sha256::Hash::hash(witness_script.as_bytes()).into(); + let wit_stack = Witness::from_slice(&vec![witness_script.to_bytes()]); - let spk = Script::new_v0_p2wsh(&wit_hash); - let blank_script = bitcoin::Script::new(); + let spk = ScriptBuf::new_v0_p2wsh(&wit_hash); + let blank_script = bitcoin::ScriptBuf::new(); // wsh without witness let err = from_txdata(&spk, &blank_script, &Witness::default()).unwrap_err(); assert_eq!(&err.to_string(), "unexpected end of stack"); // with incorrect witness - let wit = Witness::from_vec(vec![spk.to_bytes()]); + let wit = Witness::from_slice(&vec![spk.to_bytes()]); let err = from_txdata(&spk, &blank_script, &wit).unwrap_err(); assert_eq!(&err.to_string()[0..12], "parse error:"); @@ -846,7 +855,7 @@ mod tests { // nonempty script_sig let script_sig = script::Builder::new() - .push_slice(&witness_script[..]) + .push_slice(<&PushBytes>::try_from(witness_script.as_bytes()).unwrap()) .into_script(); let err = from_txdata(&spk, &script_sig, &wit_stack).unwrap_err(); assert_eq!(&err.to_string(), "segwit spend had nonempty scriptsig"); @@ -857,17 +866,17 @@ mod tests { let preimage = b"12345678----____12345678----____"; let hash = hash160::Hash::hash(&preimage[..]); let (miniscript, witness_script) = ms_inner_script(&format!("hash160({})", hash)); - let wit_hash = sha256::Hash::hash(&witness_script[..]).into(); - let wit_stack = Witness::from_vec(vec![witness_script.to_bytes()]); + let wit_hash = sha256::Hash::hash(witness_script.as_bytes()).into(); + let wit_stack = Witness::from_slice(&vec![witness_script.to_bytes()]); - let redeem_script = Script::new_v0_p2wsh(&wit_hash); + let redeem_script = ScriptBuf::new_v0_p2wsh(&wit_hash); let script_sig = script::Builder::new() - .push_slice(&redeem_script[..]) + .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap()) .into_script(); - let blank_script = bitcoin::Script::new(); + let blank_script = bitcoin::ScriptBuf::new(); - let rs_hash = hash160::Hash::hash(&redeem_script[..]).into(); - let spk = Script::new_p2sh(&rs_hash); + let rs_hash = hash160::Hash::hash(redeem_script.as_bytes()).into(); + let spk = ScriptBuf::new_p2sh(&rs_hash); // shwsh without witness or scriptsig let err = from_txdata(&spk, &blank_script, &Witness::default()).unwrap_err(); @@ -878,7 +887,7 @@ mod tests { assert_eq!(&err.to_string(), "unexpected end of stack"); // with incorrect witness - let wit = Witness::from_vec(vec![spk.to_bytes()]); + let wit = Witness::from_slice(&vec![spk.to_bytes()]); let err = from_txdata(&spk, &script_sig, &wit).unwrap_err(); assert_eq!(&err.to_string()[0..12], "parse error:"); diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 11fbf3966..2d674479b 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -11,10 +11,8 @@ use core::fmt; use core::str::FromStr; -use bitcoin::blockdata::witness::Witness; -use bitcoin::hashes::{hash160, ripemd160, sha256}; -use bitcoin::util::{sighash, taproot}; -use bitcoin::{self, secp256k1, LockTime, Sequence, TxOut}; +use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; +use bitcoin::{absolute, secp256k1, sighash, taproot, Sequence, TxOut, Witness}; use crate::miniscript::context::{NoChecks, SigType}; use crate::miniscript::ScriptContext; @@ -36,9 +34,9 @@ pub struct Interpreter<'txin> { stack: Stack<'txin>, /// For non-Taproot spends, the scriptCode; for Taproot script-spends, this /// is the leaf script; for key-spends it is `None`. - script_code: Option, + script_code: Option, age: Sequence, - lock_time: LockTime, + lock_time: absolute::LockTime, } // A type representing functions for checking signatures that accept both @@ -48,22 +46,24 @@ pub struct Interpreter<'txin> { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum KeySigPair { /// A Full public key and corresponding Ecdsa signature - Ecdsa(bitcoin::PublicKey, bitcoin::EcdsaSig), + Ecdsa(bitcoin::PublicKey, bitcoin::ecdsa::Signature), /// A x-only key and corresponding Schnorr signature - Schnorr(bitcoin::XOnlyPublicKey, bitcoin::SchnorrSig), + Schnorr(bitcoin::key::XOnlyPublicKey, bitcoin::taproot::Signature), } impl KeySigPair { - /// Obtain a pair of ([`bitcoin::PublicKey`], [`bitcoin::EcdsaSig`]) from [`KeySigPair`] - pub fn as_ecdsa(&self) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + /// Obtain a pair of ([`bitcoin::PublicKey`], [`bitcoin::ecdsa::Signature`]) from [`KeySigPair`] + pub fn as_ecdsa(&self) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { match self { KeySigPair::Ecdsa(pk, sig) => Some((*pk, *sig)), KeySigPair::Schnorr(_, _) => None, } } - /// Obtain a pair of ([`bitcoin::XOnlyPublicKey`], [`bitcoin::SchnorrSig`]) from [`KeySigPair`] - pub fn as_schnorr(&self) -> Option<(bitcoin::XOnlyPublicKey, bitcoin::SchnorrSig)> { + /// Obtain a pair of ([`bitcoin::secp256k1::XOnlyPublicKey`], [`bitcoin::taproot::Signature`]) from [`KeySigPair`] + pub fn as_schnorr( + &self, + ) -> Option<(bitcoin::key::XOnlyPublicKey, bitcoin::taproot::Signature)> { match self { KeySigPair::Ecdsa(_, _) => None, KeySigPair::Schnorr(pk, sig) => Some((*pk, *sig)), @@ -88,7 +88,7 @@ enum BitcoinKey { // Full key Fullkey(bitcoin::PublicKey), // Xonly key - XOnlyPublicKey(bitcoin::XOnlyPublicKey), + XOnlyPublicKey(bitcoin::key::XOnlyPublicKey), } impl BitcoinKey { @@ -116,8 +116,8 @@ impl From for BitcoinKey { } } -impl From for BitcoinKey { - fn from(xpk: bitcoin::XOnlyPublicKey) -> Self { +impl From for BitcoinKey { + fn from(xpk: bitcoin::key::XOnlyPublicKey) -> Self { BitcoinKey::XOnlyPublicKey(xpk) } } @@ -141,11 +141,11 @@ impl<'txin> Interpreter<'txin> { /// function; otherwise, it should be a closure containing a sighash and /// secp context, which can actually verify a given signature. pub fn from_txdata( - spk: &bitcoin::Script, + spk: &bitcoin::ScriptBuf, script_sig: &'txin bitcoin::Script, witness: &'txin Witness, - age: Sequence, // CSV, relative lock time. - lock_time: LockTime, // CLTV, absolute lock time. + age: Sequence, // CSV, relative lock time. + lock_time: absolute::LockTime, // CLTV, absolute lock time. ) -> Result { let (inner, stack, script_code) = inner::from_txdata(spk, script_sig, witness)?; Ok(Interpreter { @@ -222,25 +222,36 @@ impl<'txin> Interpreter<'txin> { sighash::Prevouts::All(prevouts) => prevouts.get(input_index), } } - let mut cache = bitcoin::util::sighash::SighashCache::new(tx); + let mut cache = bitcoin::sighash::SighashCache::new(tx); match sig { KeySigPair::Ecdsa(key, ecdsa_sig) => { let script_pubkey = self.script_code.as_ref().expect("Legacy have script code"); - let sighash = if self.is_legacy() { + let msg = if self.is_legacy() { let sighash_u32 = ecdsa_sig.hash_ty.to_u32(); - cache.legacy_signature_hash(input_idx, script_pubkey, sighash_u32) + let sighash = + cache.legacy_signature_hash(input_idx, script_pubkey, sighash_u32); + sighash.map(|hash| { + secp256k1::Message::from_slice(hash.as_byte_array()).expect("32 byte") + }) } else if self.is_segwit_v0() { let amt = match get_prevout(prevouts, input_idx) { Some(txout) => txout.borrow().value, None => return false, }; - cache.segwit_signature_hash(input_idx, script_pubkey, amt, ecdsa_sig.hash_ty) + let sighash = cache.segwit_signature_hash( + input_idx, + script_pubkey, + amt, + ecdsa_sig.hash_ty, + ); + sighash.map(|hash| { + secp256k1::Message::from_slice(hash.as_byte_array()).expect("32 byte") + }) } else { // taproot(or future) signatures in segwitv0 context return false; }; - let msg = - sighash.map(|hash| secp256k1::Message::from_slice(&hash).expect("32 byte")); + let success = msg.map(|msg| secp.verify_ecdsa(&msg, &ecdsa_sig.sig, &key.inner).is_ok()); success.unwrap_or(false) // unwrap_or checks for errors, while success would have checksig results @@ -267,8 +278,9 @@ impl<'txin> Interpreter<'txin> { // schnorr sigs in ecdsa descriptors return false; }; - let msg = - sighash_msg.map(|hash| secp256k1::Message::from_slice(&hash).expect("32 byte")); + let msg = sighash_msg.map(|hash| { + secp256k1::Message::from_slice(hash.as_byte_array()).expect("32 byte") + }); let success = msg.map(|msg| secp.verify_schnorr(&schnorr_sig.sig, &msg, xpk).is_ok()); success.unwrap_or(false) // unwrap_or_default checks for errors, while success would have checksig results @@ -484,7 +496,7 @@ pub enum SatisfiedConstraint { ///Absolute Timelock for CLTV. AbsoluteTimelock { /// The value of Absolute timelock - n: LockTime, + n: absolute::LockTime, }, } @@ -520,7 +532,7 @@ pub struct Iter<'intp, 'txin: 'intp> { state: Vec>, stack: Stack<'txin>, age: Sequence, - lock_time: LockTime, + lock_time: absolute::LockTime, has_errored: bool, sig_type: SigType, } @@ -612,7 +624,9 @@ where Terminal::After(ref n) => { debug_assert_eq!(node_state.n_evaluated, 0); debug_assert_eq!(node_state.n_satisfied, 0); - let res = self.stack.evaluate_after(&n.into(), self.lock_time); + let res = self + .stack + .evaluate_after(&absolute::LockTime::from(*n), self.lock_time); if res.is_some() { return res; } @@ -1012,7 +1026,7 @@ fn verify_sersig<'txin>( ) -> Result { match pk { BitcoinKey::Fullkey(pk) => { - let ecdsa_sig = bitcoin::EcdsaSig::from_slice(sigser)?; + let ecdsa_sig = bitcoin::ecdsa::Signature::from_slice(sigser)?; let key_sig_pair = KeySigPair::Ecdsa(*pk, ecdsa_sig); if verify_sig(&key_sig_pair) { Ok(key_sig_pair) @@ -1021,7 +1035,7 @@ fn verify_sersig<'txin>( } } BitcoinKey::XOnlyPublicKey(x_only_pk) => { - let schnorr_sig = bitcoin::SchnorrSig::from_slice(sigser)?; + let schnorr_sig = bitcoin::taproot::Signature::from_slice(sigser)?; let key_sig_pair = KeySigPair::Schnorr(*x_only_pk, schnorr_sig); if verify_sig(&key_sig_pair) { Ok(key_sig_pair) @@ -1050,11 +1064,11 @@ mod tests { ) -> ( Vec, Vec>, - Vec, + Vec, secp256k1::Message, Secp256k1, - Vec, - Vec, + Vec, + Vec, Vec>, ) { let secp = secp256k1::Secp256k1::new(); @@ -1079,22 +1093,22 @@ mod tests { compressed: true, }; let sig = secp.sign_ecdsa(&msg, &sk); - ecdsa_sigs.push(bitcoin::EcdsaSig { + ecdsa_sigs.push(bitcoin::ecdsa::Signature { sig, - hash_ty: bitcoin::EcdsaSighashType::All, + hash_ty: bitcoin::sighash::EcdsaSighashType::All, }); let mut sigser = sig.serialize_der().to_vec(); sigser.push(0x01); // sighash_all pks.push(pk); der_sigs.push(sigser); - let keypair = bitcoin::KeyPair::from_secret_key(&secp, &sk); - let (x_only_pk, _parity) = bitcoin::XOnlyPublicKey::from_keypair(&keypair); + let keypair = bitcoin::key::KeyPair::from_secret_key(&secp, &sk); + let (x_only_pk, _parity) = bitcoin::key::XOnlyPublicKey::from_keypair(&keypair); x_only_pks.push(x_only_pk); let schnorr_sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &[0u8; 32]); - let schnorr_sig = bitcoin::SchnorrSig { + let schnorr_sig = bitcoin::taproot::Signature { sig: schnorr_sig, - hash_ty: bitcoin::SchnorrSighashType::Default, + hash_ty: bitcoin::sighash::TapSighashType::Default, }; ser_schnorr_sigs.push(schnorr_sig.to_vec()); schnorr_sigs.push(schnorr_sig); @@ -1140,7 +1154,7 @@ mod tests { n_satisfied: 0, }], age: Sequence::from_height(1002), - lock_time: LockTime::from_height(1002).unwrap(), + lock_time: absolute::LockTime::from_height(1002).unwrap(), has_errored: false, sig_type: SigType::Ecdsa, } @@ -1201,7 +1215,7 @@ mod tests { assert_eq!( after_satisfied.unwrap(), vec![SatisfiedConstraint::AbsoluteTimelock { - n: LockTime::from_height(1000).unwrap() + n: absolute::LockTime::from_height(1000).unwrap() }] ); @@ -1585,7 +1599,7 @@ mod tests { } fn x_only_no_checks_ms(ms: &str) -> Miniscript { - let elem: Miniscript = + let elem: Miniscript = Miniscript::from_str_ext(ms, &ExtParams::allow_all()).unwrap(); elem.to_no_checks_ms() } diff --git a/src/interpreter/stack.rs b/src/interpreter/stack.rs index adaa83971..18e5d3f18 100644 --- a/src/interpreter/stack.rs +++ b/src/interpreter/stack.rs @@ -3,10 +3,9 @@ //! Interpreter stack -use bitcoin; use bitcoin::blockdata::{opcodes, script}; use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; -use bitcoin::{LockTime, Sequence}; +use bitcoin::{absolute, Sequence}; use super::error::PkEvalErrInner; use super::{verify_sersig, BitcoinKey, Error, HashLockType, KeySigPair, SatisfiedConstraint}; @@ -57,7 +56,7 @@ impl<'txin> Element<'txin> { ) -> Result { match ins { //Also covers the dissatisfied case as PushBytes0 - Ok(script::Instruction::PushBytes(v)) => Ok(Element::from(v)), + Ok(script::Instruction::PushBytes(v)) => Ok(Element::from(v.as_bytes())), Ok(script::Instruction::Op(opcodes::all::OP_PUSHNUM_1)) => Ok(Element::Satisfied), _ => Err(Error::ExpectedPush), } @@ -169,7 +168,7 @@ impl<'txin> Stack<'txin> { // We don't really store information about which key error. fn bitcoin_key_from_slice(sl: &[u8], sig_type: SigType) -> Option { let key: BitcoinKey = match sig_type { - SigType::Schnorr => bitcoin::XOnlyPublicKey::from_slice(sl).ok()?.into(), + SigType::Schnorr => bitcoin::key::XOnlyPublicKey::from_slice(sl).ok()?.into(), SigType::Ecdsa => bitcoin::PublicKey::from_slice(sl).ok()?.into(), }; Some(key) @@ -221,10 +220,10 @@ impl<'txin> Stack<'txin> { /// booleans pub(super) fn evaluate_after( &mut self, - n: &LockTime, - lock_time: LockTime, + n: &absolute::LockTime, + lock_time: absolute::LockTime, ) -> Option> { - use LockTime::*; + use absolute::LockTime::*; let is_satisfied = match (*n, lock_time) { (Blocks(n), Blocks(lock_time)) => n <= lock_time, diff --git a/src/lib.rs b/src/lib.rs index 4687fc9b1..07a37a311 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,6 +116,7 @@ mod macros; #[macro_use] mod pub_macros; +use internals::hex::exts::DisplayHex; pub use pub_macros::*; pub mod descriptor; @@ -129,12 +130,13 @@ pub mod psbt; mod test_utils; mod util; -use core::{fmt, hash, str}; +use core::{cmp, fmt, hash, str}; #[cfg(feature = "std")] use std::error; use bitcoin::blockdata::{opcodes, script}; use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; +use bitcoin::locktime::absolute; pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey}; pub use crate::interpreter::Interpreter; @@ -425,7 +427,7 @@ pub enum Error { /// rust-bitcoin script error Script(script::Error), /// rust-bitcoin address error - AddrError(bitcoin::util::address::Error), + AddrError(bitcoin::address::Error), /// A `CHECKMULTISIG` opcode was preceded by a number > 20 CmsTooManyKeys(u32), /// A tapscript multi_a cannot support more than MAX_BLOCK_WEIGHT/32 keys @@ -453,7 +455,7 @@ pub enum Error { /// Parsed a miniscript but there were more script opcodes after it Trailing(String), /// Failed to parse a push as a public key - BadPubkey(bitcoin::util::key::Error), + BadPubkey(bitcoin::key::Error), /// Could not satisfy a script (fragment) because of a missing hash preimage MissingHash(sha256::Hash), /// Could not satisfy a script (fragment) because of a missing signature @@ -516,8 +518,7 @@ impl fmt::Display for Error { Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op), Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok), Error::InvalidPush(ref push) => { - write!(f, "invalid push ")?; - bitcoin::hashes::hex::format_hex(push, f) + write!(f, "invalid push {:x}", push.as_hex()) }, Error::Script(ref e) => fmt::Display::fmt(e, f), Error::AddrError(ref e) => fmt::Display::fmt(e, f), @@ -677,8 +678,8 @@ impl From for Error { } #[doc(hidden)] -impl From for Error { - fn from(e: bitcoin::util::address::Error) -> Error { +impl From for Error { + fn from(e: bitcoin::address::Error) -> Error { Error::AddrError(e) } } @@ -733,9 +734,68 @@ fn push_opcode_size(script_size: usize) -> usize { /// Helper function used by tests #[cfg(test)] -fn hex_script(s: &str) -> bitcoin::Script { +fn hex_script(s: &str) -> bitcoin::ScriptBuf { let v: Vec = bitcoin::hashes::hex::FromHex::from_hex(s).unwrap(); - bitcoin::Script::from(v) + bitcoin::ScriptBuf::from(v) +} + +/// An absolute locktime that implements `Ord`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct AbsLockTime(absolute::LockTime); + +impl AbsLockTime { + /// Constructs an `AbsLockTime` from an nLockTime value or the argument to OP_CHEKCLOCKTIMEVERIFY. + pub fn from_consensus(n: u32) -> Self { + Self(absolute::LockTime::from_consensus(n)) + } + + /// Returns the inner `u32` value. This is the value used when creating this `LockTime` + /// i.e., `n OP_CHECKLOCKTIMEVERIFY` or nLockTime. + /// + /// This calls through to `absolute::LockTime::to_consensus_u32()` and the same usage warnings + /// apply. + pub fn to_consensus_u32(self) -> u32 { + self.0.to_consensus_u32() + } + + /// Returns the inner `u32` value. + /// + /// Equivalent to `AbsLockTime::to_consensus_u32()`. + pub fn to_u32(self) -> u32 { + self.to_consensus_u32() + } +} + +impl From for AbsLockTime { + fn from(lock_time: absolute::LockTime) -> Self { + Self(lock_time) + } +} + +impl From for absolute::LockTime { + fn from(lock_time: AbsLockTime) -> absolute::LockTime { + lock_time.0 + } +} + +impl cmp::PartialOrd for AbsLockTime { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl cmp::Ord for AbsLockTime { + fn cmp(&self, other: &Self) -> cmp::Ordering { + let this = self.0.to_consensus_u32(); + let that = other.0.to_consensus_u32(); + this.cmp(&that) + } +} + +impl fmt::Display for AbsLockTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } } #[cfg(test)] diff --git a/src/miniscript/astelem.rs b/src/miniscript/astelem.rs index 6a807909c..be7330274 100644 --- a/src/miniscript/astelem.rs +++ b/src/miniscript/astelem.rs @@ -11,9 +11,8 @@ use core::fmt; use core::str::FromStr; -use bitcoin::blockdata::{opcodes, script}; -use bitcoin::hashes::hash160; -use bitcoin::{LockTime, Sequence}; +use bitcoin::hashes::{hash160, Hash}; +use bitcoin::{absolute, opcodes, script, Sequence}; use sync::Arc; use crate::miniscript::context::SigType; @@ -22,8 +21,8 @@ use crate::miniscript::ScriptContext; use crate::prelude::*; use crate::util::MsKeyBuilder; use crate::{ - errstr, expression, script_num_size, Error, ForEachKey, Miniscript, MiniscriptKey, Terminal, - ToPublicKey, TranslatePk, Translator, + errstr, expression, script_num_size, AbsLockTime, Error, ForEachKey, Miniscript, MiniscriptKey, + Terminal, ToPublicKey, TranslatePk, Translator, }; impl Terminal { @@ -453,7 +452,7 @@ impl_from_tree!( } ("pk_h", 1) => expression::terminal(&top.args[0], |x| Pk::from_str(x).map(Terminal::PkH)), ("after", 1) => expression::terminal(&top.args[0], |x| { - expression::parse_num(x).map(|x| Terminal::After(LockTime::from_consensus(x).into())) + expression::parse_num(x).map(|x| Terminal::After(AbsLockTime::from(absolute::LockTime::from_consensus(x)))) }), ("older", 1) => expression::terminal(&top.args[0], |x| { expression::parse_num(x).map(|x| Terminal::Older(Sequence::from_consensus(x))) @@ -611,10 +610,10 @@ impl Terminal { Terminal::RawPkH(ref hash) => builder .push_opcode(opcodes::all::OP_DUP) .push_opcode(opcodes::all::OP_HASH160) - .push_slice(hash) + .push_slice(&hash.to_byte_array()) .push_opcode(opcodes::all::OP_EQUALVERIFY), Terminal::After(t) => builder - .push_int(t.to_u32().into()) + .push_int(absolute::LockTime::from(t).to_consensus_u32() as i64) .push_opcode(opcodes::all::OP_CLTV), Terminal::Older(t) => builder .push_int(t.to_consensus_u32().into()) @@ -624,28 +623,28 @@ impl Terminal { .push_int(32) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_SHA256) - .push_slice(&Pk::to_sha256(h)) + .push_slice(Pk::to_sha256(h).to_byte_array()) .push_opcode(opcodes::all::OP_EQUAL), Terminal::Hash256(ref h) => builder .push_opcode(opcodes::all::OP_SIZE) .push_int(32) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_HASH256) - .push_slice(&Pk::to_hash256(h)) + .push_slice(Pk::to_hash256(h).to_byte_array()) .push_opcode(opcodes::all::OP_EQUAL), Terminal::Ripemd160(ref h) => builder .push_opcode(opcodes::all::OP_SIZE) .push_int(32) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_RIPEMD160) - .push_slice(&Pk::to_ripemd160(h)) + .push_slice(Pk::to_ripemd160(h).to_byte_array()) .push_opcode(opcodes::all::OP_EQUAL), Terminal::Hash160(ref h) => builder .push_opcode(opcodes::all::OP_SIZE) .push_int(32) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&Pk::to_hash160(h)) + .push_slice(Pk::to_hash160(h).to_byte_array()) .push_opcode(opcodes::all::OP_EQUAL), Terminal::True => builder.push_opcode(opcodes::OP_TRUE), Terminal::False => builder.push_opcode(opcodes::OP_FALSE), @@ -751,7 +750,7 @@ impl Terminal { match *self { Terminal::PkK(ref pk) => Ctx::pk_len(pk), Terminal::PkH(..) | Terminal::RawPkH(..) => 24, - Terminal::After(n) => script_num_size(n.to_u32() as usize) + 1, + Terminal::After(n) => script_num_size(n.to_consensus_u32() as usize) + 1, Terminal::Older(n) => script_num_size(n.to_consensus_u32() as usize) + 1, Terminal::Sha256(..) => 33 + 6, Terminal::Hash256(..) => 33 + 6, diff --git a/src/miniscript/context.rs b/src/miniscript/context.rs index f8553bd2c..42b0cff51 100644 --- a/src/miniscript/context.rs +++ b/src/miniscript/context.rs @@ -5,8 +5,7 @@ use core::{fmt, hash}; #[cfg(feature = "std")] use std::error; -use bitcoin; -use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT; +use bitcoin::constants::MAX_BLOCK_WEIGHT; use bitcoin::hashes::{hash160, ripemd160, sha256}; use super::decode::ParseableKey; diff --git a/src/miniscript/decode.rs b/src/miniscript/decode.rs index 763aa4a1e..dbf4adcfe 100644 --- a/src/miniscript/decode.rs +++ b/src/miniscript/decode.rs @@ -11,11 +11,11 @@ use core::marker::PhantomData; #[cfg(feature = "std")] use std::error; -use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT; +use bitcoin::constants::MAX_BLOCK_WEIGHT; use bitcoin::hashes::{hash160, ripemd160, sha256, Hash}; +use bitcoin::Sequence; use sync::Arc; -use crate::bitcoin::{LockTime, PackedLockTime, Sequence}; use crate::miniscript::lex::{Token as Tk, TokenIter}; use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG; use crate::miniscript::types::extra_props::ExtData; @@ -24,7 +24,7 @@ use crate::miniscript::ScriptContext; use crate::prelude::*; #[cfg(doc)] use crate::Descriptor; -use crate::{bitcoin, hash256, Error, Miniscript, MiniscriptKey, ToPublicKey}; +use crate::{bitcoin, hash256, AbsLockTime, Error, Miniscript, MiniscriptKey, ToPublicKey}; fn return_none(_: usize) -> Option { None @@ -53,7 +53,7 @@ impl ParseableKey for bitcoin::secp256k1::XOnlyPublicKey { #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum KeyParseError { /// Bitcoin PublicKey parse error - FullKeyParseError(bitcoin::util::key::Error), + FullKeyParseError(bitcoin::key::Error), /// Xonly key parse Error XonlyKeyParseError(bitcoin::secp256k1::Error), } @@ -141,7 +141,7 @@ pub enum Terminal { RawPkH(hash160::Hash), // timelocks /// `n CHECKLOCKTIMEVERIFY` - After(PackedLockTime), + After(AbsLockTime), /// `n CHECKSEQUENCEVERIFY` Older(Sequence), // hashlocks @@ -396,7 +396,7 @@ pub fn parse( Tk::CheckSequenceVerify, Tk::Num(n) => term.reduce0(Terminal::Older(Sequence::from_consensus(n)))?, Tk::CheckLockTimeVerify, Tk::Num(n) - => term.reduce0(Terminal::After(LockTime::from_consensus(n).into()))?, + => term.reduce0(Terminal::After(AbsLockTime::from_consensus(n)))?, // hashlocks Tk::Equal => match_token!( tokens, diff --git a/src/miniscript/iter.rs b/src/miniscript/iter.rs index 0887b533e..f64b350ec 100644 --- a/src/miniscript/iter.rs +++ b/src/miniscript/iter.rs @@ -264,9 +264,9 @@ pub mod test { let preimage = vec![0xab; 32]; let sha256_hash = sha256::Hash::hash(&preimage); let sha256d_hash_rev = sha256d::Hash::hash(&preimage); - let mut sha256d_hash_bytes = sha256d_hash_rev.into_inner(); + let mut sha256d_hash_bytes = sha256d_hash_rev.to_byte_array(); sha256d_hash_bytes.reverse(); - let sha256d_hash = sha256d::Hash::from_inner(sha256d_hash_bytes); + let sha256d_hash = sha256d::Hash::from_byte_array(sha256d_hash_bytes); let hash160_hash = hash160::Hash::hash(&preimage); let ripemd160_hash = ripemd160::Hash::hash(&preimage); diff --git a/src/miniscript/lex.rs b/src/miniscript/lex.rs index 57d27c680..bb06811f9 100644 --- a/src/miniscript/lex.rs +++ b/src/miniscript/lex.rs @@ -221,20 +221,22 @@ pub fn lex(script: &'_ script::Script) -> Result>, Error> { } script::Instruction::PushBytes(bytes) => { match bytes.len() { - 20 => ret.push(Token::Hash20(bytes)), - 32 => ret.push(Token::Bytes32(bytes)), - 33 => ret.push(Token::Bytes33(bytes)), - 65 => ret.push(Token::Bytes65(bytes)), + 20 => ret.push(Token::Hash20(bytes.as_bytes())), + 32 => ret.push(Token::Bytes32(bytes.as_bytes())), + 33 => ret.push(Token::Bytes33(bytes.as_bytes())), + 65 => ret.push(Token::Bytes65(bytes.as_bytes())), _ => { - match script::read_scriptint(bytes) { + match script::read_scriptint(bytes.as_bytes()) { Ok(v) if v >= 0 => { // check minimality of the number - if &script::Builder::new().push_int(v).into_script()[1..] != bytes { - return Err(Error::InvalidPush(bytes.to_owned())); + if script::Builder::new().push_int(v).into_script()[1..].as_bytes() + != bytes.as_bytes() + { + return Err(Error::InvalidPush(bytes.to_owned().into())); } ret.push(Token::Num(v as u32)); } - Ok(_) => return Err(Error::InvalidPush(bytes.to_owned())), + Ok(_) => return Err(Error::InvalidPush(bytes.to_owned().into())), Err(e) => return Err(Error::Script(e)), } } diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index 2cf66ba54..a6666ba11 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -16,8 +16,8 @@ use core::marker::PhantomData; use core::{fmt, hash, str}; -use bitcoin::blockdata::script; -use bitcoin::util::taproot::{LeafVersion, TapLeafHash}; +use bitcoin::script; +use bitcoin::taproot::{LeafVersion, TapLeafHash}; use self::analyzable::ExtParams; pub use self::context::{BareCtx, Legacy, Segwitv0, Tap}; @@ -193,19 +193,19 @@ impl Miniscript { /// type TapScript = Miniscript; /// /// // parse x-only miniscript in Taproot context - /// let tapscript_ms = TapScript::parse(&bitcoin::Script::from(Vec::::from_hex( + /// let tapscript_ms = TapScript::parse(&bitcoin::ScriptBuf::from_hex( /// "202788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac", - /// ).expect("Even length hex"))) + /// ).expect("Even length hex")) /// .expect("Xonly keys are valid only in taproot context"); /// // tapscript fails decoding when we use them with compressed keys - /// let err = TapScript::parse(&bitcoin::Script::from(Vec::::from_hex( + /// let err = TapScript::parse(&bitcoin::ScriptBuf::from_hex( /// "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac", - /// ).expect("Even length hex"))) + /// ).expect("Even length hex")) /// .expect_err("Compressed keys cannot be used in Taproot context"); /// // Segwitv0 succeeds decoding with full keys. - /// Segwitv0Script::parse(&bitcoin::Script::from(Vec::::from_hex( + /// Segwitv0Script::parse(&bitcoin::ScriptBuf::from_hex( /// "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac", - /// ).expect("Even length hex"))) + /// ).expect("Even length hex")) /// .expect("Compressed keys are allowed in Segwit context"); /// /// ``` @@ -221,7 +221,7 @@ where Ctx: ScriptContext, { /// Encode as a Bitcoin script - pub fn encode(&self) -> script::Script + pub fn encode(&self) -> script::ScriptBuf where Pk: ToPublicKey, { @@ -462,8 +462,11 @@ serde_string_impl_pk!(Miniscript, "a miniscript", Ctx; ScriptContext); pub mod hash256 { use bitcoin::hashes::{hash_newtype, sha256d}; - #[rustfmt::skip] - hash_newtype!(Hash, sha256d::Hash, 32, doc = "A bitcoin block hash.", false); + hash_newtype! { + /// A hash256 of preimage. + #[hash_newtype(forward)] + pub struct Hash(sha256d::Hash); + } } #[cfg(test)] @@ -475,7 +478,7 @@ mod tests { use bitcoin::hashes::{hash160, sha256, Hash}; use bitcoin::secp256k1::XOnlyPublicKey; - use bitcoin::util::taproot::TapLeafHash; + use bitcoin::taproot::TapLeafHash; use bitcoin::{self, secp256k1, Sequence}; use sync::Arc; @@ -664,7 +667,7 @@ mod tests { ", ) .unwrap(); - let hash = hash160::Hash::from_inner([17; 20]); + let hash = hash160::Hash::from_byte_array([17; 20]); let pkk_ms: Miniscript = Miniscript { node: Terminal::Check(Arc::new(Miniscript { @@ -739,15 +742,12 @@ mod tests { #[test] fn true_false() { - roundtrip(&ms_str!("1"), "Script(OP_PUSHNUM_1)"); - roundtrip( - &ms_str!("tv:1"), - "Script(OP_PUSHNUM_1 OP_VERIFY OP_PUSHNUM_1)", - ); - roundtrip(&ms_str!("0"), "Script(OP_0)"); + roundtrip(&ms_str!("1"), "OP_PUSHNUM_1"); + roundtrip(&ms_str!("tv:1"), "OP_PUSHNUM_1 OP_VERIFY OP_PUSHNUM_1"); + roundtrip(&ms_str!("0"), "OP_0"); roundtrip( &ms_str!("andor(0,1,0)"), - "Script(OP_0 OP_NOTIF OP_0 OP_ELSE OP_PUSHNUM_1 OP_ENDIF)", + "OP_0 OP_NOTIF OP_0 OP_ELSE OP_PUSHNUM_1 OP_ENDIF", ); assert!(Segwitv0Script::from_str("1()").is_err()); @@ -834,20 +834,20 @@ mod tests { assert_eq!(tree.ty.corr.base, types::Base::B); let ser = tree.encode(); let s = "\ - Script(OP_DUP OP_HASH160 OP_PUSHBYTES_20 \ + OP_DUP OP_HASH160 OP_PUSHBYTES_20 \ 7e5a2a6a7610ca4ea78bd65a087bd75b1870e319 \ - OP_EQUALVERIFY OP_CHECKSIG)\ + OP_EQUALVERIFY OP_CHECKSIG\ "; assert_eq!(ser.len(), tree.script_size()); assert_eq!(ser.to_string(), s); roundtrip( &ms_str!("pk({})", keys[0]), - "Script(OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa OP_CHECKSIG)" + "OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa OP_CHECKSIG" ); roundtrip( &ms_str!("multi(3,{},{},{},{},{})", keys[0], keys[1], keys[2], keys[3], keys[4]), - "Script(OP_PUSHNUM_3 OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 OP_PUSHBYTES_33 039729247032c0dfcf45b4841fcd72f6e9a2422631fc3466cf863e87154754dd40 OP_PUSHBYTES_33 032564fe9b5beef82d3703a607253f31ef8ea1b365772df434226aee642651b3fa OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff OP_PUSHNUM_5 OP_CHECKMULTISIG)" + "OP_PUSHNUM_3 OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 OP_PUSHBYTES_33 039729247032c0dfcf45b4841fcd72f6e9a2422631fc3466cf863e87154754dd40 OP_PUSHBYTES_33 032564fe9b5beef82d3703a607253f31ef8ea1b365772df434226aee642651b3fa OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff OP_PUSHNUM_5 OP_CHECKMULTISIG" ); // Liquid policy @@ -857,7 +857,7 @@ mod tests { keys[1].to_string(), keys[3].to_string(), keys[4].to_string()), - "Script(OP_PUSHNUM_2 OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa \ + "OP_PUSHNUM_2 OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa \ OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 \ OP_PUSHNUM_2 OP_CHECKMULTISIG \ OP_IFDUP OP_NOTIF \ @@ -865,7 +865,7 @@ mod tests { OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff \ OP_PUSHNUM_2 OP_CHECKMULTISIGVERIFY \ OP_PUSHBYTES_2 1027 OP_CSV \ - OP_ENDIF)" + OP_ENDIF" ); let miniscript: Segwitv0Script = ms_str!( @@ -890,11 +890,11 @@ mod tests { assert_eq!(abs.n_keys(), 3); assert_eq!(abs.minimum_n_keys(), Some(3)); - roundtrip(&ms_str!("older(921)"), "Script(OP_PUSHBYTES_2 9903 OP_CSV)"); + roundtrip(&ms_str!("older(921)"), "OP_PUSHBYTES_2 9903 OP_CSV"); roundtrip( &ms_str!("sha256({})",sha256::Hash::hash(&[])), - "Script(OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 OP_EQUAL)" + "OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 OP_EQUAL" ); roundtrip( @@ -906,13 +906,13 @@ mod tests { keys[3], keys[4] ), - "Script(OP_PUSHNUM_3 \ + "OP_PUSHNUM_3 \ OP_PUSHBYTES_33 028c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa \ OP_PUSHBYTES_33 03ab1ac1872a38a2f196bed5a6047f0da2c8130fe8de49fc4d5dfb201f7611d8e2 \ OP_PUSHBYTES_33 039729247032c0dfcf45b4841fcd72f6e9a2422631fc3466cf863e87154754dd40 \ OP_PUSHBYTES_33 032564fe9b5beef82d3703a607253f31ef8ea1b365772df434226aee642651b3fa \ OP_PUSHBYTES_33 0289637f97580a796e050791ad5a2f27af1803645d95df021a3c2d82eb8c2ca7ff \ - OP_PUSHNUM_5 OP_CHECKMULTISIG)", + OP_PUSHNUM_5 OP_CHECKMULTISIG", ); roundtrip( @@ -921,11 +921,11 @@ mod tests { vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),\ v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5)\ )"), - "Script(OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY OP_PUSHNUM_1)" + "OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY OP_PUSHNUM_1" ); roundtrip( &ms_str!("and_n(pk(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))"), - "Script(OP_PUSHBYTES_33 03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729 OP_CHECKSIG OP_NOTIF OP_0 OP_ELSE OP_IF OP_0 OP_ELSE OP_PUSHBYTES_3 e2e440 OP_CSV OP_ENDIF OP_TOALTSTACK OP_PUSHNUM_16 OP_CSV OP_FROMALTSTACK OP_BOOLAND OP_ENDIF)" + "OP_PUSHBYTES_33 03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729 OP_CHECKSIG OP_NOTIF OP_0 OP_ELSE OP_IF OP_0 OP_ELSE OP_PUSHBYTES_3 e2e440 OP_CSV OP_ENDIF OP_TOALTSTACK OP_PUSHNUM_16 OP_CSV OP_FROMALTSTACK OP_BOOLAND OP_ENDIF" ); roundtrip( &ms_str!( @@ -938,12 +938,12 @@ mod tests { v:older(4194305),\ v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2)\ )"), - "Script(OP_PUSHNUM_3 OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e \ + "OP_PUSHNUM_3 OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e \ OP_PUSHBYTES_33 03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556 \ OP_PUSHBYTES_33 02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 \ OP_PUSHNUM_3 OP_CHECKMULTISIG OP_NOTIF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 \ OP_PUSHBYTES_32 9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2 OP_EQUALVERIFY \ - OP_ELSE OP_PUSHBYTES_3 010040 OP_CSV OP_VERIFY OP_ENDIF OP_PUSHNUM_1)" + OP_ELSE OP_PUSHBYTES_3 010040 OP_CSV OP_VERIFY OP_ENDIF OP_PUSHNUM_1" ); roundtrip( &ms_str!( @@ -951,17 +951,17 @@ mod tests { vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),\ v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5)\ )"), - "Script(\ + "\ OP_IF OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_HASH256 OP_PUSHBYTES_32 131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b OP_EQUAL \ OP_ELSE OP_0 OP_ENDIF OP_VERIFY OP_SIZE OP_PUSHBYTES_1 20 OP_EQUALVERIFY OP_SHA256 OP_PUSHBYTES_32 ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5 OP_EQUALVERIFY \ OP_PUSHNUM_1\ - )" + " ); // Thresh bug with equal verify roundtrip roundtrip( &ms_str!("tv:thresh(1,pk(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", ), - "Script(OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e OP_CHECKSIG OP_PUSHNUM_1 OP_EQUALVERIFY OP_PUSHNUM_1)", + "OP_PUSHBYTES_33 02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e OP_CHECKSIG OP_PUSHNUM_1 OP_EQUALVERIFY OP_PUSHNUM_1", ); } @@ -999,13 +999,10 @@ mod tests { #[test] fn test_tapscript_rtt() { // Test x-only invalid under segwitc0 context - let ms = Segwitv0Script::from_str_insane( + Segwitv0Script::from_str_insane( "pk(2788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)", - ); - assert_eq!( - ms.unwrap_err().to_string(), - "unexpected «key hex decoding error»", - ); + ) + .unwrap_err(); Tapscript::from_str_insane( "pk(2788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)", ) @@ -1091,10 +1088,10 @@ mod tests { &self, _pk: &Pk, _h: &TapLeafHash, - ) -> Option { - Some(bitcoin::SchnorrSig { + ) -> Option { + Some(bitcoin::taproot::Signature { sig: self.0, - hash_ty: bitcoin::SchnorrSighashType::Default, + hash_ty: bitcoin::sighash::TapSighashType::Default, }) } } diff --git a/src/miniscript/satisfy.rs b/src/miniscript/satisfy.rs index 4a47dd59d..037bdccb1 100644 --- a/src/miniscript/satisfy.rs +++ b/src/miniscript/satisfy.rs @@ -10,9 +10,9 @@ use core::{cmp, i64, mem}; use bitcoin::hashes::hash160; -use bitcoin::secp256k1::XOnlyPublicKey; -use bitcoin::util::taproot::{ControlBlock, LeafVersion, TapLeafHash}; -use bitcoin::{LockTime, Sequence}; +use bitcoin::key::XOnlyPublicKey; +use bitcoin::taproot::{ControlBlock, LeafVersion, TapLeafHash}; +use bitcoin::{absolute, Sequence}; use sync::Arc; use super::context::SigType; @@ -28,24 +28,28 @@ pub type Preimage32 = [u8; 32]; /// have data for. pub trait Satisfier { /// Given a public key, look up an ECDSA signature with that key - fn lookup_ecdsa_sig(&self, _: &Pk) -> Option { + fn lookup_ecdsa_sig(&self, _: &Pk) -> Option { None } /// Lookup the tap key spend sig - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self) -> Option { None } /// Given a public key and a associated leaf hash, look up an schnorr signature with that key - fn lookup_tap_leaf_script_sig(&self, _: &Pk, _: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig( + &self, + _: &Pk, + _: &TapLeafHash, + ) -> Option { None } /// Obtain a reference to the control block for a ver and script fn lookup_tap_control_block_map( &self, - ) -> Option<&BTreeMap> { + ) -> Option<&BTreeMap> { None } @@ -54,7 +58,7 @@ pub trait Satisfier { None } - /// Given a raw `Pkh`, lookup corresponding [`bitcoin::XOnlyPublicKey`] + /// Given a raw `Pkh`, lookup corresponding [`bitcoin::secp256k1::XOnlyPublicKey`] fn lookup_raw_pkh_x_only_pk(&self, _: &hash160::Hash) -> Option { None } @@ -66,7 +70,7 @@ pub trait Satisfier { fn lookup_raw_pkh_ecdsa_sig( &self, _: &hash160::Hash, - ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { None } @@ -77,7 +81,7 @@ pub trait Satisfier { fn lookup_raw_pkh_tap_leaf_script_sig( &self, _: &(hash160::Hash, TapLeafHash), - ) -> Option<(XOnlyPublicKey, bitcoin::SchnorrSig)> { + ) -> Option<(XOnlyPublicKey, bitcoin::taproot::Signature)> { None } @@ -107,7 +111,7 @@ pub trait Satisfier { } /// Assert whether a absolute locktime is satisfied - fn check_after(&self, _: LockTime) -> bool { + fn check_after(&self, _: absolute::LockTime) -> bool { false } } @@ -139,9 +143,9 @@ impl Satisfier for Sequence { } } -impl Satisfier for LockTime { - fn check_after(&self, n: LockTime) -> bool { - use LockTime::*; +impl Satisfier for absolute::LockTime { + fn check_after(&self, n: absolute::LockTime) -> bool { + use absolute::LockTime::*; match (n, *self) { (Blocks(n), Blocks(lock_time)) => n <= lock_time, @@ -150,16 +154,20 @@ impl Satisfier for LockTime { } } } -impl Satisfier for HashMap { - fn lookup_ecdsa_sig(&self, key: &Pk) -> Option { +impl Satisfier for HashMap { + fn lookup_ecdsa_sig(&self, key: &Pk) -> Option { self.get(key).copied() } } impl Satisfier - for HashMap<(Pk, TapLeafHash), bitcoin::SchnorrSig> + for HashMap<(Pk, TapLeafHash), bitcoin::taproot::Signature> { - fn lookup_tap_leaf_script_sig(&self, key: &Pk, h: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig( + &self, + key: &Pk, + h: &TapLeafHash, + ) -> Option { // Unfortunately, there is no way to get a &(a, b) from &a and &b without allocating // If we change the signature the of lookup_tap_leaf_script_sig to accept a tuple. We would // face the same problem while satisfying PkK. @@ -169,11 +177,11 @@ impl Satisfier } impl Satisfier - for HashMap + for HashMap where Pk: MiniscriptKey + ToPublicKey, { - fn lookup_ecdsa_sig(&self, key: &Pk) -> Option { + fn lookup_ecdsa_sig(&self, key: &Pk) -> Option { self.get(&key.to_pubkeyhash(SigType::Ecdsa)).map(|x| x.1) } @@ -184,18 +192,22 @@ where fn lookup_raw_pkh_ecdsa_sig( &self, pk_hash: &hash160::Hash, - ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { self.get(pk_hash) .map(|&(ref pk, sig)| (pk.to_public_key(), sig)) } } impl Satisfier - for HashMap<(hash160::Hash, TapLeafHash), (Pk, bitcoin::SchnorrSig)> + for HashMap<(hash160::Hash, TapLeafHash), (Pk, bitcoin::taproot::Signature)> where Pk: MiniscriptKey + ToPublicKey, { - fn lookup_tap_leaf_script_sig(&self, key: &Pk, h: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig( + &self, + key: &Pk, + h: &TapLeafHash, + ) -> Option { self.get(&(key.to_pubkeyhash(SigType::Schnorr), *h)) .map(|x| x.1) } @@ -203,18 +215,22 @@ where fn lookup_raw_pkh_tap_leaf_script_sig( &self, pk_hash: &(hash160::Hash, TapLeafHash), - ) -> Option<(XOnlyPublicKey, bitcoin::SchnorrSig)> { + ) -> Option<(XOnlyPublicKey, bitcoin::taproot::Signature)> { self.get(pk_hash) .map(|&(ref pk, sig)| (pk.to_x_only_pubkey(), sig)) } } impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &'a S { - fn lookup_ecdsa_sig(&self, p: &Pk) -> Option { + fn lookup_ecdsa_sig(&self, p: &Pk) -> Option { (**self).lookup_ecdsa_sig(p) } - fn lookup_tap_leaf_script_sig(&self, p: &Pk, h: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig( + &self, + p: &Pk, + h: &TapLeafHash, + ) -> Option { (**self).lookup_tap_leaf_script_sig(p, h) } @@ -229,24 +245,24 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &' fn lookup_raw_pkh_ecdsa_sig( &self, pkh: &hash160::Hash, - ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { (**self).lookup_raw_pkh_ecdsa_sig(pkh) } - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self) -> Option { (**self).lookup_tap_key_spend_sig() } fn lookup_raw_pkh_tap_leaf_script_sig( &self, pkh: &(hash160::Hash, TapLeafHash), - ) -> Option<(XOnlyPublicKey, bitcoin::SchnorrSig)> { + ) -> Option<(XOnlyPublicKey, bitcoin::taproot::Signature)> { (**self).lookup_raw_pkh_tap_leaf_script_sig(pkh) } fn lookup_tap_control_block_map( &self, - ) -> Option<&BTreeMap> { + ) -> Option<&BTreeMap> { (**self).lookup_tap_control_block_map() } @@ -270,21 +286,25 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &' (**self).check_older(t) } - fn check_after(&self, n: LockTime) -> bool { + fn check_after(&self, n: absolute::LockTime) -> bool { (**self).check_after(n) } } impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &'a mut S { - fn lookup_ecdsa_sig(&self, p: &Pk) -> Option { + fn lookup_ecdsa_sig(&self, p: &Pk) -> Option { (**self).lookup_ecdsa_sig(p) } - fn lookup_tap_leaf_script_sig(&self, p: &Pk, h: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig( + &self, + p: &Pk, + h: &TapLeafHash, + ) -> Option { (**self).lookup_tap_leaf_script_sig(p, h) } - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self) -> Option { (**self).lookup_tap_key_spend_sig() } @@ -299,20 +319,20 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &' fn lookup_raw_pkh_ecdsa_sig( &self, pkh: &hash160::Hash, - ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { (**self).lookup_raw_pkh_ecdsa_sig(pkh) } fn lookup_raw_pkh_tap_leaf_script_sig( &self, pkh: &(hash160::Hash, TapLeafHash), - ) -> Option<(XOnlyPublicKey, bitcoin::SchnorrSig)> { + ) -> Option<(XOnlyPublicKey, bitcoin::taproot::Signature)> { (**self).lookup_raw_pkh_tap_leaf_script_sig(pkh) } fn lookup_tap_control_block_map( &self, - ) -> Option<&BTreeMap> { + ) -> Option<&BTreeMap> { (**self).lookup_tap_control_block_map() } @@ -336,7 +356,7 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &' (**self).check_older(t) } - fn check_after(&self, n: LockTime) -> bool { + fn check_after(&self, n: absolute::LockTime) -> bool { (**self).check_after(n) } } @@ -349,7 +369,7 @@ macro_rules! impl_tuple_satisfier { Pk: MiniscriptKey + ToPublicKey, $($ty: Satisfier< Pk>,)* { - fn lookup_ecdsa_sig(&self, key: &Pk) -> Option { + fn lookup_ecdsa_sig(&self, key: &Pk) -> Option { let &($(ref $ty,)*) = self; $( if let Some(result) = $ty.lookup_ecdsa_sig(key) { @@ -359,7 +379,7 @@ macro_rules! impl_tuple_satisfier { None } - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self) -> Option { let &($(ref $ty,)*) = self; $( if let Some(result) = $ty.lookup_tap_key_spend_sig() { @@ -369,7 +389,7 @@ macro_rules! impl_tuple_satisfier { None } - fn lookup_tap_leaf_script_sig(&self, key: &Pk, h: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig(&self, key: &Pk, h: &TapLeafHash) -> Option { let &($(ref $ty,)*) = self; $( if let Some(result) = $ty.lookup_tap_leaf_script_sig(key, h) { @@ -382,7 +402,7 @@ macro_rules! impl_tuple_satisfier { fn lookup_raw_pkh_ecdsa_sig( &self, key_hash: &hash160::Hash, - ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { let &($(ref $ty,)*) = self; $( if let Some(result) = $ty.lookup_raw_pkh_ecdsa_sig(key_hash) { @@ -395,7 +415,7 @@ macro_rules! impl_tuple_satisfier { fn lookup_raw_pkh_tap_leaf_script_sig( &self, key_hash: &(hash160::Hash, TapLeafHash), - ) -> Option<(XOnlyPublicKey, bitcoin::SchnorrSig)> { + ) -> Option<(XOnlyPublicKey, bitcoin::taproot::Signature)> { let &($(ref $ty,)*) = self; $( if let Some(result) = $ty.lookup_raw_pkh_tap_leaf_script_sig(key_hash) { @@ -433,7 +453,7 @@ macro_rules! impl_tuple_satisfier { fn lookup_tap_control_block_map( &self, - ) -> Option<&BTreeMap> { + ) -> Option<&BTreeMap> { let &($(ref $ty,)*) = self; $( if let Some(result) = $ty.lookup_tap_control_block_map() { @@ -493,7 +513,7 @@ macro_rules! impl_tuple_satisfier { false } - fn check_after(&self, n: LockTime) -> bool { + fn check_after(&self, n: absolute::LockTime) -> bool { let &($(ref $ty,)*) = self; $( if $ty.check_after(n) { diff --git a/src/miniscript/types/extra_props.rs b/src/miniscript/types/extra_props.rs index 2beb5bfb3..3f12e5a88 100644 --- a/src/miniscript/types/extra_props.rs +++ b/src/miniscript/types/extra_props.rs @@ -6,7 +6,7 @@ use core::cmp; use core::iter::once; -use bitcoin::{LockTime, PackedLockTime, Sequence}; +use bitcoin::{absolute, Sequence}; use super::{Error, ErrorKind, Property, ScriptContext}; use crate::miniscript::context::SigType; @@ -339,7 +339,7 @@ impl Property for ExtData { unreachable!() } - fn from_after(t: LockTime) -> Self { + fn from_after(t: absolute::LockTime) -> Self { ExtData { pk_cost: script_num_size(t.to_consensus_u32() as usize) + 1, has_free_verify: false, @@ -934,7 +934,7 @@ impl Property for ExtData { // Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The // number on the stack would be a 5 bytes signed integer but Miniscript's B type // only consumes 4 bytes from the stack. - if t == PackedLockTime::ZERO { + if t == absolute::LockTime::ZERO.into() { return Err(Error { fragment: fragment.clone(), error: ErrorKind::InvalidTime, diff --git a/src/miniscript/types/mod.rs b/src/miniscript/types/mod.rs index 77e6362e3..d5c4ab0f7 100644 --- a/src/miniscript/types/mod.rs +++ b/src/miniscript/types/mod.rs @@ -13,7 +13,7 @@ use core::fmt; #[cfg(feature = "std")] use std::error; -use bitcoin::{LockTime, PackedLockTime, Sequence}; +use bitcoin::{absolute, Sequence}; pub use self::correctness::{Base, Correctness, Input}; pub use self::extra_props::ExtData; @@ -290,7 +290,7 @@ pub trait Property: Sized { /// Type property of an absolute timelock. Default implementation simply /// passes through to `from_time` - fn from_after(t: LockTime) -> Self { + fn from_after(t: absolute::LockTime) -> Self { Self::from_time(t.to_consensus_u32()) } @@ -424,7 +424,7 @@ pub trait Property: Sized { // Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The // number on the stack would be a 5 bytes signed integer but Miniscript's B type // only consumes 4 bytes from the stack. - if t == PackedLockTime::ZERO { + if t == absolute::LockTime::ZERO.into() { return Err(Error { fragment: fragment.clone(), error: ErrorKind::InvalidTime, @@ -618,7 +618,7 @@ impl Property for Type { } } - fn from_after(t: LockTime) -> Self { + fn from_after(t: absolute::LockTime) -> Self { Type { corr: Property::from_after(t), mall: Property::from_after(t), @@ -814,7 +814,7 @@ impl Property for Type { // Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The // number on the stack would be a 5 bytes signed integer but Miniscript's B type // only consumes 4 bytes from the stack. - if t == PackedLockTime::ZERO { + if t == absolute::LockTime::ZERO.into() { return Err(Error { fragment: fragment.clone(), error: ErrorKind::InvalidTime, diff --git a/src/policy/compiler.rs b/src/policy/compiler.rs index 5604f6221..a1b7dd676 100644 --- a/src/policy/compiler.rs +++ b/src/policy/compiler.rs @@ -1391,16 +1391,17 @@ mod tests { assert_eq!(abs.n_keys(), 5); assert_eq!(abs.minimum_n_keys(), Some(3)); - let bitcoinsig = bitcoin::EcdsaSig { + let bitcoinsig = bitcoin::ecdsa::Signature { sig, - hash_ty: bitcoin::EcdsaSighashType::All, + hash_ty: bitcoin::sighash::EcdsaSighashType::All, }; let sigvec = bitcoinsig.to_vec(); - let no_sat = HashMap::::new(); - let mut left_sat = HashMap::::new(); + let no_sat = HashMap::::new(); + let mut left_sat = HashMap::::new(); let mut right_sat = - HashMap::::new(); + HashMap::::new( + ); for i in 0..5 { left_sat.insert(keys[i], bitcoinsig); diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index 13ce815ea..b320c3da1 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -8,7 +8,7 @@ use core::{fmt, str}; #[cfg(feature = "std")] use std::error; -use bitcoin::{LockTime, PackedLockTime, Sequence}; +use bitcoin::{absolute, Sequence}; #[cfg(feature = "compiler")] use { crate::descriptor::TapTree, @@ -29,7 +29,7 @@ use crate::miniscript::types::extra_props::TimelockInfo; use crate::prelude::*; #[cfg(all(doc, not(feature = "compiler")))] use crate::Descriptor; -use crate::{errstr, Error, ForEachKey, MiniscriptKey, Translator}; +use crate::{errstr, AbsLockTime, Error, ForEachKey, MiniscriptKey, Translator}; /// Maximum TapLeafs allowed in a compiled TapTree #[cfg(feature = "compiler")] @@ -47,7 +47,7 @@ pub enum Policy { /// A public key which must sign to satisfy the descriptor Key(Pk), /// An absolute locktime restriction - After(PackedLockTime), + After(AbsLockTime), /// A relative locktime restriction Older(Sequence), /// A SHA256 whose preimage must be provided to satisfy the descriptor @@ -72,9 +72,9 @@ where Pk: MiniscriptKey, { /// Construct a `Policy::After` from `n`. Helper function equivalent to - /// `Policy::After(PackedLockTime::from(LockTime::from_consensus(n)))`. + /// `Policy::After(absolute::LockTime::from_consensus(n))`. pub fn after(n: u32) -> Policy { - Policy::After(PackedLockTime::from(LockTime::from_consensus(n))) + Policy::After(AbsLockTime::from(absolute::LockTime::from_consensus(n))) } /// Construct a `Policy::Older` from `n`. Helper function equivalent to @@ -97,7 +97,7 @@ enum PolicyArc { /// A public key which must sign to satisfy the descriptor Key(Pk), /// An absolute locktime restriction - After(u32), + After(AbsLockTime), /// A relative locktime restriction Older(u32), /// A SHA256 whose preimage must be provided to satisfy the descriptor @@ -124,7 +124,7 @@ impl From> for Policy { PolicyArc::Unsatisfiable => Policy::Unsatisfiable, PolicyArc::Trivial => Policy::Trivial, PolicyArc::Key(pk) => Policy::Key(pk), - PolicyArc::After(t) => Policy::After(PackedLockTime::from(LockTime::from_consensus(t))), + PolicyArc::After(t) => Policy::After(t), PolicyArc::Older(t) => Policy::Older(Sequence::from_consensus(t)), PolicyArc::Sha256(hash) => Policy::Sha256(hash), PolicyArc::Hash256(hash) => Policy::Hash256(hash), @@ -157,7 +157,7 @@ impl From> for PolicyArc { Policy::Unsatisfiable => PolicyArc::Unsatisfiable, Policy::Trivial => PolicyArc::Trivial, Policy::Key(pk) => PolicyArc::Key(pk), - Policy::After(PackedLockTime(t)) => PolicyArc::After(t), + Policy::After(lock_time) => PolicyArc::After(lock_time), Policy::Older(Sequence(t)) => PolicyArc::Older(t), Policy::Sha256(hash) => PolicyArc::Sha256(hash), Policy::Hash256(hash) => PolicyArc::Hash256(hash), @@ -874,8 +874,8 @@ impl Policy { Policy::After(t) => TimelockInfo { csv_with_height: false, csv_with_time: false, - cltv_with_height: LockTime::from(t).is_block_height(), - cltv_with_time: LockTime::from(t).is_block_time(), + cltv_with_height: absolute::LockTime::from(t).is_block_height(), + cltv_with_time: absolute::LockTime::from(t).is_block_time(), contains_combination: false, }, Policy::Older(t) => TimelockInfo { @@ -939,7 +939,7 @@ impl Policy { } } Policy::After(n) => { - if n == PackedLockTime::ZERO { + if n == absolute::LockTime::ZERO.into() { Err(PolicyError::ZeroTime) } else if n.to_u32() > 2u32.pow(31) { Err(PolicyError::TimeTooFar) diff --git a/src/policy/semantic.rs b/src/policy/semantic.rs index 671d227e5..fc9ee1b0b 100644 --- a/src/policy/semantic.rs +++ b/src/policy/semantic.rs @@ -6,12 +6,12 @@ use core::str::FromStr; use core::{fmt, str}; -use bitcoin::{LockTime, PackedLockTime, Sequence}; +use bitcoin::{absolute, Sequence}; use super::concrete::PolicyError; use super::ENTAILMENT_MAX_TERMINALS; use crate::prelude::*; -use crate::{errstr, expression, Error, ForEachKey, MiniscriptKey, Translator}; +use crate::{errstr, expression, AbsLockTime, Error, ForEachKey, MiniscriptKey, Translator}; /// Abstract policy which corresponds to the semantics of a Miniscript /// and which allows complex forms of analysis, e.g. filtering and @@ -28,7 +28,7 @@ pub enum Policy { /// Signature and public key matching a given hash is required Key(Pk), /// An absolute locktime restriction - After(PackedLockTime), + After(AbsLockTime), /// A relative locktime restriction Older(Sequence), /// A SHA256 whose preimage must be provided to satisfy the descriptor @@ -48,9 +48,9 @@ where Pk: MiniscriptKey, { /// Construct a `Policy::After` from `n`. Helper function equivalent to - /// `Policy::After(PackedLockTime::from(LockTime::from_consensus(n)))`. + /// `Policy::After(absolute::LockTime::from_consensus(n))`. pub fn after(n: u32) -> Policy { - Policy::After(PackedLockTime::from(LockTime::from_consensus(n))) + Policy::After(AbsLockTime::from(absolute::LockTime::from_consensus(n))) } /// Construct a `Policy::Older` from `n`. Helper function equivalent to @@ -515,7 +515,7 @@ impl Policy { | Policy::Ripemd160(..) | Policy::Hash160(..) => vec![], Policy::Older(..) => vec![], - Policy::After(t) => vec![t.0], + Policy::After(t) => vec![t.to_u32()], Policy::Threshold(_, ref subs) => subs.iter().fold(vec![], |mut acc, x| { acc.extend(x.real_absolute_timelocks()); acc @@ -556,12 +556,12 @@ impl Policy { /// Filter a policy by eliminating absolute timelock constraints /// that are not satisfied at the given `n` (`n OP_CHECKLOCKTIMEVERIFY`). - pub fn at_lock_time(mut self, n: LockTime) -> Policy { - use LockTime::*; + pub fn at_lock_time(mut self, n: absolute::LockTime) -> Policy { + use absolute::LockTime::*; self = match self { Policy::After(t) => { - let t = LockTime::from(t); + let t = absolute::LockTime::from(t); let is_satisfied_by = match (t, n) { (Blocks(t), Blocks(n)) => t <= n, (Seconds(t), Seconds(n)) => t <= n, @@ -810,32 +810,32 @@ mod tests { assert_eq!(policy.absolute_timelocks(), vec![1000]); assert_eq!(policy.relative_timelocks(), vec![]); assert_eq!( - policy.clone().at_lock_time(LockTime::ZERO), + policy.clone().at_lock_time(absolute::LockTime::ZERO), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_height(999).expect("valid block height")), + .at_lock_time(absolute::LockTime::from_height(999).expect("valid block height")), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_height(1000).expect("valid block height")), + .at_lock_time(absolute::LockTime::from_height(1000).expect("valid block height")), policy ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_height(10000).expect("valid block height")), + .at_lock_time(absolute::LockTime::from_height(10000).expect("valid block height")), policy ); // Pass a UNIX timestamp to at_lock_time while policy uses a block height. assert_eq!( policy .clone() - .at_lock_time(LockTime::from_time(500_000_001).expect("valid timestamp")), + .at_lock_time(absolute::LockTime::from_time(500_000_001).expect("valid timestamp")), Policy::Unsatisfiable ); assert_eq!(policy.n_keys(), 0); @@ -848,50 +848,50 @@ mod tests { assert_eq!(policy.relative_timelocks(), vec![]); // Pass a block height to at_lock_time while policy uses a UNIX timestapm. assert_eq!( - policy.clone().at_lock_time(LockTime::ZERO), + policy.clone().at_lock_time(absolute::LockTime::ZERO), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_height(999).expect("valid block height")), + .at_lock_time(absolute::LockTime::from_height(999).expect("valid block height")), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_height(1000).expect("valid block height")), + .at_lock_time(absolute::LockTime::from_height(1000).expect("valid block height")), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_height(10000).expect("valid block height")), + .at_lock_time(absolute::LockTime::from_height(10000).expect("valid block height")), Policy::Unsatisfiable ); // And now pass a UNIX timestamp to at_lock_time while policy also uses a timestamp. assert_eq!( policy .clone() - .at_lock_time(LockTime::from_time(500_000_000).expect("valid timestamp")), + .at_lock_time(absolute::LockTime::from_time(500_000_000).expect("valid timestamp")), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_time(500_000_001).expect("valid timestamp")), + .at_lock_time(absolute::LockTime::from_time(500_000_001).expect("valid timestamp")), Policy::Unsatisfiable ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_time(500_000_010).expect("valid timestamp")), + .at_lock_time(absolute::LockTime::from_time(500_000_010).expect("valid timestamp")), policy ); assert_eq!( policy .clone() - .at_lock_time(LockTime::from_time(500_000_012).expect("valid timestamp")), + .at_lock_time(absolute::LockTime::from_time(500_000_012).expect("valid timestamp")), policy ); assert_eq!(policy.n_keys(), 0); diff --git a/src/psbt/finalizer.rs b/src/psbt/finalizer.rs index 37ed38586..fd88d1bac 100644 --- a/src/psbt/finalizer.rs +++ b/src/psbt/finalizer.rs @@ -8,12 +8,11 @@ //! `https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki` //! -use bitcoin::blockdata::witness::Witness; +use bitcoin::key::XOnlyPublicKey; use bitcoin::secp256k1::{self, Secp256k1}; -use bitcoin::util::key::XOnlyPublicKey; -use bitcoin::util::sighash::Prevouts; -use bitcoin::util::taproot::LeafVersion; -use bitcoin::{self, PublicKey, Script, TxOut}; +use bitcoin::sighash::Prevouts; +use bitcoin::taproot::LeafVersion; +use bitcoin::{PublicKey, Script, ScriptBuf, TxOut, Witness}; use super::{sanity_check, Error, InputError, Psbt, PsbtInputSatisfier}; use crate::prelude::*; @@ -86,8 +85,8 @@ fn construct_tap_witness( } // Get the scriptpubkey for the psbt input -pub(super) fn get_scriptpubkey(psbt: &Psbt, index: usize) -> Result<&Script, InputError> { - get_utxo(psbt, index).map(|utxo| &utxo.script_pubkey) +pub(super) fn get_scriptpubkey(psbt: &Psbt, index: usize) -> Result { + get_utxo(psbt, index).map(|utxo| utxo.script_pubkey.clone()) } // Get the spending utxo for this psbt input @@ -247,7 +246,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result, In return Err(InputError::NonEmptyRedeemScript); } let ms = Miniscript::::parse_with_ext( - script_pubkey, + &script_pubkey, &ExtParams::allow_all(), )?; Ok(Descriptor::new_bare(ms)?) @@ -266,13 +265,13 @@ pub fn interpreter_check( let utxos = prevouts(psbt)?; let utxos = &Prevouts::All(&utxos); for (index, input) in psbt.inputs.iter().enumerate() { - let empty_script_sig = Script::new(); + let empty_script_sig = ScriptBuf::new(); let empty_witness = Witness::default(); let script_sig = input.final_script_sig.as_ref().unwrap_or(&empty_script_sig); let witness = input .final_script_witness .as_ref() - .map(|wit_slice| Witness::from_vec(wit_slice.to_vec())) // TODO: Update rust-bitcoin psbt API to use witness + .map(|wit_slice| Witness::from_slice(&wit_slice.to_vec())) // TODO: Update rust-bitcoin psbt API to use witness .unwrap_or(empty_witness); interpreter_inp_check(psbt, secp, index, utxos, &witness, script_sig)?; @@ -298,7 +297,7 @@ fn interpreter_inp_check>( let cltv = psbt.unsigned_tx.lock_time; let csv = psbt.unsigned_tx.input[index].sequence; let interpreter = - interpreter::Interpreter::from_txdata(spk, script_sig, witness, csv, cltv.into()) + interpreter::Interpreter::from_txdata(&spk, &script_sig, witness, csv, cltv.into()) .map_err(|e| Error::InputError(InputError::Interpreter(e), index))?; let iter = interpreter.iter(secp, &psbt.unsigned_tx, index, utxos); if let Some(error) = iter.filter_map(Result::err).next() { @@ -355,16 +354,16 @@ fn finalize_input_helper( index: usize, secp: &Secp256k1, allow_mall: bool, -) -> Result<(Witness, Script), super::Error> { +) -> Result<(Witness, ScriptBuf), super::Error> { let (witness, script_sig) = { let spk = get_scriptpubkey(psbt, index).map_err(|e| Error::InputError(e, index))?; let sat = PsbtInputSatisfier::new(psbt, index); if spk.is_v1_p2tr() { // Deal with tr case separately, unfortunately we cannot infer the full descriptor for Tr - let wit = construct_tap_witness(spk, &sat, allow_mall) + let wit = construct_tap_witness(&spk, &sat, allow_mall) .map_err(|e| Error::InputError(e, index))?; - (wit, Script::new()) + (wit, ScriptBuf::new()) } else { // Get a descriptor for this input. let desc = get_descriptor(psbt, index).map_err(|e| Error::InputError(e, index))?; @@ -380,7 +379,7 @@ fn finalize_input_helper( } }; - let witness = bitcoin::Witness::from_vec(witness); + let witness = bitcoin::Witness::from_slice(&witness); let utxos = prevouts(psbt)?; let utxos = &Prevouts::All(&utxos); interpreter_inp_check(psbt, secp, index, utxos, &witness, &script_sig)?; @@ -437,7 +436,6 @@ pub(super) fn finalize_input( #[cfg(test)] mod tests { - use bitcoin::consensus::encode::deserialize; use bitcoin::hashes::hex::FromHex; use super::*; @@ -445,12 +443,12 @@ mod tests { #[test] fn tests_from_bip174() { - let mut psbt: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); + let mut psbt = Psbt::deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); let secp = Secp256k1::verification_only(); psbt.finalize_mut(&secp).unwrap(); - let expected: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); + let expected = Psbt::deserialize(&Vec::::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap(); assert_eq!(psbt, expected); } } diff --git a/src/psbt/mod.rs b/src/psbt/mod.rs index 289c75dac..bb5bd4a3b 100644 --- a/src/psbt/mod.rs +++ b/src/psbt/mod.rs @@ -10,17 +10,15 @@ use core::convert::TryFrom; use core::fmt; -use core::ops::Deref; #[cfg(feature = "std")] use std::error; use bitcoin::hashes::{hash160, sha256d, Hash}; +use bitcoin::psbt::{self, Psbt}; use bitcoin::secp256k1::{self, Secp256k1, VerifyOnly}; -use bitcoin::util::bip32; -use bitcoin::util::psbt::{self, PartiallySignedTransaction as Psbt}; -use bitcoin::util::sighash::SighashCache; -use bitcoin::util::taproot::{self, ControlBlock, LeafVersion, TapLeafHash}; -use bitcoin::{self, EcdsaSighashType, LockTime, SchnorrSighashType, Script, Sequence}; +use bitcoin::sighash::{self, SighashCache}; +use bitcoin::taproot::{self, ControlBlock, LeafVersion, TapLeafHash}; +use bitcoin::{absolute, bip32, Script, ScriptBuf, Sequence}; use crate::miniscript::context::SigType; use crate::prelude::*; @@ -91,7 +89,7 @@ pub enum InputError { /// Get the secp Errors directly SecpErr(bitcoin::secp256k1::Error), /// Key errors - KeyErr(bitcoin::util::key::Error), + KeyErr(bitcoin::key::Error), /// Could not satisfy taproot descriptor /// This error is returned when both script path and key paths could not be /// satisfied. We cannot return a detailed error because we try all miniscripts @@ -102,16 +100,16 @@ pub enum InputError { /// Redeem script does not match the p2sh hash InvalidRedeemScript { /// Redeem script - redeem: Script, + redeem: ScriptBuf, /// Expected p2sh Script - p2sh_expected: Script, + p2sh_expected: ScriptBuf, }, /// Witness script does not match the p2wsh hash InvalidWitnessScript { /// Witness Script - witness_script: Script, + witness_script: ScriptBuf, /// Expected p2wsh script - p2wsh_expected: Script, + p2wsh_expected: ScriptBuf, }, /// Invalid sig InvalidSignature { @@ -137,13 +135,13 @@ pub enum InputError { /// Non empty Redeem script NonEmptyRedeemScript, /// Non Standard sighash type - NonStandardSighashType(bitcoin::blockdata::transaction::NonStandardSighashType), + NonStandardSighashType(sighash::NonStandardSighashType), /// Sighash did not match WrongSighashFlag { /// required sighash type - required: bitcoin::EcdsaSighashType, + required: sighash::EcdsaSighashType, /// the sighash type we got - got: bitcoin::EcdsaSighashType, + got: sighash::EcdsaSighashType, /// the corresponding publickey pubkey: bitcoin::PublicKey, }, @@ -248,8 +246,8 @@ impl From for InputError { } #[doc(hidden)] -impl From for InputError { - fn from(e: bitcoin::util::key::Error) -> InputError { +impl From for InputError { + fn from(e: bitcoin::key::Error) -> InputError { InputError::KeyErr(e) } } @@ -275,11 +273,15 @@ impl<'psbt> PsbtInputSatisfier<'psbt> { } impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfier<'psbt> { - fn lookup_tap_key_spend_sig(&self) -> Option { + fn lookup_tap_key_spend_sig(&self) -> Option { self.psbt.inputs[self.index].tap_key_sig } - fn lookup_tap_leaf_script_sig(&self, pk: &Pk, lh: &TapLeafHash) -> Option { + fn lookup_tap_leaf_script_sig( + &self, + pk: &Pk, + lh: &TapLeafHash, + ) -> Option { self.psbt.inputs[self.index] .tap_script_sigs .get(&(pk.to_x_only_pubkey(), *lh)) @@ -296,14 +298,17 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie fn lookup_tap_control_block_map( &self, - ) -> Option<&BTreeMap> { + ) -> Option<&BTreeMap> { Some(&self.psbt.inputs[self.index].tap_scripts) } fn lookup_raw_pkh_tap_leaf_script_sig( &self, pkh: &(hash160::Hash, TapLeafHash), - ) -> Option<(bitcoin::secp256k1::XOnlyPublicKey, bitcoin::SchnorrSig)> { + ) -> Option<( + bitcoin::secp256k1::XOnlyPublicKey, + bitcoin::taproot::Signature, + )> { self.psbt.inputs[self.index] .tap_script_sigs .iter() @@ -313,7 +318,7 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie .map(|((x_only_pk, _leaf_hash), sig)| (*x_only_pk, *sig)) } - fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option { + fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option { self.psbt.inputs[self.index] .partial_sigs .get(&pk.to_public_key()) @@ -323,7 +328,7 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie fn lookup_raw_pkh_ecdsa_sig( &self, pkh: &hash160::Hash, - ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> { + ) -> Option<(bitcoin::PublicKey, bitcoin::ecdsa::Signature)> { self.psbt.inputs[self.index] .partial_sigs .iter() @@ -331,12 +336,12 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie .map(|(pk, sig)| (*pk, *sig)) } - fn check_after(&self, n: LockTime) -> bool { + fn check_after(&self, n: absolute::LockTime) -> bool { if !self.psbt.unsigned_tx.input[self.index].enables_lock_time() { return false; } - let lock_time = LockTime::from(self.psbt.unsigned_tx.lock_time); + let lock_time = absolute::LockTime::from(self.psbt.unsigned_tx.lock_time); >::check_after(&lock_time, n) } @@ -374,7 +379,9 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie fn lookup_hash256(&self, h: &Pk::Hash256) -> Option { self.psbt.inputs[self.index] .hash256_preimages - .get(&sha256d::Hash::from_inner(Pk::to_hash256(h).into_inner())) // upstream psbt operates on hash256 + .get(&sha256d::Hash::from_byte_array( + Pk::to_hash256(h).to_byte_array(), + )) // upstream psbt operates on hash256 .and_then(try_vec_as_preimage32) } @@ -414,10 +421,10 @@ fn sanity_check(psbt: &Psbt) -> Result<(), Error> { Some(psbt_hash_ty) => psbt_hash_ty .ecdsa_hash_ty() .map_err(|e| Error::InputError(InputError::NonStandardSighashType(e), index))?, - None => EcdsaSighashType::All, + None => sighash::EcdsaSighashType::All, }; for (key, ecdsa_sig) in &input.partial_sigs { - let flag = bitcoin::EcdsaSighashType::from_standard(ecdsa_sig.hash_ty as u32).map_err( + let flag = sighash::EcdsaSighashType::from_standard(ecdsa_sig.hash_ty as u32).map_err( |_| { Error::InputError( InputError::Interpreter(interpreter::Error::NonStandardSighash( @@ -581,12 +588,15 @@ pub trait PsbtExt { descriptor: &Descriptor, ) -> Result<(), OutputUpdateError>; - /// Get the sighash message(data to sign) at input index `idx` based on the sighash + /// Get the sighash message(data to sign) at input index `idx`. + /// + /// Based on the sighash /// flag specified in the [`Psbt`] sighash field. If the input sighash flag psbt field is `None` - /// the [`SchnorrSighashType::Default`](bitcoin::util::sighash::SchnorrSighashType::Default) is chosen - /// for for taproot spends, otherwise [`EcdsaSignatureHashType::All`](bitcoin::EcdsaSighashType::All) is chosen. + /// the [`sighash::TapSighashType::Default`](bitcoin::sighash::TapSighashType::Default) is chosen + /// for for taproot spends, otherwise [`EcdsaSighashType::All`](bitcoin::sighash::EcdsaSighashType::All) is chosen. /// If the utxo at `idx` is a taproot output, returns a [`PsbtSighashMsg::TapSighash`] variant. - /// If the utxo at `idx` is a pre-taproot output, returns a [`PsbtSighashMsg::EcdsaSighash`] variant. + /// If the utxo at `idx` is a pre-taproot segwit output, returns a [`PsbtSighashMsg::SegwitV0Sighash`] variant. + /// For legacy outputs, returns a [`PsbtSighashMsg::LegacySighash`] variant. /// The `tapleaf_hash` parameter can be used to specify which tapleaf script hash has to be computed. If /// `tapleaf_hash` is [`None`], and the output is taproot output, the key spend hash is computed. This parameter must be /// set to [`None`] while computing sighash for pre-taproot outputs. @@ -598,8 +608,8 @@ pub trait PsbtExt { /// * `cache`: The [`SighashCache`] for used to cache/read previously cached computations /// * `tapleaf_hash`: If the output is taproot, compute the sighash for this particular leaf. /// - /// [`SighashCache`]: bitcoin::util::sighash::SighashCache - fn sighash_msg>( + /// [`SighashCache`]: bitcoin::sighash::SighashCache + fn sighash_msg>( &self, idx: usize, cache: &mut SighashCache, @@ -835,7 +845,7 @@ impl PsbtExt for Psbt { Ok(()) } - fn sighash_msg>( + fn sighash_msg>( &self, idx: usize, cache: &mut SighashCache, @@ -849,14 +859,14 @@ impl PsbtExt for Psbt { let prevouts = finalizer::prevouts(self).map_err(|_e| SighashError::MissingSpendUtxos)?; // Note that as per Psbt spec we should have access to spent_utxos for the transaction // Even if the transaction does not require SighashAll, we create `Prevouts::All` for code simplicity - let prevouts = bitcoin::util::sighash::Prevouts::All(&prevouts); + let prevouts = bitcoin::sighash::Prevouts::All(&prevouts); let inp_spk = finalizer::get_scriptpubkey(self, idx).map_err(|_e| SighashError::MissingInputUtxo)?; if inp_spk.is_v1_p2tr() { let hash_ty = inp .sighash_type - .map(|sighash_type| sighash_type.schnorr_hash_ty()) - .unwrap_or(Ok(SchnorrSighashType::Default)) + .map(|sighash_type| sighash_type.taproot_hash_ty()) + .unwrap_or(Ok(sighash::TapSighashType::Default)) .map_err(|_e| SighashError::InvalidSighashType)?; match tapleaf_hash { Some(leaf_hash) => { @@ -874,7 +884,7 @@ impl PsbtExt for Psbt { let hash_ty = inp .sighash_type .map(|sighash_type| sighash_type.ecdsa_hash_ty()) - .unwrap_or(Ok(EcdsaSighashType::All)) + .unwrap_or(Ok(sighash::EcdsaSighashType::All)) .map_err(|_e| SighashError::InvalidSighashType)?; let amt = finalizer::get_utxo(self, idx) .map_err(|_e| SighashError::MissingInputUtxo)? @@ -913,7 +923,7 @@ impl PsbtExt for Psbt { .ok_or(SighashError::MissingWitnessScript)?; cache.segwit_signature_hash(idx, script_code, amt, hash_ty)? }; - Ok(PsbtSighashMsg::EcdsaSighash(msg)) + Ok(PsbtSighashMsg::SegwitV0Sighash(msg)) } else { // legacy sighash case let script_code = if inp_spk.is_p2sh() { @@ -921,10 +931,10 @@ impl PsbtExt for Psbt { .as_ref() .ok_or(SighashError::MissingRedeemScript)? } else { - inp_spk + &inp_spk }; let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.to_u32())?; - Ok(PsbtSighashMsg::EcdsaSighash(msg)) + Ok(PsbtSighashMsg::LegacySighash(msg)) } } } @@ -1034,46 +1044,46 @@ impl Translator &mut Option