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 @@ ...@@ -136,16 +136,16 @@
"sourceCodeHash": "0x0fa0633a769e73f5937514c0003ba7947a1c275bbe5b85d78879c42f0ed8895b" "sourceCodeHash": "0x0fa0633a769e73f5937514c0003ba7947a1c275bbe5b85d78879c42f0ed8895b"
}, },
"src/cannon/MIPS.sol": { "src/cannon/MIPS.sol": {
"initCodeHash": "0xb4aec227019dacd6194d6aeb9ca68c23c60b95618d18a4ebc09243514aeb1f05", "initCodeHash": "0x2ad89ddfd9b6091af7fa4f337f6f0134b946838b53a056995eea5982e4b903c3",
"sourceCodeHash": "0x4d43b3f2918486aa76d2d59ac42e4f6aa2f58538c7e95a5cb99b63c9588b5f1c" "sourceCodeHash": "0xcd5f9762e641e4a1f6b07420ea3b2bfcaac5656da10c66a0f367ee4d4af37e9c"
}, },
"src/cannon/MIPS2.sol": { "src/cannon/MIPS2.sol": {
"initCodeHash": "0xe3879b5772820d837bc1c77c32a1200eb26cf901d9302dff9f0e9759331e380e", "initCodeHash": "0x013e6005f56eae789a48ec9766d17c0be950d765ada3eb936c9a90337567c940",
"sourceCodeHash": "0x1c45a8f4c8c9ded7043d63965cb114d17f801c6cd4d8233cb16838c5f9a02675" "sourceCodeHash": "0xdd7684d0b8efd0bbee4abae76195c649b325ecd3e09f41b687cf3a091639c887"
}, },
"src/cannon/MIPS64.sol": { "src/cannon/MIPS64.sol": {
"initCodeHash": "0xa4a761f480a26ec1926c5a8b4831440211c0441bd41d503b0aad189e030d35dc", "initCodeHash": "0xa5c2105b0d6f90d6f5ab1782f6d7acda505674a3c11355e0b401d66250406c0c",
"sourceCodeHash": "0x7ddcf8584f9bd92abd1eb45bc198f5b0ec54acaf292f60e919d674cc56fb8abc" "sourceCodeHash": "0x7cb189f5081c4aae84a7b23329309d944cb54f075ec18b03240d1725c03adc3b"
}, },
"src/cannon/PreimageOracle.sol": { "src/cannon/PreimageOracle.sol": {
"initCodeHash": "0x2bef439027c37c65dd8e7d9a987ff14e1dba94ee5fe5f316a77ecf46a8db4b3f", "initCodeHash": "0x2bef439027c37c65dd8e7d9a987ff14e1dba94ee5fe5f316a77ecf46a8db4b3f",
......
...@@ -47,8 +47,8 @@ contract MIPS is ISemver { ...@@ -47,8 +47,8 @@ contract MIPS is ISemver {
} }
/// @notice The semantic version of the MIPS contract. /// @notice The semantic version of the MIPS contract.
/// @custom:semver 1.2.1-beta.8 /// @custom:semver 1.2.1-beta.9
string public constant version = "1.2.1-beta.8"; string public constant version = "1.2.1-beta.9";
/// @notice The preimage oracle contract. /// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE; IPreimageOracle internal immutable ORACLE;
...@@ -183,7 +183,7 @@ contract MIPS is ISemver { ...@@ -183,7 +183,7 @@ contract MIPS is ISemver {
}); });
(v0, v1, state.preimageOffset, state.memRoot,,) = sys.handleSysRead(args); (v0, v1, state.preimageOffset, state.memRoot,,) = sys.handleSysRead(args);
} else if (syscall_no == sys.SYS_WRITE) { } else if (syscall_no == sys.SYS_WRITE) {
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ sys.SysWriteParams memory args = sys.SysWriteParams({
_a0: a0, _a0: a0,
_a1: a1, _a1: a1,
_a2: a2, _a2: a2,
...@@ -192,6 +192,7 @@ contract MIPS is ISemver { ...@@ -192,6 +192,7 @@ contract MIPS is ISemver {
_proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1), _proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1),
_memRoot: state.memRoot _memRoot: state.memRoot
}); });
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite(args);
} else if (syscall_no == sys.SYS_FCNTL) { } else if (syscall_no == sys.SYS_FCNTL) {
(v0, v1) = sys.handleSysFcntl(a0, a1); (v0, v1) = sys.handleSysFcntl(a0, a1);
} }
......
...@@ -63,8 +63,8 @@ contract MIPS2 is ISemver { ...@@ -63,8 +63,8 @@ contract MIPS2 is ISemver {
} }
/// @notice The semantic version of the MIPS2 contract. /// @notice The semantic version of the MIPS2 contract.
/// @custom:semver 1.0.0-beta.23 /// @custom:semver 1.0.0-beta.24
string public constant version = "1.0.0-beta.23"; string public constant version = "1.0.0-beta.24";
/// @notice The preimage oracle contract. /// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE; IPreimageOracle internal immutable ORACLE;
...@@ -462,7 +462,7 @@ contract MIPS2 is ISemver { ...@@ -462,7 +462,7 @@ contract MIPS2 is ISemver {
// Encapsulate execution to avoid stack-too-deep error // Encapsulate execution to avoid stack-too-deep error
(v0, v1) = execSysRead(state, args); (v0, v1) = execSysRead(state, args);
} else if (syscall_no == sys.SYS_WRITE) { } else if (syscall_no == sys.SYS_WRITE) {
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ sys.SysWriteParams memory args = sys.SysWriteParams({
_a0: a0, _a0: a0,
_a1: a1, _a1: a1,
_a2: a2, _a2: a2,
...@@ -471,6 +471,7 @@ contract MIPS2 is ISemver { ...@@ -471,6 +471,7 @@ contract MIPS2 is ISemver {
_proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), _proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1),
_memRoot: state.memRoot _memRoot: state.memRoot
}); });
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite(args);
} else if (syscall_no == sys.SYS_FCNTL) { } else if (syscall_no == sys.SYS_FCNTL) {
(v0, v1) = sys.handleSysFcntl(a0, a1); (v0, v1) = sys.handleSysFcntl(a0, a1);
} else if (syscall_no == sys.SYS_GETTID) { } else if (syscall_no == sys.SYS_GETTID) {
......
...@@ -67,8 +67,8 @@ contract MIPS64 is ISemver { ...@@ -67,8 +67,8 @@ contract MIPS64 is ISemver {
} }
/// @notice The semantic version of the MIPS64 contract. /// @notice The semantic version of the MIPS64 contract.
/// @custom:semver 1.0.0-beta.5 /// @custom:semver 1.0.0-beta.6
string public constant version = "1.0.0-beta.5"; string public constant version = "1.0.0-beta.6";
/// @notice The preimage oracle contract. /// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE; IPreimageOracle internal immutable ORACLE;
...@@ -504,7 +504,7 @@ contract MIPS64 is ISemver { ...@@ -504,7 +504,7 @@ contract MIPS64 is ISemver {
// Encapsulate execution to avoid stack-too-deep error // Encapsulate execution to avoid stack-too-deep error
(v0, v1) = execSysRead(state, args); (v0, v1) = execSysRead(state, args);
} else if (syscall_no == sys.SYS_WRITE) { } else if (syscall_no == sys.SYS_WRITE) {
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ sys.SysWriteParams memory args = sys.SysWriteParams({
_a0: a0, _a0: a0,
_a1: a1, _a1: a1,
_a2: a2, _a2: a2,
...@@ -513,6 +513,7 @@ contract MIPS64 is ISemver { ...@@ -513,6 +513,7 @@ contract MIPS64 is ISemver {
_proofOffset: MIPS64Memory.memoryProofOffset(MEM_PROOF_OFFSET, 1), _proofOffset: MIPS64Memory.memoryProofOffset(MEM_PROOF_OFFSET, 1),
_memRoot: state.memRoot _memRoot: state.memRoot
}); });
(v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite(args);
} else if (syscall_no == sys.SYS_FCNTL) { } else if (syscall_no == sys.SYS_FCNTL) {
(v0, v1) = sys.handleSysFcntl(a0, a1); (v0, v1) = sys.handleSysFcntl(a0, a1);
} else if (syscall_no == sys.SYS_GETTID) { } else if (syscall_no == sys.SYS_GETTID) {
......
...@@ -30,6 +30,23 @@ library MIPS64Syscalls { ...@@ -30,6 +30,23 @@ library MIPS64Syscalls {
bytes32 memRoot; 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 U64_MASK = 0xFFffFFffFFffFFff;
uint64 internal constant PAGE_ADDR_MASK = 4095; uint64 internal constant PAGE_ADDR_MASK = 4095;
uint64 internal constant PAGE_SIZE = 4096; uint64 internal constant PAGE_SIZE = 4096;
...@@ -309,26 +326,11 @@ library MIPS64Syscalls { ...@@ -309,26 +326,11 @@ library MIPS64Syscalls {
} }
/// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes. /// @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 v0_ The number of bytes written, or -1 on error.
/// @return v1_ The error code, or 0 if empty. /// @return v1_ The error code, or 0 if empty.
/// @return newPreimageKey_ The new preimageKey. /// @return newPreimageKey_ The new preimageKey.
/// @return newPreimageOffset_ The new preimageOffset. /// @return newPreimageOffset_ The new preimageOffset.
function handleSysWrite( function handleSysWrite(SysWriteParams memory _args)
uint64 _a0,
uint64 _a1,
uint64 _a2,
bytes32 _preimageKey,
uint64 _preimageOffset,
uint256 _proofOffset,
bytes32 _memRoot
)
internal internal
pure pure
returns (uint64 v0_, uint64 v1_, bytes32 newPreimageKey_, uint64 newPreimageOffset_) returns (uint64 v0_, uint64 v1_, bytes32 newPreimageKey_, uint64 newPreimageOffset_)
...@@ -338,20 +340,22 @@ library MIPS64Syscalls { ...@@ -338,20 +340,22 @@ library MIPS64Syscalls {
// returns: v0_ = written, v1_ = err code // returns: v0_ = written, v1_ = err code
v0_ = uint64(0); v0_ = uint64(0);
v1_ = uint64(0); v1_ = uint64(0);
newPreimageKey_ = _preimageKey; newPreimageKey_ = _args._preimageKey;
newPreimageOffset_ = _preimageOffset; newPreimageOffset_ = _args._preimageOffset;
if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) { if (_args._a0 == FD_STDOUT || _args._a0 == FD_STDERR || _args._a0 == FD_HINT_WRITE) {
v0_ = _a2; // tell program we have written everything v0_ = _args._a2; // tell program we have written everything
} }
// pre-image oracle // 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 // mask the addr to align it to 4 bytes
uint64 mem = MIPS64Memory.readMem(_memRoot, _a1 & arch.ADDRESS_MASK, _proofOffset); uint64 mem = MIPS64Memory.readMem(_args._memRoot, _args._a1 & arch.ADDRESS_MASK, _args._proofOffset);
bytes32 key = _preimageKey; bytes32 key = _args._preimageKey;
// Construct pre-image key from memory // Construct pre-image key from memory
// We use assembly for more precise ops, and no var count limit // We use assembly for more precise ops, and no var count limit
uint64 _a1 = _args._a1;
uint64 _a2 = _args._a2;
assembly { assembly {
let alignment := and(_a1, EXT_MASK) // the read might not start at an aligned address 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 let space := sub(WORD_SIZE_BYTES, alignment) // remaining space in memory word
...@@ -361,11 +365,12 @@ library MIPS64Syscalls { ...@@ -361,11 +365,12 @@ library MIPS64Syscalls {
mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it
key := or(key, mem) // insert into key key := or(key, mem) // insert into key
} }
_args._a2 = _a2;
// Write pre-image key to oracle // Write pre-image key to oracle
newPreimageKey_ = key; newPreimageKey_ = key;
newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start
v0_ = _a2; v0_ = _args._a2;
} else { } else {
v0_ = U64_MASK; v0_ = U64_MASK;
v1_ = EBADF; v1_ = EBADF;
......
...@@ -29,6 +29,23 @@ library MIPSSyscalls { ...@@ -29,6 +29,23 @@ library MIPSSyscalls {
bytes32 memRoot; 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_MMAP = 4090;
uint32 internal constant SYS_BRK = 4045; uint32 internal constant SYS_BRK = 4045;
uint32 internal constant SYS_CLONE = 4120; uint32 internal constant SYS_CLONE = 4120;
...@@ -299,26 +316,11 @@ library MIPSSyscalls { ...@@ -299,26 +316,11 @@ library MIPSSyscalls {
} }
/// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes. /// @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 v0_ The number of bytes written, or -1 on error.
/// @return v1_ The error code, or 0 if empty. /// @return v1_ The error code, or 0 if empty.
/// @return newPreimageKey_ The new preimageKey. /// @return newPreimageKey_ The new preimageKey.
/// @return newPreimageOffset_ The new preimageOffset. /// @return newPreimageOffset_ The new preimageOffset.
function handleSysWrite( function handleSysWrite(SysWriteParams memory _args)
uint32 _a0,
uint32 _a1,
uint32 _a2,
bytes32 _preimageKey,
uint32 _preimageOffset,
uint256 _proofOffset,
bytes32 _memRoot
)
internal internal
pure pure
returns (uint32 v0_, uint32 v1_, bytes32 newPreimageKey_, uint32 newPreimageOffset_) returns (uint32 v0_, uint32 v1_, bytes32 newPreimageKey_, uint32 newPreimageOffset_)
...@@ -328,20 +330,22 @@ library MIPSSyscalls { ...@@ -328,20 +330,22 @@ library MIPSSyscalls {
// returns: v0_ = written, v1_ = err code // returns: v0_ = written, v1_ = err code
v0_ = uint32(0); v0_ = uint32(0);
v1_ = uint32(0); v1_ = uint32(0);
newPreimageKey_ = _preimageKey; newPreimageKey_ = _args._preimageKey;
newPreimageOffset_ = _preimageOffset; newPreimageOffset_ = _args._preimageOffset;
if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) { if (_args._a0 == FD_STDOUT || _args._a0 == FD_STDERR || _args._a0 == FD_HINT_WRITE) {
v0_ = _a2; // tell program we have written everything v0_ = _args._a2; // tell program we have written everything
} }
// pre-image oracle // 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 // mask the addr to align it to 4 bytes
uint32 mem = MIPSMemory.readMem(_memRoot, _a1 & 0xFFffFFfc, _proofOffset); uint32 mem = MIPSMemory.readMem(_args._memRoot, _args._a1 & 0xFFffFFfc, _args._proofOffset);
bytes32 key = _preimageKey; bytes32 key = _args._preimageKey;
// Construct pre-image key from memory // Construct pre-image key from memory
// We use assembly for more precise ops, and no var count limit // We use assembly for more precise ops, and no var count limit
uint32 _a1 = _args._a1;
uint32 _a2 = _args._a2;
assembly { assembly {
let alignment := and(_a1, 3) // the read might not start at an aligned address let alignment := and(_a1, 3) // the read might not start at an aligned address
let space := sub(4, alignment) // remaining space in memory word let space := sub(4, alignment) // remaining space in memory word
...@@ -351,11 +355,12 @@ library MIPSSyscalls { ...@@ -351,11 +355,12 @@ library MIPSSyscalls {
mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it
key := or(key, mem) // insert into key key := or(key, mem) // insert into key
} }
_args._a2 = _a2;
// Write pre-image key to oracle // Write pre-image key to oracle
newPreimageKey_ = key; newPreimageKey_ = key;
newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start
v0_ = _a2; v0_ = _args._a2;
} else { } else {
v0_ = 0xFFffFFff; v0_ = 0xFFffFFff;
v1_ = EBADF; 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