|
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