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(())
}
fn is_defined_hashtype_signature(sig: &[u8]) -> bool {
fn is_defined_hashtype_signature(version: SignatureVersion, sig: &[u8]) -> bool {
if sig.is_empty() {
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
// 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));
}
if flags.verify_strictenc && !is_defined_hashtype_signature(sig) {
if flags.verify_strictenc && !is_defined_hashtype_signature(version, sig) {
Err(Error::SignatureHashtype)
} else {
Ok(())
@ -778,7 +778,7 @@ pub fn eval_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));
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 sig = sigs[s].clone();
try!(check_signature_encoding(&sig, flags));
try!(check_signature_encoding(&sig, flags, version));
try!(check_pubkey_encoding(&key, flags));
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 {
pub fn new(base: SighashBase, anyone_can_pay: bool, fork_id: bool) -> Self {
Sighash {
@ -76,36 +64,32 @@ impl Sighash {
}
}
pub fn is_defined(u: u32) -> bool {
// fork id must be zero
if u & 0x40 == 0x40 && u & 0xFFFFFF00 != 0 {
return false;
}
/// Used by SCRIPT_VERIFY_STRICTENC
pub fn is_defined(version: SignatureVersion, u: u32) -> bool {
// reset anyone_can_pay && fork_id (if applicable) bits
let u = match version {
SignatureVersion::ForkId => u & !(0x40 | 0x80),
_ => u & !(0x80),
};
// use 0xdf istead of 0x1f to catch 0x40 | 0x80
match u & 0xdf {
1 | 2 | 3 |
0x81 | 0x82 | 0x83 |
0x41 | 0x42 | 0x43 |
0xc1 | 0xc2 | 0xc3 => true,
x if x & 0x80 == 0x80 => true,
x if x & 0x40 == 0x40 => true,
// Only exact All | None | Single values are passing this check
match u {
1 | 2 | 3 => true,
_ => 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 fork_id = (u & 0x40) == 0x40;
let fork_id = version == SignatureVersion::ForkId && (u & 0x40) == 0x40;
let base = match u & 0x1f {
2 => SighashBase::None,
3 => SighashBase::Single,
1 => SighashBase::All,
_ if anyone_can_pay || fork_id => SighashBase::All,
_ => return None,
1 | _ => SighashBase::All,
};
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 {
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() {
return 1u8.into();
}
@ -154,9 +138,9 @@ impl TransactionInputSigner {
return 1u8.into();
}
match sighash.fork_id {
true if sigversion == SignatureVersion::ForkId => self.signature_hash_fork_id(input_index, input_amount, script_pubkey, sighashtype, sighash),
false if sigversion == SignatureVersion::Base => self.signature_hash_original(input_index, script_pubkey, sighashtype, sighash),
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),
_ => 1u8.into(),
}
}
@ -365,7 +349,8 @@ mod tests {
let script: Script = script.into();
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);
}
@ -877,8 +862,17 @@ mod tests {
#[test]
fn test_sighash_forkid_from_u32() {
assert!(!Sighash::is_defined(0b11111111111111111111111101000010)); // non-zero fork id
assert!(!Sighash::is_defined(0b00000000000000000000000101000010)); // non-zero fork id
assert!(Sighash::is_defined(0b00000000000000000000000001000010)); // zero fork id
assert!(!Sighash::is_defined(SignatureVersion::Base, 0xFFFFFF82));
assert!(!Sighash::is_defined(SignatureVersion::Base, 0x00000182));
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));
}
}