Skip to content

Commit

Permalink
fix multisig opcode
Browse files Browse the repository at this point in the history
  • Loading branch information
bloomingpeach committed Oct 5, 2024
1 parent 50155da commit 1347ddf
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 24 deletions.
36 changes: 24 additions & 12 deletions packages/engine/src/opcodes/crypto.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,22 @@ pub fn opcode_checksig<
>(
ref engine: Engine<T>
) -> Result<(), felt252> {

let pk_bytes = engine.dstack.pop_byte_array()?;
let full_sig_bytes = engine.dstack.pop_byte_array()?;

if full_sig_bytes.len() < 1 || pk_bytes.len() < 1 {
if full_sig_bytes.len() < 1 {
engine.dstack.push_bool(false);
return Result::Ok(());
}


// TODO: add witness context inside engine to check if witness is active
// if witness is active use BaseSigVerifier
let mut is_valid: bool = false;

let res = BaseSigVerifierTrait::new(ref engine, @full_sig_bytes, @pk_bytes);

if res.is_err() {
// TODO: Some errors can return an error code instead of pushing false?
if res.unwrap_err() == Error::SCRIPT_ERR_SIG_DER {
Expand Down Expand Up @@ -151,6 +154,9 @@ pub fn opcode_checkmultisig<
) -> Result<(), felt252> {
// TODO Error on taproot exec


let strict_encoding = engine.has_flag(ScriptFlags::ScriptVerifyStrictEncoding)
|| engine.has_flag(ScriptFlags::ScriptVerifyDERSignatures);
// Get number of public keys and construct array
let num_keys = engine.dstack.pop_int()?;
let mut num_pub_keys: i64 = ScriptNum::to_int32(num_keys).into();
Expand Down Expand Up @@ -236,36 +242,42 @@ pub fn opcode_checkmultisig<
if sig.len() == 0 {
continue;
}

let res = signature::parse_base_sig_and_pk(ref engine, pub_key, sig);
if res.is_err() {
success = false;
err = res.unwrap_err();
break;
}

let (parsed_pub_key, parsed_sig, hash_type) = res.unwrap();
let sig_hash: u256 = sighash::calc_signature_hash(
@script, hash_type, ref engine.transaction, engine.tx_idx
);

if is_valid_signature(sig_hash, parsed_sig.r, parsed_sig.s, parsed_pub_key) {
sig_idx += 1;
num_sigs -= 1;
}
}
};

if err != 0 {
return Result::Err(err);
}

if !success && engine.has_flag(ScriptFlags::ScriptVerifyNullFail) {
let mut err = '';
for s in sigs {
if s.len() > 0 {
err = Error::SIG_NULLFAIL;
break;
if !success {
if engine.has_flag(ScriptFlags::ScriptVerifyNullFail) {
let mut err = '';
for s in sigs {
if s.len() > 0 {
err = Error::SIG_NULLFAIL;
break;
}
};
if err != '' {
return Result::Err(err);
}
};
if err != '' {
return Result::Err(err);
} else if strict_encoding {
return Result::Err(Error::SCRIPT_ERR_SIG_DER);
}
}

Expand Down
59 changes: 47 additions & 12 deletions packages/engine/src/signature/signature.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ impl BaseSigVerifierImpl<
fn new(
ref vm: Engine<T>, sig_bytes: @ByteArray, pk_bytes: @ByteArray
) -> Result<BaseSigVerifier, felt252> {

let mut sub_script = vm.sub_script();
sub_script = remove_signature(sub_script, sig_bytes);
let (pub_key, sig, hash_type) = parse_base_sig_and_pk(ref vm, pk_bytes, sig_bytes)?;
Expand Down Expand Up @@ -373,26 +374,60 @@ pub fn parse_signature(sig_bytes: @ByteArray) -> Result<Signature, felt252> {
pub fn parse_base_sig_and_pk<T, +Drop<T>>(
ref vm: Engine<T>, pk_bytes: @ByteArray, sig_bytes: @ByteArray
) -> Result<(Secp256k1Point, Signature, u32), felt252> {
let strict_encoding = vm.has_flag(ScriptFlags::ScriptVerifyStrictEncoding)
|| vm.has_flag(ScriptFlags::ScriptVerifyDERSignatures);
if sig_bytes.len() == 0 {
return Result::Err('empty signature');
return if strict_encoding {
Result::Err(Error::SCRIPT_ERR_SIG_DER)
} else {
Result::Err('empty signature')
};
}

// TODO: strct encoding
let hash_type_offset: usize = sig_bytes.len() - 1;
let hash_type: u32 = sig_bytes[hash_type_offset].into();

check_hash_type_encoding(ref vm, hash_type)?;
let strict_encoding = vm.has_flag(ScriptFlags::ScriptVerifyStrictEncoding)
|| vm.has_flag(ScriptFlags::ScriptVerifyDERSignatures);
let res = check_signature_encoding(ref vm, sig_bytes, strict_encoding);
if strict_encoding && res.is_err() {
return Result::Err(Error::SCRIPT_ERR_SIG_DER);
} else if res.is_err() {
return Result::Err(res.unwrap_err());
if let Result::Err(e) = check_hash_type_encoding(ref vm, hash_type) {
return if strict_encoding {
Result::Err(Error::SCRIPT_ERR_SIG_DER)
} else {
Result::Err(e)
};
}
if let Result::Err(e) = check_signature_encoding(ref vm, sig_bytes, strict_encoding) {
return if strict_encoding {
Result::Err(Error::SCRIPT_ERR_SIG_DER)
} else {
Result::Err(e)
};
}

if let Result::Err(e) = check_pub_key_encoding(ref vm, pk_bytes) {
return if strict_encoding {
Result::Err(Error::SCRIPT_ERR_SIG_DER)
} else {
Result::Err(e)
};
}

let pub_key = match parse_pub_key(pk_bytes) {
Result::Ok(key) => key,
Result::Err(e) => if strict_encoding {
return Result::Err(Error::SCRIPT_ERR_SIG_DER);
} else {
return Result::Err(e);
},
};
check_pub_key_encoding(ref vm, pk_bytes)?;

let pub_key = parse_pub_key(pk_bytes)?;
let sig = parse_signature(sig_bytes)?;
let sig = match parse_signature(sig_bytes) {
Result::Ok(signature) => signature,
Result::Err(e) => if strict_encoding {
return Result::Err(Error::SCRIPT_ERR_SIG_DER);
} else {
return Result::Err(e);
},
};

Result::Ok((pub_key, sig, hash_type))
}
Expand Down

0 comments on commit 1347ddf

Please sign in to comment.