diff --git a/src/bridge/ISequencerInbox.sol b/src/bridge/ISequencerInbox.sol index 6802a42..228a127 100644 --- a/src/bridge/ISequencerInbox.sol +++ b/src/bridge/ISequencerInbox.sol @@ -269,6 +269,18 @@ interface ISequencerInbox is IDelayedMessageProvider { uint256 newMessageCount ) external; + /// @dev Proves message delays, updates delay buffers, verifies EigenDA certs, and posts them to the accumulator. + /// DelayProof proves the delay of the message and syncs the delay buffer. + function addSequencerL2BatchFromEigenDADelayProof( + uint256 sequenceNumber, + EigenDACert calldata cert, + IGasRefunder gasRefunder, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount, + DelayProof calldata delayProof + ) external; + /// @dev Proves message delays, updates delay buffers, and posts an L2 batch with blob data. /// DelayProof proves the delay of the message and syncs the delay buffer. function addSequencerL2BatchFromBlobsDelayProof( diff --git a/src/bridge/SequencerInbox.sol b/src/bridge/SequencerInbox.sol index dbf6b5e..737acbb 100644 --- a/src/bridge/SequencerInbox.sol +++ b/src/bridge/SequencerInbox.sol @@ -146,7 +146,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox // gap used to ensure forward compatiblity with newly introduced storage variables // from upstream offchainlabs/nitro-contracts. Any newly introduced storage vars // made in subsequent releases should result in decrementing the gap counter - uint256[38] internal __gap; + uint256[37] internal __gap; IRollupManager public eigenDARollupManager; constructor( @@ -455,6 +455,39 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox } } + /// @inheritdoc ISequencerInbox + function addSequencerL2BatchFromEigenDADelayProof( + uint256 sequenceNumber, + EigenDACert calldata cert, + IGasRefunder gasRefunder, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount, + DelayProof calldata delayProof + ) external refundsGas(gasRefunder, IReader4844(address(0))) { + if (!CallerChecker.isCallerCodelessOrigin()) revert NotCodelessOrigin(); + if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); + if (!isDelayBufferable) revert NotDelayBufferable(); + + delayProofImpl(afterDelayedMessagesRead, delayProof); + + // Verify that the blob was actually included before continuing + eigenDARollupManager.verifyBlob(cert.blobHeader, cert.blobVerificationProof); + // Form the EigenDA data hash and get the time bounds + (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = + formEigenDADataHash(cert, 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 addSequencerL2BatchFromEigenDA( uint256 sequenceNumber, EigenDACert calldata cert, @@ -463,9 +496,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox uint256 prevMessageCount, uint256 newMessageCount ) external refundsGas(gasRefunder, IReader4844(address(0))) { - if (msg.sender != tx.origin) revert NotOrigin(); + if (!CallerChecker.isCallerCodelessOrigin()) revert NotCodelessOrigin(); if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); - if (address(msg.sender).code.length > 0) revert NotEOA(); + if (isDelayProofRequired(afterDelayedMessagesRead)) revert DelayProofRequired(); + // Verify that the blob was actually included before continuing eigenDARollupManager.verifyBlob(cert.blobHeader, cert.blobVerificationProof); // Form the EigenDA data hash and get the time bounds diff --git a/test/contract/sequencerInboxDelayBufferable.spec.ts b/test/contract/sequencerInboxDelayBufferable.spec.ts index 5f30a0b..fe5bacf 100644 --- a/test/contract/sequencerInboxDelayBufferable.spec.ts +++ b/test/contract/sequencerInboxDelayBufferable.spec.ts @@ -11,6 +11,7 @@ import { forceIncludeMessages, } from './testHelpers' +// TODO: Add delay proof tests for EigenDA entrypoint describe('SequencerInboxDelayBufferable', async () => { it('can deplete buffer', async () => { const { bridge, sequencerInbox, batchPoster, delayConfig, maxDelay } = diff --git a/test/foundry/SequencerInbox.t.sol b/test/foundry/SequencerInbox.t.sol index 4cb9a7f..aa34da1 100644 --- a/test/foundry/SequencerInbox.t.sol +++ b/test/foundry/SequencerInbox.t.sol @@ -446,9 +446,10 @@ contract SequencerInboxTest is Test { subMessageCount, subMessageCount + 1 ); + } - // TODO: put these in jsons later - // create illegal commitment + function testAddSequencerL2BatchFromEigenDAFailsWithInvalidCert() public { + // TODO: put these in json files BN254.G1Point memory illegalCommitment = BN254.G1Point({ X: 11151623676041303181597631684634074376466382703418354161831688442589830350329, Y: 4222041728992406478862708226745479381252734858741080790666424175645694456140 @@ -479,6 +480,40 @@ contract SequencerInboxTest is Test { inclusionProof: bytes(""), quorumIndices: bytes("") }); + + // finish filling out the illegalBlobHeader + illegalBlobHeader.commitment = illegalCommitment; + illegalBlobHeader.dataLength = 20; + + ISequencerInbox.EigenDACert memory illegalCert = ISequencerInbox.EigenDACert({ + blobHeader: illegalBlobHeader, + blobVerificationProof: illegalBlobVerificationProof + }); + + // change the eigenDAServiceManager to use the holesky testnet contract + (SequencerInbox seqInbox, Bridge bridge,) = deployRollup(false, false, bufferConfigDefault); + address delayedInboxSender = address(140); + uint8 delayedInboxKind = 3; + bytes32 messageDataHash = RAND.Bytes32(); + + vm.prank(dummyInbox); + bridge.enqueueDelayedMessage(delayedInboxKind, delayedInboxSender, messageDataHash); + + uint256 subMessageCount = bridge.sequencerReportedSubMessageCount(); + uint256 sequenceNumber = bridge.sequencerMessageCount(); + uint256 delayedMessagesRead = bridge.delayedMessageCount(); + + vm.prank(tx.origin); + + vm.expectRevert(); + seqInbox.addSequencerL2BatchFromEigenDA( + sequenceNumber, + illegalCert, + IGasRefunder(address(0)), + delayedMessagesRead, + subMessageCount, + subMessageCount + 1 + ); } function testAddSequencerL2BatchFromOrigin_ArbitrumHosted( @@ -862,9 +897,6 @@ contract SequencerInboxTest is Test { blobHeader.dataLength = uint32(uint256(vm.parseJsonInt(json, ".blob_info.blob_header.data_length"))); - //bytes memory quorumParamsBytes = vm.parseJson(json, ".blob_info.blob_header.blob_quorum_params"); - - // TODO: Parse these from the array, for some reason parsing them reads in the wrong order IEigenDAServiceManager.QuorumBlobParam[] memory quorumParams = new IEigenDAServiceManager.QuorumBlobParam[](2);