Skip to content

Commit

Permalink
feat: add getNumberOfInputsBeforeCurrentBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
guidanoli committed Jan 10, 2025
1 parent f9c97d5 commit 92da65b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
8 changes: 8 additions & 0 deletions contracts/inputs/IInputBox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ interface IInputBox {
address appContract
) external view returns (uint256);

/// @notice Get the number of inputs sent to an application
/// before the current block. This can be useful for deriving
/// input ranges from block ranges.
/// @param appContract The application contract address
function getNumberOfInputsBeforeCurrentBlock(
address appContract
) external view returns (uint256);

/// @notice Get the hash of an input in an application's input box.
/// @param appContract The application contract address
/// @param index The input index
Expand Down
31 changes: 30 additions & 1 deletion contracts/inputs/InputBox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ contract InputBox is IInputBox {
/// @notice Mapping of application contract addresses to arrays of input hashes.
mapping(address => bytes32[]) private _inputBoxes;

/// @notice Snapshot of number of inputs
struct Snapshot {
uint256 blockNumber;
uint256 numberOfInputsBeforeBlock;
}

/// @notice Mapping of application contract addresses to snapshot.
mapping(address => Snapshot) private _snapshots;

/// @inheritdoc IInputBox
function addInput(
address appContract,
Expand All @@ -20,6 +29,13 @@ contract InputBox is IInputBox {

uint256 index = inputBox.length;

// take snapshot if first input of block
Snapshot storage snapshot = _snapshots[appContract];
if (snapshot.blockNumber < block.number) {
snapshot.blockNumber = block.number;
snapshot.numberOfInputsBeforeBlock = index;
}

bytes memory input = abi.encodeCall(
Inputs.EvmAdvance,
(
Expand Down Expand Up @@ -54,10 +70,23 @@ contract InputBox is IInputBox {
/// @inheritdoc IInputBox
function getNumberOfInputs(
address appContract
) external view override returns (uint256) {
) public view override returns (uint256) {
return _inputBoxes[appContract].length;
}

/// @inheritdoc IInputBox
function getNumberOfInputsBeforeCurrentBlock(
address appContract
) external view returns (uint256) {
Snapshot storage snapshot = _snapshots[appContract];
if (snapshot.blockNumber == block.number) {
return snapshot.numberOfInputsBeforeBlock;
} else {
// snapshot.blockNumber < block.number
return getNumberOfInputs(appContract);
}
}

/// @inheritdoc IInputBox
function getInputHash(
address appContract,
Expand Down
14 changes: 14 additions & 0 deletions test/inputs/InputBox.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ contract InputBoxTest is Test {

function testNoInputs(address appContract) public view {
assertEq(_inputBox.getNumberOfInputs(appContract), 0);
assertEq(_inputBox.getNumberOfInputsBeforeCurrentBlock(appContract), 0);
}

function testAddLargeInput() public {
Expand Down Expand Up @@ -105,6 +106,19 @@ contract InputBoxTest is Test {
}
}

function testNumberOfInputsBeforeCurrentBlock() external {
address appContract = vm.addr(1);
for (uint256 j; j < 3; ++j) {
uint256 n = _inputBox.getNumberOfInputs(appContract);
for (uint256 i; i < 2; ++i) {
_inputBox.addInput(appContract, new bytes(0));
// prettier-ignore
assertEq(_inputBox.getNumberOfInputsBeforeCurrentBlock(appContract), n);
}
vm.roll(vm.getBlockNumber() + 1);
}
}

function _prevrandao(uint256 blockNumber) internal pure returns (uint256) {
return uint256(keccak256(abi.encode("prevrandao", blockNumber)));
}
Expand Down

0 comments on commit 92da65b

Please sign in to comment.