core: adjust System.Runtime.GetRandom

1. Make seed dependant on the GetRandom invocations counter.
2. Adjust syscall price.
This commit is contained in:
Anna Shaleva 2022-05-26 13:27:24 +03:00
parent c6666c52bc
commit c4ad434f20
4 changed files with 51 additions and 30 deletions

View file

@ -45,26 +45,27 @@ type Ledger interface {
// Context represents context in which interops are executed. // Context represents context in which interops are executed.
type Context struct { type Context struct {
Chain Ledger Chain Ledger
Container hash.Hashable Container hash.Hashable
Network uint32 Network uint32
Hardforks map[string]uint32 Hardforks map[string]uint32
Natives []Contract Natives []Contract
Trigger trigger.Type Trigger trigger.Type
Block *block.Block Block *block.Block
NonceData [16]byte NonceData [16]byte
Tx *transaction.Transaction Tx *transaction.Transaction
DAO *dao.Simple DAO *dao.Simple
Notifications []state.NotificationEvent Notifications []state.NotificationEvent
Log *zap.Logger Log *zap.Logger
VM *vm.VM VM *vm.VM
Functions []Function Functions []Function
Invocations map[util.Uint160]int Invocations map[util.Uint160]int
cancelFuncs []context.CancelFunc cancelFuncs []context.CancelFunc
getContract func(*dao.Simple, util.Uint160) (*state.Contract, error) getContract func(*dao.Simple, util.Uint160) (*state.Contract, error)
baseExecFee int64 baseExecFee int64
baseStorageFee int64 baseStorageFee int64
signers []transaction.Signer GetRandomCounter uint32
signers []transaction.Signer
} }
// NewContext returns new interop context. // NewContext returns new interop context.

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"math/big" "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/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "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. // GetRandom returns pseudo-random number which depends on block nonce and transaction hash.
func GetRandom(ic *interop.Context) error { 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))) ic.VM.Estack().PushItem(stackitem.NewBigInteger(bigint.FromBytesUnsigned(res)))
copy(ic.NonceData[:], res)
return nil return nil
} }

View file

@ -46,25 +46,26 @@ func TestRuntimeGetRandomCompatibility(t *testing.T) {
b := getSharpTestGenesis(t) b := getSharpTestGenesis(t)
tx := getSharpTestTx(util.Uint160{}) tx := getSharpTestTx(util.Uint160{})
ic := bc.newInteropContext(trigger.Application, bc.dao.GetWrapped(), b, tx) 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 = vm.New()
ic.VM.LoadScript([]byte{0x01}) ic.VM.LoadScript([]byte{0x01})
ic.VM.GasLimit = 1100_00000000
require.NoError(t, runtime.GetRandom(ic)) 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.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.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.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.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 { func getSharpTestTx(sender util.Uint160) *transaction.Transaction {
@ -74,7 +75,8 @@ func getSharpTestTx(sender util.Uint160) *transaction.Transaction {
Account: sender, Account: sender,
Scopes: transaction.CalledByEntry, 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 return tx
} }

View file

@ -53,7 +53,7 @@ var systemInterops = []interop.Function{
{Name: interopnames.SystemRuntimeGetInvocationCounter, Func: runtime.GetInvocationCounter, Price: 1 << 4}, {Name: interopnames.SystemRuntimeGetInvocationCounter, Func: runtime.GetInvocationCounter, Price: 1 << 4},
{Name: interopnames.SystemRuntimeGetNetwork, Func: runtime.GetNetwork, Price: 1 << 3}, {Name: interopnames.SystemRuntimeGetNetwork, Func: runtime.GetNetwork, Price: 1 << 3},
{Name: interopnames.SystemRuntimeGetNotifications, Func: runtime.GetNotifications, Price: 1 << 12, ParamCount: 1}, {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.SystemRuntimeGetScriptContainer, Func: engineGetScriptContainer, Price: 1 << 3},
{Name: interopnames.SystemRuntimeGetTime, Func: runtime.GetTime, Price: 1 << 3, RequiredFlags: callflag.ReadStates}, {Name: interopnames.SystemRuntimeGetTime, Func: runtime.GetTime, Price: 1 << 3, RequiredFlags: callflag.ReadStates},
{Name: interopnames.SystemRuntimeGetTrigger, Func: runtime.GetTrigger, Price: 1 << 3}, {Name: interopnames.SystemRuntimeGetTrigger, Func: runtime.GetTrigger, Price: 1 << 3},