From 8773cb4a42c10e1d42b9105eb95b818dac1e91ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Fri, 24 Jan 2020 16:25:05 -0800 Subject: [PATCH 1/2] Document `sighash_u32` of `Transaction::signature_hash` --- src/blockdata/transaction.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index c083b712..e06ef471 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -307,6 +307,10 @@ impl Transaction { /// through an ECDSA signer, the SigHashType appended to the resulting sig, and a script /// written around this, but this is the general (and hard) part. /// + /// The `sighash_u32` supports arbitrary `u32` value, instead of just [`SigHashType`], + /// because internally 4 bytes are being hashed, even though only lowest byte + /// is appended to signature in a transaction. + /// /// *Warning* This does NOT attempt to support OP_CODESEPARATOR. In general this would require /// evaluating `script_pubkey` to determine which separators get evaluated and which don't, /// which we don't have the information to determine. @@ -318,11 +322,11 @@ impl Transaction { mut writer: Write, input_index: usize, script_pubkey: &Script, - sighash_u32: u32 + sighash_type: u32 ) -> Result<(), encode::Error> { assert!(input_index < self.input.len()); // Panic on OOB - let (sighash, anyone_can_pay) = SigHashType::from_u32(sighash_u32).split_anyonecanpay_flag(); + let (sighash, anyone_can_pay) = SigHashType::from_u32(sighash_type).split_anyonecanpay_flag(); // Special-case sighash_single bug because this is easy enough. if sighash == SigHashType::Single && input_index >= self.output.len() { @@ -374,7 +378,7 @@ impl Transaction { }; // hash the result tx.consensus_encode(&mut writer)?; - let sighash_arr = endian::u32_to_array_le(sighash_u32); + let sighash_arr = endian::u32_to_array_le(sighash_type); sighash_arr.consensus_encode(&mut writer)?; Ok(()) } From cf2c12a816e1644ac65770a82634cce55fd2b585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Fri, 24 Jan 2020 16:30:57 -0800 Subject: [PATCH 2/2] Add ability to pass `SigHashType` directly to `signature_hash` --- src/blockdata/transaction.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index e06ef471..b7829ac6 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -307,7 +307,7 @@ impl Transaction { /// through an ECDSA signer, the SigHashType appended to the resulting sig, and a script /// written around this, but this is the general (and hard) part. /// - /// The `sighash_u32` supports arbitrary `u32` value, instead of just [`SigHashType`], + /// The `sighash_type` supports arbitrary `u32` value, instead of just [`SigHashType`], /// because internally 4 bytes are being hashed, even though only lowest byte /// is appended to signature in a transaction. /// @@ -317,13 +317,14 @@ impl Transaction { /// /// # Panics Panics if `input_index` is greater than or equal to `self.input.len()` /// - pub fn encode_signing_data_to( + pub fn encode_signing_data_to>( &self, mut writer: Write, input_index: usize, script_pubkey: &Script, - sighash_type: u32 + sighash_type: U, ) -> Result<(), encode::Error> { + let sighash_type : u32 = sighash_type.into(); assert!(input_index < self.input.len()); // Panic on OOB let (sighash, anyone_can_pay) = SigHashType::from_u32(sighash_type).split_anyonecanpay_flag(); @@ -685,6 +686,11 @@ impl SigHashType { pub fn as_u32(self) -> u32 { self as u32 } } +impl From for u32 { + fn from(t: SigHashType) -> u32 { + t.as_u32() + } +} #[cfg(test)] mod tests {