From 8cd409d56169e6bc76eb5179ecce9ca0a20ee1ab Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 21 Sep 2023 13:35:12 +1000 Subject: [PATCH 1/2] Deprecate push_bitcoin_signature The `Witness::push_bitcoin_signature` method is old and a bit stale. Bitcoin has taproot signatures now so the name is stale, also we have the `crate::ecdsa::Signature` type that holds the secp sig and the hash type so we can use that instead of having two separate parameters. Add a new, up to date, `Witness::push_ecdsa_signature` function and deprecate the `push_bitcoin_signature` one. --- bitcoin/src/blockdata/witness.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index 9d7102cf..61e0449e 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -9,10 +9,9 @@ use core::convert::TryInto; use core::fmt; use core::ops::Index; -use secp256k1::ecdsa; - use crate::consensus::encode::{Error, MAX_VEC_SIZE}; use crate::consensus::{Decodable, Encodable, WriteExt}; +use crate::crypto::ecdsa; use crate::io::{self, Read, Write}; use crate::prelude::*; use crate::sighash::EcdsaSighashType; @@ -321,9 +320,10 @@ impl Witness { /// Pushes a DER-encoded ECDSA signature with a signature hash type as a new element on the /// witness, requires an allocation. + #[deprecated(since = "0.30.0", note = "use push_ecdsa_signature instead")] pub fn push_bitcoin_signature( &mut self, - signature: &ecdsa::SerializedSignature, + signature: &secp256k1::ecdsa::SerializedSignature, hash_type: EcdsaSighashType, ) { // Note that a maximal length ECDSA signature is 72 bytes, plus the sighash type makes 73 @@ -333,6 +333,13 @@ impl Witness { self.push(&sig[..signature.len() + 1]); } + /// Pushes, as a new element on the witness, an ECDSA signature. + /// + /// Pushes the DER encoded signature + sighash_type, requires an allocation. + pub fn push_ecdsa_signature(&mut self, signature: &ecdsa::Signature) { + self.push_slice(&signature.serialize()) + } + fn element_at(&self, index: usize) -> Option<&[u8]> { let varint = VarInt::consensus_decode(&mut &self.content[index..]).ok()?; let start = index + varint.len(); @@ -525,8 +532,6 @@ impl From> for Witness { #[cfg(test)] mod test { - use secp256k1::ecdsa; - use super::*; use crate::consensus::{deserialize, serialize}; use crate::internal_macros::hex; @@ -624,9 +629,10 @@ mod test { // The very first signature in block 734,958 let sig_bytes = hex!("304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b541"); - let sig = ecdsa::Signature::from_der(&sig_bytes).unwrap(); + let sig = secp256k1::ecdsa::Signature::from_der(&sig_bytes).unwrap(); let mut witness = Witness::default(); - witness.push_bitcoin_signature(&sig.serialize_der(), EcdsaSighashType::All); + let signature = ecdsa::Signature { sig, hash_ty: EcdsaSighashType::All }; + witness.push_ecdsa_signature(&signature); let expected_witness = vec![hex!( "304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b54101") ]; From 5901d35095544c01d8ee693249114db9be8bba11 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 20 Sep 2023 15:03:25 +1000 Subject: [PATCH 2/2] Add push_p2wpkh function on Witness In order to create the witness to spend p2wpkh output one must push the signature and the pubkey, we should have a function for this. --- bitcoin/src/blockdata/witness.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index 61e0449e..16c762b9 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -236,6 +236,19 @@ impl Witness { /// Creates a new empty [`Witness`]. pub fn new() -> Self { Witness::default() } + /// Creates a witness required to spend a P2WPKH output. + /// + /// The witness will be made up of the DER encoded signature + sighash_type followed by the + /// serialized public key. Also useful for spending a P2SH-P2WPKH output. + /// + /// It is expected that `pubkey` is related to the secret key used to create `signature`. + pub fn p2wpkh(signature: &ecdsa::Signature, pubkey: &secp256k1::PublicKey) -> Witness { + let mut witness = Witness::new(); + witness.push_slice(&signature.serialize()); + witness.push_slice(&pubkey.serialize()); + witness + } + /// Creates a [`Witness`] object from a slice of bytes slices where each slice is a witness item. pub fn from_slice>(slice: &[T]) -> Self { let witness_elements = slice.len();