Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Cert timing bug for L2s #32

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/bridge/EigenDABlobVerifierL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
pragma solidity ^0.8.9;

import "./IRollupManager.sol";
import {
ExpiredEigenDACert
} from "../libraries/Error.sol";

contract EigenDABlobVerifierL1 is IRollupManager {
IEigenDAServiceManager public immutable EIGEN_DA_SERVICE_MANAGER;
uint256 internal constant MAX_CERTIFICATE_DRIFT = 100;

constructor(address _eigenDAServiceManager) {
EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager);
Expand All @@ -14,6 +18,23 @@ contract EigenDABlobVerifierL1 is IRollupManager {
IEigenDAServiceManager.BlobHeader calldata blobHeader,
EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof
) external view {
/*
Verify that the certificate is less than 2 epochs old from the L1 reference block number
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 epoch is about 24mins. In addition, referenceBlockNumber is not right, because it is smaller than confirmationBlockNumber. ReferenceBlockNumber is the number we used to anchor the stake used to distribute chunks to DA nodes. The time diff is the batchingInterval+75(which is some number we introduced to prevent reorg).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we stick with confirmationBlockNumber. I think 20 mins is sufficient.

This is to prevent timing attacks where the sequencer could submit an expired or close to expired
certificate which could impact liveness of full nodes as well as the safety of the bridge
*/
if (
(blobVerificationProof.batchMetadata.confirmationBlockNumber +
MAX_CERTIFICATE_DRIFT) < block.number
) {
revert ExpiredEigenDACert(
block.number,
blobVerificationProof.batchMetadata.confirmationBlockNumber +
MAX_CERTIFICATE_DRIFT
);
}


EigenDARollupUtils.verifyBlob(blobHeader, EIGEN_DA_SERVICE_MANAGER, blobVerificationProof);
}
}
3 changes: 3 additions & 0 deletions src/libraries/Error.sol
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ error BadSequencerMessageNumber(uint256 stored, uint256 received);
/// @dev Tried to create an already valid Data Availability Service keyset
error AlreadyValidDASKeyset(bytes32);

/// @dev The EigenDA certificate provided to the inbox was stale
error ExpiredEigenDACert(uint256 currentBlock, uint256 l1ReferenceBlock);

/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
error NoSuchKeyset(bytes32);

Expand Down
67 changes: 67 additions & 0 deletions test/foundry/EigenDABlobVerifierL1.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "forge-std/Test.sol";
import "../../src/bridge/EigenDABlobVerifierL1.sol";
import "../../src/libraries/Error.sol";
import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol";
import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol";
import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol";
import {SequencerInboxTest} from "./SequencerInbox.t.sol";
import {
ExpiredEigenDACert
} from "../../src/libraries/Error.sol";

contract EigenDABlobVerifierL1Test is Test {
EigenDABlobVerifierL1 public verifier;
IEigenDAServiceManager dummyEigenDAServiceManager = IEigenDAServiceManager(address(138));

SequencerInboxTest inboxTest = new SequencerInboxTest();

function setUp() public {
// Deploy the verifier contract with a mock EigenDA Service Manager
verifier = new EigenDABlobVerifierL1(address(dummyEigenDAServiceManager));
}

function testCertificateTooOld() public {
(
IEigenDAServiceManager.BlobHeader memory blobHeader,
EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof
) = inboxTest.readAndParseBlobInfo();

// Set the confirmation block number to be MAX_CERTIFICATE_DRIFT + 1
blobVerificationProof.batchMetadata.confirmationBlockNumber = 0;

vm.roll(101);
vm.expectRevert(
abi.encodeWithSelector(
ExpiredEigenDACert.selector,
block.number,
100
)
);

verifier.verifyBlob(
blobHeader,
blobVerificationProof
);
}

function testCertificateWithinSafetyBound() public {
(
IEigenDAServiceManager.BlobHeader memory blobHeader,
EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof
) = inboxTest.readAndParseBlobInfo();

// Set the confirmation block number to be MAX_CERTIFICATE_DRIFT + 1
blobVerificationProof.batchMetadata.confirmationBlockNumber = 100;

vm.roll(101);
vm.expectRevert(bytes(""));

verifier.verifyBlob(
blobHeader,
blobVerificationProof
);
}
}
Loading