Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cannon-contracts): MIPS64 conversion #11404

Open
wants to merge 6 commits into
base: cl/cannon-64bit
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cannon/mipsevm/exec/mips_instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint64) uint64 {
return uint64(int64(rt) >> ((insn >> 6) & 0x1f))
case 0x3C: // dsll32
return rt << (((insn >> 6) & 0x1f) + 32)
case 0x3E: // dsll32
case 0x3E: // dsrl32
return rt >> (((insn >> 6) & 0x1f) + 32)
case 0x3F: // dsll32
case 0x3F: // dsra32
return uint64(int64(rt) >> (((insn >> 6) & 0x1f) + 32))
default:
panic(fmt.Sprintf("invalid instruction: %x", insn))
Expand Down Expand Up @@ -315,7 +315,7 @@ func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint64) uint64 {
sl := 24 - ((rs & 3) << 3)
val := ((rt & 0xFFFFFFFF) << sl) << (32 - ((rs & 0x4) << 3))
mask := uint64(uint32(0xFFFFFFFF)<<sl) << (32 - ((rs & 0x4) << 3))
return (mem & ^mask) | val
return (mem & ^mask) | (val & mask)
case 0x30: // ll
return SignExtend((mem>>(32-((rs&0x4)<<3)))&0xFFFFFFFF, 32)
case 0x38: // sc
Expand Down
12 changes: 6 additions & 6 deletions cannon/mipsevm/tests/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ func TestEVM(t *testing.T) {
"mipsevm produced different state than EVM at step %d", state.Step)
}
if exitGroup {
require.NotEqual(t, uint32(testutil.EndAddr), goState.GetState().GetPC(), "must not reach end")
require.NotEqual(t, uint64(testutil.EndAddr), goState.GetState().GetPC(), "must not reach end")
require.True(t, goState.GetState().GetExited(), "must set exited state")
require.Equal(t, uint8(1), goState.GetState().GetExitCode(), "must exit with 1")
} else {
require.Equal(t, uint32(testutil.EndAddr), state.Cpu.PC, "must reach end")
require.Equal(t, uint64(testutil.EndAddr), state.Cpu.PC, "must reach end")
// inspect test result
done, result := state.Memory.GetMemory(testutil.BaseAddrEnd+4), state.Memory.GetMemory(testutil.BaseAddrEnd+8)
require.Equal(t, done, uint32(1), "must be done")
require.Equal(t, result, uint32(1), "must have success result")
done, result := uint64(state.Memory.GetMemory(testutil.BaseAddrEnd+4)), uint64(state.Memory.GetMemory(testutil.BaseAddrEnd+8))
require.Equal(t, done, uint64(1), "must be done")
require.Equal(t, result, uint64(1), "must have success result")
}
})
}
Expand Down Expand Up @@ -387,7 +387,7 @@ func TestEVMFault(t *testing.T) {
nextPC uint64
insn uint32
}{
{"illegal instruction", 0, 0xFF_FF_FF_FF},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a valid SD instruction, fyi

{"illegal instruction", 0, 0xbe_ef_be_ef},
{"branch in delay-slot", 8, 0x11_02_00_03},
{"jump in delay-slot", 8, 0x0c_00_00_0c},
}
Expand Down
100 changes: 50 additions & 50 deletions cannon/mipsevm/tests/fuzz_evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const syscallInsn = uint32(0x00_00_00_0c)
func FuzzStateSyscallBrk(f *testing.F) {
contracts, addrs := testContractsSetup(f)
f.Fuzz(func(t *testing.T, pc uint64, step uint64, preimageOffset uint64) {
pc = pc & 0xFF_FF_FF_FC // align PC
pc = pc & 0xFFFFFFFFFFFFFFF8 // align PC
nextPC := pc + 4
state := &singlethreaded.State{
Cpu: mipsevm.CpuScalars{
Expand Down Expand Up @@ -54,9 +54,9 @@ func FuzzStateSyscallBrk(f *testing.F) {

require.Equal(t, pc+4, state.Cpu.PC)
require.Equal(t, nextPC+4, state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
Expand All @@ -76,7 +76,7 @@ func FuzzStateSyscallBrk(f *testing.F) {
func FuzzStateSyscallClone(f *testing.F) {
contracts, addrs := testContractsSetup(f)
f.Fuzz(func(t *testing.T, pc uint64, step uint64, preimageOffset uint64) {
pc = pc & 0xFF_FF_FF_FC // align PC
pc = pc & 0xFFFFFFFFFFFFFFF8 // align PC
nextPC := pc + 4
state := &singlethreaded.State{
Cpu: mipsevm.CpuScalars{
Expand Down Expand Up @@ -105,9 +105,9 @@ func FuzzStateSyscallClone(f *testing.F) {

require.Equal(t, pc+4, state.Cpu.PC)
require.Equal(t, nextPC+4, state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
Expand Down Expand Up @@ -152,16 +152,16 @@ func FuzzStateSyscallMmap(f *testing.F) {
require.NoError(t, err)
require.False(t, stepWitness.HasPreimage())

require.Equal(t, uint32(4), state.Cpu.PC)
require.Equal(t, uint32(8), state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint64(4), state.Cpu.PC)
require.Equal(t, uint64(8), state.Cpu.NextPC)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
require.Equal(t, uint64(1), state.Step)
require.Equal(t, common.Hash{}, state.PreimageKey)
require.Equal(t, uint32(0), state.PreimageOffset)
require.Equal(t, uint64(0), state.PreimageOffset)
if addr == 0 {
expectedRegisters := preStateRegisters
expectedRegisters[2] = heap
Expand All @@ -170,12 +170,12 @@ func FuzzStateSyscallMmap(f *testing.F) {
if sizAlign&memory.PageAddrMask != 0 { // adjust size to align with page size
sizAlign = siz + memory.PageSize - (siz & memory.PageAddrMask)
}
require.Equal(t, uint32(heap+sizAlign), state.Heap)
require.Equal(t, uint64(heap+sizAlign), state.Heap)
} else {
expectedRegisters := preStateRegisters
expectedRegisters[2] = addr
require.Equal(t, expectedRegisters, state.Registers)
require.Equal(t, uint32(heap), state.Heap)
require.Equal(t, uint64(heap), state.Heap)
}

evm := testutil.NewMIPSEVM(contracts, addrs)
Expand All @@ -189,7 +189,7 @@ func FuzzStateSyscallMmap(f *testing.F) {
func FuzzStateSyscallExitGroup(f *testing.F) {
contracts, addrs := testContractsSetup(f)
f.Fuzz(func(t *testing.T, exitCode uint8, pc uint64, step uint64) {
pc = pc & 0xFF_FF_FF_FC // align PC
pc = pc & 0xFFFFFFFFFFFFFFF8 // align PC
nextPC := pc + 4
state := &singlethreaded.State{
Cpu: mipsevm.CpuScalars{
Expand Down Expand Up @@ -217,16 +217,16 @@ func FuzzStateSyscallExitGroup(f *testing.F) {

require.Equal(t, pc, state.Cpu.PC)
require.Equal(t, nextPC, state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(exitCode), state.ExitCode)
require.Equal(t, true, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
require.Equal(t, preStateRegisters, state.Registers)
require.Equal(t, step+1, state.Step)
require.Equal(t, common.Hash{}, state.PreimageKey)
require.Equal(t, uint32(0), state.PreimageOffset)
require.Equal(t, uint64(0), state.PreimageOffset)

evm := testutil.NewMIPSEVM(contracts, addrs)
evmPost := evm.Step(t, stepWitness, step, singlethreaded.GetStateHashFn())
Expand Down Expand Up @@ -264,17 +264,17 @@ func FuzzStateSyscallFcntl(f *testing.F) {
require.NoError(t, err)
require.False(t, stepWitness.HasPreimage())

require.Equal(t, uint32(4), state.Cpu.PC)
require.Equal(t, uint32(8), state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(4), state.Cpu.PC)
require.Equal(t, uint64(8), state.Cpu.NextPC)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
require.Equal(t, uint64(1), state.Step)
require.Equal(t, common.Hash{}, state.PreimageKey)
require.Equal(t, uint32(0), state.PreimageOffset)
require.Equal(t, uint64(0), state.PreimageOffset)
if cmd == 3 {
expectedRegisters := preStateRegisters
switch fd {
Expand All @@ -283,13 +283,13 @@ func FuzzStateSyscallFcntl(f *testing.F) {
case exec.FdStdout, exec.FdStderr, exec.FdPreimageWrite, exec.FdHintWrite:
expectedRegisters[2] = 1
default:
expectedRegisters[2] = 0xFF_FF_FF_FF
expectedRegisters[2] = 0xFF_FF_FF_FF_FF_FF_FF_FF
expectedRegisters[7] = exec.MipsEBADF
}
require.Equal(t, expectedRegisters, state.Registers)
} else {
expectedRegisters := preStateRegisters
expectedRegisters[2] = 0xFF_FF_FF_FF
expectedRegisters[2] = 0xFF_FF_FF_FF_FF_FF_FF_FF
expectedRegisters[7] = exec.MipsEINVAL
require.Equal(t, expectedRegisters, state.Registers)
}
Expand Down Expand Up @@ -335,11 +335,11 @@ func FuzzStateHintRead(f *testing.F) {
require.NoError(t, err)
require.False(t, stepWitness.HasPreimage())

require.Equal(t, uint32(4), state.Cpu.PC)
require.Equal(t, uint32(8), state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(4), state.Cpu.PC)
require.Equal(t, uint64(8), state.Cpu.NextPC)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
Expand Down Expand Up @@ -396,11 +396,11 @@ func FuzzStatePreimageRead(f *testing.F) {
require.NoError(t, err)
require.True(t, stepWitness.HasPreimage())

require.Equal(t, uint32(4), state.Cpu.PC)
require.Equal(t, uint32(8), state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(4), state.Cpu.PC)
require.Equal(t, uint64(8), state.Cpu.NextPC)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
if writeLen > 0 {
Expand Down Expand Up @@ -463,11 +463,11 @@ func FuzzStateHintWrite(f *testing.F) {
require.NoError(t, err)
require.False(t, stepWitness.HasPreimage())

require.Equal(t, uint32(4), state.Cpu.PC)
require.Equal(t, uint32(8), state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(4), state.Cpu.PC)
require.Equal(t, uint64(8), state.Cpu.NextPC)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
Expand Down Expand Up @@ -507,7 +507,7 @@ func FuzzStatePreimageWrite(f *testing.F) {
state.Memory.SetMemory(0, syscallInsn)
preStateRoot := state.Memory.MerkleRoot()
expectedRegisters := state.Registers
sz := 4 - (addr & 0x3)
sz := 8 - (addr & 0x7)
if sz < count {
count = sz
}
Expand All @@ -519,16 +519,16 @@ func FuzzStatePreimageWrite(f *testing.F) {
require.NoError(t, err)
require.False(t, stepWitness.HasPreimage())

require.Equal(t, uint32(4), state.Cpu.PC)
require.Equal(t, uint32(8), state.Cpu.NextPC)
require.Equal(t, uint32(0), state.Cpu.LO)
require.Equal(t, uint32(0), state.Cpu.HI)
require.Equal(t, uint32(0), state.Heap)
require.Equal(t, uint64(4), state.Cpu.PC)
require.Equal(t, uint64(8), state.Cpu.NextPC)
require.Equal(t, uint64(0), state.Cpu.LO)
require.Equal(t, uint64(0), state.Cpu.HI)
require.Equal(t, uint64(0), state.Heap)
require.Equal(t, uint8(0), state.ExitCode)
require.Equal(t, false, state.Exited)
require.Equal(t, preStateRoot, state.Memory.MerkleRoot())
require.Equal(t, uint64(1), state.Step)
require.Equal(t, uint32(0), state.PreimageOffset)
require.Equal(t, uint64(0), state.PreimageOffset)
require.Equal(t, expectedRegisters, state.Registers)

evm := testutil.NewMIPSEVM(contracts, addrs)
Expand Down
2 changes: 1 addition & 1 deletion op-program/Dockerfile.repro
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build cd cannon && make cannon \
RUN --mount=type=cache,target=/root/.cache/go-build cd op-program && make op-program-host \
GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROGRAM_VERSION"
RUN --mount=type=cache,target=/root/.cache/go-build cd op-program && make op-program-client-mips \
GOOS=linux GOARCH=mips GOMIPS=softfloat GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROGRAM_VERSION"
GOOS=linux GOARCH=mips64 GOMIPS64=softfloat GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROGRAM_VERSION"

# Run the op-program-client.elf binary directly through cannon's load-elf subcommand.
RUN /app/cannon/bin/cannon load-elf --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.json --meta ""
Expand Down
63 changes: 48 additions & 15 deletions packages/contracts-bedrock/scripts/go-ffi/differential-testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,22 +364,55 @@ func DiffTestUtils() {
if len(args) != 3 && len(args) != 5 {
panic("Error: cannonMemoryProofWithProof requires 2 or 4 arguments")
}
pc, err := strconv.ParseUint(args[1], 10, 32)
pc, err := strconv.ParseUint(args[1], 10, 64)
checkErr(err, "Error decoding addr")
insn, err := strconv.ParseUint(args[2], 10, 32)
checkErr(err, "Error decoding insn")
mem.SetMemory(uint32(pc), uint32(insn))
mem.SetMemory(uint64(pc), uint32(insn))

var insnProof, memProof [896]byte
var insnProof, memProof [1920]byte
if len(args) == 5 {
memAddr, err := strconv.ParseUint(args[3], 10, 32)
memAddr, err := strconv.ParseUint(args[3], 10, 64)
checkErr(err, "Error decoding memAddr")
memValue, err := strconv.ParseUint(args[4], 10, 32)
checkErr(err, "Error decoding memValue")
mem.SetMemory(uint32(memAddr), uint32(memValue))
memProof = mem.MerkleProof(uint32(memAddr))
mem.SetMemory(uint64(memAddr), uint32(memValue))
memProof = mem.MerkleProof(uint64(memAddr))
}
insnProof = mem.MerkleProof(uint32(pc))
insnProof = mem.MerkleProof(uint64(pc))

output := struct {
MemRoot common.Hash
Proof []byte
}{
MemRoot: mem.MerkleRoot(),
Proof: append(insnProof[:], memProof[:]...),
}
packed, err := cannonMemoryProofArgs.Pack(&output)
checkErr(err, "Error encoding output")
fmt.Print(hexutil.Encode(packed[32:]))
case "cannonMemoryProofDoubleWord":
// <pc, insn, [memAddr, memValue]>
mem := memory.NewMemory()
if len(args) != 3 && len(args) != 5 {
panic("Error: cannonMemoryProofWithProof requires 2 or 4 arguments")
}
pc, err := strconv.ParseUint(args[1], 10, 64)
checkErr(err, "Error decoding addr")
insn, err := strconv.ParseUint(args[2], 10, 32)
checkErr(err, "Error decoding insn")
mem.SetMemory(uint64(pc), uint32(insn))

var insnProof, memProof [1920]byte
if len(args) == 5 {
memAddr, err := strconv.ParseUint(args[3], 10, 64)
checkErr(err, "Error decoding memAddr")
memValue, err := strconv.ParseUint(args[4], 10, 64)
checkErr(err, "Error decoding memValue")
mem.SetDoubleWord(uint64(memAddr), uint64(memValue))
memProof = mem.MerkleProof(uint64(memAddr))
}
insnProof = mem.MerkleProof(uint64(pc))

output := struct {
MemRoot common.Hash
Expand All @@ -397,22 +430,22 @@ func DiffTestUtils() {
if len(args) != 5 {
panic("Error: cannonMemoryProofWrongLeaf requires 4 arguments")
}
pc, err := strconv.ParseUint(args[1], 10, 32)
pc, err := strconv.ParseUint(args[1], 10, 64)
checkErr(err, "Error decoding addr")
insn, err := strconv.ParseUint(args[2], 10, 32)
checkErr(err, "Error decoding insn")
mem.SetMemory(uint32(pc), uint32(insn))
mem.SetMemory(uint64(pc), uint32(insn))

var insnProof, memProof [896]byte
memAddr, err := strconv.ParseUint(args[3], 10, 32)
var insnProof, memProof [1920]byte
memAddr, err := strconv.ParseUint(args[3], 10, 64)
checkErr(err, "Error decoding memAddr")
memValue, err := strconv.ParseUint(args[4], 10, 32)
memValue, err := strconv.ParseUint(args[4], 10, 64)
checkErr(err, "Error decoding memValue")
mem.SetMemory(uint32(memAddr), uint32(memValue))
mem.SetDoubleWord(uint64(memAddr), uint64(memValue))

// Compute a valid proof for the root, but for the wrong leaves.
memProof = mem.MerkleProof(uint32(memAddr + 32))
insnProof = mem.MerkleProof(uint32(pc + 32))
memProof = mem.MerkleProof(uint64(memAddr + 32))
insnProof = mem.MerkleProof(uint64(pc + 32))

output := struct {
MemRoot common.Hash
Expand Down
Loading