|
3 | 3 | //! This module contains the [`Witness`] struct and related methods to operate on it |
4 | 4 | //! |
5 | 5 |
|
| 6 | +use blockdata::transaction::EcdsaSighashType; |
6 | 7 | use consensus::encode::{Error, MAX_VEC_SIZE}; |
7 | 8 | use consensus::{Decodable, Encodable, WriteExt}; |
8 | 9 | use io::{self, Read, Write}; |
9 | 10 | use prelude::*; |
| 11 | +use secp256k1::ecdsa; |
10 | 12 | use VarInt; |
11 | 13 |
|
12 | 14 | #[cfg(feature = "serde")] |
@@ -211,6 +213,17 @@ impl Witness { |
211 | 213 | self.content[end_varint..].copy_from_slice(new_element); |
212 | 214 | } |
213 | 215 |
|
| 216 | + /// Pushes a DER-encoded ECDSA signature with a signature hash type as a new element on the |
| 217 | + /// witness, requires an allocation. |
| 218 | + pub fn push_bitcoin_signature(&mut self, signature: &ecdsa::SerializedSignature, hash_type: EcdsaSighashType) { |
| 219 | + // Note that a maximal length ECDSA signature is 72 bytes, plus the sighash type makes 73 |
| 220 | + let mut sig = [0; 73]; |
| 221 | + sig[..signature.len()].copy_from_slice(&signature); |
| 222 | + sig[signature.len()] = hash_type as u8; |
| 223 | + self.push(&sig[..signature.len() + 1]); |
| 224 | + } |
| 225 | + |
| 226 | + |
214 | 227 | fn element_at(&self, index: usize) -> Option<&[u8]> { |
215 | 228 | let varint = VarInt::consensus_decode(&self.content[index..]).ok()?; |
216 | 229 | let start = index + varint.len(); |
@@ -289,10 +302,12 @@ impl<'de> serde::Deserialize<'de> for Witness { |
289 | 302 |
|
290 | 303 | #[cfg(test)] |
291 | 304 | mod test { |
| 305 | + use blockdata::transaction::EcdsaSighashType; |
292 | 306 | use blockdata::witness::Witness; |
293 | 307 | use consensus::{deserialize, serialize}; |
294 | 308 | use hashes::hex::{FromHex, ToHex}; |
295 | 309 | use Transaction; |
| 310 | + use secp256k1::ecdsa; |
296 | 311 |
|
297 | 312 | #[test] |
298 | 313 | fn test_push() { |
@@ -321,6 +336,20 @@ mod test { |
321 | 336 | assert_eq!(witness.second_to_last(), Some(&[0u8][..])); |
322 | 337 | } |
323 | 338 |
|
| 339 | + #[test] |
| 340 | + fn test_push_ecdsa_sig() { |
| 341 | + // The very first signature in block 734,958 |
| 342 | + let sig_bytes = |
| 343 | + Vec::from_hex("304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b541"); |
| 344 | + let sig = ecdsa::Signature::from_der(&sig_bytes.unwrap()).unwrap(); |
| 345 | + let mut witness = Witness::default(); |
| 346 | + witness.push_bitcoin_signature(&sig.serialize_der(), EcdsaSighashType::All); |
| 347 | + let expected_witness = vec![Vec::from_hex( |
| 348 | + "304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b54101") |
| 349 | + .unwrap()]; |
| 350 | + assert_eq!(witness.to_vec(), expected_witness); |
| 351 | + } |
| 352 | + |
324 | 353 | #[test] |
325 | 354 | fn test_witness() { |
326 | 355 | let w0 = |
|
0 commit comments