forked from TrueCloudLab/neoneo-go
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:
parent
fac778d3dd
commit
c3591d8897
1 changed files with 10 additions and 2 deletions
12
pkg/vm/vm.go
12
pkg/vm/vm.go
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue