FORKID sighash fixes
This commit is contained in:
parent
8008885a80
commit
78bd3e5485
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -38,6 +38,7 @@ impl SignatureChecker for NoopSignatureChecker {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TransactionSignatureChecker {
|
||||
pub signer: TransactionInputSigner,
|
||||
pub input_index: usize,
|
||||
|
|
Loading…
Reference in New Issue