From c4ad434f20b8369fbc2b67529a46e1acf0fc4011 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 26 May 2022 13:27:24 +0300 Subject: [PATCH] core: adjust System.Runtime.GetRandom 1. Make seed dependant on the GetRandom invocations counter. 2. Adjust syscall price. --- pkg/core/interop/context.go | 41 ++++++++++++++-------------- pkg/core/interop/runtime/util.go | 22 +++++++++++++-- pkg/core/interop_system_core_test.go | 16 ++++++----- pkg/core/interops.go | 2 +- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index e6d2c30e6..abdd8576f 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -45,26 +45,27 @@ type Ledger interface { // Context represents context in which interops are executed. type Context struct { - Chain Ledger - Container hash.Hashable - Network uint32 - Hardforks map[string]uint32 - Natives []Contract - Trigger trigger.Type - Block *block.Block - NonceData [16]byte - Tx *transaction.Transaction - DAO *dao.Simple - Notifications []state.NotificationEvent - Log *zap.Logger - VM *vm.VM - Functions []Function - Invocations map[util.Uint160]int - cancelFuncs []context.CancelFunc - getContract func(*dao.Simple, util.Uint160) (*state.Contract, error) - baseExecFee int64 - baseStorageFee int64 - signers []transaction.Signer + Chain Ledger + Container hash.Hashable + Network uint32 + Hardforks map[string]uint32 + Natives []Contract + Trigger trigger.Type + Block *block.Block + NonceData [16]byte + Tx *transaction.Transaction + DAO *dao.Simple + Notifications []state.NotificationEvent + Log *zap.Logger + VM *vm.VM + Functions []Function + Invocations map[util.Uint160]int + cancelFuncs []context.CancelFunc + getContract func(*dao.Simple, util.Uint160) (*state.Contract, error) + baseExecFee int64 + baseStorageFee int64 + GetRandomCounter uint32 + signers []transaction.Signer } // NewContext returns new interop context. diff --git a/pkg/core/interop/runtime/util.go b/pkg/core/interop/runtime/util.go index e00345f87..84d669fe7 100644 --- a/pkg/core/interop/runtime/util.go +++ b/pkg/core/interop/runtime/util.go @@ -5,6 +5,7 @@ import ( "errors" "math/big" + "github.com/nspcc-dev/neo-go/pkg/config" "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/encoding/address" @@ -88,9 +89,26 @@ func GetNetwork(ic *interop.Context) error { // GetRandom returns pseudo-random number which depends on block nonce and transaction hash. func GetRandom(ic *interop.Context) error { - res := murmur128(ic.NonceData[:], ic.Network) + var ( + price int64 + seed = ic.Network + ) + isHF := ic.IsHardforkEnabled(config.HF2712FixSyscallFees) + if isHF { + price = 1 << 13 + seed += ic.GetRandomCounter + ic.GetRandomCounter++ + } else { + price = 1 << 4 + } + res := murmur128(ic.NonceData[:], seed) + if !isHF { + copy(ic.NonceData[:], res) + } + if !ic.VM.AddGas(ic.BaseExecFee() * price) { + return errors.New("gas limit exceeded") + } ic.VM.Estack().PushItem(stackitem.NewBigInteger(bigint.FromBytesUnsigned(res))) - copy(ic.NonceData[:], res) return nil } diff --git a/pkg/core/interop_system_core_test.go b/pkg/core/interop_system_core_test.go index 2c7b34307..1534aba33 100644 --- a/pkg/core/interop_system_core_test.go +++ b/pkg/core/interop_system_core_test.go @@ -46,25 +46,26 @@ func TestRuntimeGetRandomCompatibility(t *testing.T) { b := getSharpTestGenesis(t) tx := getSharpTestTx(util.Uint160{}) ic := bc.newInteropContext(trigger.Application, bc.dao.GetWrapped(), b, tx) - ic.Network = 5195086 // Old mainnet magic used by C# tests. + ic.Network = 860833102 // Old mainnet magic used by C# tests. ic.VM = vm.New() ic.VM.LoadScript([]byte{0x01}) + ic.VM.GasLimit = 1100_00000000 require.NoError(t, runtime.GetRandom(ic)) - require.Equal(t, "225932872514876835587448704843370203748", ic.VM.Estack().Pop().BigInt().String()) + require.Equal(t, "271339657438512451304577787170704246350", ic.VM.Estack().Pop().BigInt().String()) require.NoError(t, runtime.GetRandom(ic)) - require.Equal(t, "190129535548110356450238097068474508661", ic.VM.Estack().Pop().BigInt().String()) + require.Equal(t, "98548189559099075644778613728143131367", ic.VM.Estack().Pop().BigInt().String()) require.NoError(t, runtime.GetRandom(ic)) - require.Equal(t, "48930406787011198493485648810190184269", ic.VM.Estack().Pop().BigInt().String()) + require.Equal(t, "247654688993873392544380234598471205121", ic.VM.Estack().Pop().BigInt().String()) require.NoError(t, runtime.GetRandom(ic)) - require.Equal(t, "66199389469641263539889463157823839112", ic.VM.Estack().Pop().BigInt().String()) + require.Equal(t, "291082758879475329976578097236212073607", ic.VM.Estack().Pop().BigInt().String()) require.NoError(t, runtime.GetRandom(ic)) - require.Equal(t, "217172703763162599519098299724476526911", ic.VM.Estack().Pop().BigInt().String()) + require.Equal(t, "247152297361212656635216876565962360375", ic.VM.Estack().Pop().BigInt().String()) } func getSharpTestTx(sender util.Uint160) *transaction.Transaction { @@ -74,7 +75,8 @@ func getSharpTestTx(sender util.Uint160) *transaction.Transaction { Account: sender, Scopes: transaction.CalledByEntry, }) - tx.Scripts = append(tx.Scripts, transaction.Witness{}) + tx.Attributes = []transaction.Attribute{} + tx.Scripts = append(tx.Scripts, transaction.Witness{InvocationScript: []byte{}, VerificationScript: []byte{}}) return tx } diff --git a/pkg/core/interops.go b/pkg/core/interops.go index b3efb8032..cf2e3982b 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -53,7 +53,7 @@ var systemInterops = []interop.Function{ {Name: interopnames.SystemRuntimeGetInvocationCounter, Func: runtime.GetInvocationCounter, Price: 1 << 4}, {Name: interopnames.SystemRuntimeGetNetwork, Func: runtime.GetNetwork, Price: 1 << 3}, {Name: interopnames.SystemRuntimeGetNotifications, Func: runtime.GetNotifications, Price: 1 << 12, ParamCount: 1}, - {Name: interopnames.SystemRuntimeGetRandom, Func: runtime.GetRandom, Price: 1 << 4}, + {Name: interopnames.SystemRuntimeGetRandom, Func: runtime.GetRandom, Price: 0}, {Name: interopnames.SystemRuntimeGetScriptContainer, Func: engineGetScriptContainer, Price: 1 << 3}, {Name: interopnames.SystemRuntimeGetTime, Func: runtime.GetTime, Price: 1 << 3, RequiredFlags: callflag.ReadStates}, {Name: interopnames.SystemRuntimeGetTrigger, Func: runtime.GetTrigger, Price: 1 << 3},