diff --git a/src/bridge/EigenDABlobVerifierL1.sol b/src/bridge/EigenDABlobVerifierL1.sol new file mode 100644 index 00000000..dcae90d8 --- /dev/null +++ b/src/bridge/EigenDABlobVerifierL1.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "./IRollupManager.sol"; + +contract EigenDABlobVerifierL1 is IRollupManager { + + IEigenDAServiceManager public immutable eigenDAServiceManager; + + constructor(address _eigenDAServiceManager) { + eigenDAServiceManager = IEigenDAServiceManager(_eigenDAServiceManager); + } + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata blobHeader, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof + ) external view { + EigenDARollupUtils.verifyBlob(blobHeader, eigenDAServiceManager, blobVerificationProof); + } +} \ No newline at end of file diff --git a/src/bridge/EigenDABlobVerifierL2.sol b/src/bridge/EigenDABlobVerifierL2.sol new file mode 100644 index 00000000..f22ca017 --- /dev/null +++ b/src/bridge/EigenDABlobVerifierL2.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "./IRollupManager.sol"; + +contract EigenDABlobVerifierL2 is IRollupManager { + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata blobHeader, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof + ) external view { + //EigenDA blob verifcation is only supported on L1 currently + } +} diff --git a/src/bridge/IRollupManager.sol b/src/bridge/IRollupManager.sol new file mode 100644 index 00000000..7e9647bd --- /dev/null +++ b/src/bridge/IRollupManager.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; +import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; + +interface IRollupManager { + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata blobHeader, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof + ) external view; +} \ No newline at end of file diff --git a/src/bridge/RollupManager.sol b/src/bridge/RollupManager.sol deleted file mode 100644 index 7e8a4a39..00000000 --- a/src/bridge/RollupManager.sol +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.9; - -import {Merkle} from "@eigenda/eigenda-utils/libraries/Merkle.sol"; -import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol"; -import {EigenDAHasher} from "@eigenda/eigenda-utils/libraries/EigenDAHasher.sol"; -import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; -import {BitmapUtils} from "@eigenda/eigenda-utils/libraries/BitmapUtils.sol"; -import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; -import {IBLSSignatureChecker} from "@eigenda/eigenda-utils/interfaces/IBLSSignatureChecker.sol"; -import {IPaymentCoordinator} from "@eigenda/eigenda-utils/interfaces/IPaymentCoordinator.sol"; -import {ISignatureUtils} from "@eigenda/eigenda-utils/interfaces/ISignatureUtils.sol"; - -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - -interface IRollupManager { - - function verifyBlob( - IEigenDAServiceManager.BlobHeader calldata blobHeader, - EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof - ) external view; - - function openCommitment( - uint256 point, - uint256 evaluation, - BN254.G1Point memory tau, - BN254.G1Point memory commitment, - BN254.G2Point memory proof - ) external view returns(bool); - -} - -// EigenDADummyManager is a dummy implementation of IRollupManager -// and is used in nitro-testnode to avoid the overhead of deploying core EigenDA contracts -// to simplify the testing process. -contract EigenDADummyManager { - - function verifyBlob( - IEigenDAServiceManager.BlobHeader calldata, - EigenDARollupUtils.BlobVerificationProof calldata - ) external view { - return ; - } - - function openCommitment( - uint256 point, - uint256 evaluation, - BN254.G1Point memory tau, - BN254.G1Point memory commitment, - BN254.G2Point memory proof - ) internal view returns(bool) { - - return EigenDARollupUtils.openCommitment(point, evaluation, tau, commitment, proof); - } -} - -contract EigenDARollupManager is Ownable, IRollupManager { - using BN254 for BN254.G1Point; - - address public eigenDAServiceManager; - - function verifyBlob( - IEigenDAServiceManager.BlobHeader calldata blobHeader, - EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof - ) external view { - return EigenDARollupUtils.verifyBlob(blobHeader, IEigenDAServiceManager(eigenDAServiceManager), blobVerificationProof); - } - - function openCommitment( - uint256 point, - uint256 evaluation, - BN254.G1Point memory tau, - BN254.G1Point memory commitment, - BN254.G2Point memory proof - ) external view returns(bool) { - - return EigenDARollupUtils.openCommitment(point, evaluation, tau, commitment, proof); - } - - function setEigenDAServiceManager(address _eigenDAServiceManager) external onlyOwner { - eigenDAServiceManager = _eigenDAServiceManager; - } -} diff --git a/src/bridge/SequencerInbox.sol b/src/bridge/SequencerInbox.sol index 23b912b2..8173072c 100644 --- a/src/bridge/SequencerInbox.sol +++ b/src/bridge/SequencerInbox.sol @@ -47,9 +47,7 @@ import {GasRefundEnabled} from "../libraries/GasRefundEnabled.sol"; import "../libraries/ArbitrumChecker.sol"; import {IERC20Bridge} from "./IERC20Bridge.sol"; -import {IRollupManager} from "./RollupManager.sol"; -import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; - +import "./IRollupManager.sol"; /** * @title Accepts batches from the sequencer and adds them to the rollup inbox. @@ -63,8 +61,6 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox IBridge public bridge; - address public eigenDARollupManager; - /// @inheritdoc ISequencerInbox uint256 public constant HEADER_LENGTH = 40; @@ -104,6 +100,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo; + IRollupManager public rollupManager; + modifier onlyRollupOwner() { if (msg.sender != rollup.owner()) revert NotOwner(msg.sender, rollup.owner()); _; @@ -409,59 +407,56 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox } } + function addSequencerL2BatchFromEigenDA( + uint256 sequenceNumber, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof, + IEigenDAServiceManager.BlobHeader calldata blobHeader, + IGasRefunder gasRefunder, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount + ) external refundsGas(gasRefunder, IReader4844(address(0))) { + if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); + // Verify that the blob was actually included before continuing + rollupManager.verifyBlob(blobHeader, blobVerificationProof); + // Form the EigenDA data hash and get the time bounds + (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formEigenDADataHash(blobHeader, afterDelayedMessagesRead); + + ISequencerInbox.SequenceMetadata memory metadata = ISequencerInbox.SequenceMetadata({ + sequenceNumber: sequenceNumber, + afterDelayedMessagesRead: afterDelayedMessagesRead, + prevMessageCount: prevMessageCount, + newMessageCount: newMessageCount + }); + + // Call a helper function to add the sequencer L2 batch + _addSequencerL2Batch(metadata, dataHash, timeBounds); + } + + function _addSequencerL2Batch( + ISequencerInbox.SequenceMetadata memory sequenceMetadata, + bytes32 dataHash, + IBridge.TimeBounds memory timeBounds + ) internal { + (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = + addSequencerL2BatchImpl(dataHash, sequenceMetadata.afterDelayedMessagesRead, 0, sequenceMetadata.prevMessageCount, sequenceMetadata.newMessageCount); + uint256 sequenceNumber = sequenceMetadata.sequenceNumber; + // Check the sequence number + if (seqMessageIndex != sequenceNumber && sequenceNumber != ~uint256(0)) { + revert BadSequencerNumber(seqMessageIndex, sequenceNumber); + } -function addSequencerL2BatchFromEigenDA( - uint256 sequenceNumber, - EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof, - IEigenDAServiceManager.BlobHeader calldata blobHeader, - IGasRefunder gasRefunder, - uint256 afterDelayedMessagesRead, - uint256 prevMessageCount, - uint256 newMessageCount -) external { - if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); - return; - // Verify that the blob was actually included before continuing - IRollupManager(eigenDARollupManager).verifyBlob(blobHeader, blobVerificationProof); - // Form the EigenDA data hash and get the time bounds - (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formEigenDADataHash(blobHeader, afterDelayedMessagesRead); - - ISequencerInbox.SequenceMetadata memory metadata = ISequencerInbox.SequenceMetadata({ - sequenceNumber: sequenceNumber, - afterDelayedMessagesRead: afterDelayedMessagesRead, - prevMessageCount: prevMessageCount, - newMessageCount: newMessageCount - }); - - // Call a helper function to add the sequencer L2 batch - _addSequencerL2Batch(metadata, dataHash, timeBounds); -} - -function _addSequencerL2Batch( - ISequencerInbox.SequenceMetadata memory sequenceMetadata, - bytes32 dataHash, - IBridge.TimeBounds memory timeBounds -) internal { - (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = - addSequencerL2BatchImpl(dataHash, sequenceMetadata.afterDelayedMessagesRead, 0, sequenceMetadata.prevMessageCount, sequenceMetadata.newMessageCount); - - uint256 sequenceNumber = sequenceMetadata.sequenceNumber; - // Check the sequence number - if (seqMessageIndex != sequenceNumber && sequenceNumber != ~uint256(0)) { - revert BadSequencerNumber(seqMessageIndex, sequenceNumber); - } - - emit SequencerBatchDelivered( - sequenceNumber, - beforeAcc, - afterAcc, - delayedAcc, - totalDelayedMessagesRead, - timeBounds, - IBridge.BatchDataLocation.EigenDA - ); -} + emit SequencerBatchDelivered( + sequenceNumber, + beforeAcc, + afterAcc, + delayedAcc, + totalDelayedMessagesRead, + timeBounds, + IBridge.BatchDataLocation.EigenDA + ); + } function addSequencerL2Batch( uint256 sequenceNumber, @@ -780,7 +775,7 @@ function _addSequencerL2Batch( emit OwnerFunctionCalled(5); } - /// @inheritdoc ISequencerInbox + /// @inheritdoc ISequencerInbox function setRollupAddress() external onlyRollupOwner { IOwnable newRollup = bridge.rollup(); if (rollup == newRollup) revert RollupNotChanged(); @@ -788,13 +783,12 @@ function _addSequencerL2Batch( emit OwnerFunctionCalled(6); } - /// @inheritdoc ISequencerInbox function setEigenDARollupManager(address newRollupManager) external onlyRollupOwner { - eigenDARollupManager = newRollupManager; + rollupManager = IRollupManager(newRollupManager); emit OwnerFunctionCalled(7); } - /// @notice Allows the rollup owner to sync the rollup address + /// @notice Allows the rollup owner to sync the rollup address function updateRollupAddress() external { if (msg.sender != IOwnable(rollup).owner()) revert NotOwner(msg.sender, IOwnable(rollup).owner()); diff --git a/src/mocks/SequencerInboxStub.sol b/src/mocks/SequencerInboxStub.sol index bf24ab9f..18d9e7c2 100644 --- a/src/mocks/SequencerInboxStub.sol +++ b/src/mocks/SequencerInboxStub.sol @@ -8,8 +8,7 @@ import "../bridge/SequencerInbox.sol"; import "../bridge/IEthBridge.sol"; import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol"; -import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; -import {IRollupManager} from "../bridge/RollupManager.sol"; +import "../bridge/IRollupManager.sol"; contract SequencerInboxStub is SequencerInbox { constructor( @@ -56,4 +55,4 @@ contract SequencerInboxStub is SequencerInbox { this; // silence warning about function not being view return bounds; } -} +} \ No newline at end of file diff --git a/test/foundry/DummyEigenDABlobVerifier.sol b/test/foundry/DummyEigenDABlobVerifier.sol new file mode 100644 index 00000000..8bcc5223 --- /dev/null +++ b/test/foundry/DummyEigenDABlobVerifier.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "../../src/bridge/IRollupManager.sol"; + +contract DummyEigenDABlobVerifier is IRollupManager{ + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata blobHeader, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof + ) external view {} +} \ No newline at end of file diff --git a/test/foundry/SequencerInbox.t.sol b/test/foundry/SequencerInbox.t.sol index 06fd0a5a..0c3e77db 100644 --- a/test/foundry/SequencerInbox.t.sol +++ b/test/foundry/SequencerInbox.t.sol @@ -8,9 +8,7 @@ import "../../src/bridge/SequencerInbox.sol"; import {ERC20Bridge} from "../../src/bridge/ERC20Bridge.sol"; import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; -import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; -import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; -import {IRollupManager, EigenDADummyManager} from "../../src/bridge/RollupManager.sol"; +import "./DummyEigenDABlobVerifier.sol"; import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol"; contract RollupMock { @@ -592,7 +590,7 @@ contract SequencerInboxTest is Test { function testAddSequencerL2BatchFromEigenDA() public { - EigenDADummyManager rollupManagerImpl = new EigenDADummyManager(); + DummyEigenDABlobVerifier rollupManagerImpl = new DummyEigenDABlobVerifier(); (SequencerInbox seqInbox, Bridge bridge) = deployRollup(false); // update the dummyEigenDAServiceManager to use the holesky serviceManager contract @@ -731,21 +729,26 @@ contract SequencerInboxTest is Test { vm.expectRevert(abi.encodeWithSelector(AlreadyInit.selector)); vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), + abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); - // IMPORTANT: slots have moved down by one because we have added additional variables for eigenDA - vm.store(address(seqInbox), bytes32(uint256(6)), bytes32(uint256(delayBlocks))); // slot 6: delayBlocks - vm.store(address(seqInbox), bytes32(uint256(7)), bytes32(uint256(futureBlocks))); // slot 7: futureBlocks - vm.store(address(seqInbox), bytes32(uint256(8)), bytes32(uint256(delaySeconds))); // slot 8: delaySeconds - vm.store(address(seqInbox), bytes32(uint256(9)), bytes32(uint256(futureSeconds))); // slot 9: futureSeconds + vm.store(address(seqInbox), bytes32(uint256(4)), bytes32(uint256(delayBlocks))); // slot 4: delayBlocks + vm.store(address(seqInbox), bytes32(uint256(5)), bytes32(uint256(futureBlocks))); // slot 5: futureBlocks + vm.store(address(seqInbox), bytes32(uint256(6)), bytes32(uint256(delaySeconds))); // slot 6: delaySeconds + vm.store(address(seqInbox), bytes32(uint256(7)), bytes32(uint256(futureSeconds))); // slot 7: futureSeconds vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), + abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); - (uint256 delayBlocks_, uint256 futureBlocks_, uint256 delaySeconds_, uint256 futureSeconds_) - = seqInbox.maxTimeVariation(); + ( + uint256 delayBlocks_, + uint256 futureBlocks_, + uint256 delaySeconds_, + uint256 futureSeconds_ + ) = seqInbox.maxTimeVariation(); assertEq(delayBlocks_, delayBlocks); assertEq(futureBlocks_, futureBlocks); assertEq(delaySeconds_, delaySeconds); @@ -754,7 +757,8 @@ contract SequencerInboxTest is Test { vm.expectRevert(abi.encodeWithSelector(AlreadyInit.selector)); vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), + abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); } @@ -889,4 +893,4 @@ contract SequencerInboxTest is Test { } -} +} \ No newline at end of file