diff --git a/Cargo.toml b/Cargo.toml index 567b7f5e7..d7111e343 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "miniscript" -version = "7.0.0-rc.1" +version = "7.0.0-rc.2" authors = ["Andrew Poelstra , Sanket Kanjalkar "] repository = "https://github.com/apoelstra/miniscript" description = "Miniscript: a subset of Bitcoin Script designed for analysis" @@ -15,8 +15,7 @@ use-serde = ["bitcoin/use-serde", "serde"] rand = ["bitcoin/rand"] [dependencies] -# bitcoin = "0.27" -bitcoin = "0.28.0-rc.1" +bitcoin = "0.28.0-rc.2" [dependencies.serde] version = "1.0" diff --git a/examples/verify_tx.rs b/examples/verify_tx.rs index b297fe4d4..1725238a6 100644 --- a/examples/verify_tx.rs +++ b/examples/verify_tx.rs @@ -18,8 +18,8 @@ extern crate bitcoin; extern crate miniscript; use bitcoin::consensus::Decodable; -use bitcoin::secp256k1; // secp256k1 re-exported from rust-bitcoin use bitcoin::util::sighash; +use bitcoin::{secp256k1, TxOut}; // secp256k1 re-exported from rust-bitcoin use miniscript::interpreter::KeySigPair; use std::str::FromStr; @@ -139,7 +139,7 @@ fn main() { // We can set prevouts to be empty list because this is a legacy transaction // and this information is not required for sighash computation. - let prevouts = sighash::Prevouts::All(&[]); + let prevouts = sighash::Prevouts::All::(&[]); println!("\nExample two"); for elem in interpreter.iter(&secp, &transaction, 0, &prevouts) { diff --git a/integration_test/src/test_cpp.rs b/integration_test/src/test_cpp.rs index 2a25862d9..3ec32de8c 100644 --- a/integration_test/src/test_cpp.rs +++ b/integration_test/src/test_cpp.rs @@ -187,7 +187,7 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) { let sig = secp.sign_ecdsa(&msg, &sk); let pk = pks[sks.iter().position(|&x| x == sk).unwrap()]; psbts[i].inputs[0].partial_sigs.insert( - pk.inner, + pk, bitcoin::EcdsaSig { sig, hash_ty: sighash_ty, diff --git a/integration_test/src/test_desc.rs b/integration_test/src/test_desc.rs index 26fda3d76..9f0b81deb 100644 --- a/integration_test/src/test_desc.rs +++ b/integration_test/src/test_desc.rs @@ -234,7 +234,7 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: &str) -> Witnes let pk = pks[sks.iter().position(|&x| x == sk).unwrap()]; assert!(secp.verify_ecdsa(&msg, &sig, &pk.inner).is_ok()); psbt.inputs[0].partial_sigs.insert( - pk.inner, + pk, bitcoin::EcdsaSig { sig, hash_ty: hash_ty, diff --git a/src/interpreter/inner.rs b/src/interpreter/inner.rs index daf2cbbc5..45690146e 100644 --- a/src/interpreter/inner.rs +++ b/src/interpreter/inner.rs @@ -15,7 +15,6 @@ use bitcoin; use bitcoin::blockdata::witness::Witness; use bitcoin::hashes::{hash160, sha256, Hash}; -use bitcoin::schnorr::TapTweak; use bitcoin::util::taproot::{ControlBlock, TAPROOT_ANNEX_PREFIX}; use {BareCtx, Legacy, Segwitv0, Tap}; @@ -241,11 +240,7 @@ pub(super) fn from_txdata<'txin>( let tap_script = tap_script.encode(); // Should not really need to call dangerous assumed tweaked here. // Should be fixed after RC - if ctrl_blk.verify_taproot_commitment( - &secp, - &output_key.dangerous_assume_tweaked(), - &tap_script, - ) { + if ctrl_blk.verify_taproot_commitment(&secp, output_key, &tap_script) { Ok(( Inner::Script(ms, ScriptType::Tr), wit_stack, diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 098c04dd3..b544b25a9 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -21,11 +21,12 @@ use bitcoin::blockdata::witness::Witness; use bitcoin::util::{sighash, taproot}; +use std::borrow::Borrow; use std::fmt; use std::str::FromStr; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; -use bitcoin::{self, secp256k1}; +use bitcoin::{self, secp256k1, TxOut}; use miniscript::context::NoChecks; use miniscript::ScriptContext; use Miniscript; @@ -224,18 +225,18 @@ impl<'txin> Interpreter<'txin> { /// - Insufficient sighash information is present /// - sighash single without corresponding output // TODO: Create a good first isse to change this to error - pub fn verify_sig( + pub fn verify_sig>( &self, secp: &secp256k1::Secp256k1, tx: &bitcoin::Transaction, input_idx: usize, - prevouts: &sighash::Prevouts, + prevouts: &sighash::Prevouts, sig: &KeySigPair, ) -> bool { - fn get_prevout<'u>( - prevouts: &sighash::Prevouts<'u>, + fn get_prevout<'u, T: Borrow>( + prevouts: &'u sighash::Prevouts<'u, T>, input_index: usize, - ) -> Option<&'u bitcoin::TxOut> { + ) -> Option<&'u T> { match prevouts { sighash::Prevouts::One(index, prevout) => { if input_index == *index { @@ -252,11 +253,11 @@ impl<'txin> Interpreter<'txin> { 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 sighash_u32 = ecdsa_sig.hash_ty.as_u32(); + let sighash_u32 = ecdsa_sig.hash_ty.to_u32(); cache.legacy_signature_hash(input_idx, &script_pubkey, sighash_u32) } else if self.is_segwit_v0() { let amt = match get_prevout(prevouts, input_idx) { - Some(txout) => txout.value, + Some(txout) => txout.borrow().value, None => return false, }; cache.segwit_signature_hash(input_idx, &script_pubkey, amt, ecdsa_sig.hash_ty) @@ -318,12 +319,12 @@ impl<'txin> Interpreter<'txin> { /// - For legacy outputs, no information about prevouts is required /// - For segwitv0 outputs, prevout at corresponding index with correct amount must be provided /// - For taproot outputs, information about all prevouts must be supplied - pub fn iter<'iter, C: secp256k1::Verification>( + pub fn iter<'iter, C: secp256k1::Verification, T: Borrow>( &'iter self, secp: &'iter secp256k1::Secp256k1, tx: &'txin bitcoin::Transaction, input_idx: usize, - prevouts: &'iter sighash::Prevouts, // actually a 'prevouts, but 'prevouts: 'iter + prevouts: &'iter sighash::Prevouts, // actually a 'prevouts, but 'prevouts: 'iter ) -> Iter<'txin, 'iter> { self.iter_custom(Box::new(move |sig| { self.verify_sig(secp, tx, input_idx, prevouts, sig) diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index 683800143..c20ed8938 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -968,7 +968,7 @@ mod tests { )); assert_eq!( ms.unwrap_err().to_string(), - "unexpected «Key secp256k1 error: secp: malformed public key»" + "unexpected «Key hex decoding error: bad hex string length 64 (expected 66)»" ); Tapscript::from_str_insane(&format!( "pk(2788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99)" diff --git a/src/psbt/finalizer.rs b/src/psbt/finalizer.rs index c184e3443..47abafd00 100644 --- a/src/psbt/finalizer.rs +++ b/src/psbt/finalizer.rs @@ -20,6 +20,7 @@ //! use bitcoin::util::sighash::Prevouts; +use std::borrow::Borrow; use util::witness_size; use super::{sanity_check, Psbt}; @@ -28,7 +29,7 @@ use bitcoin::blockdata::witness::Witness; use bitcoin::secp256k1::{self, Secp256k1}; use bitcoin::util::key::XOnlyPublicKey; use bitcoin::util::taproot::LeafVersion; -use bitcoin::{self, PublicKey, Script}; +use bitcoin::{self, PublicKey, Script, TxOut}; use descriptor::DescriptorTrait; use interpreter; use Descriptor; @@ -116,11 +117,11 @@ pub(super) fn get_utxo(psbt: &Psbt, index: usize) -> Result<&bitcoin::TxOut, Inp } /// Get the Prevouts for the psbt -pub(super) fn prevouts<'a>(psbt: &'a Psbt) -> Result, super::Error> { +pub(super) fn prevouts<'a>(psbt: &'a Psbt) -> Result, super::Error> { let mut utxos = vec![]; for i in 0..psbt.inputs.len() { let utxo_ref = get_utxo(psbt, i).map_err(|e| Error::InputError(e, i))?; - utxos.push(utxo_ref.clone()); // RC fix would allow references here instead of clone + utxos.push(utxo_ref); } Ok(utxos) } @@ -157,13 +158,12 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result, In // Partial sigs loses the compressed flag that is necessary // TODO: See https://github.com/rust-bitcoin/rust-bitcoin/pull/836 // The type checker will fail again after we update to 0.28 and this can be removed - let pk = bitcoin::PublicKey::new(pk); let addr = bitcoin::Address::p2pkh(&pk, bitcoin::Network::Bitcoin); *script_pubkey == addr.script_pubkey() }) .next(); match partial_sig_contains_pk { - Some((pk, _sig)) => Ok(Descriptor::new_pkh(bitcoin::PublicKey::new(*pk))), + Some((pk, _sig)) => Ok(Descriptor::new_pkh(*pk)), None => Err(InputError::MissingPubkey), } } else if script_pubkey.is_v0_p2wpkh() { @@ -174,14 +174,13 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result, In .filter(|&(&pk, _sig)| { // Indirect way to check the equivalence of pubkey-hashes. // Create a pubkey hash and check if they are the same. - let pk = bitcoin::PublicKey::new(pk); let addr = bitcoin::Address::p2wpkh(&pk, bitcoin::Network::Bitcoin) .expect("Address corresponding to valid pubkey"); *script_pubkey == addr.script_pubkey() }) .next(); match partial_sig_contains_pk { - Some((pk, _sig)) => Ok(Descriptor::new_wpkh(bitcoin::PublicKey::new(*pk))?), + Some((pk, _sig)) => Ok(Descriptor::new_wpkh(*pk)?), None => Err(InputError::MissingPubkey), } } else if script_pubkey.is_v0_p2wsh() { @@ -233,16 +232,13 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result, In .partial_sigs .iter() .filter(|&(&pk, _sig)| { - let pk = bitcoin::PublicKey::new(pk); let addr = bitcoin::Address::p2wpkh(&pk, bitcoin::Network::Bitcoin) .expect("Address corresponding to valid pubkey"); *redeem_script == addr.script_pubkey() }) .next(); match partial_sig_contains_pk { - Some((pk, _sig)) => { - Ok(Descriptor::new_sh_wpkh(bitcoin::PublicKey::new(*pk))?) - } + Some((pk, _sig)) => Ok(Descriptor::new_sh_wpkh(*pk)?), None => Err(InputError::MissingPubkey), } } else { @@ -300,11 +296,11 @@ pub fn interpreter_check( } // Run the miniscript interpreter on a single psbt input -fn interpreter_inp_check( +fn interpreter_inp_check>( psbt: &Psbt, secp: &Secp256k1, index: usize, - utxos: &Prevouts, + utxos: &Prevouts, witness: &Witness, script_sig: &Script, ) -> Result<(), Error> { diff --git a/src/psbt/mod.rs b/src/psbt/mod.rs index 25e8f6953..df794a4cc 100644 --- a/src/psbt/mod.rs +++ b/src/psbt/mod.rs @@ -287,7 +287,7 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option { self.psbt.inputs[self.index] .partial_sigs - .get(&pk.to_public_key().inner) + .get(&pk.to_public_key()) .map(|sig| *sig) } @@ -298,11 +298,9 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie self.psbt.inputs[self.index] .partial_sigs .iter() - .filter(|&(pubkey, _sig)| { - bitcoin::PublicKey::new(*pubkey).to_pubkeyhash() == Pk::hash_to_hash160(pkh) - }) + .filter(|&(pubkey, _sig)| pubkey.to_pubkeyhash() == Pk::hash_to_hash160(pkh)) .next() - .map(|(pk, sig)| (bitcoin::PublicKey::new(*pk), *sig)) + .map(|(pk, sig)| (*pk, *sig)) } fn check_after(&self, n: u32) -> bool { @@ -393,21 +391,22 @@ fn sanity_check(psbt: &Psbt) -> Result<(), Error> { None => EcdsaSigHashType::All, }; for (key, ecdsa_sig) in &input.partial_sigs { - let flag = bitcoin::EcdsaSigHashType::from_u32_standard(ecdsa_sig.hash_ty as u32) - .map_err(|_| { + let flag = bitcoin::EcdsaSigHashType::from_standard(ecdsa_sig.hash_ty as u32).map_err( + |_| { Error::InputError( InputError::Interpreter(interpreter::Error::NonStandardSigHash( ecdsa_sig.to_vec(), )), index, ) - })?; + }, + )?; if target_ecdsa_sighash_ty != flag { return Err(Error::InputError( InputError::WrongSigHashFlag { required: target_ecdsa_sighash_ty, got: flag, - pubkey: bitcoin::PublicKey::new(*key), + pubkey: *key, }, index, )); @@ -855,7 +854,7 @@ impl PsbtExt for Psbt { } else { inp_spk }; - let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.as_u32())?; + let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.to_u32())?; Ok(PsbtSigHashMsg::EcdsaSigHash(msg)) } }