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

fix mips contracts stack too deep errors #13137

Merged
merged 1 commit into from
Dec 2, 2024
Merged
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
12 changes: 6 additions & 6 deletions packages/contracts-bedrock/snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,16 @@
"sourceCodeHash": "0x0fa0633a769e73f5937514c0003ba7947a1c275bbe5b85d78879c42f0ed8895b"
},
"src/cannon/MIPS.sol": {
"initCodeHash": "0xb4aec227019dacd6194d6aeb9ca68c23c60b95618d18a4ebc09243514aeb1f05",
"sourceCodeHash": "0x4d43b3f2918486aa76d2d59ac42e4f6aa2f58538c7e95a5cb99b63c9588b5f1c"
"initCodeHash": "0x2ad89ddfd9b6091af7fa4f337f6f0134b946838b53a056995eea5982e4b903c3",
"sourceCodeHash": "0xcd5f9762e641e4a1f6b07420ea3b2bfcaac5656da10c66a0f367ee4d4af37e9c"
},
"src/cannon/MIPS2.sol": {
"initCodeHash": "0xe3879b5772820d837bc1c77c32a1200eb26cf901d9302dff9f0e9759331e380e",
"sourceCodeHash": "0x1c45a8f4c8c9ded7043d63965cb114d17f801c6cd4d8233cb16838c5f9a02675"
"initCodeHash": "0x013e6005f56eae789a48ec9766d17c0be950d765ada3eb936c9a90337567c940",
"sourceCodeHash": "0xdd7684d0b8efd0bbee4abae76195c649b325ecd3e09f41b687cf3a091639c887"
},
"src/cannon/MIPS64.sol": {
"initCodeHash": "0xa4a761f480a26ec1926c5a8b4831440211c0441bd41d503b0aad189e030d35dc",
"sourceCodeHash": "0x7ddcf8584f9bd92abd1eb45bc198f5b0ec54acaf292f60e919d674cc56fb8abc"
"initCodeHash": "0xa5c2105b0d6f90d6f5ab1782f6d7acda505674a3c11355e0b401d66250406c0c",
"sourceCodeHash": "0x7cb189f5081c4aae84a7b23329309d944cb54f075ec18b03240d1725c03adc3b"
},
"src/cannon/PreimageOracle.sol": {
"initCodeHash": "0x2bef439027c37c65dd8e7d9a987ff14e1dba94ee5fe5f316a77ecf46a8db4b3f",
Expand Down
7 changes: 4 additions & 3 deletions packages/contracts-bedrock/src/cannon/MIPS.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ contract MIPS is ISemver {
}

/// @notice The semantic version of the MIPS contract.
/// @custom:semver 1.2.1-beta.8
string public constant version = "1.2.1-beta.8";
/// @custom:semver 1.2.1-beta.9
string public constant version = "1.2.1-beta.9";

/// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE;
Expand Down Expand Up @@ -183,7 +183,7 @@ contract MIPS is ISemver {
});
(v0, v1, state.preimageOffset, state.memRoot,,) = sys.handleSysRead(args);
} else if (syscall_no == sys.SYS_WRITE) {
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({
sys.SysWriteParams memory args = sys.SysWriteParams({
_a0: a0,
_a1: a1,
_a2: a2,
Expand All @@ -192,6 +192,7 @@ contract MIPS is ISemver {
_proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1),
_memRoot: state.memRoot
});
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite(args);
} else if (syscall_no == sys.SYS_FCNTL) {
(v0, v1) = sys.handleSysFcntl(a0, a1);
}
Expand Down
7 changes: 4 additions & 3 deletions packages/contracts-bedrock/src/cannon/MIPS2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ contract MIPS2 is ISemver {
}

/// @notice The semantic version of the MIPS2 contract.
/// @custom:semver 1.0.0-beta.23
string public constant version = "1.0.0-beta.23";
/// @custom:semver 1.0.0-beta.24
string public constant version = "1.0.0-beta.24";

/// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE;
Expand Down Expand Up @@ -462,7 +462,7 @@ contract MIPS2 is ISemver {
// Encapsulate execution to avoid stack-too-deep error
(v0, v1) = execSysRead(state, args);
} else if (syscall_no == sys.SYS_WRITE) {
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({
sys.SysWriteParams memory args = sys.SysWriteParams({
_a0: a0,
_a1: a1,
_a2: a2,
Expand All @@ -471,6 +471,7 @@ contract MIPS2 is ISemver {
_proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1),
_memRoot: state.memRoot
});
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite(args);
} else if (syscall_no == sys.SYS_FCNTL) {
(v0, v1) = sys.handleSysFcntl(a0, a1);
} else if (syscall_no == sys.SYS_GETTID) {
Expand Down
7 changes: 4 additions & 3 deletions packages/contracts-bedrock/src/cannon/MIPS64.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ contract MIPS64 is ISemver {
}

/// @notice The semantic version of the MIPS64 contract.
/// @custom:semver 1.0.0-beta.5
string public constant version = "1.0.0-beta.5";
/// @custom:semver 1.0.0-beta.6
string public constant version = "1.0.0-beta.6";

/// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE;
Expand Down Expand Up @@ -504,7 +504,7 @@ contract MIPS64 is ISemver {
// Encapsulate execution to avoid stack-too-deep error
(v0, v1) = execSysRead(state, args);
} else if (syscall_no == sys.SYS_WRITE) {
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({
sys.SysWriteParams memory args = sys.SysWriteParams({
_a0: a0,
_a1: a1,
_a2: a2,
Expand All @@ -513,6 +513,7 @@ contract MIPS64 is ISemver {
_proofOffset: MIPS64Memory.memoryProofOffset(MEM_PROOF_OFFSET, 1),
_memRoot: state.memRoot
});
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite(args);
} else if (syscall_no == sys.SYS_FCNTL) {
(v0, v1) = sys.handleSysFcntl(a0, a1);
} else if (syscall_no == sys.SYS_GETTID) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ library MIPS64Syscalls {
bytes32 memRoot;
}

/// @custom:field _a0 The file descriptor.
/// @custom:field _a1 The memory address to read from.
/// @custom:field _a2 The number of bytes to read.
/// @custom:field _preimageKey The current preimaageKey.
/// @custom:field _preimageOffset The current preimageOffset.
/// @custom:field _proofOffset The offset of the memory proof in calldata.
/// @custom:field _memRoot The current memory root.
struct SysWriteParams {
uint64 _a0;
uint64 _a1;
uint64 _a2;
bytes32 _preimageKey;
uint64 _preimageOffset;
uint256 _proofOffset;
bytes32 _memRoot;
}

uint64 internal constant U64_MASK = 0xFFffFFffFFffFFff;
uint64 internal constant PAGE_ADDR_MASK = 4095;
uint64 internal constant PAGE_SIZE = 4096;
Expand Down Expand Up @@ -309,26 +326,11 @@ library MIPS64Syscalls {
}

/// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes.
/// @param _a0 The file descriptor.
/// @param _a1 The memory address to read from.
/// @param _a2 The number of bytes to read.
/// @param _preimageKey The current preimaageKey.
/// @param _preimageOffset The current preimageOffset.
/// @param _proofOffset The offset of the memory proof in calldata.
/// @param _memRoot The current memory root.
/// @return v0_ The number of bytes written, or -1 on error.
/// @return v1_ The error code, or 0 if empty.
/// @return newPreimageKey_ The new preimageKey.
/// @return newPreimageOffset_ The new preimageOffset.
function handleSysWrite(
uint64 _a0,
uint64 _a1,
uint64 _a2,
bytes32 _preimageKey,
uint64 _preimageOffset,
uint256 _proofOffset,
bytes32 _memRoot
)
function handleSysWrite(SysWriteParams memory _args)
internal
pure
returns (uint64 v0_, uint64 v1_, bytes32 newPreimageKey_, uint64 newPreimageOffset_)
Expand All @@ -338,20 +340,22 @@ library MIPS64Syscalls {
// returns: v0_ = written, v1_ = err code
v0_ = uint64(0);
v1_ = uint64(0);
newPreimageKey_ = _preimageKey;
newPreimageOffset_ = _preimageOffset;
newPreimageKey_ = _args._preimageKey;
newPreimageOffset_ = _args._preimageOffset;

if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) {
v0_ = _a2; // tell program we have written everything
if (_args._a0 == FD_STDOUT || _args._a0 == FD_STDERR || _args._a0 == FD_HINT_WRITE) {
v0_ = _args._a2; // tell program we have written everything
}
// pre-image oracle
else if (_a0 == FD_PREIMAGE_WRITE) {
else if (_args._a0 == FD_PREIMAGE_WRITE) {
// mask the addr to align it to 4 bytes
uint64 mem = MIPS64Memory.readMem(_memRoot, _a1 & arch.ADDRESS_MASK, _proofOffset);
bytes32 key = _preimageKey;
uint64 mem = MIPS64Memory.readMem(_args._memRoot, _args._a1 & arch.ADDRESS_MASK, _args._proofOffset);
bytes32 key = _args._preimageKey;

// Construct pre-image key from memory
// We use assembly for more precise ops, and no var count limit
uint64 _a1 = _args._a1;
uint64 _a2 = _args._a2;
assembly {
let alignment := and(_a1, EXT_MASK) // the read might not start at an aligned address
let space := sub(WORD_SIZE_BYTES, alignment) // remaining space in memory word
Expand All @@ -361,11 +365,12 @@ library MIPS64Syscalls {
mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it
key := or(key, mem) // insert into key
}
_args._a2 = _a2;

// Write pre-image key to oracle
newPreimageKey_ = key;
newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start
v0_ = _a2;
v0_ = _args._a2;
} else {
v0_ = U64_MASK;
v1_ = EBADF;
Expand Down
53 changes: 29 additions & 24 deletions packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@ library MIPSSyscalls {
bytes32 memRoot;
}

/// @custom:field _a0 The file descriptor.
/// @custom:field _a1 The memory address to read from.
/// @custom:field _a2 The number of bytes to read.
/// @custom:field _preimageKey The current preimaageKey.
/// @custom:field _preimageOffset The current preimageOffset.
/// @custom:field _proofOffset The offset of the memory proof in calldata.
/// @custom:field _memRoot The current memory root.
struct SysWriteParams {
uint32 _a0;
uint32 _a1;
uint32 _a2;
bytes32 _preimageKey;
uint32 _preimageOffset;
uint256 _proofOffset;
bytes32 _memRoot;
}

uint32 internal constant SYS_MMAP = 4090;
uint32 internal constant SYS_BRK = 4045;
uint32 internal constant SYS_CLONE = 4120;
Expand Down Expand Up @@ -299,26 +316,11 @@ library MIPSSyscalls {
}

/// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes.
/// @param _a0 The file descriptor.
/// @param _a1 The memory address to read from.
/// @param _a2 The number of bytes to read.
/// @param _preimageKey The current preimaageKey.
/// @param _preimageOffset The current preimageOffset.
/// @param _proofOffset The offset of the memory proof in calldata.
/// @param _memRoot The current memory root.
/// @return v0_ The number of bytes written, or -1 on error.
/// @return v1_ The error code, or 0 if empty.
/// @return newPreimageKey_ The new preimageKey.
/// @return newPreimageOffset_ The new preimageOffset.
function handleSysWrite(
uint32 _a0,
uint32 _a1,
uint32 _a2,
bytes32 _preimageKey,
uint32 _preimageOffset,
uint256 _proofOffset,
bytes32 _memRoot
)
function handleSysWrite(SysWriteParams memory _args)
internal
pure
returns (uint32 v0_, uint32 v1_, bytes32 newPreimageKey_, uint32 newPreimageOffset_)
Expand All @@ -328,20 +330,22 @@ library MIPSSyscalls {
// returns: v0_ = written, v1_ = err code
v0_ = uint32(0);
v1_ = uint32(0);
newPreimageKey_ = _preimageKey;
newPreimageOffset_ = _preimageOffset;
newPreimageKey_ = _args._preimageKey;
newPreimageOffset_ = _args._preimageOffset;

if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) {
v0_ = _a2; // tell program we have written everything
if (_args._a0 == FD_STDOUT || _args._a0 == FD_STDERR || _args._a0 == FD_HINT_WRITE) {
v0_ = _args._a2; // tell program we have written everything
}
// pre-image oracle
else if (_a0 == FD_PREIMAGE_WRITE) {
else if (_args._a0 == FD_PREIMAGE_WRITE) {
// mask the addr to align it to 4 bytes
uint32 mem = MIPSMemory.readMem(_memRoot, _a1 & 0xFFffFFfc, _proofOffset);
bytes32 key = _preimageKey;
uint32 mem = MIPSMemory.readMem(_args._memRoot, _args._a1 & 0xFFffFFfc, _args._proofOffset);
bytes32 key = _args._preimageKey;

// Construct pre-image key from memory
// We use assembly for more precise ops, and no var count limit
uint32 _a1 = _args._a1;
uint32 _a2 = _args._a2;
assembly {
let alignment := and(_a1, 3) // the read might not start at an aligned address
let space := sub(4, alignment) // remaining space in memory word
Expand All @@ -351,11 +355,12 @@ library MIPSSyscalls {
mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it
key := or(key, mem) // insert into key
}
_args._a2 = _a2;

// Write pre-image key to oracle
newPreimageKey_ = key;
newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start
v0_ = _a2;
v0_ = _args._a2;
} else {
v0_ = 0xFFffFFff;
v1_ = EBADF;
Expand Down