Commit 73d56a9d authored by mbaxter's avatar mbaxter Committed by GitHub

cannon: Encapsulate syscall helpers (#10978)

* cannon: Increment MIPS.sol version

* cannon: Add syscall args helper

* cannon: Extract mmap helper

* cannon: Extract sysRead helper

Also:
- Extract solidity memory helpers into new lib.
- Reorganize syscall constants.

* cannon: Add NatSpec documentation to solidity syscall helpers

* cannon: Extract sysWrite helper

* cannon: Use consistent naming convention

* cannon: Extract sysFcntl helper, fix typos

* cannon: Consolidate comments, fix formatting

* cannon: Add helper for setting registers, pc fields

* cannon: Reorganize syscall constants

* cannon: Fix MIPSMemory import

* cannon: Run semver-lock and snapshots

* cannon: Explicitly inject proof offsets into helper fns

Proofs offsets may differ between implementations, so these values must
be passed into helper functions rather than calculated internally.

* cannon: Remove hard-coded state.memRoot references from MIPSMemory.sol

* cannon: Work around stack too deep error

* cannon: Rework stack-too-deep fix

* cannon: Run semver-lock and snapshots

* cannon: Validate calldata size directly in readMem, writeMem

* cannon: Run semver-lock and snapshots
parent d8bde214
...@@ -30,7 +30,7 @@ fuzz: ...@@ -30,7 +30,7 @@ fuzz:
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallClone ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallClone ./mipsevm
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallMmap ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallMmap ./mipsevm
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallExitGroup ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallExitGroup ./mipsevm
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallFnctl ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallFcntl ./mipsevm
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateHintRead ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateHintRead ./mipsevm
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 20s -fuzz=FuzzStatePreimageRead ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 20s -fuzz=FuzzStatePreimageRead ./mipsevm
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateHintWrite ./mipsevm go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateHintWrite ./mipsevm
......
...@@ -229,7 +229,7 @@ func FuzzStateSyscallExitGroup(f *testing.F) { ...@@ -229,7 +229,7 @@ func FuzzStateSyscallExitGroup(f *testing.F) {
}) })
} }
func FuzzStateSyscallFnctl(f *testing.F) { func FuzzStateSyscallFcntl(f *testing.F) {
contracts, addrs := testContractsSetup(f) contracts, addrs := testContractsSetup(f)
f.Fuzz(func(t *testing.T, fd uint32, cmd uint32) { f.Fuzz(func(t *testing.T, fd uint32, cmd uint32) {
state := &State{ state := &State{
......
...@@ -39,21 +39,6 @@ type InstrumentedState struct { ...@@ -39,21 +39,6 @@ type InstrumentedState struct {
debugEnabled bool debugEnabled bool
} }
const (
fdStdin = 0
fdStdout = 1
fdStderr = 2
fdHintRead = 3
fdHintWrite = 4
fdPreimageRead = 5
fdPreimageWrite = 6
)
const (
MipsEBADF = 0x9
MipsEINVAL = 0x16
)
func NewInstrumentedState(state *State, po PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState { func NewInstrumentedState(state *State, po PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState {
return &InstrumentedState{ return &InstrumentedState{
state: state, state: state,
......
...@@ -3,17 +3,9 @@ package mipsevm ...@@ -3,17 +3,9 @@ package mipsevm
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io"
)
const ( "github.com/ethereum/go-ethereum/common"
sysMmap = 4090 "github.com/ethereum/go-ethereum/common/hexutil"
sysBrk = 4045
sysClone = 4120
sysExitGroup = 4246
sysRead = 4003
sysWrite = 4004
sysFcntl = 4055
) )
func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) { func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) {
...@@ -43,29 +35,17 @@ func (m *InstrumentedState) trackMemAccess(effAddr uint32) { ...@@ -43,29 +35,17 @@ func (m *InstrumentedState) trackMemAccess(effAddr uint32) {
} }
func (m *InstrumentedState) handleSyscall() error { func (m *InstrumentedState) handleSyscall() error {
syscallNum := m.state.Registers[2] // v0 syscallNum, a0, a1, a2 := getSyscallArgs(&m.state.Registers)
v0 := uint32(0) v0 := uint32(0)
v1 := uint32(0) v1 := uint32(0)
a0 := m.state.Registers[4]
a1 := m.state.Registers[5]
a2 := m.state.Registers[6]
//fmt.Printf("syscall: %d\n", syscallNum) //fmt.Printf("syscall: %d\n", syscallNum)
switch syscallNum { switch syscallNum {
case sysMmap: case sysMmap:
sz := a1 var newHeap uint32
if sz&PageAddrMask != 0 { // adjust size to align with page size v0, v1, newHeap = handleSysMmap(a0, a1, m.state.Heap)
sz += PageSize - (sz & PageAddrMask) m.state.Heap = newHeap
}
if a0 == 0 {
v0 = m.state.Heap
//fmt.Printf("mmap heap 0x%x size 0x%x\n", v0, sz)
m.state.Heap += sz
} else {
v0 = a0
//fmt.Printf("mmap hint 0x%x size 0x%x\n", v0, sz)
}
case sysBrk: case sysBrk:
v0 = 0x40000000 v0 = 0x40000000
case sysClone: // clone (not supported) case sysClone: // clone (not supported)
...@@ -75,107 +55,22 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -75,107 +55,22 @@ func (m *InstrumentedState) handleSyscall() error {
m.state.ExitCode = uint8(a0) m.state.ExitCode = uint8(a0)
return nil return nil
case sysRead: case sysRead:
// args: a0 = fd, a1 = addr, a2 = count var newPreimageOffset uint32
// returns: v0 = read, v1 = err code v0, v1, newPreimageOffset = handleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.readPreimage, m.state.Memory, m.trackMemAccess)
switch a0 { m.state.PreimageOffset = newPreimageOffset
case fdStdin:
// leave v0 and v1 zero: read nothing, no error
case fdPreimageRead: // pre-image oracle
effAddr := a1 & 0xFFffFFfc
m.trackMemAccess(effAddr)
mem := m.state.Memory.GetMemory(effAddr)
dat, datLen := m.readPreimage(m.state.PreimageKey, m.state.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)
alignment := a1 & 3
space := 4 - alignment
if space < datLen {
datLen = space
}
if a2 < datLen {
datLen = a2
}
var outMem [4]byte
binary.BigEndian.PutUint32(outMem[:], mem)
copy(outMem[alignment:], dat[:datLen])
m.state.Memory.SetMemory(effAddr, binary.BigEndian.Uint32(outMem[:]))
m.state.PreimageOffset += datLen
v0 = datLen
//fmt.Printf("read %d pre-image bytes, new offset: %d, eff addr: %08x mem: %08x\n", datLen, m.state.PreimageOffset, effAddr, outMem)
case fdHintRead: // hint response
// don't actually read into memory, just say we read it all, we ignore the result anyway
v0 = a2
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
case sysWrite: case sysWrite:
// args: a0 = fd, a1 = addr, a2 = count var newLastHint hexutil.Bytes
// returns: v0 = written, v1 = err code var newPreimageKey common.Hash
switch a0 { var newPreimageOffset uint32
case fdStdout: v0, v1, newLastHint, newPreimageKey, newPreimageOffset = handleSysWrite(a0, a1, a2, m.state.LastHint, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.trackMemAccess, m.stdOut, m.stdErr)
_, _ = io.Copy(m.stdOut, m.state.Memory.ReadMemoryRange(a1, a2)) m.state.LastHint = newLastHint
v0 = a2 m.state.PreimageKey = newPreimageKey
case fdStderr: m.state.PreimageOffset = newPreimageOffset
_, _ = io.Copy(m.stdErr, m.state.Memory.ReadMemoryRange(a1, a2))
v0 = a2
case fdHintWrite:
hintData, _ := io.ReadAll(m.state.Memory.ReadMemoryRange(a1, a2))
m.state.LastHint = append(m.state.LastHint, hintData...)
for len(m.state.LastHint) >= 4 { // process while there is enough data to check if there are any hints
hintLen := binary.BigEndian.Uint32(m.state.LastHint[:4])
if hintLen <= uint32(len(m.state.LastHint[4:])) {
hint := m.state.LastHint[4 : 4+hintLen] // without the length prefix
m.state.LastHint = m.state.LastHint[4+hintLen:]
m.preimageOracle.Hint(hint)
} else {
break // stop processing hints if there is incomplete data buffered
}
}
v0 = a2
case fdPreimageWrite:
effAddr := a1 & 0xFFffFFfc
m.trackMemAccess(effAddr)
mem := m.state.Memory.GetMemory(effAddr)
key := m.state.PreimageKey
alignment := a1 & 3
space := 4 - alignment
if space < a2 {
a2 = space
}
copy(key[:], key[a2:])
var tmp [4]byte
binary.BigEndian.PutUint32(tmp[:], mem)
copy(key[32-a2:], tmp[alignment:])
m.state.PreimageKey = key
m.state.PreimageOffset = 0
//fmt.Printf("updating pre-image key: %s\n", m.state.PreimageKey)
v0 = a2
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
case sysFcntl: case sysFcntl:
// args: a0 = fd, a1 = cmd v0, v1 = handleSysFcntl(a0, a1)
if a1 == 3 { // F_GETFL: get file descriptor flags
switch a0 {
case fdStdin, fdPreimageRead, fdHintRead:
v0 = 0 // O_RDONLY
case fdStdout, fdStderr, fdPreimageWrite, fdHintWrite:
v0 = 1 // O_WRONLY
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
} else {
v0 = 0xFFffFFff
v1 = MipsEINVAL // cmd not recognized by this kernel
}
} }
m.state.Registers[2] = v0
m.state.Registers[7] = v1
m.state.Cpu.PC = m.state.Cpu.NextPC handleSyscallUpdates(&m.state.Cpu, &m.state.Registers, v0, v1)
m.state.Cpu.NextPC = m.state.Cpu.NextPC + 4
return nil return nil
} }
......
package mipsevm
import (
"encoding/binary"
"io"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
const (
sysMmap = 4090
sysBrk = 4045
sysClone = 4120
sysExitGroup = 4246
sysRead = 4003
sysWrite = 4004
sysFcntl = 4055
)
const (
fdStdin = 0
fdStdout = 1
fdStderr = 2
fdHintRead = 3
fdHintWrite = 4
fdPreimageRead = 5
fdPreimageWrite = 6
)
const (
MipsEBADF = 0x9
MipsEINVAL = 0x16
)
type PreimageReader func(key [32]byte, offset uint32) (dat [32]byte, datLen uint32)
type MemTracker func(addr uint32)
func getSyscallArgs(registers *[32]uint32) (syscallNum, a0, a1, a2 uint32) {
syscallNum = registers[2] // v0
a0 = registers[4]
a1 = registers[5]
a2 = registers[6]
return syscallNum, a0, a1, a2
}
func handleSysMmap(a0, a1, heap uint32) (v0, v1, newHeap uint32) {
v1 = uint32(0)
newHeap = heap
sz := a1
if sz&PageAddrMask != 0 { // adjust size to align with page size
sz += PageSize - (sz & PageAddrMask)
}
if a0 == 0 {
v0 = heap
//fmt.Printf("mmap heap 0x%x size 0x%x\n", v0, sz)
newHeap += sz
} else {
v0 = a0
//fmt.Printf("mmap hint 0x%x size 0x%x\n", v0, sz)
}
return v0, v1, newHeap
}
func handleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *Memory, memTracker MemTracker) (v0, v1, newPreimageOffset uint32) {
// args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = read, v1 = err code
v0 = uint32(0)
v1 = uint32(0)
newPreimageOffset = preimageOffset
switch a0 {
case fdStdin:
// leave v0 and v1 zero: read nothing, no error
case fdPreimageRead: // pre-image oracle
effAddr := a1 & 0xFFffFFfc
memTracker(effAddr)
mem := memory.GetMemory(effAddr)
dat, datLen := preimageReader(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)
alignment := a1 & 3
space := 4 - alignment
if space < datLen {
datLen = space
}
if a2 < datLen {
datLen = a2
}
var outMem [4]byte
binary.BigEndian.PutUint32(outMem[:], mem)
copy(outMem[alignment:], dat[:datLen])
memory.SetMemory(effAddr, binary.BigEndian.Uint32(outMem[:]))
newPreimageOffset += datLen
v0 = datLen
//fmt.Printf("read %d pre-image bytes, new offset: %d, eff addr: %08x mem: %08x\n", datLen, m.state.PreimageOffset, effAddr, outMem)
case fdHintRead: // hint response
// don't actually read into memory, just say we read it all, we ignore the result anyway
v0 = a2
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
return v0, v1, newPreimageOffset
}
func handleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]byte, preimageOffset uint32, oracle PreimageOracle, memory *Memory, memTracker MemTracker, stdOut, stdErr io.Writer) (v0, v1 uint32, newLastHint hexutil.Bytes, newPreimageKey common.Hash, newPreimageOffset uint32) {
// args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = written, v1 = err code
v1 = uint32(0)
newLastHint = lastHint
newPreimageKey = preimageKey
newPreimageOffset = preimageOffset
switch a0 {
case fdStdout:
_, _ = io.Copy(stdOut, memory.ReadMemoryRange(a1, a2))
v0 = a2
case fdStderr:
_, _ = io.Copy(stdErr, memory.ReadMemoryRange(a1, a2))
v0 = a2
case fdHintWrite:
hintData, _ := io.ReadAll(memory.ReadMemoryRange(a1, a2))
lastHint = append(lastHint, hintData...)
for len(lastHint) >= 4 { // process while there is enough data to check if there are any hints
hintLen := binary.BigEndian.Uint32(lastHint[:4])
if hintLen <= uint32(len(lastHint[4:])) {
hint := lastHint[4 : 4+hintLen] // without the length prefix
lastHint = lastHint[4+hintLen:]
oracle.Hint(hint)
} else {
break // stop processing hints if there is incomplete data buffered
}
}
newLastHint = lastHint
v0 = a2
case fdPreimageWrite:
effAddr := a1 & 0xFFffFFfc
memTracker(effAddr)
mem := memory.GetMemory(effAddr)
key := preimageKey
alignment := a1 & 3
space := 4 - alignment
if space < a2 {
a2 = space
}
copy(key[:], key[a2:])
var tmp [4]byte
binary.BigEndian.PutUint32(tmp[:], mem)
copy(key[32-a2:], tmp[alignment:])
newPreimageKey = key
newPreimageOffset = 0
//fmt.Printf("updating pre-image key: %s\n", m.state.PreimageKey)
v0 = a2
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
return v0, v1, newLastHint, newPreimageKey, newPreimageOffset
}
func handleSysFcntl(a0, a1 uint32) (v0, v1 uint32) {
// args: a0 = fd, a1 = cmd
v1 = uint32(0)
if a1 == 3 { // F_GETFL: get file descriptor flags
switch a0 {
case fdStdin, fdPreimageRead, fdHintRead:
v0 = 0 // O_RDONLY
case fdStdout, fdStderr, fdPreimageWrite, fdHintWrite:
v0 = 1 // O_WRONLY
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
} else {
v0 = 0xFFffFFff
v1 = MipsEINVAL // cmd not recognized by this kernel
}
return v0, v1
}
func handleSyscallUpdates(cpu *CpuScalars, registers *[32]uint32, v0, v1 uint32) {
registers[2] = v0
registers[7] = v1
cpu.PC = cpu.NextPC
cpu.NextPC = cpu.NextPC + 4
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
.ent test .ent test
test: test:
# fnctl(0, 3) # fcntl(0, 3)
li $v0, 4055 li $v0, 4055
li $a0, 0x0 li $a0, 0x0
li $a1, 0x3 li $a1, 0x3
......
...@@ -124,8 +124,8 @@ ...@@ -124,8 +124,8 @@
"sourceCodeHash": "0x3ff4a3f21202478935412d47fd5ef7f94a170402ddc50e5c062013ce5544c83f" "sourceCodeHash": "0x3ff4a3f21202478935412d47fd5ef7f94a170402ddc50e5c062013ce5544c83f"
}, },
"src/cannon/MIPS.sol": { "src/cannon/MIPS.sol": {
"initCodeHash": "0x1742f31c43d067f94e669e50e632875ba2a2795127ea5bf429acf7ed39ddbc48", "initCodeHash": "0xe9183ee3b69d9ec9594d6b3923d78c86c996cd738ccbc09675bb281284c060af",
"sourceCodeHash": "0xa50b47ddaee92c52c5f7cfb4b526f9d734c2eec524e7bb609b991d608f124c02" "sourceCodeHash": "0x7c2eab73da8b2eeadba30eadb39f20e91307bc29218938fadfc5f73fadcf13bc"
}, },
"src/cannon/PreimageOracle.sol": { "src/cannon/PreimageOracle.sol": {
"initCodeHash": "0xe5db668fe41436f53995e910488c7c140766ba8745e19743773ebab508efd090", "initCodeHash": "0xe5db668fe41436f53995e910488c7c140766ba8745e19743773ebab508efd090",
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
library MIPSMemory {
/// @notice Reads a 32-bit value from memory.
/// @param _memRoot The current memory root
/// @param _addr The address to read from.
/// @param _proofOffset The offset of the memory proof in calldata.
/// @return out_ The hashed MIPS state.
function readMem(bytes32 _memRoot, uint32 _addr, uint256 _proofOffset) internal pure returns (uint32 out_) {
unchecked {
validateMemoryProofAvailability(_proofOffset);
assembly {
// Validate the address alignement.
if and(_addr, 3) { revert(0, 0) }
// Load the leaf value.
let leaf := calldataload(_proofOffset)
_proofOffset := add(_proofOffset, 32)
// Convenience function to hash two nodes together in scratch space.
function hashPair(a, b) -> h {
mstore(0, a)
mstore(32, b)
h := keccak256(0, 64)
}
// Start with the leaf node.
// Work back up by combining with siblings, to reconstruct the root.
let path := shr(5, _addr)
let node := leaf
for { let i := 0 } lt(i, 27) { i := add(i, 1) } {
let sibling := calldataload(_proofOffset)
_proofOffset := add(_proofOffset, 32)
switch and(shr(i, path), 1)
case 0 { node := hashPair(node, sibling) }
case 1 { node := hashPair(sibling, node) }
}
// Verify the root matches.
if iszero(eq(node, _memRoot)) {
mstore(0, 0x0badf00d)
revert(0, 32)
}
// Bits to shift = (32 - 4 - (addr % 32)) * 8
let shamt := shl(3, sub(sub(32, 4), and(_addr, 31)))
out_ := and(shr(shamt, leaf), 0xFFffFFff)
}
}
}
/// @notice Writes a 32-bit value to memory.
/// This function first overwrites the part of the leaf.
/// Then it recomputes the memory merkle root.
/// @param _addr The address to write to.
/// @param _proofOffset The offset of the memory proof in calldata.
/// @param _val The value to write.
/// @return newMemRoot_ The new memory root after modification
function writeMem(uint32 _addr, uint256 _proofOffset, uint32 _val) internal pure returns (bytes32 newMemRoot_) {
unchecked {
validateMemoryProofAvailability(_proofOffset);
assembly {
// Validate the address alignement.
if and(_addr, 3) { revert(0, 0) }
// Load the leaf value.
let leaf := calldataload(_proofOffset)
let shamt := shl(3, sub(sub(32, 4), and(_addr, 31)))
// Mask out 4 bytes, and OR in the value
leaf := or(and(leaf, not(shl(shamt, 0xFFffFFff))), shl(shamt, _val))
_proofOffset := add(_proofOffset, 32)
// Convenience function to hash two nodes together in scratch space.
function hashPair(a, b) -> h {
mstore(0, a)
mstore(32, b)
h := keccak256(0, 64)
}
// Start with the leaf node.
// Work back up by combining with siblings, to reconstruct the root.
let path := shr(5, _addr)
let node := leaf
for { let i := 0 } lt(i, 27) { i := add(i, 1) } {
let sibling := calldataload(_proofOffset)
_proofOffset := add(_proofOffset, 32)
switch and(shr(i, path), 1)
case 0 { node := hashPair(node, sibling) }
case 1 { node := hashPair(sibling, node) }
}
newMemRoot_ := node
}
}
return newMemRoot_;
}
/// @notice Computes the offset of a memory proof in the calldata.
/// @param _proofDataOffset The offset of the set of all memory proof data within calldata (proof.offset)
/// Equal to the offset of the first memory proof (at _proofIndex 0).
/// @param _proofIndex The index of the proof in the calldata.
/// @return offset_ The offset of the memory proof at the given _proofIndex in the calldata.
function memoryProofOffset(uint256 _proofDataOffset, uint8 _proofIndex) internal pure returns (uint256 offset_) {
unchecked {
// A proof of 32 bit memory, with 32-byte leaf values, is (32-5)=27 bytes32 entries.
// And the leaf value itself needs to be encoded as well: (27 + 1) = 28 bytes32 entries.
offset_ = _proofDataOffset + (uint256(_proofIndex) * (28 * 32));
return offset_;
}
}
/// @notice Validates that enough calldata is available to hold a full memory proof at the given offset
/// @param _proofStartOffset The index of the first byte of the target memory proof in calldata
function validateMemoryProofAvailability(uint256 _proofStartOffset) internal pure {
uint256 s = 0;
assembly {
s := calldatasize()
}
// A memory proof consists of 28 bytes32 values - verify we have enough calldata
require(s >= (_proofStartOffset + 28 * 32), "check that there is enough calldata");
}
}
...@@ -1470,7 +1470,7 @@ contract MIPS_Test is CommonTest { ...@@ -1470,7 +1470,7 @@ contract MIPS_Test is CommonTest {
function test_fcntl_succeeds() external { function test_fcntl_succeeds() external {
uint32 insn = 0x0000000c; // syscall uint32 insn = 0x0000000c; // syscall
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[2] = 4055; // fnctl syscall state.registers[2] = 4055; // fcntl syscall
state.registers[4] = 0x0; // a0 state.registers[4] = 0x0; // a0
state.registers[5] = 0x3; // a1 state.registers[5] = 0x3; // a1
......
...@@ -25,7 +25,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -25,7 +25,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865; address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865;
address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b;
address internal constant l1StandardBridgeProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; address internal constant l1StandardBridgeProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F;
address internal constant mipsAddress = 0x49E77cdE01fFBAB1266813b9a2FaADc1B757F435; address internal constant mipsAddress = 0x28bF1582225713139c0E898326Db808B6484cFd4;
address internal constant optimismPortal2Address = 0xfcbb237388CaF5b08175C9927a37aB6450acd535; address internal constant optimismPortal2Address = 0xfcbb237388CaF5b08175C9927a37aB6450acd535;
address internal constant optimismPortalProxyAddress = 0x978e3286EB805934215a88694d80b09aDed68D90; address internal constant optimismPortalProxyAddress = 0x978e3286EB805934215a88694d80b09aDed68D90;
address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75; address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75;
......
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