Commit 1888081c authored by clabby's avatar clabby

refactor

parent 557071f0
This diff is collapsed.
......@@ -509,37 +509,6 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) ExtraData() ([]byte, err
return _FaultDisputeGame.Contract.ExtraData(&_FaultDisputeGame.CallOpts)
}
// ExtraDataLen is a free data retrieval call binding the contract method 0x1f62d0c6.
//
// Solidity: function extraDataLen() pure returns(uint256 extraDataLen_)
func (_FaultDisputeGame *FaultDisputeGameCaller) ExtraDataLen(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _FaultDisputeGame.contract.Call(opts, &out, "extraDataLen")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// ExtraDataLen is a free data retrieval call binding the contract method 0x1f62d0c6.
//
// Solidity: function extraDataLen() pure returns(uint256 extraDataLen_)
func (_FaultDisputeGame *FaultDisputeGameSession) ExtraDataLen() (*big.Int, error) {
return _FaultDisputeGame.Contract.ExtraDataLen(&_FaultDisputeGame.CallOpts)
}
// ExtraDataLen is a free data retrieval call binding the contract method 0x1f62d0c6.
//
// Solidity: function extraDataLen() pure returns(uint256 extraDataLen_)
func (_FaultDisputeGame *FaultDisputeGameCallerSession) ExtraDataLen() (*big.Int, error) {
return _FaultDisputeGame.Contract.ExtraDataLen(&_FaultDisputeGame.CallOpts)
}
// GameData is a free data retrieval call binding the contract method 0xfa24f743.
//
// Solidity: function gameData() pure returns(uint8 gameType_, bytes32 rootClaim_, bytes extraData_)
......
This diff is collapsed.
This diff is collapsed.
......@@ -201,37 +201,6 @@ func (_PreimageOracle *PreimageOracleTransactorRaw) Transact(opts *bind.Transact
return _PreimageOracle.Contract.contract.Transact(opts, method, params...)
}
// ComputeKeccak256PreimageKey is a free data retrieval call binding the contract method 0xdfb77667.
//
// Solidity: function computeKeccak256PreimageKey(bytes _preimage) pure returns(bytes32 key_)
func (_PreimageOracle *PreimageOracleCaller) ComputeKeccak256PreimageKey(opts *bind.CallOpts, _preimage []byte) ([32]byte, error) {
var out []interface{}
err := _PreimageOracle.contract.Call(opts, &out, "computeKeccak256PreimageKey", _preimage)
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// ComputeKeccak256PreimageKey is a free data retrieval call binding the contract method 0xdfb77667.
//
// Solidity: function computeKeccak256PreimageKey(bytes _preimage) pure returns(bytes32 key_)
func (_PreimageOracle *PreimageOracleSession) ComputeKeccak256PreimageKey(_preimage []byte) ([32]byte, error) {
return _PreimageOracle.Contract.ComputeKeccak256PreimageKey(&_PreimageOracle.CallOpts, _preimage)
}
// ComputeKeccak256PreimageKey is a free data retrieval call binding the contract method 0xdfb77667.
//
// Solidity: function computeKeccak256PreimageKey(bytes _preimage) pure returns(bytes32 key_)
func (_PreimageOracle *PreimageOracleCallerSession) ComputeKeccak256PreimageKey(_preimage []byte) ([32]byte, error) {
return _PreimageOracle.Contract.ComputeKeccak256PreimageKey(&_PreimageOracle.CallOpts, _preimage)
}
// PreimageLengths is a free data retrieval call binding the contract method 0xfef2b4ed.
//
// Solidity: function preimageLengths(bytes32 ) view returns(uint256)
......@@ -412,23 +381,23 @@ func (_PreimageOracle *PreimageOracleTransactorSession) LoadKeccak256PreimagePar
return _PreimageOracle.Contract.LoadKeccak256PreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _preimage)
}
// LoadLocalData is a paid mutator transaction binding the contract method 0x3eba58ce.
// LoadLocalPart is a paid mutator transaction binding the contract method 0x90fbc1e2.
//
// Solidity: function loadLocalData(bytes _bootInfo) returns()
func (_PreimageOracle *PreimageOracleTransactor) LoadLocalData(opts *bind.TransactOpts, _bootInfo []byte) (*types.Transaction, error) {
return _PreimageOracle.contract.Transact(opts, "loadLocalData", _bootInfo)
// Solidity: function loadLocalPart(uint256 _partOffset, uint256 _ident, bytes32 _part, uint256 _size) returns()
func (_PreimageOracle *PreimageOracleTransactor) LoadLocalPart(opts *bind.TransactOpts, _partOffset *big.Int, _ident *big.Int, _part [32]byte, _size *big.Int) (*types.Transaction, error) {
return _PreimageOracle.contract.Transact(opts, "loadLocalPart", _partOffset, _ident, _part, _size)
}
// LoadLocalData is a paid mutator transaction binding the contract method 0x3eba58ce.
// LoadLocalPart is a paid mutator transaction binding the contract method 0x90fbc1e2.
//
// Solidity: function loadLocalData(bytes _bootInfo) returns()
func (_PreimageOracle *PreimageOracleSession) LoadLocalData(_bootInfo []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadLocalData(&_PreimageOracle.TransactOpts, _bootInfo)
// Solidity: function loadLocalPart(uint256 _partOffset, uint256 _ident, bytes32 _part, uint256 _size) returns()
func (_PreimageOracle *PreimageOracleSession) LoadLocalPart(_partOffset *big.Int, _ident *big.Int, _part [32]byte, _size *big.Int) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadLocalPart(&_PreimageOracle.TransactOpts, _partOffset, _ident, _part, _size)
}
// LoadLocalData is a paid mutator transaction binding the contract method 0x3eba58ce.
// LoadLocalPart is a paid mutator transaction binding the contract method 0x90fbc1e2.
//
// Solidity: function loadLocalData(bytes _bootInfo) returns()
func (_PreimageOracle *PreimageOracleTransactorSession) LoadLocalData(_bootInfo []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadLocalData(&_PreimageOracle.TransactOpts, _bootInfo)
// Solidity: function loadLocalPart(uint256 _partOffset, uint256 _ident, bytes32 _part, uint256 _size) returns()
func (_PreimageOracle *PreimageOracleTransactorSession) LoadLocalPart(_partOffset *big.Int, _ident *big.Int, _part [32]byte, _size *big.Int) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadLocalPart(&_PreimageOracle.TransactOpts, _partOffset, _ident, _part, _size)
}
......@@ -2,6 +2,7 @@
pragma solidity 0.7.6;
import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol";
import { PreimageKeyLib } from "./PreimageKeyLib.sol";
/// @title MIPS
/// @notice The MIPS contract emulates a single MIPS instruction.
......@@ -169,19 +170,11 @@ contract MIPS {
// verify proof 1 is correct, and get the existing memory.
uint32 mem = readMem(a1 & 0xFFffFFfc, 1); // mask the addr to align it to 4 bytes
bytes32 preimageKey = state.preimageKey;
assembly {
// If the preimage key has a local data type, we need to hash it with the sender address
// (the dispute game) to get the context-specific key and re-set it's type byte.
if eq(byte(0, preimageKey), 1) {
// Store preimage key and caller in scratch space
mstore(0x00, preimageKey)
mstore(0x20, caller())
// Local key alteration for the sender's context:
// localize(k) = H(k .. sender) & ~(0xFF << 248) | (0x01 << 248)
preimageKey := or(and(keccak256(0x00, 0x40), not(shl(248, 0xFF))), shl(248, 0x01))
}
// If the preimage key is a local key, localize it in the context of the caller.
if (uint8(preimageKey[0]) == 1) {
preimageKey = PreimageKeyLib.localize(preimageKey);
}
(bytes32 dat, uint256 datLen) = oracle.readPreimage(state.preimageKey, state.preimageOffset);
(bytes32 dat, uint256 datLen) = oracle.readPreimage(preimageKey, state.preimageOffset);
// Transform data for writing to memory
// We use assembly for more precise ops, and no var count limit
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
/// @title PreimageKeyLib
/// @notice Shared utilities for localizing local keys in the preimage oracle.
library PreimageKeyLib {
/// @notice Generates a context-specific local key for the given local data identifier.
/// @dev See `localize` for a description of the localization operation.
/// @param _ident The identifier of the local data. [0, 32) bytes in size.
/// @return key_ The context-specific local key.
function localizeIdent(uint256 _ident) internal view returns (bytes32 key_) {
assembly {
// Set the type byte in the given identifier to `1` (Local). We only care about
// the [1, 32) bytes in this value.
key_ := or(shl(248, 1), and(_ident, not(shl(248, 0xFF))))
}
key_ = localize(key_);
}
/// @notice Localizes a given local data key for the caller's context.
/// @dev The localization operation is defined as:
/// localize(k) = H(k .. sender) & ~(0xFF << 248) | (0x01 << 248)
/// where H is the Keccak-256 hash function.
/// @param _key The local data key to localize.
/// @return localizedKey_ The localized local data key.
function localize(bytes32 _key) internal view returns (bytes32 localizedKey_) {
assembly {
// Store the local data key and caller next to each other in memory for hashing.
mstore(0, _key)
mstore(0x20, caller())
// Localize the key with the above `localize` operation.
localizedKey_ := or(and(keccak256(0, 0x40), not(shl(248, 0xFF))), shl(248, 1))
}
}
/// @notice Computes and returns the key for a global keccak pre-image.
/// @param _preimage The pre-image.
/// @return key_ The pre-image key.
function keccak256PreimageKey(bytes memory _preimage)
internal
pure
returns (bytes32 key_)
{
assembly {
// Grab the size of the `_preimage`
let size := mload(_preimage)
// Compute the pre-image keccak256 hash (aka the pre-image key)
let h := keccak256(add(_preimage, 0x20), size)
// Mask out prefix byte, replace with type 2 byte
key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 2))
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.7.6;
import { PreimageKeyLib } from "./PreimageKeyLib.sol";
/// @title PreimageOracle
/// @notice A contract for storing permissioned pre-images.
......@@ -35,11 +37,11 @@ contract PreimageOracle {
dat_ = preimageParts[_key][_offset];
}
// TODO(CLI-4104):
// we need to mix-in the ID of the dispute for local-type keys to avoid collisions,
// and restrict local pre-image insertion to the dispute-managing contract.
// For now we permit anyone to write any pre-image unchecked, to make testing easy.
// This method is DANGEROUS. And NOT FOR PRODUCTION.
/// TODO(CLI-4104):
/// we need to mix-in the ID of the dispute for local-type keys to avoid collisions,
/// and restrict local pre-image insertion to the dispute-managing contract.
/// For now we permit anyone to write any pre-image unchecked, to make testing easy.
/// This method is DANGEROUS. And NOT FOR PRODUCTION.
function cheat(
uint256 partOffset,
bytes32 key,
......@@ -51,88 +53,25 @@ contract PreimageOracle {
preimageLengths[key] = size;
}
/// @notice Loads local data into the pre-image oracle in the context of the caller.
/// @param _bootInfo The boot info struct encoded as a tuple of .
function loadLocalData(bytes memory _bootInfo) external {
(
bytes32 l1head,
bytes32 l2head,
bytes32 l2claim,
uint64 l2ClaimBlockNumber,
bytes memory l2ChainConfig,
bytes memory rollupConfig
) = abi.decode(_bootInfo, (bytes32, bytes32, bytes32, uint64, bytes, bytes));
assembly {
/// Store a value in a mapping
function storeInMapping(k, v, mappingSlot) {
// Value slot: `keccak256(k . mappingSlot)`
mstore(0x00, k)
mstore(0x20, mappingSlot)
sstore(keccak256(0x00, 0x40), v)
}
/// Store a value in a nested mapping
function storeInNestedMapping(ka, kb, v, mappingSlot) {
// Compute the slot of the nested mapping
mstore(0x00, ka)
mstore(0x20, mappingSlot)
let nestedSlot := keccak256(0x00, 0x40)
// Compute the slot of the value & store it
mstore(0x00, kb)
mstore(0x20, nestedSlot)
sstore(keccak256(0x00, 0x40), v)
}
/// Compute the context-specifc key for a given local data identifier
function contextKey(ident) -> key {
// Store the global key (1 << 248 | ident)
mstore(0, or(shl(248, 1), ident))
// Store the caller to add context to the local data's global key
mstore(0x20, caller())
// Hash the data to get the context-specific key
// localize(k) = H(k .. sender) & ~(0xFF << 248) | (1 << 248)
key := or(and(keccak256(0, 0x40), not(shl(248, 0xFF))), shl(248, 1))
}
/// Store a fixed-size piece of local data
function storeFixed(ident, offset, size, data) {
// Grab the context key for the given `ident`
let k := contextKey(ident)
// Store the fixed data
storeInNestedMapping(k, offset, true, preimagePartOk.slot)
storeInNestedMapping(k, offset, data, preimageParts.slot)
storeInMapping(k, size, preimageLengths.slot)
}
/// Store a dynamic-size piece of local data
function storeDyn(ident, dataOffset) {
// Grab the length of the data
let size := mload(dataOffset)
// Grab the context key for the given `ident`
let k := contextKey(ident)
// Store each component of the preimage key.
let dataStart := add(dataOffset, 0x20)
for { let i := 0 } lt(i, size) { i := add(i, 0x20) } {
// Load the part at the given offset
// TODO(clabby): Verify size.
let part := mload(add(dataStart, i))
storeInNestedMapping(k, i, true, preimagePartOk.slot)
storeInNestedMapping(k, i, part, preimageParts.slot)
storeInMapping(k, size, preimageLengths.slot)
}
}
/// @notice Loads a local data part into the preimage oracle.
/// @param _partOffset The offset of the local data part.
/// @param _ident The identifier of the local data.
/// @param _part The local data part.
/// @param _size The size of the local data.
/// @dev The local data part is loaded into the preimage oracle under the context
/// of the caller - no other account can write to the caller's context
/// specific data.
function loadLocalPart(
uint256 _partOffset,
uint256 _ident,
bytes32 _part,
uint256 _size
) external {
bytes32 key = PreimageKeyLib.localizeIdent(_ident);
// Store all components of the boot info.
storeFixed(0, 0, 32, l1head)
storeFixed(1, 0, 32, l2head)
storeFixed(2, 0, 32, l2claim)
storeFixed(3, 0, 32, l2ClaimBlockNumber)
storeDyn(4, l2ChainConfig)
storeDyn(5, rollupConfig)
}
preimagePartOk[key][_partOffset] = true;
preimageParts[key][_partOffset] = _part;
preimageLengths[key] = _size;
}
/// @notice Prepares a pre-image to be read by keccak256 key, starting at
......@@ -170,30 +109,4 @@ contract PreimageOracle {
preimageParts[key][_partOffset] = part;
preimageLengths[key] = size;
}
/// @notice Computes and returns the key for a global keccak pre-image.
/// @param _preimage The pre-image.
/// @return key_ The pre-image key.
function computeKeccak256PreimageKey(bytes calldata _preimage) external pure returns (bytes32 key_) {
assembly {
let size := calldataload(0x24)
// Leave slots 0x40 and 0x60 untouched,
// and everything after as scratch-memory.
let ptr := 0x80
// Store size as a big-endian uint64 at the start of pre-image
mstore(ptr, shl(192, size))
ptr := add(ptr, 8)
// Copy preimage payload into memory so we can hash and read it.
calldatacopy(ptr, _preimage.offset, size)
// Compute the pre-image keccak256 hash (aka the pre-image key)
let h := keccak256(ptr, size)
// Mask out prefix byte, replace with type 2 byte
key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 2))
}
}
}
......@@ -93,9 +93,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver {
}
// Clone the implementation contract and initialize it with the given parameters.
proxy = IDisputeGame(
address(impl).clone(abi.encodePacked(rootClaim, extraData.length, extraData))
);
proxy = IDisputeGame(address(impl).clone(abi.encodePacked(rootClaim, extraData)));
proxy.initialize();
// Compute the unique identifier for the dispute game.
......
......@@ -243,7 +243,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
/// @inheritdoc IFaultDisputeGame
function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) {
l2BlockNumber_ = _getArgUint256(0x20);
l2BlockNumber_ = _getArgUint256(0x40);
}
////////////////////////////////////////////////////////////////
......@@ -334,16 +334,11 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
rootClaim_ = Claim.wrap(_getArgFixedBytes(0x00));
}
/// @inheritdoc IDisputeGame
function extraDataLen() public pure returns (uint256 extraDataLen_) {
// The extra data length is in the second word of the cwia calldata.
extraDataLen_ = _getArgUint256(0x20);
}
/// @inheritdoc IDisputeGame
function extraData() public pure returns (bytes memory extraData_) {
// The extra data starts at the third word within the cwia calldata.
extraData_ = _getArgDynBytes(0x40, uint64(extraDataLen()));
// Account for the `l2BlockNumber` argument @ 0x40.
extraData_ = _getArgDynBytes(0x20, 0x20);
}
/// @inheritdoc IDisputeGame
......@@ -383,8 +378,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
})
);
// Load the local data into the preimage oracle.
VM.oracle().loadLocalData(extraData());
// TODO(clabby): Load the local data into the preimage oracle.
}
/// @notice Returns the length of the `claimData` array.
......
......@@ -39,7 +39,15 @@ interface IBigStepper {
/// @notice Temporary interface for the `IPreimageOracle`. Remove once we've upgraded
/// the cannon contracts to a newer version of solc.
interface IPreimageOracle {
/// @notice Loads local data into the pre-image oracle in the context of the caller.
/// @param _bootInfo The boot info struct encoded as a tuple of .
function loadLocalData(bytes memory _bootInfo) external;
/// @notice Loads a local data part into the preimage oracle.
/// @param _partOffset The offset of the local data part.
/// @param _ident The identifier of the local data.
/// @param _part The local data part.
/// @param _size The size of the local data.
function loadLocalPart(
uint256 _partOffset,
uint256 _ident,
bytes32 _part,
uint256 _size
) external;
}
......@@ -32,13 +32,8 @@ interface IDisputeGame is IInitializable {
/// @return rootClaim_ The root claim of the DisputeGame.
function rootClaim() external pure returns (Claim rootClaim_);
/// @notice Getter for the length of the extra data.
/// @dev `clones-with-immutable-args` argument #2
/// @return extraDataLen_ The length of the `extraData`
function extraDataLen() external pure returns (uint256 extraDataLen_);
/// @notice Getter for the extra data.
/// @dev `clones-with-immutable-args` argument #3
/// @dev `clones-with-immutable-args` argument #2
/// @return extraData_ Any extra data supplied to the dispute game contract by the creator.
function extraData() external pure returns (bytes memory extraData_);
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.7.6;
pragma abicoder v2;
import { Test } from "forge-std/Test.sol";
import { PreimageOracle } from "../src/cannon/PreimageOracle.sol";
import { PreimageOracle } from "../cannon/PreimageOracle.sol";
import { PreimageKeyLib } from "../cannon/PreimageKeyLib.sol";
contract PreimageOracle_Test is Test {
PreimageOracle oracle;
......@@ -15,9 +17,9 @@ contract PreimageOracle_Test is Test {
}
/// @notice Test the pre-image key computation with a known pre-image.
function test_computePreimageKey_succeeds() public {
function test_keccak256PreimageKey_succeeds() public {
bytes memory preimage = hex"deadbeef";
bytes32 key = oracle.computeKeccak256PreimageKey(preimage);
bytes32 key = PreimageKeyLib.keccak256PreimageKey(preimage);
bytes32 known = 0x02fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1;
assertEq(key, known);
}
......@@ -26,7 +28,7 @@ contract PreimageOracle_Test is Test {
function test_loadKeccak256PreimagePart_succeeds() public {
// Set the pre-image
bytes memory preimage = hex"deadbeef";
bytes32 key = oracle.computeKeccak256PreimageKey(preimage);
bytes32 key = PreimageKeyLib.keccak256PreimageKey(preimage);
uint256 offset = 0;
oracle.loadKeccak256PreimagePart(offset, preimage);
......
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