From d1abfd9c30df9544200940b975508102fac93c22 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 8 Mar 2022 17:19:01 +1100 Subject: [PATCH] Add unit test for sighash single bug When signing a transaction will result in the sighash single bug being exploitable we should return the 'one array' (equivalent to 1 as a uint256) as the signature hash. Add a unit test to verify we return uint256 1 value when use of SIGHASH_SINGLE is invalid. --- src/blockdata/transaction.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 9c026097..729e853f 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -835,7 +835,7 @@ impl ::std::error::Error for SigHashTypeParseError {} #[cfg(test)] mod tests { - use super::{OutPoint, ParseOutPointError, Transaction, TxIn, NonStandardSigHashType}; + use super::*; use core::str::FromStr; use blockdata::constants::WITNESS_SCALE_FACTOR; @@ -1147,6 +1147,29 @@ mod tests { assert_eq!(EcdsaSigHashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSigHashType(0x04))); } + #[test] + fn sighash_single_bug() { + const SIGHASH_SINGLE: u32 = 3; + // We need a tx with more inputs than outputs. + let mut input = Vec::new(); + input.push(TxIn::default()); + input.push(TxIn::default()); + let mut output = Vec::new(); + output.push(TxOut::default()); + + let tx = Transaction { + version: 1, + lock_time: 0, + input: input, + output: output, // TODO: Use Vec::from([TxOut]) once we bump MSRV. + }; + let script = Script::new(); + let got = tx.signature_hash(1, &script, SIGHASH_SINGLE); + let want = SigHash::from_slice(&UINT256_ONE).unwrap(); + + assert_eq!(got, want) + } + fn run_test_sighash(tx: &str, script: &str, input_index: usize, hash_type: i32, expected_result: &str) { let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()[..]).unwrap(); let script = Script::from(Vec::from_hex(script).unwrap());