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.
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.

View file

@ -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
}

View file

@ -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
}

View file

@ -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},