FORKID sighash fixes

This commit is contained in:
Svyatoslav Nikolsky 2017-08-15 11:26:09 +03:00
parent 8008885a80
commit 78bd3e5485
4 changed files with 28 additions and 7 deletions

View File

@ -40,6 +40,8 @@ pub enum Error {
// BIP62
SignatureHashtype,
SignatureDer,
SignatureIllegalForkId,
SignatureMustUseForkId,
Minimaldata,
SignaturePushOnly,
SignatureHighS,
@ -88,6 +90,8 @@ impl fmt::Display for Error {
// BIP62
Error::SignatureHashtype => "Invalid Signature Hashtype".fmt(f),
Error::SignatureDer => "Invalid Signature".fmt(f),
Error::SignatureIllegalForkId => "Illegal use of SIGHASH_FORKID".fmt(f),
Error::SignatureMustUseForkId => "Signature must use SIGHASH_FORKID".fmt(f),
Error::Minimaldata => "Check minimaldata failed".fmt(f),
Error::SignaturePushOnly => "Only push opcodes are allowed in this signature".fmt(f),
Error::SignatureHighS => "Invalid High S in Signature".fmt(f),

View File

@ -154,7 +154,11 @@ fn is_defined_hashtype_signature(version: SignatureVersion, sig: &[u8]) -> bool
return false;
}
Sighash::is_defined(version, sig[sig.len() -1] as u32)
Sighash::is_defined(version, sig[sig.len() - 1] as u32)
}
fn parse_hash_type(version: SignatureVersion, sig: &[u8]) -> Sighash {
Sighash::from_u32(version, if sig.is_empty() { 0 } else { sig[sig.len() - 1] as u32 })
}
fn check_signature_encoding(sig: &[u8], flags: &VerificationFlags, version: SignatureVersion) -> Result<(), Error> {
@ -174,10 +178,21 @@ fn check_signature_encoding(sig: &[u8], flags: &VerificationFlags, version: Sign
}
if flags.verify_strictenc && !is_defined_hashtype_signature(version, sig) {
Err(Error::SignatureHashtype)
} else {
Ok(())
return Err(Error::SignatureHashtype)
}
// verify_strictenc is currently enabled for BitcoinCash only
if flags.verify_strictenc {
let uses_fork_id = parse_hash_type(version, sig).fork_id;
let enabled_fork_id = version == SignatureVersion::ForkId;
if uses_fork_id && !enabled_fork_id {
return Err(Error::SignatureIllegalForkId)
} else if !uses_fork_id && enabled_fork_id {
return Err(Error::SignatureMustUseForkId);
}
}
Ok(())
}
fn check_pubkey_encoding(v: &[u8], flags: &VerificationFlags) -> Result<(), Error> {
@ -772,8 +787,9 @@ pub fn eval_script(
Opcode::OP_CHECKSIG | Opcode::OP_CHECKSIGVERIFY => {
let pubkey = try!(stack.pop());
let signature = try!(stack.pop());
let sighash = parse_hash_type(version, &signature);
let mut subscript = script.subscript(begincode);
if version == SignatureVersion::Base {
if version != SignatureVersion::ForkId || !sighash.fork_id {
let signature_script = Builder::default().push_data(&*signature).into_script();
subscript = subscript.find_and_delete(&*signature_script);
}

View File

@ -141,8 +141,8 @@ impl TransactionInputSigner {
}
match sigversion {
SignatureVersion::Base => self.signature_hash_original(input_index, script_pubkey, sighashtype, sighash),
SignatureVersion::ForkId if sighash.fork_id => self.signature_hash_fork_id(input_index, input_amount, script_pubkey, sighashtype, sighash),
SignatureVersion::Base | SignatureVersion::ForkId => self.signature_hash_original(input_index, script_pubkey, sighashtype, sighash),
_ => 1u8.into(),
}
}
@ -275,7 +275,7 @@ impl TransactionInputSigner {
stream.append(&hash_prevouts);
stream.append(&hash_sequence);
stream.append(&self.inputs[input_index].previous_output);
stream.append_slice(&**script_pubkey);
stream.append_list(&**script_pubkey);
stream.append(&input_amount);
stream.append(&self.inputs[input_index].sequence);
stream.append(&hash_outputs);

View File

@ -38,6 +38,7 @@ impl SignatureChecker for NoopSignatureChecker {
}
}
#[derive(Debug)]
pub struct TransactionSignatureChecker {
pub signer: TransactionInputSigner,
pub input_index: usize,