cache signature portions
This commit is contained in:
parent
fb2c60f61b
commit
9742b113df
|
@ -11,7 +11,7 @@ use {
|
|||
|
||||
/// Helper function.
|
||||
fn check_signature(
|
||||
checker: &SignatureChecker,
|
||||
checker: &mut SignatureChecker,
|
||||
mut script_sig: Vec<u8>,
|
||||
public: Vec<u8>,
|
||||
script_code: &Script,
|
||||
|
@ -33,7 +33,7 @@ fn check_signature(
|
|||
|
||||
/// Helper function.
|
||||
fn verify_signature(
|
||||
checker: &SignatureChecker,
|
||||
checker: &mut SignatureChecker,
|
||||
signature: Vec<u8>,
|
||||
public: Vec<u8>,
|
||||
message: Message,
|
||||
|
@ -249,7 +249,7 @@ pub fn verify_script(
|
|||
script_sig: &Script,
|
||||
script_pubkey: &Script,
|
||||
flags: &VerificationFlags,
|
||||
checker: &SignatureChecker,
|
||||
checker: &mut SignatureChecker,
|
||||
) -> Result<(), Error> {
|
||||
if flags.verify_sigpushonly && !script_sig.is_push_only() {
|
||||
return Err(Error::SignaturePushOnly);
|
||||
|
@ -311,7 +311,7 @@ pub fn eval_script(
|
|||
stack: &mut Stack<Bytes>,
|
||||
script: &Script,
|
||||
flags: &VerificationFlags,
|
||||
checker: &SignatureChecker,
|
||||
checker: &mut SignatureChecker,
|
||||
) -> Result<bool, Error> {
|
||||
if script.len() > script::MAX_SCRIPT_SIZE {
|
||||
return Err(Error::ScriptSize);
|
||||
|
@ -1055,7 +1055,7 @@ mod tests {
|
|||
let expected: Stack<Bytes> = vec![vec![0x5a].into()].into();
|
||||
let flags = VerificationFlags::default()
|
||||
.verify_p2sh(true);
|
||||
let checker = NoopSignatureChecker;
|
||||
let mut checker = NoopSignatureChecker;
|
||||
let direct: Script = vec![Opcode::OP_PUSHBYTES_1 as u8, 0x5a].into();
|
||||
let pushdata1: Script = vec![Opcode::OP_PUSHDATA1 as u8, 0x1, 0x5a].into();
|
||||
let pushdata2: Script = vec![Opcode::OP_PUSHDATA2 as u8, 0x1, 0, 0x5a].into();
|
||||
|
@ -1065,10 +1065,10 @@ mod tests {
|
|||
let mut pushdata1_stack = Stack::new();
|
||||
let mut pushdata2_stack = Stack::new();
|
||||
let mut pushdata4_stack = Stack::new();
|
||||
assert!(eval_script(&mut direct_stack, &direct, &flags, &checker).unwrap());
|
||||
assert!(eval_script(&mut pushdata1_stack, &pushdata1, &flags, &checker).unwrap());
|
||||
assert!(eval_script(&mut pushdata2_stack, &pushdata2, &flags, &checker).unwrap());
|
||||
assert!(eval_script(&mut pushdata4_stack, &pushdata4, &flags, &checker).unwrap());
|
||||
assert!(eval_script(&mut direct_stack, &direct, &flags, &mut checker).unwrap());
|
||||
assert!(eval_script(&mut pushdata1_stack, &pushdata1, &flags, &mut checker).unwrap());
|
||||
assert!(eval_script(&mut pushdata2_stack, &pushdata2, &flags, &mut checker).unwrap());
|
||||
assert!(eval_script(&mut pushdata4_stack, &pushdata4, &flags, &mut checker).unwrap());
|
||||
|
||||
assert_eq!(direct_stack, expected);
|
||||
assert_eq!(pushdata1_stack, expected);
|
||||
|
@ -1077,9 +1077,9 @@ mod tests {
|
|||
}
|
||||
|
||||
fn basic_test_with_flags(script: &Script, flags: &VerificationFlags, expected: Result<bool, Error>, expected_stack: Stack<Bytes>) {
|
||||
let checker = NoopSignatureChecker;
|
||||
let mut checker = NoopSignatureChecker;
|
||||
let mut stack = Stack::new();
|
||||
assert_eq!(eval_script(&mut stack, script, &flags, &checker), expected);
|
||||
assert_eq!(eval_script(&mut stack, script, &flags, &mut checker), expected);
|
||||
if expected.is_ok() {
|
||||
assert_eq!(stack, expected_stack);
|
||||
}
|
||||
|
@ -1977,17 +1977,18 @@ mod tests {
|
|||
fn test_check_transaction_signature() {
|
||||
let tx: Transaction = "0100000001484d40d45b9ea0d652fca8258ab7caa42541eb52975857f96fb50cd732c8b481000000008a47304402202cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff71302206c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e8201410414e301b2328f17442c0b8310d787bf3d8a404cfbd0704f135b6ad4b2d3ee751310f981926e53a6e8c39bd7d3fefd576c543cce493cbac06388f2651d1aacbfcdffffffff0162640100000000001976a914c8e90996c7c6080ee06284600c684ed904d14c5c88ac00000000".into();
|
||||
let signer: TransactionInputSigner = tx.into();
|
||||
let checker = TransactionSignatureChecker {
|
||||
let mut checker = TransactionSignatureChecker {
|
||||
signer: signer,
|
||||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: 0,
|
||||
cache: None,
|
||||
};
|
||||
let input: Script = "47304402202cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff71302206c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e8201410414e301b2328f17442c0b8310d787bf3d8a404cfbd0704f135b6ad4b2d3ee751310f981926e53a6e8c39bd7d3fefd576c543cce493cbac06388f2651d1aacbfcd".into();
|
||||
let output: Script = "76a914df3bd30160e6c6145baaf2c88a8844c13a00d1d588ac".into();
|
||||
let flags = VerificationFlags::default()
|
||||
.verify_p2sh(true);
|
||||
assert_eq!(verify_script(&input, &output, &flags, &checker), Ok(()));
|
||||
assert_eq!(verify_script(&input, &output, &flags, &mut checker), Ok(()));
|
||||
}
|
||||
|
||||
// https://blockchain.info/rawtx/02b082113e35d5386285094c2829e7e2963fa0b5369fb7f4b79c4c90877dcd3d
|
||||
|
@ -1995,17 +1996,18 @@ mod tests {
|
|||
fn test_check_transaction_multisig() {
|
||||
let tx: Transaction = "01000000013dcd7d87904c9cb7f4b79f36b5a03f96e2e729284c09856238d5353e1182b00200000000fd5e0100483045022100deeb1f13b5927b5e32d877f3c42a4b028e2e0ce5010fdb4e7f7b5e2921c1dcd2022068631cb285e8c1be9f061d2968a18c3163b780656f30a049effee640e80d9bff01483045022100ee80e164622c64507d243bd949217d666d8b16486e153ac6a1f8e04c351b71a502203691bef46236ca2b4f5e60a82a853a33d6712d6a1e7bf9a65e575aeb7328db8c014cc9524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353aeffffffff0130d90000000000001976a914569076ba39fc4ff6a2291d9ea9196d8c08f9c7ab88ac00000000".into();
|
||||
let signer: TransactionInputSigner = tx.into();
|
||||
let checker = TransactionSignatureChecker {
|
||||
let mut checker = TransactionSignatureChecker {
|
||||
signer: signer,
|
||||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: 0,
|
||||
cache: None,
|
||||
};
|
||||
let input: Script = "00483045022100deeb1f13b5927b5e32d877f3c42a4b028e2e0ce5010fdb4e7f7b5e2921c1dcd2022068631cb285e8c1be9f061d2968a18c3163b780656f30a049effee640e80d9bff01483045022100ee80e164622c64507d243bd949217d666d8b16486e153ac6a1f8e04c351b71a502203691bef46236ca2b4f5e60a82a853a33d6712d6a1e7bf9a65e575aeb7328db8c014cc9524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353ae".into();
|
||||
let output: Script = "a9141a8b0026343166625c7475f01e48b5ede8c0252e87".into();
|
||||
let flags = VerificationFlags::default()
|
||||
.verify_p2sh(true);
|
||||
assert_eq!(verify_script(&input, &output, &flags, &checker), Ok(()));
|
||||
assert_eq!(verify_script(&input, &output, &flags, &mut checker), Ok(()));
|
||||
}
|
||||
|
||||
// https://blockchain.info/en/tx/12b5633bad1f9c167d523ad1aa1947b2732a865bf5414eab2f9e5ae5d5c191ba?show_adv=true
|
||||
|
@ -2013,17 +2015,18 @@ mod tests {
|
|||
fn test_transaction_with_high_s_signature() {
|
||||
let tx: Transaction = "010000000173805864da01f15093f7837607ab8be7c3705e29a9d4a12c9116d709f8911e590100000049483045022052ffc1929a2d8bd365c6a2a4e3421711b4b1e1b8781698ca9075807b4227abcb0221009984107ddb9e3813782b095d0d84361ed4c76e5edaf6561d252ae162c2341cfb01ffffffff0200e1f50500000000434104baa9d36653155627c740b3409a734d4eaf5dcca9fb4f736622ee18efcf0aec2b758b2ec40db18fbae708f691edb2d4a2a3775eb413d16e2e3c0f8d4c69119fd1ac009ce4a60000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000".into();
|
||||
let signer: TransactionInputSigner = tx.into();
|
||||
let checker = TransactionSignatureChecker {
|
||||
let mut checker = TransactionSignatureChecker {
|
||||
signer: signer,
|
||||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: 0,
|
||||
cache: None,
|
||||
};
|
||||
let input: Script = "483045022052ffc1929a2d8bd365c6a2a4e3421711b4b1e1b8781698ca9075807b4227abcb0221009984107ddb9e3813782b095d0d84361ed4c76e5edaf6561d252ae162c2341cfb01".into();
|
||||
let output: Script = "410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac".into();
|
||||
let flags = VerificationFlags::default()
|
||||
.verify_p2sh(true);
|
||||
assert_eq!(verify_script(&input, &output, &flags, &checker), Ok(()));
|
||||
assert_eq!(verify_script(&input, &output, &flags, &mut checker), Ok(()));
|
||||
}
|
||||
|
||||
// https://blockchain.info/rawtx/fb0a1d8d34fa5537e461ac384bac761125e1bfa7fec286fa72511240fa66864d
|
||||
|
@ -2031,17 +2034,18 @@ mod tests {
|
|||
fn test_transaction_from_124276() {
|
||||
let tx: Transaction = "01000000012316aac445c13ff31af5f3d1e2cebcada83e54ba10d15e01f49ec28bddc285aa000000008e4b3048022200002b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602220000334a96676e58b1bb01784cb7c556dd8ce1c220171904da22e18fe1e7d1510db5014104d0fe07ff74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9ce769d43e94bd58c5c7e331a188922b3fe9ca1f5affffffff01c0c62d00000000001976a9147a2a3b481ca80c4ba7939c54d9278e50189d94f988ac00000000".into();
|
||||
let signer: TransactionInputSigner = tx.into();
|
||||
let checker = TransactionSignatureChecker {
|
||||
let mut checker = TransactionSignatureChecker {
|
||||
signer: signer,
|
||||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: 0,
|
||||
cache: None,
|
||||
};
|
||||
let input: Script = "4b3048022200002b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602220000334a96676e58b1bb01784cb7c556dd8ce1c220171904da22e18fe1e7d1510db5014104d0fe07ff74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a".into();
|
||||
let output: Script = "76a9147a2a3b481ca80c4ba7939c54d9278e50189d94f988ac".into();
|
||||
let flags = VerificationFlags::default()
|
||||
.verify_p2sh(true);
|
||||
assert_eq!(verify_script(&input, &output, &flags, &checker), Ok(()));
|
||||
assert_eq!(verify_script(&input, &output, &flags, &mut checker), Ok(()));
|
||||
}
|
||||
|
||||
// https://blockchain.info/rawtx/54fabd73f1d20c980a0686bf0035078e07f69c58437e4d586fb29aa0bee9814f
|
||||
|
@ -2049,16 +2053,17 @@ mod tests {
|
|||
fn test_arithmetic_correct_arguments_order() {
|
||||
let tx: Transaction = "01000000010c0e314bd7bb14721b3cfd8e487cd6866173354f87ca2cf4d13c8d3feb4301a6000000004a483045022100d92e4b61452d91a473a43cde4b469a472467c0ba0cbd5ebba0834e4f4762810402204802b76b7783db57ac1f61d2992799810e173e91055938750815b6d8a675902e014fffffffff0140548900000000001976a914a86e8ee2a05a44613904e18132e49b2448adc4e688ac00000000".into();
|
||||
let signer: TransactionInputSigner = tx.into();
|
||||
let checker = TransactionSignatureChecker {
|
||||
let mut checker = TransactionSignatureChecker {
|
||||
signer: signer,
|
||||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: 0,
|
||||
cache: None,
|
||||
};
|
||||
let input: Script = "483045022100d92e4b61452d91a473a43cde4b469a472467c0ba0cbd5ebba0834e4f4762810402204802b76b7783db57ac1f61d2992799810e173e91055938750815b6d8a675902e014f".into();
|
||||
let output: Script = "76009f69905160a56b210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71ad6c".into();
|
||||
let flags = VerificationFlags::default();
|
||||
assert_eq!(verify_script(&input, &output, &flags, &checker), Ok(()));
|
||||
assert_eq!(verify_script(&input, &output, &flags, &mut checker), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -31,7 +31,7 @@ pub use self::interpreter::{eval_script, verify_script};
|
|||
pub use self::opcode::Opcode;
|
||||
pub use self::num::Num;
|
||||
pub use self::script::{Script, ScriptType, ScriptAddress};
|
||||
pub use self::sign::{TransactionInputSigner, UnsignedTransactionInput};
|
||||
pub use self::sign::{SighashCache, TransactionInputSigner, UnsignedTransactionInput};
|
||||
pub use self::stack::Stack;
|
||||
pub use self::verify::{SignatureChecker, NoopSignatureChecker, TransactionSignatureChecker};
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ impl TransactionInputSigner {
|
|||
/// Pass None as input_index to compute transparent input signature
|
||||
pub fn signature_hash(
|
||||
&self,
|
||||
cache: &mut Option<SighashCache>,
|
||||
input_index: Option<usize>,
|
||||
input_amount: u64,
|
||||
script_pubkey: &Script,
|
||||
|
@ -162,6 +163,7 @@ impl TransactionInputSigner {
|
|||
match signature_version {
|
||||
SignatureVersion::Sprout => self.signature_hash_sprout(input_index, script_pubkey, sighashtype, sighash),
|
||||
SignatureVersion::Overwinter | SignatureVersion::Sapling => self.signature_hash_post_overwinter(
|
||||
cache,
|
||||
input_index,
|
||||
input_amount,
|
||||
script_pubkey,
|
||||
|
@ -246,6 +248,7 @@ impl TransactionInputSigner {
|
|||
/// Overwinter/sapling version of the signature.
|
||||
fn signature_hash_post_overwinter(
|
||||
&self,
|
||||
cache: &mut Option<SighashCache>,
|
||||
input_index: Option<usize>,
|
||||
input_amount: u64,
|
||||
script_pubkey: &Script,
|
||||
|
@ -254,21 +257,37 @@ impl TransactionInputSigner {
|
|||
consensus_branch_id: u32,
|
||||
sapling: bool,
|
||||
) -> H256 {
|
||||
let hash_prevouts = compute_hash_prevouts(sighash, &self.inputs);
|
||||
let hash_sequence = compute_hash_sequence(sighash, &self.inputs);
|
||||
let hash_outputs = compute_hash_outputs(sighash, input_index, &self.outputs);
|
||||
let hash_join_split = compute_hash_join_split(self.join_split.as_ref());
|
||||
// compute signature portions that can be reused for other inputs
|
||||
let hash_prevouts = cache.as_ref().map(|c| c.hash_prevouts)
|
||||
.unwrap_or_else(|| compute_hash_prevouts(sighash, &self.inputs));
|
||||
let hash_sequence = cache.as_ref().map(|c| c.hash_sequence)
|
||||
.unwrap_or_else(|| compute_hash_sequence(sighash, &self.inputs));
|
||||
let hash_outputs = compute_hash_outputs(cache, sighash, input_index, &self.outputs);
|
||||
let hash_join_split = cache.as_ref().map(|c| c.hash_join_split)
|
||||
.unwrap_or_else(|| compute_hash_join_split(self.join_split.as_ref()));
|
||||
let hash_sapling_spends = if sapling {
|
||||
compute_hash_sapling_spends(self.sapling.as_ref())
|
||||
cache.as_ref().map(|c| c.hash_sapling_spends)
|
||||
.unwrap_or_else(|| compute_hash_sapling_spends(self.sapling.as_ref()))
|
||||
} else {
|
||||
Default::default()
|
||||
0u8.into()
|
||||
};
|
||||
let hash_sapling_outputs = if sapling {
|
||||
compute_hash_sapling_outputs(self.sapling.as_ref())
|
||||
cache.as_ref().map(|c| c.hash_sapling_spends)
|
||||
.unwrap_or_else(|| compute_hash_sapling_outputs(self.sapling.as_ref()))
|
||||
} else {
|
||||
Default::default()
|
||||
0u8.into()
|
||||
};
|
||||
|
||||
// update cache
|
||||
*cache = Some(SighashCache {
|
||||
hash_prevouts,
|
||||
hash_sequence,
|
||||
hash_outputs,
|
||||
hash_join_split,
|
||||
hash_sapling_spends,
|
||||
hash_sapling_outputs,
|
||||
});
|
||||
|
||||
let mut personalization = [0u8; 16];
|
||||
personalization[..12].copy_from_slice(b"ZcashSigHash");
|
||||
LittleEndian::write_u32(&mut personalization[12..], consensus_branch_id);
|
||||
|
@ -352,16 +371,24 @@ fn compute_hash_sequence(sighash: Sighash, inputs: &[UnsignedTransactionInput])
|
|||
}
|
||||
}
|
||||
|
||||
fn compute_hash_outputs(sighash: Sighash, input_index: Option<usize>, outputs: &[TransactionOutput]) -> H256 {
|
||||
fn compute_hash_outputs(
|
||||
cache: &mut Option<SighashCache>,
|
||||
sighash: Sighash,
|
||||
input_index: Option<usize>,
|
||||
outputs: &[TransactionOutput]
|
||||
) -> H256 {
|
||||
const PERSONALIZATION: &'static [u8; 16] = b"ZcashOutputsHash";
|
||||
|
||||
match (sighash.base, input_index) {
|
||||
(SighashBase::All, _) => {
|
||||
let mut stream = Stream::default();
|
||||
for output in outputs {
|
||||
stream.append(output);
|
||||
}
|
||||
blake2b_personal(PERSONALIZATION, &stream.out())
|
||||
cache.as_ref().map(|c| c.hash_outputs)
|
||||
.unwrap_or_else(|| {
|
||||
let mut stream = Stream::default();
|
||||
for output in outputs {
|
||||
stream.append(output);
|
||||
}
|
||||
blake2b_personal(PERSONALIZATION, &stream.out())
|
||||
})
|
||||
},
|
||||
(SighashBase::Single, Some(input_index)) if input_index < outputs.len() => {
|
||||
let mut stream = Stream::default();
|
||||
|
@ -479,7 +506,8 @@ mod tests {
|
|||
sapling: None,
|
||||
};
|
||||
|
||||
let hash = input_signer.signature_hash(Some(0), 0, &previous_output, SighashBase::All.into(), 0);
|
||||
let mut cache = None;
|
||||
let hash = input_signer.signature_hash(&mut cache, Some(0), 0, &previous_output, SighashBase::All.into(), 0);
|
||||
assert_eq!(hash, expected_signature_hash);
|
||||
}
|
||||
|
||||
|
@ -508,8 +536,9 @@ mod tests {
|
|||
let expected: H256 = result.parse().unwrap();
|
||||
let expected = expected.reversed();
|
||||
|
||||
let mut cache = None;
|
||||
let input_index = if input_index as u64 == ::std::u64::MAX { None } else { Some(input_index) };
|
||||
let hash = signer.signature_hash(input_index, 0, &script, hash_type as u32, consensus_branch_id);
|
||||
let hash = signer.signature_hash(&mut cache, input_index, 0, &script, hash_type as u32, consensus_branch_id);
|
||||
if expected != hash {
|
||||
panic!("Test#{} of {:?} sighash failed: expected {}, got {}", idx, signer.signature_version(), expected, hash);
|
||||
} else {
|
||||
|
|
|
@ -3,7 +3,7 @@ use chain::constants::{
|
|||
SEQUENCE_FINAL, SEQUENCE_LOCKTIME_DISABLE_FLAG,
|
||||
SEQUENCE_LOCKTIME_MASK, SEQUENCE_LOCKTIME_TYPE_FLAG, LOCKTIME_THRESHOLD
|
||||
};
|
||||
use {Script, TransactionInputSigner, Num};
|
||||
use {Script, SighashCache, TransactionInputSigner, Num};
|
||||
|
||||
/// Checks transaction signature
|
||||
pub trait SignatureChecker {
|
||||
|
@ -15,7 +15,7 @@ pub trait SignatureChecker {
|
|||
) -> bool;
|
||||
|
||||
fn check_signature(
|
||||
&self,
|
||||
&mut self,
|
||||
signature: &Signature,
|
||||
public: &Public,
|
||||
script_code: &Script,
|
||||
|
@ -34,7 +34,7 @@ impl SignatureChecker for NoopSignatureChecker {
|
|||
public.verify(hash, signature).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn check_signature(&self, _: &Signature, _: &Public, _: &Script, _: u32) -> bool {
|
||||
fn check_signature(&mut self, _: &Signature, _: &Public, _: &Script, _: u32) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,7 @@ pub struct TransactionSignatureChecker {
|
|||
pub input_index: usize,
|
||||
pub input_amount: u64,
|
||||
pub consensus_branch_id: u32,
|
||||
pub cache: Option<SighashCache>,
|
||||
}
|
||||
|
||||
impl SignatureChecker for TransactionSignatureChecker {
|
||||
|
@ -66,13 +67,14 @@ impl SignatureChecker for TransactionSignatureChecker {
|
|||
}
|
||||
|
||||
fn check_signature(
|
||||
&self,
|
||||
&mut self,
|
||||
signature: &Signature,
|
||||
public: &Public,
|
||||
script_code: &Script,
|
||||
sighashtype: u32,
|
||||
) -> bool {
|
||||
let hash = self.signer.signature_hash(
|
||||
&mut self.cache,
|
||||
Some(self.input_index),
|
||||
self.input_amount,
|
||||
script_code,
|
||||
|
|
|
@ -358,6 +358,7 @@ impl<'a> TransactionEval<'a> {
|
|||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: self.consensus_branch_id,
|
||||
cache: None,
|
||||
};
|
||||
|
||||
for (index, input) in self.transaction.raw.inputs.iter().enumerate() {
|
||||
|
@ -390,7 +391,7 @@ impl<'a> TransactionEval<'a> {
|
|||
.verify_sigpushonly(self.verify_sigpushonly)
|
||||
.verify_cleanstack(self.verify_cleanstack);
|
||||
|
||||
verify_script(&input, &output, &flags, &checker)
|
||||
verify_script(&input, &output, &flags, &mut checker)
|
||||
.map_err(|e| TransactionError::Signature(index, e))?;
|
||||
}
|
||||
|
||||
|
@ -560,15 +561,16 @@ mod tests {
|
|||
|
||||
let signer: TransactionInputSigner = spending_tx.into();
|
||||
|
||||
let checker = TransactionSignatureChecker {
|
||||
let mut checker = TransactionSignatureChecker {
|
||||
signer: signer,
|
||||
input_index: 0,
|
||||
input_amount: 0,
|
||||
consensus_branch_id: 0,
|
||||
cache: None,
|
||||
};
|
||||
|
||||
let flags = VerificationFlags::default()
|
||||
.verify_p2sh(true);
|
||||
assert_eq!(verify_script(&input_script, &output_script, &flags, &checker), Ok(()));
|
||||
assert_eq!(verify_script(&input_script, &output_script, &flags, &mut checker), Ok(()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue