Skip to content

Commit

Permalink
feat: blockchain agnostic inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
ZzzzHui committed Oct 9, 2023
1 parent 6f45119 commit e795739
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 33 deletions.
4 changes: 2 additions & 2 deletions onchain/rollups/contracts/inputs/IInputBox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface IInputBox {
/// @param dapp The address of the DApp
/// @param inputIndex The index of the input in the input box
/// @param sender The address that sent the input
/// @param input The contents of the input
/// @param input The input payload
/// @dev MUST be triggered on a successful call to `addInput`.
event InputAdded(
address indexed dapp,
Expand All @@ -20,7 +20,7 @@ interface IInputBox {

/// @notice Add an input to a DApp's input box.
/// @param _dapp The address of the DApp
/// @param _input The contents of the input
/// @param _input The input payload
/// @return The hash of the input plus some extra metadata
/// @dev MUST fire an `InputAdded` event accordingly.
/// Input larger than machine limit will raise `InputSizeExceedsLimit` error.
Expand Down
6 changes: 3 additions & 3 deletions onchain/rollups/contracts/inputs/InputBox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ contract InputBox is IInputBox {
bytes32[] storage inputBox = inputBoxes[_dapp];
uint256 inputIndex = inputBox.length;

bytes32 inputHash = LibInput.computeInputHash(
bytes32 inputHash = LibInput.computeEvmInputHash(
msg.sender,
block.number,
block.timestamp,
_input,
inputIndex
inputIndex,
_input
);

// add input to the input box
Expand Down
35 changes: 16 additions & 19 deletions onchain/rollups/contracts/library/LibInput.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,29 @@ library LibInput {
/// @param sender `msg.sender`
/// @param blockNumber `block.number`
/// @param blockTimestamp `block.timestamp`
/// @param input The input blob
/// @param inputIndex The index of the input in the input box
/// @return The input hash
function computeInputHash(
/// @param input The input payload
/// @return The EVM input hash
function computeEvmInputHash(
address sender,
uint256 blockNumber,
uint256 blockTimestamp,
bytes calldata input,
uint256 inputIndex
uint256 inputIndex,
bytes calldata input
) internal pure returns (bytes32) {
if (input.length > CanonicalMachine.INPUT_MAX_SIZE) {
revert InputSizeExceedsLimit();
}

bytes32 keccakMetadata = keccak256(
abi.encode(
sender,
blockNumber,
blockTimestamp,
0, //TODO decide how to deal with epoch index
inputIndex // input index in the input box
)
bytes memory inputBlob = abi.encodeWithSignature(
"EvmInput(address,uint256,uint256,uint256,bytes)",
sender,
blockNumber,
blockTimestamp,
inputIndex,
input
);

bytes32 keccakInput = keccak256(input);
if (inputBlob.length > CanonicalMachine.INPUT_MAX_SIZE) {
revert InputSizeExceedsLimit();
}

return keccak256(abi.encode(keccakMetadata, keccakInput));
return keccak256(inputBlob);
}
}
36 changes: 27 additions & 9 deletions onchain/rollups/test/foundry/inputs/InputBox.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ contract InputBoxHandler is Test {
);

// Compute the input hash from the arguments passed to `addInput`
bytes32 computedInputHash = LibInput.computeInputHash(
bytes32 computedInputHash = LibInput.computeEvmInputHash(
msg.sender,
block.number,
block.timestamp,
_input,
index
index,
_input
);

// Check if the input hash matches the computed one
Expand Down Expand Up @@ -158,13 +158,31 @@ contract InputBoxTest is Test {
assertEq(inputBox.getNumberOfInputs(_dapp), 0);
}

function getMaxInputPayloadLength() internal pure returns (uint256) {
// an input blob instance
bytes memory blob = abi.encodeWithSignature(
"EvmInput(address,uint256,uint256,uint256,bytes)",
address(0),
0,
0,
0,
new bytes(32)
);
// number of bytes in input blob excluding input payload
uint256 extraBytes = blob.length - 32;
// because it's abi encoded, input payloads are stored as multiples of 32 bytes
return ((CanonicalMachine.INPUT_MAX_SIZE - extraBytes) / 32) * 32;
}

function testAddLargeInput() public {
address dapp = vm.addr(1);

inputBox.addInput(dapp, new bytes(CanonicalMachine.INPUT_MAX_SIZE));
uint256 maxLength = getMaxInputPayloadLength();

inputBox.addInput(dapp, new bytes(maxLength));

vm.expectRevert(LibInput.InputSizeExceedsLimit.selector);
inputBox.addInput(dapp, new bytes(CanonicalMachine.INPUT_MAX_SIZE + 1));
inputBox.addInput(dapp, new bytes(maxLength + 1));
}

// fuzz testing with multiple inputs
Expand All @@ -175,7 +193,7 @@ contract InputBoxTest is Test {

// assume #bytes for each input is within bounds
for (uint256 i; i < numInputs; ++i) {
vm.assume(_inputs[i].length <= CanonicalMachine.INPUT_MAX_SIZE);
vm.assume(_inputs[i].length <= getMaxInputPayloadLength());
}

// adding inputs
Expand All @@ -199,12 +217,12 @@ contract InputBoxTest is Test {
// testing added inputs
for (uint256 i; i < numInputs; ++i) {
// compute input hash for each input
bytes32 inputHash = LibInput.computeInputHash(
bytes32 inputHash = LibInput.computeEvmInputHash(
address(this),
i, // block.number
i + year2022, // block.timestamp
_inputs[i],
i // inputBox.length
i, // inputBox.length
_inputs[i]
);
// test if input hash is the same as in InputBox
assertEq(inputHash, inputBox.getInputHash(_dapp, i));
Expand Down

0 comments on commit e795739

Please sign in to comment.