From 26e3b6abbe827613f9f616c644dd11e20e40c162 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 1 Oct 2019 16:37:42 +0300 Subject: [PATCH] vm: extend interops to contain price The same way C# node does. --- pkg/vm/tests/vm_test.go | 6 +++--- pkg/vm/vm.go | 20 +++++++++++++------- pkg/vm/vm_test.go | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pkg/vm/tests/vm_test.go b/pkg/vm/tests/vm_test.go index 5ace8c269..885e3ebc6 100644 --- a/pkg/vm/tests/vm_test.go +++ b/pkg/vm/tests/vm_test.go @@ -45,9 +45,9 @@ func vmAndCompile(t *testing.T, src string) *vm.VM { vm := vm.New(vm.ModeMute) storePlugin := newStoragePlugin() - vm.RegisterInteropFunc("Neo.Storage.Get", storePlugin.Get) - vm.RegisterInteropFunc("Neo.Storage.Put", storePlugin.Put) - vm.RegisterInteropFunc("Neo.Storage.GetContext", storePlugin.GetContext) + vm.RegisterInteropFunc("Neo.Storage.Get", storePlugin.Get, 1) + vm.RegisterInteropFunc("Neo.Storage.Put", storePlugin.Put, 1) + vm.RegisterInteropFunc("Neo.Storage.GetContext", storePlugin.GetContext, 1) b, err := compiler.Compile(strings.NewReader(src), &compiler.Options{}) if err != nil { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 5754a7436..310e18b6f 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -33,7 +33,7 @@ type VM struct { state State // registered interop hooks. - interop map[string]InteropFunc + interop map[string]InteropFuncPrice // callback to get scripts. getScript func(util.Uint160) []byte @@ -48,10 +48,16 @@ type VM struct { checkhash []byte } +// InteropFuncPrice represents an interop function with a price. +type InteropFuncPrice struct { + Func InteropFunc + Price int +} + // New returns a new VM object ready to load .avm bytecode scripts. func New(mode Mode) *VM { vm := &VM{ - interop: make(map[string]InteropFunc), + interop: make(map[string]InteropFuncPrice), getScript: nil, state: haltState, istack: NewStack("invocation"), @@ -63,15 +69,15 @@ func New(mode Mode) *VM { } // Register native interop hooks. - vm.RegisterInteropFunc("Neo.Runtime.Log", runtimeLog) - vm.RegisterInteropFunc("Neo.Runtime.Notify", runtimeNotify) + vm.RegisterInteropFunc("Neo.Runtime.Log", runtimeLog, 1) + vm.RegisterInteropFunc("Neo.Runtime.Notify", runtimeNotify, 1) return vm } // RegisterInteropFunc will register the given InteropFunc to the VM. -func (v *VM) RegisterInteropFunc(name string, f InteropFunc) { - v.interop[name] = f +func (v *VM) RegisterInteropFunc(name string, f InteropFunc, price int) { + v.interop[name] = InteropFuncPrice{f, price} } // Estack will return the evaluation stack so interop hooks can utilize this. @@ -850,7 +856,7 @@ func (v *VM) execute(ctx *Context, op Instruction) { if !ok { panic(fmt.Sprintf("interop hook (%s) not registered", api)) } - if err := ifunc(v); err != nil { + if err := ifunc.Func(v); err != nil { panic(fmt.Sprintf("failed to invoke syscall: %s", err)) } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index b1cc8cd65..7e11eb7c5 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -18,7 +18,7 @@ func TestInteropHook(t *testing.T) { v.RegisterInteropFunc("foo", func(evm *VM) error { evm.Estack().PushVal(1) return nil - }) + }, 1) buf := new(bytes.Buffer) EmitSyscall(buf, "foo") @@ -33,7 +33,7 @@ func TestInteropHook(t *testing.T) { func TestRegisterInterop(t *testing.T) { v := New(ModeMute) currRegistered := len(v.interop) - v.RegisterInteropFunc("foo", func(evm *VM) error { return nil }) + v.RegisterInteropFunc("foo", func(evm *VM) error { return nil }, 1) assert.Equal(t, currRegistered+1, len(v.interop)) _, ok := v.interop["foo"] assert.Equal(t, true, ok)