From 62675f4b4f14cc2d40cfa87e77ac28edc1209fa2 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Mon, 16 Nov 2020 19:08:00 +0000 Subject: [PATCH] Use the SHA-256d HashReader and HashWriter for transaction hashing. This hashes the transaction as it is read, rather than hashing a re-serialization. Co-authored-by: Jack Grigg Signed-off-by: Daira Hopwood --- zcash_primitives/src/transaction/mod.rs | 60 ++++++++++++++----------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 42ea690ea..9c4a99822 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -1,12 +1,16 @@ //! Structs and methods for handling Zcash transactions. use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use sha2::{Digest, Sha256}; use std::fmt; use std::io::{self, Read, Write}; use std::ops::Deref; -use crate::{consensus::BlockHeight, redjubjub::Signature, serialize::Vector}; +use crate::{ + consensus::BlockHeight, + redjubjub::Signature, + serialize::Vector, + util::sha256d::{HashReader, HashWriter}, +}; pub mod builder; pub mod components; @@ -194,11 +198,9 @@ impl Transaction { txid: TxId([0; 32]), data, }; - let mut raw = vec![]; - tx.write(&mut raw)?; - tx.txid - .0 - .copy_from_slice(&Sha256::digest(&Sha256::digest(&raw))); + let mut writer = HashWriter::default(); + tx.write(&mut writer)?; + tx.txid.0.copy_from_slice(&writer.into_hash()); Ok(tx) } @@ -206,7 +208,9 @@ impl Transaction { self.txid } - pub fn read(mut reader: R) -> io::Result { + pub fn read(reader: R) -> io::Result { + let mut reader = HashReader::new(reader); + let header = reader.read_u32::()?; let overwintered = (header >> 31) == 1; let version = header & 0x7FFFFFFF; @@ -291,23 +295,29 @@ impl Transaction { None }; - Transaction::from_data(TransactionData { - overwintered, - version, - version_group_id, - vin, - vout, - tze_inputs, - tze_outputs, - lock_time, - expiry_height, - value_balance, - shielded_spends, - shielded_outputs, - joinsplits, - joinsplit_pubkey, - joinsplit_sig, - binding_sig, + let mut txid = [0; 32]; + txid.copy_from_slice(&reader.into_hash()); + + Ok(Transaction { + txid: TxId(txid), + data: TransactionData { + overwintered, + version, + version_group_id, + vin, + vout, + tze_inputs, + tze_outputs, + lock_time, + expiry_height, + value_balance, + shielded_spends, + shielded_outputs, + joinsplits, + joinsplit_pubkey, + joinsplit_sig, + binding_sig, + }, }) }