fix build && fix fork_id strict check

This commit is contained in:
Svyatoslav Nikolsky 2017-08-09 17:34:23 +03:00
parent 333edfd257
commit a338b4d5df
2 changed files with 39 additions and 45 deletions

View File

@ -149,15 +149,15 @@ fn is_low_der_signature(sig: &[u8]) -> Result<(), Error> {
Ok(()) Ok(())
} }
fn is_defined_hashtype_signature(sig: &[u8]) -> bool { fn is_defined_hashtype_signature(version: SignatureVersion, sig: &[u8]) -> bool {
if sig.is_empty() { if sig.is_empty() {
return false; return false;
} }
Sighash::is_defined(sig[sig.len() -1] as u32) Sighash::is_defined(version, sig[sig.len() -1] as u32)
} }
fn check_signature_encoding(sig: &[u8], flags: &VerificationFlags) -> Result<(), Error> { fn check_signature_encoding(sig: &[u8], flags: &VerificationFlags, version: SignatureVersion) -> Result<(), Error> {
// Empty signature. Not strictly DER encoded, but allowed to provide a // Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
@ -173,7 +173,7 @@ fn check_signature_encoding(sig: &[u8], flags: &VerificationFlags) -> Result<(),
try!(is_low_der_signature(sig)); try!(is_low_der_signature(sig));
} }
if flags.verify_strictenc && !is_defined_hashtype_signature(sig) { if flags.verify_strictenc && !is_defined_hashtype_signature(version, sig) {
Err(Error::SignatureHashtype) Err(Error::SignatureHashtype)
} else { } else {
Ok(()) Ok(())
@ -778,7 +778,7 @@ pub fn eval_script(
subscript = subscript.find_and_delete(&*signature_script); subscript = subscript.find_and_delete(&*signature_script);
} }
try!(check_signature_encoding(&signature, flags)); try!(check_signature_encoding(&signature, flags, version));
try!(check_pubkey_encoding(&pubkey, flags)); try!(check_pubkey_encoding(&pubkey, flags));
let success = check_signature(checker, signature.into(), pubkey.into(), &subscript, version); let success = check_signature(checker, signature.into(), pubkey.into(), &subscript, version);
@ -830,7 +830,7 @@ pub fn eval_script(
let key = keys[k].clone(); let key = keys[k].clone();
let sig = sigs[s].clone(); let sig = sigs[s].clone();
try!(check_signature_encoding(&sig, flags)); try!(check_signature_encoding(&sig, flags, version));
try!(check_pubkey_encoding(&key, flags)); try!(check_pubkey_encoding(&key, flags));
let ok = check_signature(checker, sig.into(), key.into(), &subscript, version); let ok = check_signature(checker, sig.into(), key.into(), &subscript, version);

View File

@ -55,18 +55,6 @@ impl From<Sighash> for u32 {
} }
} }
impl From<u32> for Sighash {
fn from(u: u32) -> Self {
Sighash::new(match u & 0x1f {
2 => SighashBase::None,
3 => SighashBase::Single,
1 | _ => SighashBase::All,
},
u & 0x80 == 0x80,
u & 0x40 == 0x40 && u & 0xFFFFFF00 == 0)
}
}
impl Sighash { impl Sighash {
pub fn new(base: SighashBase, anyone_can_pay: bool, fork_id: bool) -> Self { pub fn new(base: SighashBase, anyone_can_pay: bool, fork_id: bool) -> Self {
Sighash { Sighash {
@ -76,36 +64,32 @@ impl Sighash {
} }
} }
pub fn is_defined(u: u32) -> bool { /// Used by SCRIPT_VERIFY_STRICTENC
// fork id must be zero pub fn is_defined(version: SignatureVersion, u: u32) -> bool {
if u & 0x40 == 0x40 && u & 0xFFFFFF00 != 0 { // reset anyone_can_pay && fork_id (if applicable) bits
return false; let u = match version {
} SignatureVersion::ForkId => u & !(0x40 | 0x80),
_ => u & !(0x80),
};
// use 0xdf istead of 0x1f to catch 0x40 | 0x80 // Only exact All | None | Single values are passing this check
match u & 0xdf { match u {
1 | 2 | 3 | 1 | 2 | 3 => true,
0x81 | 0x82 | 0x83 |
0x41 | 0x42 | 0x43 |
0xc1 | 0xc2 | 0xc3 => true,
x if x & 0x80 == 0x80 => true,
x if x & 0x40 == 0x40 => true,
_ => false, _ => false,
} }
} }
pub fn from_u32(u: u32) -> Option<Self> { /// Creates Sighash from any u, even if is_defined() == false
pub fn from_u32(version: SignatureVersion, u: u32) -> Self {
let anyone_can_pay = (u & 0x80) == 0x80; let anyone_can_pay = (u & 0x80) == 0x80;
let fork_id = (u & 0x40) == 0x40; let fork_id = version == SignatureVersion::ForkId && (u & 0x40) == 0x40;
let base = match u & 0x1f { let base = match u & 0x1f {
2 => SighashBase::None, 2 => SighashBase::None,
3 => SighashBase::Single, 3 => SighashBase::Single,
1 => SighashBase::All, 1 | _ => SighashBase::All,
_ if anyone_can_pay || fork_id => SighashBase::All,
_ => return None,
}; };
Some(Sighash::new(base, anyone_can_pay, fork_id)) Sighash::new(base, anyone_can_pay, fork_id)
} }
} }
@ -145,7 +129,7 @@ impl From<Transaction> for TransactionInputSigner {
impl TransactionInputSigner { impl TransactionInputSigner {
pub fn signature_hash(&self, input_index: usize, input_amount: u64, script_pubkey: &Script, sigversion: SignatureVersion, sighashtype: u32) -> H256 { pub fn signature_hash(&self, input_index: usize, input_amount: u64, script_pubkey: &Script, sigversion: SignatureVersion, sighashtype: u32) -> H256 {
let sighash = Sighash::from(sighashtype); let sighash = Sighash::from_u32(sigversion, sighashtype);
if input_index >= self.inputs.len() { if input_index >= self.inputs.len() {
return 1u8.into(); return 1u8.into();
} }
@ -154,9 +138,9 @@ impl TransactionInputSigner {
return 1u8.into(); return 1u8.into();
} }
match sighash.fork_id { match sigversion {
true if sigversion == SignatureVersion::ForkId => self.signature_hash_fork_id(input_index, input_amount, script_pubkey, sighashtype, sighash), SignatureVersion::Base => self.signature_hash_original(input_index, script_pubkey, sighashtype, sighash),
false if 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),
_ => 1u8.into(), _ => 1u8.into(),
} }
} }
@ -365,7 +349,8 @@ mod tests {
let script: Script = script.into(); let script: Script = script.into();
let expected = H256::from_reversed_str(result); let expected = H256::from_reversed_str(result);
let hash = signer.signature_hash_original(input_index, &script, hash_type as u32, (hash_type as u32).into()); let sighash = Sighash::from_u32(SignatureVersion::Base, hash_type as u32);
let hash = signer.signature_hash_original(input_index, &script, hash_type as u32, sighash);
assert_eq!(expected, hash); assert_eq!(expected, hash);
} }
@ -877,8 +862,17 @@ mod tests {
#[test] #[test]
fn test_sighash_forkid_from_u32() { fn test_sighash_forkid_from_u32() {
assert!(!Sighash::is_defined(0b11111111111111111111111101000010)); // non-zero fork id assert!(!Sighash::is_defined(SignatureVersion::Base, 0xFFFFFF82));
assert!(!Sighash::is_defined(0b00000000000000000000000101000010)); // non-zero fork id assert!(!Sighash::is_defined(SignatureVersion::Base, 0x00000182));
assert!(Sighash::is_defined(0b00000000000000000000000001000010)); // zero fork id assert!(!Sighash::is_defined(SignatureVersion::Base, 0x00000080));
assert!( Sighash::is_defined(SignatureVersion::Base, 0x00000001));
assert!( Sighash::is_defined(SignatureVersion::Base, 0x00000082));
assert!( Sighash::is_defined(SignatureVersion::Base, 0x00000003));
assert!(!Sighash::is_defined(SignatureVersion::ForkId, 0xFFFFFFC2));
assert!(!Sighash::is_defined(SignatureVersion::ForkId, 0x000001C2));
assert!( Sighash::is_defined(SignatureVersion::ForkId, 0x00000081));
assert!( Sighash::is_defined(SignatureVersion::ForkId, 0x000000C2));
assert!( Sighash::is_defined(SignatureVersion::ForkId, 0x00000043));
} }
} }