vm: leave single CHECKMULTISIG implementation

Remove sequential implementation and benchmarks.
They will be still present in commit history.
This commit is contained in:
Evgenii Stratonikov 2020-02-05 17:14:18 +03:00
parent 02a5e036fc
commit 2a86149c82
2 changed files with 1 additions and 126 deletions

View file

@ -84,8 +84,6 @@ type VM struct {
// Public keys cache.
keys map[string]*keys.PublicKey
checkMultisig func(*VM, [][]byte, [][]byte) bool
}
// New returns a new VM object ready to load .avm bytecode scripts.
@ -1223,13 +1221,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
panic("VM is not set up properly for signature checks")
}
var sigok bool
if v.checkMultisig == nil {
sigok = checkMultisigPar(v, pkeys, sigs)
} else {
sigok = v.checkMultisig(v, pkeys, sigs)
}
sigok := checkMultisigPar(v, pkeys, sigs)
v.estack.PushVal(sigok)
case opcode.NEWMAP:
@ -1523,30 +1515,6 @@ func checkMultisig1(v *VM, pkeys [][]byte, sig []byte) bool {
return false
}
func checkMultisigSeq(v *VM, pkeys [][]byte, sigs [][]byte) bool {
// j counts keys and i counts signatures.
j := 0
for i := 0; j < len(pkeys) && i < len(sigs); {
pkey := v.bytesToPublicKey(pkeys[j])
// 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) {
i++
}
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 {
return false
}
}
return true
}
func cloneIfStruct(item StackItem) StackItem {
switch it := item.(type) {
case *StructItem:

View file

@ -2790,99 +2790,6 @@ func TestCHECKMULTISIGBad(t *testing.T) {
t.Run("3_2 duplicate sig", func(t *testing.T) { testCHECKMULTISIGBad(t, 3, nil, []int{0, 0}) })
}
func benchCHECKMULTISIG(b *testing.B, size int, is [][]int, check func(*VM, [][]byte, [][]byte) bool) {
prog := makeProgram(opcode.CHECKMULTISIG)
msg := []byte("NEO - An Open Network For Smart Economy")
h := hash.Sha256(msg).BytesBE()
pubs, sigs, keyMap, err := initCHECKMULTISIG(msg, size)
if err != nil {
b.Fatalf("error on initialize: %v", err)
}
sigsStack := make([][]StackItem, 0, len(is))
for i := range is {
sigsStack = append(sigsStack, subSlice(sigs, is[i]))
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for j := range sigsStack {
vm := load(prog)
vm.SetCheckedHash(h)
vm.SetPublicKeys(keyMap)
vm.checkMultisig = check
vm.estack.PushVal(sigsStack[j])
vm.estack.PushVal(pubs)
_ = vm.Run()
}
}
}
func BenchmarkCHECKMULTISIG(b *testing.B) {
fs := []struct {
name string
f func(*VM, [][]byte, [][]byte) bool
}{
{"seq", checkMultisigSeq},
{"par", checkMultisigPar},
}
b.Run("4_3 start", func(b *testing.B) {
for i := range fs {
b.Run(fs[i].name, func(b *testing.B) {
benchCHECKMULTISIG(b, 4, [][]int{{0, 1, 2}}, fs[i].f)
})
}
})
b.Run("4_3 all", func(b *testing.B) {
for i := range fs {
b.Run(fs[i].name, func(b *testing.B) {
benchCHECKMULTISIG(b, 4, combinations(4, 3), fs[i].f)
})
}
})
b.Run("7_5 start", func(b *testing.B) {
for i := range fs {
b.Run(fs[i].name, func(b *testing.B) {
benchCHECKMULTISIG(b, 7, [][]int{{0, 1, 2, 3, 4}}, fs[i].f)
})
}
})
b.Run("7_5 all", func(b *testing.B) {
for i := range fs {
b.Run(fs[i].name, func(b *testing.B) {
benchCHECKMULTISIG(b, 7, combinations(7, 5), fs[i].f)
})
}
})
}
func combinations(n, k int) [][]int {
if n < k {
return nil
} else if k == 0 {
return [][]int{{}}
} else if n == k {
res := make([]int, k)
for i := 0; i < k; i++ {
res[i] = i
}
return [][]int{res}
}
result := combinations(n-1, k)
for _, c := range combinations(n-1, k-1) {
result = append(result, append(c, n-1))
}
return result
}
func TestSWAPGood(t *testing.T) {
prog := makeProgram(opcode.SWAP)
vm := load(prog)