Commit a486daec authored by Michael Amadi's avatar Michael Amadi Committed by GitHub

fix mips contracts stack too deep errors (#13137)

parent 1a1ab6ec
......@@ -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",
......
......@@ -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;
......@@ -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,
......@@ -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);
}
......
......@@ -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;
......@@ -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,
......@@ -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) {
......
......@@ -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;
......@@ -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,
......@@ -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) {
......
......@@ -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;
......@@ -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_)
......@@ -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
......@@ -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;
......
......@@ -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;
......@@ -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_)
......@@ -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
......@@ -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;
......
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