diff --git a/examples/engine/engine.go b/examples/engine/engine.go index d5a914c68..e747863d1 100644 --- a/examples/engine/engine.go +++ b/examples/engine/engine.go @@ -1,22 +1,21 @@ package enginecontract import ( - "github.com/nspcc-dev/neo-go/pkg/interop/engine" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" ) // Main is that famous Main() function, you know. func Main() bool { - tx := engine.GetScriptContainer() + tx := runtime.GetScriptContainer() runtime.Notify(tx) - callingScriptHash := engine.GetCallingScriptHash() + callingScriptHash := runtime.GetCallingScriptHash() runtime.Notify(callingScriptHash) - execScriptHash := engine.GetExecutingScriptHash() + execScriptHash := runtime.GetExecutingScriptHash() runtime.Notify(execScriptHash) - entryScriptHash := engine.GetEntryScriptHash() + entryScriptHash := runtime.GetEntryScriptHash() runtime.Notify(entryScriptHash) return true diff --git a/examples/token/nep5/nep5.go b/examples/token/nep5/nep5.go index 742e0e3df..7082ad65b 100644 --- a/examples/token/nep5/nep5.go +++ b/examples/token/nep5/nep5.go @@ -1,7 +1,6 @@ package nep5 import ( - "github.com/nspcc-dev/neo-go/pkg/interop/engine" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" @@ -85,7 +84,7 @@ func IsUsableAddress(addr []byte) bool { } // Check if a smart contract is calling scripthash - callingScriptHash := engine.GetCallingScriptHash() + callingScriptHash := runtime.GetCallingScriptHash() if util.Equals(callingScriptHash, addr) { return true } diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 9055abd16..27cfeca14 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -586,6 +586,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { case *ast.Ident: if tv := c.typeAndValueOf(n); tv.Value != nil { c.emitLoadConst(tv) + } else if n.Name == "nil" { + emit.Opcode(c.prog.BinWriter, opcode.PUSHNULL) } else { c.emitLoadVar(n.Name) } diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index 2a4b12fa9..be1b8a9c9 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -24,6 +24,14 @@ var syscalls = map[string]map[string]string{ "Put": "System.Storage.Put", }, "runtime": { + "GetScriptContainer": "System.Runtime.GetScriptContainer", + "GetCallingScriptHash": "System.Runtime.GetCallingScriptHash", + "GetEntryScriptHash": "System.Runtime.GetEntryScriptHash", + "GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash", + "GetNotifications": "System.Runtime.GetNotifications", + "GetInvocationCounter": "System.Runtime.GetInvocationCounter", + + "GasLeft": "System.Runtime.GasLeft", "GetTrigger": "System.Runtime.GetTrigger", "CheckWitness": "System.Runtime.CheckWitness", "Notify": "System.Runtime.Notify", @@ -44,12 +52,9 @@ var syscalls = map[string]map[string]string{ "Create": "System.Contract.Create", "Destroy": "System.Contract.Destroy", "Update": "System.Contract.Update", - }, - "engine": { - "GetScriptContainer": "System.ExecutionEngine.GetScriptContainer", - "GetCallingScriptHash": "System.ExecutionEngine.GetCallingScriptHash", - "GetEntryScriptHash": "System.ExecutionEngine.GetEntryScriptHash", - "GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash", + + "IsStandard": "System.Contract.IsStandard", + "CreateStandardAccount": "System.Contract.CreateStandardAccount", }, "iterator": { "Concat": "System.Iterator.Concat", diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 51462f5c5..f0db627c4 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -566,7 +566,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { v.LoadScriptWithFlags(tx.Script, smartcontract.All) v.SetPriceGetter(getPrice) if bc.config.FreeGasLimit > 0 { - v.SetGasLimit(bc.config.FreeGasLimit + tx.SystemFee) + v.GasLimit = bc.config.FreeGasLimit + tx.SystemFee } err := v.Run() diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index 10d2c376e..b0b59c586 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -30,6 +30,7 @@ type Context struct { DAO *dao.Cached Notifications []state.NotificationEvent Log *zap.Logger + Invocations map[util.Uint160]int } // NewContext returns new interop context. @@ -45,6 +46,7 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO, n DAO: dao, Notifications: nes, Log: log, + Invocations: make(map[util.Uint160]int), } } diff --git a/pkg/core/interop/runtime/util.go b/pkg/core/interop/runtime/util.go new file mode 100644 index 000000000..e9a122507 --- /dev/null +++ b/pkg/core/interop/runtime/util.go @@ -0,0 +1,61 @@ +package runtime + +import ( + "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/pkg/errors" +) + +// GasLeft returns remaining amount of GAS. +func GasLeft(_ *interop.Context, v *vm.VM) error { + v.Estack().PushVal(int64(v.GasLimit - v.GasConsumed())) + return nil +} + +// GetNotifications returns notifications emitted by current contract execution. +func GetNotifications(ic *interop.Context, v *vm.VM) error { + item := v.Estack().Pop().Item() + notifications := ic.Notifications + if _, ok := item.(stackitem.Null); !ok { + b, err := item.TryBytes() + if err != nil { + return err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return err + } + notifications = []state.NotificationEvent{} + for i := range ic.Notifications { + if ic.Notifications[i].ScriptHash.Equals(u) { + notifications = append(notifications, ic.Notifications[i]) + } + } + } + if len(notifications) > vm.MaxStackSize { + return errors.New("too many notifications") + } + arr := stackitem.NewArray(make([]stackitem.Item, 0, len(notifications))) + for i := range notifications { + ev := stackitem.NewArray([]stackitem.Item{ + stackitem.NewByteArray(notifications[i].ScriptHash.BytesBE()), + notifications[i].Item, + }) + arr.Append(ev) + } + v.Estack().PushVal(arr) + return nil +} + +// GetInvocationCounter returns how many times current contract was invoked during current tx execution. +func GetInvocationCounter(ic *interop.Context, v *vm.VM) error { + count, ok := ic.Invocations[v.GetCurrentScriptHash()] + if !ok { + return errors.New("current contract wasn't invoked from others") + } + v.Estack().PushVal(count) + return nil +} diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index b4c6ed2c7..c0a66ed06 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -443,6 +443,7 @@ func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stac return errors.New("disallowed method call") } } + ic.Invocations[u]++ v.LoadScriptWithHash(cs.Script, u, v.Context().GetCallFlags()&f) v.Estack().PushVal(args) v.Estack().PushVal(method) diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 613351459..a47894946 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -5,7 +5,9 @@ import ( "testing" "github.com/nspcc-dev/dbft/crypto" + "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -197,3 +199,66 @@ func TestContractCreateAccount(t *testing.T) { require.Error(t, contractCreateStandardAccount(ic, v)) }) } + +func TestRuntimeGasLeft(t *testing.T) { + v, ic, chain := createVM(t) + defer chain.Close() + + v.GasLimit = 100 + v.AddGas(58) + require.NoError(t, runtime.GasLeft(ic, v)) + require.EqualValues(t, 42, v.Estack().Pop().BigInt().Int64()) +} + +func TestRuntimeGetNotifications(t *testing.T) { + v, ic, chain := createVM(t) + defer chain.Close() + + ic.Notifications = []state.NotificationEvent{ + {ScriptHash: util.Uint160{1}, Item: stackitem.NewByteArray([]byte{11})}, + {ScriptHash: util.Uint160{2}, Item: stackitem.NewByteArray([]byte{22})}, + {ScriptHash: util.Uint160{1}, Item: stackitem.NewByteArray([]byte{33})}, + } + + t.Run("NoFilter", func(t *testing.T) { + v.Estack().PushVal(stackitem.Null{}) + require.NoError(t, runtime.GetNotifications(ic, v)) + + arr := v.Estack().Pop().Array() + require.Equal(t, len(ic.Notifications), len(arr)) + for i := range arr { + elem := arr[i].Value().([]stackitem.Item) + require.Equal(t, ic.Notifications[i].ScriptHash.BytesBE(), elem[0].Value()) + require.Equal(t, ic.Notifications[i].Item, elem[1]) + } + }) + + t.Run("WithFilter", func(t *testing.T) { + h := util.Uint160{2}.BytesBE() + v.Estack().PushVal(h) + require.NoError(t, runtime.GetNotifications(ic, v)) + + arr := v.Estack().Pop().Array() + require.Equal(t, 1, len(arr)) + elem := arr[0].Value().([]stackitem.Item) + require.Equal(t, h, elem[0].Value()) + require.Equal(t, ic.Notifications[1].Item, elem[1]) + }) +} + +func TestRuntimeGetInvocationCounter(t *testing.T) { + v, ic, chain := createVM(t) + defer chain.Close() + + ic.Invocations[hash.Hash160([]byte{2})] = 42 + + t.Run("Zero", func(t *testing.T) { + v.LoadScript([]byte{1}) + require.Error(t, runtime.GetInvocationCounter(ic, v)) + }) + t.Run("NonZero", func(t *testing.T) { + v.LoadScript([]byte{2}) + require.NoError(t, runtime.GetInvocationCounter(ic, v)) + require.EqualValues(t, 42, v.Estack().Pop().BigInt().Int64()) + }) +} diff --git a/pkg/core/interops.go b/pkg/core/interops.go index e3af4d4ec..7f8629061 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -99,10 +99,6 @@ var systemInterops = []interop.Function{ {Name: "System.Enumerator.Create", Func: enumerator.Create, Price: 400}, {Name: "System.Enumerator.Next", Func: enumerator.Next, Price: 1000000}, {Name: "System.Enumerator.Value", Func: enumerator.Value, Price: 400}, - {Name: "System.ExecutionEngine.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 1}, - {Name: "System.ExecutionEngine.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 1}, - {Name: "System.ExecutionEngine.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 1}, - {Name: "System.ExecutionEngine.GetScriptContainer", Func: engineGetScriptContainer, Price: 1}, {Name: "System.Iterator.Concat", Func: iterator.Concat, Price: 400}, {Name: "System.Iterator.Create", Func: iterator.Create, Price: 400}, {Name: "System.Iterator.Key", Func: iterator.Key, Price: 400}, @@ -110,13 +106,19 @@ var systemInterops = []interop.Function{ {Name: "System.Iterator.Values", Func: iterator.Values, Price: 400}, {Name: "System.Json.Deserialize", Func: json.Deserialize, Price: 500000}, {Name: "System.Json.Serialize", Func: json.Serialize, Price: 100000}, - {Name: "System.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 200, RequiredFlags: smartcontract.AllowStates}, - {Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 1, - AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowStates}, - {Name: "System.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 1}, - {Name: "System.Runtime.Log", Func: runtimeLog, Price: 1, RequiredFlags: smartcontract.AllowNotify}, - {Name: "System.Runtime.Notify", Func: runtimeNotify, Price: 1, RequiredFlags: smartcontract.AllowNotify}, - {Name: "System.Runtime.Platform", Func: runtimePlatform, Price: 1}, + {Name: "System.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 30000}, + {Name: "System.Runtime.GasLeft", Func: runtime.GasLeft, Price: 400}, + {Name: "System.Runtime.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 400}, + {Name: "System.Runtime.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 400}, + {Name: "System.Runtime.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 400}, + {Name: "System.Runtime.GetInvocationCounter", Func: runtime.GetInvocationCounter, Price: 400}, + {Name: "System.Runtime.GetScriptContainer", Func: engineGetScriptContainer, Price: 250}, + {Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 250, + AllowedTriggers: trigger.Application}, + {Name: "System.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 250}, + {Name: "System.Runtime.Log", Func: runtimeLog, Price: 1000000, RequiredFlags: smartcontract.AllowNotify}, + {Name: "System.Runtime.Notify", Func: runtimeNotify, Price: 1000000, RequiredFlags: smartcontract.AllowNotify}, + {Name: "System.Runtime.Platform", Func: runtimePlatform, Price: 250}, {Name: "System.Storage.Delete", Func: storageDelete, Price: StoragePrice, AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates}, {Name: "System.Storage.Find", Func: storageFind, Price: 1000000, diff --git a/pkg/interop/contract/contract.go b/pkg/interop/contract/contract.go index 509b41a17..12e530bc9 100644 --- a/pkg/interop/contract/contract.go +++ b/pkg/interop/contract/contract.go @@ -32,3 +32,15 @@ func Update(script []byte, manifest []byte) Contract { // not by any outside code. When contract is deleted all associated storage // items are deleted too. This function uses `System.Contract.Destroy` syscall. func Destroy() {} + +// IsStandard checks if contract with provided hash is a standard signature/multisig contract. +// This function uses `System.Contract.IsStandard` syscall. +func IsStandard(h []byte) bool { + return false +} + +// CreateStandardAccount calculates script hash of a given public key. +// This function uses `System.Contract.CreateStandardAccount` syscall. +func CreateStandardAccount(pub []byte) []byte { + return nil +} diff --git a/pkg/interop/engine/engine.go b/pkg/interop/engine/engine.go index ace2ceff3..d126a5b99 100644 --- a/pkg/interop/engine/engine.go +++ b/pkg/interop/engine/engine.go @@ -1,47 +1,10 @@ /* -Package engine provides access to VM execution metadata and allows to make contract calls. +Package engine allows to make contract calls. It's roughly similar in function to ExecutionEngine class in the Neo .net framework. */ package engine -import "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" - -// GetScriptContainer returns the transaction that initially triggered current -// execution context. It never changes in a single execution, no matter how deep -// this execution goes. This function uses -// `System.ExecutionEngine.GetScriptContainer` syscall. -func GetScriptContainer() blockchain.Transaction { - return blockchain.Transaction{} -} - -// GetExecutingScriptHash returns script hash (160 bit in BE form represented -// as 20-byte slice) of the contract that is currently being executed. Any -// AppCall can change the value returned by this function if it calls a -// different contract. This function uses -// `System.ExecutionEngine.GetExecutingScriptHash` syscall. -func GetExecutingScriptHash() []byte { - return nil -} - -// GetCallingScriptHash returns script hash (160 bit in BE form represented -// as 20-byte slice) of the contract that started the execution of the currently -// running context (caller of current contract or function), so it's one level -// above the GetExecutingScriptHash in the call stack. It uses -// `System.ExecutionEngine.GetCallingScriptHash` syscall. -func GetCallingScriptHash() []byte { - return nil -} - -// GetEntryScriptHash returns script hash (160 bit in BE form represented -// as 20-byte slice) of the contract that initially started current execution -// (this is a script that is contained in a transaction returned by -// GetScriptContainer) execution from the start. This function uses -// `System.ExecutionEngine.GetEntryScriptHash` syscall. -func GetEntryScriptHash() []byte { - return nil -} - // AppCall executes previously deployed blockchain contract with specified hash // (160 bit in BE form represented as 20-byte slice) using provided arguments. // It returns whatever this contract returns. Even though this function accepts diff --git a/pkg/interop/runtime/engine.go b/pkg/interop/runtime/engine.go new file mode 100644 index 000000000..c71173c1b --- /dev/null +++ b/pkg/interop/runtime/engine.go @@ -0,0 +1,38 @@ +package runtime + +import "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" + +// GetScriptContainer returns the transaction that initially triggered current +// execution context. It never changes in a single execution, no matter how deep +// this execution goes. This function uses +// `System.Runtime.GetScriptContainer` syscall. +func GetScriptContainer() blockchain.Transaction { + return blockchain.Transaction{} +} + +// GetExecutingScriptHash returns script hash (160 bit in BE form represented +// as 20-byte slice) of the contract that is currently being executed. Any +// AppCall can change the value returned by this function if it calls a +// different contract. This function uses +// `System.Runtime.GetExecutingScriptHash` syscall. +func GetExecutingScriptHash() []byte { + return nil +} + +// GetCallingScriptHash returns script hash (160 bit in BE form represented +// as 20-byte slice) of the contract that started the execution of the currently +// running context (caller of current contract or function), so it's one level +// above the GetExecutingScriptHash in the call stack. It uses +// `System.Runtime.GetCallingScriptHash` syscall. +func GetCallingScriptHash() []byte { + return nil +} + +// GetEntryScriptHash returns script hash (160 bit in BE form represented +// as 20-byte slice) of the contract that initially started current execution +// (this is a script that is contained in a transaction returned by +// GetScriptContainer) execution from the start. This function uses +// `System.Runtime.GetEntryScriptHash` syscall. +func GetEntryScriptHash() []byte { + return nil +} diff --git a/pkg/interop/runtime/runtime.go b/pkg/interop/runtime/runtime.go index 916fed6fb..5695fa780 100644 --- a/pkg/interop/runtime/runtime.go +++ b/pkg/interop/runtime/runtime.go @@ -54,3 +54,23 @@ func Application() byte { func Verification() byte { return 0x00 } + +// GasLeft returns the amount of gas available for the current execution. +// This function uses `System.Runtime.GasLeft` syscall. +func GasLeft() int64 { + return 0 +} + +// GetNotifications returns notifications emitted by contract h. +// 'nil' literal means no filtering. It returns slice consisting of following elements: +// [ scripthash of notification's contract , emitted item ]. +// This function uses `System.Runtime.GetNotifications` syscall. +func GetNotifications(h []byte) [][]interface{} { + return nil +} + +// GetInvocationCounter returns how many times current contract was invoked during current tx execution. +// This function uses `System.Runtime.GetInvocationCounter` syscall. +func GetInvocationCounter() int { + return 0 +} diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 1e05c32d7..55db4fd97 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -906,7 +906,7 @@ func (s *Server) invokescript(reqParams request.Params) (interface{}, *response. // result. func (s *Server) runScriptInVM(script []byte, tx *transaction.Transaction) *result.Invoke { vm := s.chain.GetTestVM(tx) - vm.SetGasLimit(s.config.MaxGasInvoke) + vm.GasLimit = s.config.MaxGasInvoke vm.LoadScriptWithFlags(script, smartcontract.All) _ = vm.Run() result := &result.Invoke{ diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 60437d2b1..e206b6b03 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -50,18 +50,18 @@ type rpcTestCase struct { check func(t *testing.T, e *executor, result interface{}) } -const testContractHash = "279c86355b30d452386c1717e2ffa01c9dac31f3" +const testContractHash = "e65ff7b3a02d207b584a5c27057d4e9862ef01da" var rpcTestCases = map[string][]rpcTestCase{ "getapplicationlog": { { name: "positive", - params: `["136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20"]`, + params: `["9352fa8d351635bb151e7e5a3a923bfe4d8fb90f05b605ec00af95c2410b594d"]`, result: func(e *executor) interface{} { return &result.ApplicationLog{} }, check: func(t *testing.T, e *executor, acc interface{}) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) - expectedTxHash, err := util.Uint256DecodeStringLE("136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20") + expectedTxHash, err := util.Uint256DecodeStringLE("9352fa8d351635bb151e7e5a3a923bfe4d8fb90f05b605ec00af95c2410b594d") require.NoError(t, err) assert.Equal(t, expectedTxHash, res.TxHash) assert.Equal(t, 1, len(res.Executions)) @@ -483,7 +483,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "gettransactionheight": { { name: "positive", - params: `["136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20"]`, + params: `["9352fa8d351635bb151e7e5a3a923bfe4d8fb90f05b605ec00af95c2410b594d"]`, result: func(e *executor) interface{} { h := 0 return &h diff --git a/pkg/rpc/server/testdata/test_contract.avm b/pkg/rpc/server/testdata/test_contract.avm index 459d4e221..eec2f3ea4 100755 Binary files a/pkg/rpc/server/testdata/test_contract.avm and b/pkg/rpc/server/testdata/test_contract.avm differ diff --git a/pkg/rpc/server/testdata/test_contract.go b/pkg/rpc/server/testdata/test_contract.go index 9eb87fe4e..c8d7609d0 100644 --- a/pkg/rpc/server/testdata/test_contract.go +++ b/pkg/rpc/server/testdata/test_contract.go @@ -1,7 +1,6 @@ package testdata import ( - "github.com/nspcc-dev/neo-go/pkg/interop/engine" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" ) @@ -71,7 +70,7 @@ func Main(operation string, args []interface{}) interface{} { return true case "init": ctx := storage.GetContext() - h := engine.GetExecutingScriptHash() + h := runtime.GetExecutingScriptHash() amount := totalSupply storage.Put(ctx, h, amount) runtime.Notify("transfer", []byte{}, h, amount) diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index 482613445..e175a3066 100644 Binary files a/pkg/rpc/server/testdata/testblocks.acc and b/pkg/rpc/server/testdata/testblocks.acc differ diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 5bd960b62..1c201dfd7 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -78,7 +78,7 @@ type VM struct { refs *refCounter gasConsumed util.Fixed8 - gasLimit util.Fixed8 + GasLimit util.Fixed8 trigger trigger.Type @@ -134,16 +134,10 @@ func (v *VM) GasConsumed() util.Fixed8 { return v.gasConsumed } -// SetGasLimit sets maximum amount of gas which v can spent. -// If max <= 0, no limit is imposed. -func (v *VM) SetGasLimit(max util.Fixed8) { - v.gasLimit = max -} - // AddGas consumes specified amount of gas. It returns true iff gas limit wasn't exceeded. func (v *VM) AddGas(gas util.Fixed8) bool { v.gasConsumed += gas - return v.gasLimit == 0 || v.gasConsumed <= v.gasLimit + return v.GasLimit == 0 || v.gasConsumed <= v.GasLimit } // Estack returns the evaluation stack so interop hooks can utilize this. @@ -520,7 +514,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if v.getPrice != nil && ctx.ip < len(ctx.prog) { v.gasConsumed += v.getPrice(v, op, parameter) - if v.gasLimit > 0 && v.gasConsumed > v.gasLimit { + if v.GasLimit > 0 && v.gasConsumed > v.GasLimit { panic("gas limit is exceeded") } } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 83fa9f04c..ca93b2bd7 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -90,7 +90,7 @@ func TestVM_SetPriceGetter(t *testing.T) { t.Run("with sufficient gas limit", func(t *testing.T) { v.Load(prog) - v.SetGasLimit(9) + v.GasLimit = 9 runVM(t, v) require.EqualValues(t, 9, v.GasConsumed()) @@ -98,14 +98,14 @@ func TestVM_SetPriceGetter(t *testing.T) { t.Run("with small gas limit", func(t *testing.T) { v.Load(prog) - v.SetGasLimit(8) + v.GasLimit = 8 checkVMFailed(t, v) }) } func TestAddGas(t *testing.T) { v := New() - v.SetGasLimit(10) + v.GasLimit = 10 require.True(t, v.AddGas(5)) require.True(t, v.AddGas(5)) require.False(t, v.AddGas(5))