forked from TrueCloudLab/neoneo-go
vm: leave single CHECKMULTISIG implementation
Remove sequential implementation and benchmarks. They will be still present in commit history.
This commit is contained in:
parent
02a5e036fc
commit
2a86149c82
2 changed files with 1 additions and 126 deletions
34
pkg/vm/vm.go
34
pkg/vm/vm.go
|
@ -84,8 +84,6 @@ type VM struct {
|
||||||
|
|
||||||
// Public keys cache.
|
// Public keys cache.
|
||||||
keys map[string]*keys.PublicKey
|
keys map[string]*keys.PublicKey
|
||||||
|
|
||||||
checkMultisig func(*VM, [][]byte, [][]byte) bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new VM object ready to load .avm bytecode scripts.
|
// 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")
|
panic("VM is not set up properly for signature checks")
|
||||||
}
|
}
|
||||||
|
|
||||||
var sigok bool
|
sigok := checkMultisigPar(v, pkeys, sigs)
|
||||||
if v.checkMultisig == nil {
|
|
||||||
sigok = checkMultisigPar(v, pkeys, sigs)
|
|
||||||
} else {
|
|
||||||
sigok = v.checkMultisig(v, pkeys, sigs)
|
|
||||||
}
|
|
||||||
|
|
||||||
v.estack.PushVal(sigok)
|
v.estack.PushVal(sigok)
|
||||||
|
|
||||||
case opcode.NEWMAP:
|
case opcode.NEWMAP:
|
||||||
|
@ -1523,30 +1515,6 @@ func checkMultisig1(v *VM, pkeys [][]byte, sig []byte) bool {
|
||||||
return false
|
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 {
|
func cloneIfStruct(item StackItem) StackItem {
|
||||||
switch it := item.(type) {
|
switch it := item.(type) {
|
||||||
case *StructItem:
|
case *StructItem:
|
||||||
|
|
|
@ -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}) })
|
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) {
|
func TestSWAPGood(t *testing.T) {
|
||||||
prog := makeProgram(opcode.SWAP)
|
prog := makeProgram(opcode.SWAP)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
|
Loading…
Add table
Reference in a new issue