From da387dd432ab874197ab14e0efcf05f1c7144cb0 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:22:14 -0300 Subject: [PATCH 1/5] Add blobVerificationProof --- .../da-layers/eigenda/DummyEigenDABridge.sol | 6 ++--- .../da-layers/eigenda/IEigenDABridge.sol | 25 ++++++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index dd893253b8..e2bd5e2445 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -20,8 +20,8 @@ contract DummyEigenDABridge is IEigenDABridge { function verifyBlobLeaf(MerkleProofInput calldata merkleProof) external view returns (bool) { // Inspired by eigenlayer contracts Merkle.verifyInclusionKeccak // https://github.com/Layr-Labs/eigenlayer-contracts/blob/3f3f83bd194b3bdc77d06d8fe6b101fafc3bcfd5/src/contracts/libraries/Merkle.sol - uint256 index = merkleProof.index; - bytes memory inclusionProof = merkleProof.inclusionProof; + uint256 index = merkleProof.blobVerificationProof.blobIndex; + bytes memory inclusionProof = merkleProof.blobVerificationProof.inclusionProof; require(inclusionProof.length % 32 == 0, "proof length not multiple of 32"); bytes32 computedHash = merkleProof.leaf; uint256 length = inclusionProof.length; @@ -44,7 +44,7 @@ contract DummyEigenDABridge is IEigenDABridge { } } } - require(computedHash == merkleProof.batchRoot, "invalid proof"); + require(computedHash == merkleProof.blobVerificationProof.batchMetadata.batchHeader.blobHeadersRoot, "invalid proof"); return true; } } diff --git a/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol index 11947e0458..359c40cd8d 100644 --- a/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol @@ -6,11 +6,30 @@ import {IImplementation} from "./IImplementation.sol"; interface IEigenDABridge { // solhint-disable-next-line gas-struct-packing + struct BatchHeader { + bytes32 blobHeadersRoot; + bytes quorumNumbers; + bytes signedStakeForQuorums; + uint32 referenceBlockNumber; + } + + struct BatchMetadata { + BatchHeader batchHeader; + bytes32 signatoryRecordHash; + uint32 confirmationBlockNumber; + } + + struct BlobVerificationProof { + uint32 batchId; + uint32 blobIndex; + BatchMetadata batchMetadata; + bytes inclusionProof; + bytes quorumIndices; + } + struct MerkleProofInput { - bytes32 batchRoot; bytes32 leaf; - uint256 index; - bytes inclusionProof; + BlobVerificationProof blobVerificationProof; } function implementation() external view returns (IImplementation implementation); From 18982e2b2e7063eb46546b7e7721f9bed7bc4934 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 18:02:52 -0300 Subject: [PATCH 2/5] Add hash batch metadata --- .../contracts/da-layers/eigenda/DummyEigenDABridge.sol | 5 +++++ da-contracts/foundry.toml | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index e2bd5e2445..3e5c02602e 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -17,9 +17,14 @@ contract DummyEigenDABridge is IEigenDABridge { return implementationContract; } + function hashBatchMetadata(BatchMetadata calldata batchMetadata) external pure returns (bytes32) { + return keccak256(abi.encodePacked(keccak256(abi.encode(batchMetadata.batchHeader)),batchMetadata.signatoryRecordHash,batchMetadata.confirmationBlockNumber)); + } + function verifyBlobLeaf(MerkleProofInput calldata merkleProof) external view returns (bool) { // Inspired by eigenlayer contracts Merkle.verifyInclusionKeccak // https://github.com/Layr-Labs/eigenlayer-contracts/blob/3f3f83bd194b3bdc77d06d8fe6b101fafc3bcfd5/src/contracts/libraries/Merkle.sol + bytes32 hashedBatchMetadata = this.hashBatchMetadata(merkleProof.blobVerificationProof.batchMetadata); uint256 index = merkleProof.blobVerificationProof.blobIndex; bytes memory inclusionProof = merkleProof.blobVerificationProof.inclusionProof; require(inclusionProof.length % 32 == 0, "proof length not multiple of 32"); diff --git a/da-contracts/foundry.toml b/da-contracts/foundry.toml index 6f29a31ccb..f4c9638e0c 100644 --- a/da-contracts/foundry.toml +++ b/da-contracts/foundry.toml @@ -5,7 +5,11 @@ libs = ['node_modules', 'lib'] remappings = [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", - "l2-contracts/=../l2-contracts/contracts/" + "l2-contracts/=../l2-contracts/contracts/", + "@eigenda/eigenda-utils/libraries/=lib/eigenda/contracts/src/libraries/", + "@eigenda/eigenda-utils/interfaces/=lib/eigenda/contracts/src/interfaces/", + "eigenlayer-middleware/=lib/eigenda/contracts/lib/eigenlayer-middleware/src/", + "eigenlayer-core/=lib/eigenda/contracts/lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/" ] allow_paths = ["../l2-contracts/contracts"] fs_permissions = [ From 4a5a54fc5ebbf817a4774ae5e1decc583551e614 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 18:04:49 -0300 Subject: [PATCH 3/5] forge install: eigenda v0.8.6 --- .gitmodules | 3 +++ da-contracts/lib/eigenda | 1 + 2 files changed, 4 insertions(+) create mode 160000 da-contracts/lib/eigenda diff --git a/.gitmodules b/.gitmodules index f94071e535..d89963a2cc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,3 +15,6 @@ [submodule "lib/@matterlabs/zksync-contracts"] path = lib/@matterlabs/zksync-contracts url = https://github.com/matter-labs/v2-testnet-contracts +[submodule "da-contracts/lib/eigenda"] + path = da-contracts/lib/eigenda + url = https://github.com/Layr-Labs/eigenda diff --git a/da-contracts/lib/eigenda b/da-contracts/lib/eigenda new file mode 160000 index 0000000000..82af794f09 --- /dev/null +++ b/da-contracts/lib/eigenda @@ -0,0 +1 @@ +Subproject commit 82af794f09b4c3739aee020c23100739b922107d From b25f258f12344a02378f9df5d2e50b8ae2a40dbb Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 18:56:15 -0300 Subject: [PATCH 4/5] Add eigendaservice manager --- .../contracts/da-layers/eigenda/DummyEigenDABridge.sol | 6 +++++- l1-contracts/deploy-scripts/DeployL1.s.sol | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index 3e5c02602e..4b5f08e62c 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -5,12 +5,15 @@ pragma solidity 0.8.24; import {IEigenDABridge} from "./IEigenDABridge.sol"; import {IImplementation} from "./IImplementation.sol"; import {DummyImplementation} from "./DummyImplementation.sol"; +import {IEigenDABatchMetadataStorage} from "@eigenda/eigenda-utils/interfaces/IEigenDABatchMetadataStorage.sol"; contract DummyEigenDABridge is IEigenDABridge { IImplementation public implementationContract; + IEigenDABatchMetadataStorage public eigenDaServiceManager; - constructor() { + constructor(address _eigenDaServiceManager) { implementationContract = new DummyImplementation(); + eigenDaServiceManager = IEigenDABatchMetadataStorage(_eigenDaServiceManager); } function implementation() external view returns (IImplementation) { @@ -25,6 +28,7 @@ contract DummyEigenDABridge is IEigenDABridge { // Inspired by eigenlayer contracts Merkle.verifyInclusionKeccak // https://github.com/Layr-Labs/eigenlayer-contracts/blob/3f3f83bd194b3bdc77d06d8fe6b101fafc3bcfd5/src/contracts/libraries/Merkle.sol bytes32 hashedBatchMetadata = this.hashBatchMetadata(merkleProof.blobVerificationProof.batchMetadata); + require(hashedBatchMetadata == IEigenDABatchMetadataStorage(eigenDaServiceManager).batchIdToBatchMetadataHash(merkleProof.blobVerificationProof.batchId), "invalid batch metadata"); uint256 index = merkleProof.blobVerificationProof.blobIndex; bytes memory inclusionProof = merkleProof.blobVerificationProof.inclusionProof; require(inclusionProof.length % 32 == 0, "proof length not multiple of 32"); diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 0d8378ed14..07c9c2738a 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -212,7 +212,8 @@ contract DeployL1Script is Script, DeployUtils { } if (config.contracts.eigenDAL1Validator == address(0)) { - address eigendaBridge = deployViaCreate2(Utils.readDummyEigenDABridgeBytecode(), ""); + address eigenDAServiceManagerAddress = address(0); + address eigendaBridge = deployViaCreate2(Utils.readDummyEigenDABridgeBytecode(), abi.encode(eigenDAServiceManagerAddress)); addresses.daAddresses.eigenDAL1Validator = deployViaCreate2( Utils.readEigenDAL1ValidatorBytecode(), abi.encode(eigendaBridge) From f15ccb83184d60f6ca451729469f261c40458a64 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:55:00 -0300 Subject: [PATCH 5/5] Add blob verifier --- .../da-layers/eigenda/DummyEigenDABridge.sol | 42 +++---------------- .../da-layers/eigenda/IBlobVerifier.sol | 12 ++++++ .../da-layers/eigenda/IEigenDABridge.sol | 20 ++++++++- l1-contracts/deploy-scripts/DeployL1.s.sol | 3 +- l1-contracts/deploy-scripts/DeployUtils.s.sol | 5 +++ 5 files changed, 42 insertions(+), 40 deletions(-) create mode 100644 da-contracts/contracts/da-layers/eigenda/IBlobVerifier.sol diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index 4b5f08e62c..115226c8c2 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -5,55 +5,23 @@ pragma solidity 0.8.24; import {IEigenDABridge} from "./IEigenDABridge.sol"; import {IImplementation} from "./IImplementation.sol"; import {DummyImplementation} from "./DummyImplementation.sol"; -import {IEigenDABatchMetadataStorage} from "@eigenda/eigenda-utils/interfaces/IEigenDABatchMetadataStorage.sol"; +import {IBlobVerifier} from "./IBlobVerifier.sol"; contract DummyEigenDABridge is IEigenDABridge { IImplementation public implementationContract; - IEigenDABatchMetadataStorage public eigenDaServiceManager; + IBlobVerifier public eigenBlobVerifier; - constructor(address _eigenDaServiceManager) { + constructor(address _eigenBlobVerifier) { implementationContract = new DummyImplementation(); - eigenDaServiceManager = IEigenDABatchMetadataStorage(_eigenDaServiceManager); + eigenBlobVerifier = IBlobVerifier(_eigenBlobVerifier); } function implementation() external view returns (IImplementation) { return implementationContract; } - function hashBatchMetadata(BatchMetadata calldata batchMetadata) external pure returns (bytes32) { - return keccak256(abi.encodePacked(keccak256(abi.encode(batchMetadata.batchHeader)),batchMetadata.signatoryRecordHash,batchMetadata.confirmationBlockNumber)); - } - function verifyBlobLeaf(MerkleProofInput calldata merkleProof) external view returns (bool) { - // Inspired by eigenlayer contracts Merkle.verifyInclusionKeccak - // https://github.com/Layr-Labs/eigenlayer-contracts/blob/3f3f83bd194b3bdc77d06d8fe6b101fafc3bcfd5/src/contracts/libraries/Merkle.sol - bytes32 hashedBatchMetadata = this.hashBatchMetadata(merkleProof.blobVerificationProof.batchMetadata); - require(hashedBatchMetadata == IEigenDABatchMetadataStorage(eigenDaServiceManager).batchIdToBatchMetadataHash(merkleProof.blobVerificationProof.batchId), "invalid batch metadata"); - uint256 index = merkleProof.blobVerificationProof.blobIndex; - bytes memory inclusionProof = merkleProof.blobVerificationProof.inclusionProof; - require(inclusionProof.length % 32 == 0, "proof length not multiple of 32"); - bytes32 computedHash = merkleProof.leaf; - uint256 length = inclusionProof.length; - for (uint256 i = 32; i <= length; i += 32) { - if (index % 2 == 0) { - // if ith bit of index is 0, then computedHash is a left sibling - assembly { - mstore(0x00, computedHash) - mstore(0x20, mload(add(inclusionProof, i))) - computedHash := keccak256(0x00, 0x40) - index := div(index, 2) - } - } else { - // if ith bit of index is 1, then computedHash is a right sibling - assembly { - mstore(0x00, mload(add(inclusionProof, i))) - mstore(0x20, computedHash) - computedHash := keccak256(0x00, 0x40) - index := div(index, 2) - } - } - } - require(computedHash == merkleProof.blobVerificationProof.batchMetadata.batchHeader.blobHeadersRoot, "invalid proof"); + eigenBlobVerifier.verifyBlobV1(merkleProof.blobHeader, merkleProof.blobVerificationProof); return true; } } diff --git a/da-contracts/contracts/da-layers/eigenda/IBlobVerifier.sol b/da-contracts/contracts/da-layers/eigenda/IBlobVerifier.sol new file mode 100644 index 0000000000..7fecf12a7c --- /dev/null +++ b/da-contracts/contracts/da-layers/eigenda/IBlobVerifier.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {IEigenDABridge} from "./IEigenDABridge.sol"; + +interface IBlobVerifier { + function verifyBlobV1( + IEigenDABridge.BlobHeader calldata blobHeader, + IEigenDABridge.BlobVerificationProof calldata blobVerificationProof + ) external view; +} diff --git a/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol index 359c40cd8d..39deb43be3 100644 --- a/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol @@ -27,8 +27,26 @@ interface IEigenDABridge { bytes quorumIndices; } + struct QuorumBlobParam { + uint8 quorumNumber; + uint8 adversaryThresholdPercentage; + uint8 confirmationThresholdPercentage; + uint32 chunkLength; + } + + struct G1Point { + uint256 X; + uint256 Y; + } + + struct BlobHeader { + G1Point commitment; + uint32 dataLength; + QuorumBlobParam[] quorumBlobParams; + } + struct MerkleProofInput { - bytes32 leaf; + BlobHeader blobHeader; BlobVerificationProof blobVerificationProof; } diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 07c9c2738a..2c34745248 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -212,8 +212,7 @@ contract DeployL1Script is Script, DeployUtils { } if (config.contracts.eigenDAL1Validator == address(0)) { - address eigenDAServiceManagerAddress = address(0); - address eigendaBridge = deployViaCreate2(Utils.readDummyEigenDABridgeBytecode(), abi.encode(eigenDAServiceManagerAddress)); + address eigendaBridge = deployViaCreate2(Utils.readDummyEigenDABridgeBytecode(), abi.encode(config.contracts.eigenDABlobVerifier)); addresses.daAddresses.eigenDAL1Validator = deployViaCreate2( Utils.readEigenDAL1ValidatorBytecode(), abi.encode(eigendaBridge) diff --git a/l1-contracts/deploy-scripts/DeployUtils.s.sol b/l1-contracts/deploy-scripts/DeployUtils.s.sol index e795169049..68f4333d13 100644 --- a/l1-contracts/deploy-scripts/DeployUtils.s.sol +++ b/l1-contracts/deploy-scripts/DeployUtils.s.sol @@ -167,6 +167,7 @@ struct ContractsConfig { bytes32 defaultAAHash; address availL1DAValidator; address eigenDAL1Validator; + address eigenDABlobVerifier; } struct TokensConfig { @@ -246,6 +247,10 @@ contract DeployUtils is Script { config.contracts.eigenDAL1Validator = toml.readAddress("$.contracts.eigenda_l1_validator"); } + if (vm.keyExistsToml(toml, "$.contracts.eigenda_blob_verifier_addr")) { + config.contracts.eigenDABlobVerifier = toml.readAddress("$.contracts.eigenda_blob_verifier_addr"); + } + config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); }