Commit e9bc4efb authored by mbaxter's avatar mbaxter Committed by GitHub

cannon: Refactor and add test utils (#11573)

* cannon: Reorganize state mutator testutils

* cannon: Add some testutils to randomize state, standardize validation

* cannon: Attach ticket to TODOs

* cannon: Remove redundant register randomization

* cannon: Clarify testutil import names

* cannon: Clarify comment
parent 6e06fa53
...@@ -187,7 +187,7 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3 ...@@ -187,7 +187,7 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3
memTracker.TrackMemAccess(effAddr) memTracker.TrackMemAccess(effAddr)
mem := memory.GetMemory(effAddr) mem := memory.GetMemory(effAddr)
dat, datLen := preimageReader.ReadPreimage(preimageKey, preimageOffset) dat, datLen := preimageReader.ReadPreimage(preimageKey, preimageOffset)
//fmt.Printf("reading pre-image data: addr: %08x, offset: %d, datLen: %d, data: %x, key: %s count: %d\n", a1, m.state.PreimageOffset, datLen, dat[:datLen], m.state.PreimageKey, a2) //fmt.Printf("reading pre-image data: addr: %08x, offset: %d, datLen: %d, data: %x, key: %s count: %d\n", a1, preimageOffset, datLen, dat[:datLen], preimageKey, a2)
alignment := a1 & 3 alignment := a1 & 3
space := 4 - alignment space := 4 - alignment
if space < datLen { if space < datLen {
......
...@@ -42,7 +42,7 @@ type FPVMState interface { ...@@ -42,7 +42,7 @@ type FPVMState interface {
// so a VM can start from any state without fetching prior pre-images, // so a VM can start from any state without fetching prior pre-images,
// and instead just repeat the last hint on setup, // and instead just repeat the last hint on setup,
// to make sure pre-image requests can be served. // to make sure pre-image requests can be served.
// The first 4 bytes are a uin32 length prefix. // The first 4 bytes are a uint32 length prefix.
// Warning: the hint MAY NOT BE COMPLETE. I.e. this is buffered, // Warning: the hint MAY NOT BE COMPLETE. I.e. this is buffered,
// and should only be read when len(LastHint) > 4 && uint32(LastHint[:4]) <= len(LastHint[4:]) // and should only be read when len(LastHint) > 4 && uint32(LastHint[:4]) <= len(LastHint[4:])
GetLastHint() hexutil.Bytes GetLastHint() hexutil.Bytes
......
package testutil
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil"
)
type StateMutatorMultiThreaded struct {
state *multithreaded.State
}
var _ testutil.StateMutator = (*StateMutatorMultiThreaded)(nil)
func NewStateMutatorMultiThreaded(state *multithreaded.State) testutil.StateMutator {
return &StateMutatorMultiThreaded{state: state}
}
func (m *StateMutatorMultiThreaded) SetHI(val uint32) {
m.state.GetCurrentThread().Cpu.HI = val
}
func (m *StateMutatorMultiThreaded) SetLO(val uint32) {
m.state.GetCurrentThread().Cpu.LO = val
}
func (m *StateMutatorMultiThreaded) SetExitCode(val uint8) {
m.state.ExitCode = val
}
func (m *StateMutatorMultiThreaded) SetExited(val bool) {
m.state.Exited = val
}
func (m *StateMutatorMultiThreaded) SetPC(val uint32) {
thread := m.state.GetCurrentThread()
thread.Cpu.PC = val
}
func (m *StateMutatorMultiThreaded) SetHeap(val uint32) {
m.state.Heap = val
}
func (m *StateMutatorMultiThreaded) SetNextPC(val uint32) {
thread := m.state.GetCurrentThread()
thread.Cpu.NextPC = val
}
func (m *StateMutatorMultiThreaded) SetLastHint(val hexutil.Bytes) {
m.state.LastHint = val
}
func (m *StateMutatorMultiThreaded) SetPreimageKey(val common.Hash) {
m.state.PreimageKey = val
}
func (m *StateMutatorMultiThreaded) SetPreimageOffset(val uint32) {
m.state.PreimageOffset = val
}
func (m *StateMutatorMultiThreaded) SetStep(val uint64) {
m.state.Step = val
}
func (m *StateMutatorMultiThreaded) GetRegistersRef() *[32]uint32 {
return m.state.GetRegistersRef()
}
package testutil
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil"
)
type StateMutatorSingleThreaded struct {
state *singlethreaded.State
}
var _ testutil.StateMutator = (*StateMutatorSingleThreaded)(nil)
func NewStateMutatorSingleThreaded(state *singlethreaded.State) testutil.StateMutator {
return &StateMutatorSingleThreaded{state: state}
}
func (m *StateMutatorSingleThreaded) SetPC(val uint32) {
m.state.Cpu.PC = val
}
func (m *StateMutatorSingleThreaded) SetNextPC(val uint32) {
m.state.Cpu.NextPC = val
}
func (m *StateMutatorSingleThreaded) SetHI(val uint32) {
m.state.Cpu.HI = val
}
func (m *StateMutatorSingleThreaded) SetLO(val uint32) {
m.state.Cpu.LO = val
}
func (m *StateMutatorSingleThreaded) SetHeap(val uint32) {
m.state.Heap = val
}
func (m *StateMutatorSingleThreaded) SetExitCode(val uint8) {
m.state.ExitCode = val
}
func (m *StateMutatorSingleThreaded) SetExited(val bool) {
m.state.Exited = val
}
func (m *StateMutatorSingleThreaded) SetLastHint(val hexutil.Bytes) {
m.state.LastHint = val
}
func (m *StateMutatorSingleThreaded) SetPreimageKey(val common.Hash) {
m.state.PreimageKey = val
}
func (m *StateMutatorSingleThreaded) SetPreimageOffset(val uint32) {
m.state.PreimageOffset = val
}
func (m *StateMutatorSingleThreaded) SetStep(val uint64) {
m.state.Step = val
}
func (m *StateMutatorSingleThreaded) GetRegistersRef() *[32]uint32 {
return m.state.GetRegistersRef()
}
This diff is collapsed.
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"os" "os"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -17,37 +16,27 @@ func FuzzStateSyscallCloneMT(f *testing.F) { ...@@ -17,37 +16,27 @@ func FuzzStateSyscallCloneMT(f *testing.F) {
v := GetMultiThreadedTestCase(f) v := GetMultiThreadedTestCase(f)
// t.Skip is causing linting check to fail, disable for now // t.Skip is causing linting check to fail, disable for now
//nolint:staticcheck //nolint:staticcheck
f.Fuzz(func(t *testing.T, pc uint32, step uint64, preimageOffset uint32) { f.Fuzz(func(t *testing.T, seed int64) {
// TODO(cp-903) Customize test for multi-threaded vm // TODO(cp-903) Customize test for multi-threaded vm
t.Skip("TODO - customize this test for MTCannon") t.Skip("TODO - customize this test for MTCannon")
pc = pc & 0xFF_FF_FF_FC // align PC goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(seed))
nextPC := pc + 4
goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(),
WithPC(pc), WithNextPC(nextPC), WithStep(step), WithPreimageOffset(preimageOffset))
state := goVm.GetState() state := goVm.GetState()
state.GetRegistersRef()[2] = exec.SysClone state.GetRegistersRef()[2] = exec.SysClone
state.GetMemory().SetMemory(state.GetPC(), syscallInsn)
step := state.GetStep()
state.GetMemory().SetMemory(pc, syscallInsn) expected := testutil.CreateExpectedState(state)
preStateRoot := state.GetMemory().MerkleRoot() expected.Step += 1
expectedRegisters := testutil.CopyRegisters(state) expected.PC = state.GetCpu().NextPC
expectedRegisters[2] = 0x1 expected.NextPC = state.GetCpu().NextPC + 4
expected.Registers[2] = 0x1
expected.Registers[7] = 0
stepWitness, err := goVm.Step(true) stepWitness, err := goVm.Step(true)
require.NoError(t, err) require.NoError(t, err)
require.False(t, stepWitness.HasPreimage()) require.False(t, stepWitness.HasPreimage())
require.Equal(t, pc+4, state.GetCpu().PC) expected.Validate(t, state)
require.Equal(t, nextPC+4, state.GetCpu().NextPC)
require.Equal(t, uint32(0), state.GetCpu().LO)
require.Equal(t, uint32(0), state.GetCpu().HI)
require.Equal(t, uint32(0), state.GetHeap())
require.Equal(t, uint8(0), state.GetExitCode())
require.Equal(t, false, state.GetExited())
require.Equal(t, preStateRoot, state.GetMemory().MerkleRoot())
require.Equal(t, expectedRegisters, state.GetRegistersRef())
require.Equal(t, step+1, state.GetStep())
require.Equal(t, common.Hash{}, state.GetPreimageKey())
require.Equal(t, preimageOffset, state.GetPreimageOffset())
evm := testutil.NewMIPSEVM(v.Contracts) evm := testutil.NewMIPSEVM(v.Contracts)
evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) evmPost := evm.Step(t, stepWitness, step, v.StateHashFn)
......
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"os" "os"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -14,35 +13,25 @@ import ( ...@@ -14,35 +13,25 @@ import (
func FuzzStateSyscallCloneST(f *testing.F) { func FuzzStateSyscallCloneST(f *testing.F) {
v := GetSingleThreadedTestCase(f) v := GetSingleThreadedTestCase(f)
f.Fuzz(func(t *testing.T, pc uint32, step uint64, preimageOffset uint32) { f.Fuzz(func(t *testing.T, seed int64) {
pc = pc & 0xFF_FF_FF_FC // align PC goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(seed))
nextPC := pc + 4
goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(),
WithPC(pc), WithNextPC(nextPC), WithStep(step), WithPreimageOffset(preimageOffset))
state := goVm.GetState() state := goVm.GetState()
state.GetRegistersRef()[2] = exec.SysClone state.GetRegistersRef()[2] = exec.SysClone
state.GetMemory().SetMemory(state.GetPC(), syscallInsn)
step := state.GetStep()
state.GetMemory().SetMemory(pc, syscallInsn) expected := testutil.CreateExpectedState(state)
preStateRoot := state.GetMemory().MerkleRoot() expected.Step += 1
expectedRegisters := testutil.CopyRegisters(state) expected.PC = state.GetCpu().NextPC
expectedRegisters[2] = 0x1 expected.NextPC = state.GetCpu().NextPC + 4
expected.Registers[2] = 0x1
expected.Registers[7] = 0
stepWitness, err := goVm.Step(true) stepWitness, err := goVm.Step(true)
require.NoError(t, err) require.NoError(t, err)
require.False(t, stepWitness.HasPreimage()) require.False(t, stepWitness.HasPreimage())
require.Equal(t, pc+4, state.GetCpu().PC) expected.Validate(t, state)
require.Equal(t, nextPC+4, state.GetCpu().NextPC)
require.Equal(t, uint32(0), state.GetCpu().LO)
require.Equal(t, uint32(0), state.GetCpu().HI)
require.Equal(t, uint32(0), state.GetHeap())
require.Equal(t, uint8(0), state.GetExitCode())
require.Equal(t, false, state.GetExited())
require.Equal(t, preStateRoot, state.GetMemory().MerkleRoot())
require.Equal(t, expectedRegisters, state.GetRegistersRef())
require.Equal(t, step+1, state.GetStep())
require.Equal(t, common.Hash{}, state.GetPreimageKey())
require.Equal(t, preimageOffset, state.GetPreimageOffset())
evm := testutil.NewMIPSEVM(v.Contracts) evm := testutil.NewMIPSEVM(v.Contracts)
evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) evmPost := evm.Step(t, stepWitness, step, v.StateHashFn)
......
...@@ -3,155 +3,31 @@ package tests ...@@ -3,155 +3,31 @@ package tests
import ( import (
"io" "io"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded"
mttestutil "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded/testutil"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded"
sttestutil "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded/testutil"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil"
) )
type StateMutator interface { type VMFactory func(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...testutil.StateOption) mipsevm.FPVM
SetPC(pc uint32)
SetNextPC(nextPC uint32)
SetHeap(addr uint32)
SetLastHint(lastHint hexutil.Bytes)
SetPreimageKey(key common.Hash)
SetPreimageOffset(offset uint32)
SetStep(step uint64)
}
type singlethreadedMutator struct {
state *singlethreaded.State
}
var _ StateMutator = (*singlethreadedMutator)(nil)
func (m *singlethreadedMutator) SetPC(pc uint32) {
m.state.Cpu.PC = pc
}
func (m *singlethreadedMutator) SetNextPC(nextPC uint32) {
m.state.Cpu.NextPC = nextPC
}
func (m *singlethreadedMutator) SetHeap(addr uint32) {
m.state.Heap = addr
}
func (m *singlethreadedMutator) SetLastHint(lastHint hexutil.Bytes) {
m.state.LastHint = lastHint
}
func (m *singlethreadedMutator) SetPreimageKey(key common.Hash) {
m.state.PreimageKey = key
}
func (m *singlethreadedMutator) SetPreimageOffset(offset uint32) {
m.state.PreimageOffset = offset
}
func (m *singlethreadedMutator) SetStep(step uint64) {
m.state.Step = step
}
type multithreadedMutator struct {
state *multithreaded.State
}
var _ StateMutator = (*multithreadedMutator)(nil)
func (m *multithreadedMutator) SetPC(pc uint32) {
thread := m.state.GetCurrentThread()
thread.Cpu.PC = pc
}
func (m *multithreadedMutator) SetHeap(addr uint32) {
m.state.Heap = addr
}
func (m *multithreadedMutator) SetNextPC(nextPC uint32) {
thread := m.state.GetCurrentThread()
thread.Cpu.NextPC = nextPC
}
func (m *multithreadedMutator) SetLastHint(lastHint hexutil.Bytes) {
m.state.LastHint = lastHint
}
func (m *multithreadedMutator) SetPreimageKey(key common.Hash) {
m.state.PreimageKey = key
}
func (m *multithreadedMutator) SetPreimageOffset(offset uint32) {
m.state.PreimageOffset = offset
}
func (m *multithreadedMutator) SetStep(step uint64) {
m.state.Step = step
}
type VMOption func(vm StateMutator)
func WithPC(pc uint32) VMOption {
return func(state StateMutator) {
state.SetPC(pc)
}
}
func WithNextPC(nextPC uint32) VMOption {
return func(state StateMutator) {
state.SetNextPC(nextPC)
}
}
func WithHeap(addr uint32) VMOption {
return func(state StateMutator) {
state.SetHeap(addr)
}
}
func WithLastHint(lastHint hexutil.Bytes) VMOption {
return func(state StateMutator) {
state.SetLastHint(lastHint)
}
}
func WithPreimageKey(key common.Hash) VMOption {
return func(state StateMutator) {
state.SetPreimageKey(key)
}
}
func WithPreimageOffset(offset uint32) VMOption {
return func(state StateMutator) {
state.SetPreimageOffset(offset)
}
}
func WithStep(step uint64) VMOption {
return func(state StateMutator) {
state.SetStep(step)
}
}
type VMFactory func(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...VMOption) mipsevm.FPVM
func singleThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...VMOption) mipsevm.FPVM { func singleThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...testutil.StateOption) mipsevm.FPVM {
state := singlethreaded.CreateEmptyState() state := singlethreaded.CreateEmptyState()
mutator := &singlethreadedMutator{state: state} mutator := sttestutil.NewStateMutatorSingleThreaded(state)
for _, opt := range opts { for _, opt := range opts {
opt(mutator) opt(mutator)
} }
return singlethreaded.NewInstrumentedState(state, po, stdOut, stdErr, nil) return singlethreaded.NewInstrumentedState(state, po, stdOut, stdErr, nil)
} }
func multiThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...VMOption) mipsevm.FPVM { func multiThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...testutil.StateOption) mipsevm.FPVM {
state := multithreaded.CreateEmptyState() state := multithreaded.CreateEmptyState()
mutator := &multithreadedMutator{state: state} mutator := mttestutil.NewStateMutatorMultiThreaded(state)
for _, opt := range opts { for _, opt := range opts {
opt(mutator) opt(mutator)
} }
......
...@@ -145,3 +145,19 @@ func SelectOracleFixture(t *testing.T, programName string) mipsevm.PreimageOracl ...@@ -145,3 +145,19 @@ func SelectOracleFixture(t *testing.T, programName string) mipsevm.PreimageOracl
return nil return nil
} }
} }
type HintTrackingOracle struct {
hints [][]byte
}
func (t *HintTrackingOracle) Hint(v []byte) {
t.hints = append(t.hints, v)
}
func (t *HintTrackingOracle) GetPreimage(k [32]byte) []byte {
return nil
}
func (t *HintTrackingOracle) Hints() [][]byte {
return t.hints
}
package testutil package testutil
import ( import (
"fmt"
"math/rand" "math/rand"
"slices"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
) )
func RandomRegisters(seed int64) [32]uint32 { func CopyRegisters(state mipsevm.FPVMState) *[32]uint32 {
copy := new([32]uint32)
*copy = *state.GetRegistersRef()
return copy
}
type StateMutator interface {
SetPreimageKey(val common.Hash)
SetPreimageOffset(val uint32)
SetPC(val uint32)
SetNextPC(val uint32)
SetHI(val uint32)
SetLO(val uint32)
SetHeap(addr uint32)
SetExitCode(val uint8)
SetExited(val bool)
SetStep(val uint64)
SetLastHint(val hexutil.Bytes)
GetRegistersRef() *[32]uint32
}
type StateOption func(state StateMutator)
func WithPC(pc uint32) StateOption {
return func(state StateMutator) {
state.SetPC(pc)
}
}
func WithNextPC(nextPC uint32) StateOption {
return func(state StateMutator) {
state.SetNextPC(nextPC)
}
}
func WithHeap(addr uint32) StateOption {
return func(state StateMutator) {
state.SetHeap(addr)
}
}
func WithLastHint(lastHint hexutil.Bytes) StateOption {
return func(state StateMutator) {
state.SetLastHint(lastHint)
}
}
func WithPreimageKey(key common.Hash) StateOption {
return func(state StateMutator) {
state.SetPreimageKey(key)
}
}
func WithPreimageOffset(offset uint32) StateOption {
return func(state StateMutator) {
state.SetPreimageOffset(offset)
}
}
func WithStep(step uint64) StateOption {
return func(state StateMutator) {
state.SetStep(step)
}
}
func WithRandomization(seed int64) StateOption {
return func(mut StateMutator) {
RandomizeState(seed, mut)
}
}
func RandomizeState(seed int64, mut StateMutator) {
r := rand.New(rand.NewSource(seed)) r := rand.New(rand.NewSource(seed))
var registers [32]uint32
// Memory-align random pc and leave room for nextPC
pc := r.Uint32() & 0xFF_FF_FF_FC // Align address
if pc >= 0xFF_FF_FF_FC {
// Leave room to set and then increment nextPC
pc = 0xFF_FF_FF_FC - 8
}
// Set random step, but leave room to increment
step := r.Uint64()
if step == ^uint64(0) {
step -= 1
}
mut.SetPreimageKey(randHash(r))
mut.SetPreimageOffset(r.Uint32())
mut.SetPC(pc)
mut.SetNextPC(pc + 4)
mut.SetHI(r.Uint32())
mut.SetLO(r.Uint32())
mut.SetHeap(r.Uint32())
mut.SetStep(step)
mut.SetLastHint(randHint(r))
*mut.GetRegistersRef() = *randRegisters(r)
}
type ExpectedState struct {
PreimageKey common.Hash
PreimageOffset uint32
PC uint32
NextPC uint32
HI uint32
LO uint32
Heap uint32
ExitCode uint8
Exited bool
Step uint64
LastHint hexutil.Bytes
Registers [32]uint32
MemoryRoot common.Hash
}
func CreateExpectedState(fromState mipsevm.FPVMState) *ExpectedState {
return &ExpectedState{
PreimageKey: fromState.GetPreimageKey(),
PreimageOffset: fromState.GetPreimageOffset(),
PC: fromState.GetPC(),
NextPC: fromState.GetCpu().NextPC,
HI: fromState.GetCpu().HI,
LO: fromState.GetCpu().LO,
Heap: fromState.GetHeap(),
ExitCode: fromState.GetExitCode(),
Exited: fromState.GetExited(),
Step: fromState.GetStep(),
LastHint: fromState.GetLastHint(),
Registers: *fromState.GetRegistersRef(),
MemoryRoot: fromState.GetMemory().MerkleRoot(),
}
}
type StateValidationFlags int
// TODO(cp-983) - Remove these validation hacks
const (
SkipMemoryValidation StateValidationFlags = iota
SkipHintValidation
SkipPreimageKeyValidation
)
func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState, flags ...StateValidationFlags) {
if !slices.Contains(flags, SkipPreimageKeyValidation) {
require.Equal(t, e.PreimageKey, actualState.GetPreimageKey(), fmt.Sprintf("Expect preimageKey = %v", e.PreimageKey))
}
require.Equal(t, e.PreimageOffset, actualState.GetPreimageOffset(), fmt.Sprintf("Expect preimageOffset = %v", e.PreimageOffset))
require.Equal(t, e.PC, actualState.GetCpu().PC, fmt.Sprintf("Expect PC = 0x%x", e.PC))
require.Equal(t, e.NextPC, actualState.GetCpu().NextPC, fmt.Sprintf("Expect nextPC = 0x%x", e.NextPC))
require.Equal(t, e.HI, actualState.GetCpu().HI, fmt.Sprintf("Expect HI = 0x%x", e.HI))
require.Equal(t, e.LO, actualState.GetCpu().LO, fmt.Sprintf("Expect LO = 0x%x", e.LO))
require.Equal(t, e.Heap, actualState.GetHeap(), fmt.Sprintf("Expect heap = 0x%x", e.Heap))
require.Equal(t, e.ExitCode, actualState.GetExitCode(), fmt.Sprintf("Expect exitCode = 0x%x", e.ExitCode))
require.Equal(t, e.Exited, actualState.GetExited(), fmt.Sprintf("Expect exited = %v", e.Exited))
require.Equal(t, e.Step, actualState.GetStep(), fmt.Sprintf("Expect step = %d", e.Step))
if !slices.Contains(flags, SkipHintValidation) {
require.Equal(t, e.LastHint, actualState.GetLastHint(), fmt.Sprintf("Expect lastHint = %v", e.LastHint))
}
require.Equal(t, e.Registers, *actualState.GetRegistersRef(), fmt.Sprintf("Expect registers = %v", e.Registers))
if !slices.Contains(flags, SkipMemoryValidation) {
require.Equal(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), fmt.Sprintf("Expect memory root = %v", e.MemoryRoot))
}
}
func randHash(r *rand.Rand) common.Hash {
var bytes [32]byte
_, err := r.Read(bytes[:])
if err != nil {
panic(err)
}
return bytes
}
func randHint(r *rand.Rand) []byte {
count := r.Intn(10)
bytes := make([]byte, count)
_, err := r.Read(bytes[:])
if err != nil {
panic(err)
}
return bytes
}
func randRegisters(r *rand.Rand) *[32]uint32 {
registers := new([32]uint32)
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
registers[i] = r.Uint32() registers[i] = r.Uint32()
} }
return registers return registers
} }
func CopyRegisters(state mipsevm.FPVMState) *[32]uint32 { func RandomBytes(t require.TestingT, seed int64, length uint32) []byte {
copy := new([32]uint32) r := rand.New(rand.NewSource(seed))
*copy = *state.GetRegistersRef() randBytes := make([]byte, length)
return copy if _, err := r.Read(randBytes); err != nil {
require.NoError(t, err)
}
return randBytes
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment