diff --git a/.gitmodules b/.gitmodules index 8471ea6..b563528 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "lib/block-hash-pusher"] - path = lib/block-hash-pusher - url = https://github.com/Offchainlabs/block-hash-pusher [submodule "lib/scroll-contracts"] path = lib/scroll-contracts url = https://github.com/scroll-tech/scroll-contracts diff --git a/foundry.lock b/foundry.lock index bfc57e4..06ae529 100644 --- a/foundry.lock +++ b/foundry.lock @@ -1,7 +1,4 @@ { - "lib/block-hash-pusher": { - "rev": "085872efb820563b9c50d85732457147523fbe67" - }, "lib/forge-std": { "rev": "8bbcf6e3f8f62f419e5429a0bd89331c85c37824" }, diff --git a/lib/block-hash-pusher b/lib/block-hash-pusher deleted file mode 160000 index 085872e..0000000 --- a/lib/block-hash-pusher +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 085872efb820563b9c50d85732457147523fbe67 diff --git a/remappings.txt b/remappings.txt index 7c17139..a441b90 100644 --- a/remappings.txt +++ b/remappings.txt @@ -3,6 +3,5 @@ forge-std/=lib/forge-std/src/ @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ @eth-optimism/=node_modules/@eth-optimism/ @arbitrum/nitro-contracts/=node_modules/@arbitrum/nitro-contracts -block-hash-pusher/=lib/block-hash-pusher/ @scroll-tech/scroll-contracts/=lib/scroll-contracts/src/ @linea-contracts/=lib/linea-monorepo/contracts/src/ \ No newline at end of file diff --git a/snapshots/verifyBroadcastMessage.json b/snapshots/verifyBroadcastMessage.json index 3d9d274..8c32d44 100644 --- a/snapshots/verifyBroadcastMessage.json +++ b/snapshots/verifyBroadcastMessage.json @@ -1,9 +1,9 @@ { - "EthereumToOptimism": "1642608", - "EthereumToTaikoL2": "1055627", + "EthereumToOptimism": "1639195", + "EthereumToTaikoL2": "1052214", "LineaL2ToEthereum": "2551776", - "ScrollL2ToEthereum": "1363077", - "ScrollToOptimism": "1349825", - "TaikoL2ToEthereum": "1025690", + "ScrollL2ToEthereum": "1361940", + "ScrollToOptimism": "1348688", + "TaikoL2ToEthereum": "1022277", "ZkSyncL2ToEthereum": "125479" } \ No newline at end of file diff --git a/src/contracts/block-hash-pusher/BaseBuffer.sol b/src/contracts/block-hash-pusher/BaseBuffer.sol index 1404b31..462c688 100644 --- a/src/contracts/block-hash-pusher/BaseBuffer.sol +++ b/src/contracts/block-hash-pusher/BaseBuffer.sol @@ -19,22 +19,14 @@ abstract contract BaseBuffer is IBuffer { /// @dev The block number of the newest block in the buffer. uint256 private _newestBlockNumber; - struct BufferSlot { - uint256 blockNumber; - bytes32 blockHash; - } + /// @dev Mapping of block numbers to block hashes. + mapping(uint256 blockNumber => bytes32 blockHash) private _blockHashes; - BufferSlot[_BUFFER_SIZE] private _buffer; + uint256[_BUFFER_SIZE] private _blockNumberBuffer; /// @inheritdoc IBuffer function parentChainBlockHash(uint256 parentChainBlockNumber) external view returns (bytes32) { - BufferSlot storage s = _buffer[parentChainBlockNumber % _BUFFER_SIZE]; - - if (s.blockNumber != parentChainBlockNumber) { - revert UnknownParentChainBlockHash(parentChainBlockNumber); - } - - bytes32 blockHash = s.blockHash; + bytes32 blockHash = _blockHashes[parentChainBlockNumber]; if (blockHash == 0) { revert UnknownParentChainBlockHash(parentChainBlockNumber); } @@ -54,19 +46,22 @@ abstract contract BaseBuffer is IBuffer { revert EmptyBlockHashes(); } - // write the hashes to the buffer, evicting old hashes as necessary + // write the hashes to both the mapping and circular buffer for (uint256 i = 0; i < blockHashesLength; i++) { uint256 blockNumber = firstBlockNumber + i; uint256 bufferIndex = blockNumber % _BUFFER_SIZE; + uint256 existingBlockNumber = _blockNumberBuffer[bufferIndex]; - BufferSlot storage bufferSlot = _buffer[bufferIndex]; - if (blockNumber <= bufferSlot.blockNumber) { - // noop + if (blockNumber <= existingBlockNumber) { continue; } - bufferSlot.blockNumber = blockNumber; - bufferSlot.blockHash = blockHashes[i]; + if (existingBlockNumber != 0) { + _blockHashes[existingBlockNumber] = 0; + } + + _blockHashes[blockNumber] = blockHashes[i]; + _blockNumberBuffer[bufferIndex] = blockNumber; } uint256 lastBlockNumber = firstBlockNumber + blockHashesLength - 1; diff --git a/src/contracts/provers/arbitrum/ChildToParentProver.sol b/src/contracts/provers/arbitrum/ChildToParentProver.sol index cf848e9..6434549 100644 --- a/src/contracts/provers/arbitrum/ChildToParentProver.sol +++ b/src/contracts/provers/arbitrum/ChildToParentProver.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.30; import {ProverUtils} from "../../libraries/ProverUtils.sol"; import {IStateProver} from "../../interfaces/IStateProver.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../block-hash-pusher/interfaces/IBuffer.sol"; import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol"; /// @notice Arbitrum implementation of a child to parent IStateProver. diff --git a/src/contracts/provers/linea/ChildToParentProver.sol b/src/contracts/provers/linea/ChildToParentProver.sol index 42d4091..fd32bf3 100644 --- a/src/contracts/provers/linea/ChildToParentProver.sol +++ b/src/contracts/provers/linea/ChildToParentProver.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.30; import {ProverUtils} from "../../libraries/ProverUtils.sol"; import {IStateProver} from "../../interfaces/IStateProver.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../block-hash-pusher/interfaces/IBuffer.sol"; import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol"; /// @notice Linea implementation of a child to parent IStateProver. @@ -14,7 +14,7 @@ contract ChildToParentProver is IStateProver { address public immutable blockHashBuffer; /// @dev Storage slot the buffer contract uses to store block hashes. /// See https://github.com/openintentsframework/broadcaster/blob/main/src/contracts/block-hash-pusher/BaseBuffer.sol - uint256 public constant blockHashMappingSlot = 51; + uint256 public constant blockHashMappingSlot = 1; /// @dev The chain ID of the home chain (child chain). uint256 public immutable homeChainId; diff --git a/src/contracts/provers/scroll/ChildToParentProver.sol b/src/contracts/provers/scroll/ChildToParentProver.sol index fdcba4a..c24c401 100644 --- a/src/contracts/provers/scroll/ChildToParentProver.sol +++ b/src/contracts/provers/scroll/ChildToParentProver.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.30; import {ProverUtils} from "../../libraries/ProverUtils.sol"; import {IStateProver} from "../../interfaces/IStateProver.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../block-hash-pusher/interfaces/IBuffer.sol"; import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol"; /// @notice Scroll implementation of a child to parent IStateProver. @@ -15,7 +15,7 @@ contract ChildToParentProver is IStateProver { address public immutable blockHashBuffer; /// @dev Storage slot the buffer contract uses to store block hashes. /// https://github.com/openintentsframework/broadcaster/blob/main/src/contracts/block-hash-pusher/BaseBuffer.sol - uint256 public constant blockHashMappingSlot = 51; + uint256 public constant blockHashMappingSlot = 1; /// @dev The chain ID of the home chain (child chain). uint256 public immutable homeChainId; diff --git a/src/contracts/provers/zksync/ChildToParentProver.sol b/src/contracts/provers/zksync/ChildToParentProver.sol index a025a69..20a950c 100644 --- a/src/contracts/provers/zksync/ChildToParentProver.sol +++ b/src/contracts/provers/zksync/ChildToParentProver.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.30; import {ProverUtils} from "../../libraries/ProverUtils.sol"; import {IStateProver} from "../../interfaces/IStateProver.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../block-hash-pusher/interfaces/IBuffer.sol"; import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol"; /// @notice ZkSync implementation of a child to parent IStateProver. @@ -15,7 +15,7 @@ contract ChildToParentProver is IStateProver { address public immutable blockHashBuffer; /// @dev Storage slot the buffer contract uses to store block hashes. /// See https://github.com/openintentsframework/broadcaster/blob/main/src/contracts/block-hash-pusher/BaseBuffer.sol - uint256 public constant blockHashMappingSlot = 51; + uint256 public constant blockHashMappingSlot = 1; /// @dev The chain ID of the home chain (child chain). uint256 public immutable homeChainId; diff --git a/test/Receiver.ethereum.t.sol b/test/Receiver.ethereum.t.sol index 9b098c0..1bc5e9f 100644 --- a/test/Receiver.ethereum.t.sol +++ b/test/Receiver.ethereum.t.sol @@ -10,7 +10,7 @@ import {IOutbox} from "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import {IStateProverPointer} from "../src/contracts/interfaces/IStateProverPointer.sol"; import {STATE_PROVER_POINTER_SLOT} from "../src/contracts/StateProverPointer.sol"; import {BlockHeaders} from "./utils/BlockHeaders.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; import {BufferMock} from "./mocks/BufferMock.sol"; import {ChildToParentProver as ArbChildToParentProver} from "../src/contracts/provers/arbitrum/ChildToParentProver.sol"; diff --git a/test/Receiver.t.sol b/test/Receiver.t.sol index a7f1aaf..2def15b 100644 --- a/test/Receiver.t.sol +++ b/test/Receiver.t.sol @@ -10,7 +10,7 @@ import {IOutbox} from "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import {IStateProverPointer} from "../src/contracts/interfaces/IStateProverPointer.sol"; import {STATE_PROVER_POINTER_SLOT} from "../src/contracts/StateProverPointer.sol"; import {BlockHeaders} from "./utils/BlockHeaders.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; import {BufferMock} from "./mocks/BufferMock.sol"; import {ChildToParentProver as ArbChildToParentProver} from "../src/contracts/provers/arbitrum/ChildToParentProver.sol"; diff --git a/test/mocks/BufferMock.sol b/test/mocks/BufferMock.sol index a2db6c3..898c0c6 100644 --- a/test/mocks/BufferMock.sol +++ b/test/mocks/BufferMock.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; contract BufferMock is IBuffer { mapping(uint256 => bytes32) public parentChainBlockHash; - uint64 public newestBlockNumber; + uint256 public newestBlockNumber; function receiveHashes(uint256 firstBlockNumber, bytes32[] memory blockHashes) external { for (uint256 i = 0; i < blockHashes.length; i++) { @@ -16,30 +16,8 @@ contract BufferMock is IBuffer { newestBlockNumber = uint64(firstBlockNumber + blockHashes.length - 1); } - function bufferSize() external view returns (uint256) { - return 0; - } - - function systemPusher() external view returns (address) { - return address(0); - } - - /// @dev The aliased address of the pusher contract on the parent chain. - function aliasedPusher() external view returns (address) { + /// @dev The address of the pusher contract on the parent chain. + function pusher() external view returns (address) { return address(0); } - - function blockHashMapping(uint256) external view returns (bytes32) { - return bytes32(0); - } - - function blockNumberBuffer(uint256) external view returns (uint256) { - return 0; - } - - /// @dev Whether the system address has pushed a block hash to the buffer. - /// Once this is set, only the system address can push more hashes. - function systemHasPushed() external view returns (bool) { - return false; - } } diff --git a/test/provers/arbitrum/ChildToParentProver.t.sol b/test/provers/arbitrum/ChildToParentProver.t.sol index e8d0113..7e342b3 100644 --- a/test/provers/arbitrum/ChildToParentProver.t.sol +++ b/test/provers/arbitrum/ChildToParentProver.t.sol @@ -9,7 +9,7 @@ import {ParentToChildProver} from "../../../src/contracts/provers/arbitrum/Paren import {IOutbox} from "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import {ChildToParentProver} from "../../../src/contracts/provers/arbitrum/ChildToParentProver.sol"; import {Bytes} from "@openzeppelin/contracts/utils/Bytes.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; import {RLP} from "@openzeppelin/contracts/utils/RLP.sol"; import {BlockHeaders} from "../../utils/BlockHeaders.sol"; diff --git a/test/provers/linea/ChildToParentProver.t.sol b/test/provers/linea/ChildToParentProver.t.sol index 3ec128a..ee80332 100644 --- a/test/provers/linea/ChildToParentProver.t.sol +++ b/test/provers/linea/ChildToParentProver.t.sol @@ -8,7 +8,7 @@ import {IBroadcaster} from "../../../src/contracts/interfaces/IBroadcaster.sol"; import {IOutbox} from "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import {ChildToParentProver} from "../../../src/contracts/provers/linea/ChildToParentProver.sol"; import {Bytes} from "@openzeppelin/contracts/utils/Bytes.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; import {BufferMock} from "../../mocks/BufferMock.sol"; import {RLP} from "@openzeppelin/contracts/utils/RLP.sol"; import {BlockHeaders} from "../../utils/BlockHeaders.sol"; diff --git a/test/provers/scroll/ChildToParentProver.t.sol b/test/provers/scroll/ChildToParentProver.t.sol index 61f054f..f42e9c9 100644 --- a/test/provers/scroll/ChildToParentProver.t.sol +++ b/test/provers/scroll/ChildToParentProver.t.sol @@ -8,7 +8,7 @@ import {IBroadcaster} from "../../../src/contracts/interfaces/IBroadcaster.sol"; import {IOutbox} from "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import {ChildToParentProver} from "../../../src/contracts/provers/scroll/ChildToParentProver.sol"; import {Bytes} from "@openzeppelin/contracts/utils/Bytes.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; import {BufferMock} from "../../mocks/BufferMock.sol"; import {RLP} from "@openzeppelin/contracts/utils/RLP.sol"; import {BlockHeaders} from "../../utils/BlockHeaders.sol"; diff --git a/test/provers/zksync/ChildToParentProver.t.sol b/test/provers/zksync/ChildToParentProver.t.sol index 1756d47..71f3d80 100644 --- a/test/provers/zksync/ChildToParentProver.t.sol +++ b/test/provers/zksync/ChildToParentProver.t.sol @@ -8,7 +8,7 @@ import {IBroadcaster} from "../../../src/contracts/interfaces/IBroadcaster.sol"; import {IOutbox} from "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import {ChildToParentProver} from "../../../src/contracts/provers/zksync/ChildToParentProver.sol"; import {Bytes} from "@openzeppelin/contracts/utils/Bytes.sol"; -import {IBuffer} from "block-hash-pusher/contracts/interfaces/IBuffer.sol"; +import {IBuffer} from "../../../src/contracts/block-hash-pusher/interfaces/IBuffer.sol"; import {BufferMock} from "../../mocks/BufferMock.sol"; import {RLP} from "@openzeppelin/contracts/utils/RLP.sol"; import {BlockHeaders} from "../../utils/BlockHeaders.sol";