vm: fix CHECKMULTISIG to comply with NEO VM implementation

Testing with testnet quickly revealed that our code has an issue when the key
count doesn't equal signature count, fix it and add some comments.
This commit is contained in:
Roman Khimov 2019-09-30 16:52:35 +03:00
parent fac778d3dd
commit c3591d8897

View file

@ -907,6 +907,8 @@ func (v *VM) execute(ctx *Context, op Instruction) {
if err != nil { if err != nil {
panic(fmt.Sprintf("wrong parameters: %s", err.Error())) panic(fmt.Sprintf("wrong parameters: %s", err.Error()))
} }
// It's ok to have more keys than there are signatures (it would
// just mean that some keys didn't sign), but not the other way around.
if len(pkeys) < len(sigs) { if len(pkeys) < len(sigs) {
panic("more signatures than there are keys") panic("more signatures than there are keys")
} }
@ -914,18 +916,24 @@ func (v *VM) execute(ctx *Context, op Instruction) {
panic("VM is not set up properly for signature checks") panic("VM is not set up properly for signature checks")
} }
sigok := true sigok := true
// j counts keys and i counts signatures.
j := 0 j := 0
for i := 0; sigok && i < len(pkeys) && j < len(sigs); { for i := 0; sigok && j < len(pkeys) && i < len(sigs); {
pkey := &keys.PublicKey{} pkey := &keys.PublicKey{}
err := pkey.DecodeBytes(pkeys[j]) err := pkey.DecodeBytes(pkeys[j])
if err != nil { if err != nil {
panic(err.Error()) panic(err.Error())
} }
// We only move to the next signature if the check was
// successful, but if it's not maybe the next key will
// fit, so we always move to the next key.
if pkey.Verify(sigs[i], v.checkhash) { if pkey.Verify(sigs[i], v.checkhash) {
i++ i++
} }
j++ j++
if len(pkeys)-i > len(sigs)-j { // When there are more signatures left to check than
// there are keys the check won't successed for sure.
if len(sigs)-i > len(pkeys)-j {
sigok = false sigok = false
} }
} }