From ad2a75a500daf800791973696b38c40758c31451 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jun 2020 11:54:48 +0300 Subject: [PATCH 1/8] core: move System.ExecutionEngine.* interops to System.Runtime.* --- examples/engine/engine.go | 9 +++-- examples/token/nep5/nep5.go | 3 +- pkg/compiler/syscall.go | 11 +++--- pkg/core/interops.go | 8 ++--- pkg/interop/engine/engine.go | 39 +--------------------- pkg/interop/runtime/engine.go | 38 +++++++++++++++++++++ pkg/rpc/server/server_test.go | 8 ++--- pkg/rpc/server/testdata/test_contract.avm | Bin 727 -> 727 bytes pkg/rpc/server/testdata/test_contract.go | 3 +- pkg/rpc/server/testdata/testblocks.acc | Bin 6784 -> 6784 bytes 10 files changed, 58 insertions(+), 61 deletions(-) create mode 100644 pkg/interop/runtime/engine.go 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/syscall.go b/pkg/compiler/syscall.go index 2a4b12fa9..d5c7c5908 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -24,6 +24,11 @@ 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", + "GetTrigger": "System.Runtime.GetTrigger", "CheckWitness": "System.Runtime.CheckWitness", "Notify": "System.Runtime.Notify", @@ -45,12 +50,6 @@ var syscalls = map[string]map[string]string{ "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", - }, "iterator": { "Concat": "System.Iterator.Concat", "Create": "System.Iterator.Create", diff --git a/pkg/core/interops.go b/pkg/core/interops.go index e3af4d4ec..aa64a714c 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}, @@ -111,6 +107,10 @@ var systemInterops = []interop.Function{ {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.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 400}, + {Name: "System.Runtime.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 400}, + {Name: "System.Runtime.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 400}, + {Name: "System.Runtime.GetScriptContainer", Func: engineGetScriptContainer, Price: 250}, {Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 1, AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowStates}, {Name: "System.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 1}, 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/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 459d4e2218a10e24888c309d04009ca6d91f4c67..eec2f3ea44896e5efd3bca6d65da162028afd9bc 100755 GIT binary patch delta 16 Ycmcc4dYyGcB@@f-e=ABR*D^%`06&-qNdN!< delta 16 Xcmcc4dYyGcB@;{g;Y%r#Ynh?|JO>8U 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 48261344581038f8c46b38b4dce64a704ccaeeaf..e175a3066ee5c7cbcc12965de385f2d1b5e047c9 100644 GIT binary patch delta 2595 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 From 1f97f3abd8750c577866c67aea3f82560dfea968 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jun 2020 11:56:51 +0300 Subject: [PATCH 2/8] core: adjust prices and flags for System.Runtime.* interops Related #1055. --- pkg/core/interops.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/core/interops.go b/pkg/core/interops.go index aa64a714c..b8d78bca6 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -106,17 +106,17 @@ 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.CheckWitness", Func: runtime.CheckWitness, Price: 30000}, {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.GetScriptContainer", Func: engineGetScriptContainer, Price: 250}, - {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.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, From a7d4fff8977b65848c2a1f58bec459e83704ef93 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jun 2020 15:13:18 +0300 Subject: [PATCH 3/8] vm: make (*VM).GasLimit public VM is inherently single-threaded and replacing setter/getter methods with public field simplifies code a bit. --- pkg/core/blockchain.go | 2 +- pkg/rpc/server/server.go | 2 +- pkg/vm/vm.go | 12 +++--------- pkg/vm/vm_test.go | 6 +++--- 4 files changed, 8 insertions(+), 14 deletions(-) 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/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/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)) From a4e443996700d7813a54b92ff83482a019b11d2c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jun 2020 12:04:08 +0300 Subject: [PATCH 4/8] core,vm: implement System.Runtime.GasLeft syscall --- pkg/compiler/syscall.go | 1 + pkg/core/interop/runtime/util.go | 12 ++++++++++++ pkg/core/interop_system_test.go | 11 +++++++++++ pkg/core/interops.go | 1 + pkg/interop/runtime/runtime.go | 6 ++++++ 5 files changed, 31 insertions(+) create mode 100644 pkg/core/interop/runtime/util.go diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index d5c7c5908..dd8394560 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -29,6 +29,7 @@ var syscalls = map[string]map[string]string{ "GetEntryScriptHash": "System.Runtime.GetEntryScriptHash", "GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash", + "GasLeft": "System.Runtime.GasLeft", "GetTrigger": "System.Runtime.GetTrigger", "CheckWitness": "System.Runtime.CheckWitness", "Notify": "System.Runtime.Notify", diff --git a/pkg/core/interop/runtime/util.go b/pkg/core/interop/runtime/util.go new file mode 100644 index 000000000..65ad6756c --- /dev/null +++ b/pkg/core/interop/runtime/util.go @@ -0,0 +1,12 @@ +package runtime + +import ( + "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/vm" +) + +// GasLeft returns remaining amount of GAS. +func GasLeft(_ *interop.Context, v *vm.VM) error { + v.Estack().PushVal(int64(v.GasLimit - v.GasConsumed())) + return nil +} diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 613351459..436284bbb 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -5,6 +5,7 @@ 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/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -197,3 +198,13 @@ 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()) +} diff --git a/pkg/core/interops.go b/pkg/core/interops.go index b8d78bca6..3ad59985a 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -107,6 +107,7 @@ var systemInterops = []interop.Function{ {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: 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}, diff --git a/pkg/interop/runtime/runtime.go b/pkg/interop/runtime/runtime.go index 916fed6fb..538f0f490 100644 --- a/pkg/interop/runtime/runtime.go +++ b/pkg/interop/runtime/runtime.go @@ -54,3 +54,9 @@ 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 +} From afd8f3b87a9d176b5f40680493c965bb66f8bc33 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 17 Jun 2020 11:21:37 +0300 Subject: [PATCH 5/8] compiler: push Null item for `nil` values --- pkg/compiler/codegen.go | 2 ++ 1 file changed, 2 insertions(+) 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) } From 75e597f880639f92faa77121a95114687889c4c7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jun 2020 12:30:25 +0300 Subject: [PATCH 6/8] core: implement System.Runtime.GetNotifications syscall --- pkg/compiler/syscall.go | 1 + pkg/core/interop/runtime/util.go | 39 ++++++++++++++++++++++++++++++++ pkg/core/interop_system_test.go | 36 +++++++++++++++++++++++++++++ pkg/interop/runtime/runtime.go | 8 +++++++ 4 files changed, 84 insertions(+) diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index dd8394560..e6da7eb70 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -28,6 +28,7 @@ var syscalls = map[string]map[string]string{ "GetCallingScriptHash": "System.Runtime.GetCallingScriptHash", "GetEntryScriptHash": "System.Runtime.GetEntryScriptHash", "GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash", + "GetNotifications": "System.Runtime.GetNotifications", "GasLeft": "System.Runtime.GasLeft", "GetTrigger": "System.Runtime.GetTrigger", diff --git a/pkg/core/interop/runtime/util.go b/pkg/core/interop/runtime/util.go index 65ad6756c..48cab46c0 100644 --- a/pkg/core/interop/runtime/util.go +++ b/pkg/core/interop/runtime/util.go @@ -2,7 +2,11 @@ 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. @@ -10,3 +14,38 @@ 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 +} diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 436284bbb..bd87315e4 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -208,3 +208,39 @@ func TestRuntimeGasLeft(t *testing.T) { 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]) + }) +} diff --git a/pkg/interop/runtime/runtime.go b/pkg/interop/runtime/runtime.go index 538f0f490..0306e6743 100644 --- a/pkg/interop/runtime/runtime.go +++ b/pkg/interop/runtime/runtime.go @@ -60,3 +60,11 @@ func Verification() byte { 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 +} From 3762ebdd084d0b8406ea95c563bcac70a22ecb21 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jun 2020 12:47:42 +0300 Subject: [PATCH 7/8] core: implement System.Runtime.GetInvocationCounter syscall --- pkg/compiler/syscall.go | 1 + pkg/core/interop/context.go | 2 ++ pkg/core/interop/runtime/util.go | 10 ++++++++++ pkg/core/interop_system.go | 1 + pkg/core/interop_system_test.go | 18 ++++++++++++++++++ pkg/core/interops.go | 1 + pkg/interop/runtime/runtime.go | 6 ++++++ 7 files changed, 39 insertions(+) diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index e6da7eb70..e93d2f484 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -29,6 +29,7 @@ var syscalls = map[string]map[string]string{ "GetEntryScriptHash": "System.Runtime.GetEntryScriptHash", "GetExecutingScriptHash": "System.Runtime.GetExecutingScriptHash", "GetNotifications": "System.Runtime.GetNotifications", + "GetInvocationCounter": "System.Runtime.GetInvocationCounter", "GasLeft": "System.Runtime.GasLeft", "GetTrigger": "System.Runtime.GetTrigger", 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 index 48cab46c0..e9a122507 100644 --- a/pkg/core/interop/runtime/util.go +++ b/pkg/core/interop/runtime/util.go @@ -49,3 +49,13 @@ func GetNotifications(ic *interop.Context, v *vm.VM) error { 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 bd87315e4..a47894946 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -7,6 +7,7 @@ import ( "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" @@ -244,3 +245,20 @@ func TestRuntimeGetNotifications(t *testing.T) { 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 3ad59985a..7f8629061 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -111,6 +111,7 @@ var systemInterops = []interop.Function{ {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}, diff --git a/pkg/interop/runtime/runtime.go b/pkg/interop/runtime/runtime.go index 0306e6743..5695fa780 100644 --- a/pkg/interop/runtime/runtime.go +++ b/pkg/interop/runtime/runtime.go @@ -68,3 +68,9 @@ func GasLeft() int64 { 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 +} From 61cae8d8b14a6182ef4e45ae43aa3440422f32bd Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 17 Jun 2020 11:38:32 +0300 Subject: [PATCH 8/8] compiler: implement missing `System.Contract.*` interops Support System.Contract.IsStandard/CreateStandardAccount syscall. --- pkg/compiler/syscall.go | 3 +++ pkg/interop/contract/contract.go | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index e93d2f484..be1b8a9c9 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -52,6 +52,9 @@ var syscalls = map[string]map[string]string{ "Create": "System.Contract.Create", "Destroy": "System.Contract.Destroy", "Update": "System.Contract.Update", + + "IsStandard": "System.Contract.IsStandard", + "CreateStandardAccount": "System.Contract.CreateStandardAccount", }, "iterator": { "Concat": "System.Iterator.Concat", 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 +}