From 071aa0e4e9d98f7869c38d88792386bf639b901d Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:59:51 -0300 Subject: [PATCH 01/14] Remove validium check --- .../contracts/state-transition/chain-deps/facets/Executor.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index cb43a5880..c6a0e67a6 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -51,7 +51,7 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { bytes32[] memory blobCommitments = new bytes32[](MAX_NUMBER_OF_BLOBS); if (pricingMode == PubdataPricingMode.Validium) { // skipping data validation for validium, we just check that the data is empty - require(_newBatch.pubdataCommitments.length == 1, "EF: v0l"); + //require(_newBatch.pubdataCommitments.length == 1, "EF: v0l"); for (uint8 i = uint8(SystemLogKey.BLOB_ONE_HASH_KEY); i <= uint8(SystemLogKey.BLOB_SIX_HASH_KEY); i++) { logOutput.blobHashes[i - uint8(SystemLogKey.BLOB_ONE_HASH_KEY)] = bytes32(0); } From aaad97e6f3e9576f4ad8cf2941f2d47d14ffc217 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:20:23 -0300 Subject: [PATCH 02/14] Add verifier contract --- .../contracts/eigenda/EigenDAVerifier.sol | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 l1-contracts/contracts/eigenda/EigenDAVerifier.sol diff --git a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol new file mode 100644 index 000000000..7a628c220 --- /dev/null +++ b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol @@ -0,0 +1,25 @@ +// 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"; + +contract EigenDAVerifier { + + struct BlobInfo { + IEigenDAServiceManager.BlobHeader blobHeader; + EigenDARollupUtils.BlobVerificationProof blobVerificationProof; + } + + IEigenDAServiceManager public immutable EIGEN_DA_SERVICE_MANAGER; + + constructor(address _eigenDAServiceManager) { + EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager); + } + + function verifyBlob( + BlobInfo calldata blobInfo + ) external view { + EigenDARollupUtils.verifyBlob(blobInfo.blobHeader, EIGEN_DA_SERVICE_MANAGER, blobInfo.blobVerificationProof); + } +} From 9717debd45b88c1da1ac839fa6b6f360effc4cc8 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:27:28 -0300 Subject: [PATCH 03/14] forge install: eigenda v0.8.4 --- .gitmodules | 3 +++ l1-contracts/lib/eigenda | 1 + 2 files changed, 4 insertions(+) create mode 160000 l1-contracts/lib/eigenda diff --git a/.gitmodules b/.gitmodules index 5cbc631ba..73acc54c8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,3 +12,6 @@ path = l1-contracts/lib/openzeppelin-contracts url = https://github.com/Openzeppelin/openzeppelin-contracts branch = release-v4.9 +[submodule "l1-contracts/lib/eigenda"] + path = l1-contracts/lib/eigenda + url = https://github.com/Layr-Labs/eigenda diff --git a/l1-contracts/lib/eigenda b/l1-contracts/lib/eigenda new file mode 160000 index 000000000..e30979abf --- /dev/null +++ b/l1-contracts/lib/eigenda @@ -0,0 +1 @@ +Subproject commit e30979abf8668eb3aa8033d1ffd32b15eaf9776b From ebb94203bcb75b224d74b0522d7870545a68d1e4 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:40:58 -0300 Subject: [PATCH 04/14] Update remappings --- l1-contracts/foundry.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/l1-contracts/foundry.toml b/l1-contracts/foundry.toml index 82910dad0..b931fc47b 100644 --- a/l1-contracts/foundry.toml +++ b/l1-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 6973094095635397686dd404499d47d4e301c316 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:45:31 -0300 Subject: [PATCH 05/14] Add deploy eigenda verifier --- l1-contracts/deploy-scripts/DeployL1.s.sol | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index f4de831a8..2b776b1b9 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -33,6 +33,7 @@ import {FeeParams, PubdataPricingMode} from "contracts/state-transition/chain-de import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {L1ERC20Bridge} from "contracts/bridge/L1ERC20Bridge.sol"; import {DiamondProxy} from "contracts/state-transition/chain-deps/DiamondProxy.sol"; +import {EigenDAVerifier} from "contracts/eigenda/EigenDAVerifier.sol"; contract DeployL1Script is Script { using stdToml for string; @@ -50,6 +51,7 @@ contract DeployL1Script is Script { address blobVersionedHashRetriever; address validatorTimelock; address create2Factory; + address eigendaVerifier; } struct BridgehubDeployedAddresses { @@ -113,6 +115,7 @@ contract DeployL1Script is Script { bytes diamondCutData; bytes32 bootloaderHash; bytes32 defaultAAHash; + address eigenServiceManager; } struct TokensConfig { @@ -135,6 +138,7 @@ contract DeployL1Script is Script { deployDefaultUpgrade(); deployGenesisUpgrade(); deployValidatorTimelock(); + deployEigenDAVerifier(); deployGovernance(); deployChainAdmin(); @@ -209,6 +213,7 @@ contract DeployL1Script is Script { config.contracts.bootloaderHash = toml.readBytes32("$.contracts.bootloader_hash"); config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); + config.contracts.eigenServiceManager = toml.readAddress("$.contracts.eigen_service_manager"); } function instantiateCreate2Factory() internal { @@ -280,6 +285,16 @@ contract DeployL1Script is Script { addresses.validatorTimelock = contractAddress; } + function deployEigenDAVerifier() internal { + bytes memory bytecode = abi.encodePacked( + type(EigenDAVerifier).creationCode, + abi.encode(config.contracts.eigenServiceManager) + ); + address contractAddress = deployViaCreate2(bytecode); + console.log("EigenDAVerifier deployed at:", contractAddress); + addresses.eigendaVerifier = contractAddress; + } + function deployGovernance() internal { bytes memory bytecode = abi.encodePacked( type(Governance).creationCode, @@ -706,6 +721,7 @@ contract DeployL1Script is Script { ); vm.serializeAddress("deployed_addresses", "validator_timelock_addr", addresses.validatorTimelock); vm.serializeAddress("deployed_addresses", "chain_admin", addresses.chainAdmin); + vm.serializeAddress("deployed_addresses", "eigen_da_verifier", addresses.eigendaVerifier); vm.serializeString("deployed_addresses", "bridgehub", bridgehub); vm.serializeString("deployed_addresses", "state_transition", stateTransition); string memory deployedAddresses = vm.serializeString("deployed_addresses", "bridges", bridges); From 5715277469275a78b99813fb900fce14443cacb4 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:34:54 -0300 Subject: [PATCH 06/14] Fix name --- l1-contracts/deploy-scripts/DeployL1.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 2b776b1b9..5ddc15791 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -721,7 +721,7 @@ contract DeployL1Script is Script { ); vm.serializeAddress("deployed_addresses", "validator_timelock_addr", addresses.validatorTimelock); vm.serializeAddress("deployed_addresses", "chain_admin", addresses.chainAdmin); - vm.serializeAddress("deployed_addresses", "eigen_da_verifier", addresses.eigendaVerifier); + vm.serializeAddress("deployed_addresses", "eigenda_verifier_addr", addresses.eigendaVerifier); vm.serializeString("deployed_addresses", "bridgehub", bridgehub); vm.serializeString("deployed_addresses", "state_transition", stateTransition); string memory deployedAddresses = vm.serializeString("deployed_addresses", "bridges", bridges); From aec2b24ae693a3381653c7b718c829034d879393 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:36:29 -0300 Subject: [PATCH 07/14] Add ownable to verifier --- l1-contracts/contracts/eigenda/EigenDAVerifier.sol | 13 ++++++++++--- l1-contracts/deploy-scripts/DeployL1.s.sol | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol index 7a628c220..0b960a270 100644 --- a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol +++ b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol @@ -3,23 +3,30 @@ pragma solidity ^0.8.9; import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; -contract EigenDAVerifier { +contract EigenDAVerifier is Ownable { struct BlobInfo { IEigenDAServiceManager.BlobHeader blobHeader; EigenDARollupUtils.BlobVerificationProof blobVerificationProof; } - IEigenDAServiceManager public immutable EIGEN_DA_SERVICE_MANAGER; + IEigenDAServiceManager public EIGEN_DA_SERVICE_MANAGER; - constructor(address _eigenDAServiceManager) { + constructor(address _initialOwner, address _eigenDAServiceManager) { + _transferOwnership(_initialOwner); + EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager); + } + + function setServiceManager(address _eigenDAServiceManager) external onlyOwner { EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager); } function verifyBlob( BlobInfo calldata blobInfo ) external view { + require(address(EIGEN_DA_SERVICE_MANAGER) != address(0), "EigenDAVerifier: EIGEN_DA_SERVICE_MANAGER not set"); EigenDARollupUtils.verifyBlob(blobInfo.blobHeader, EIGEN_DA_SERVICE_MANAGER, blobInfo.blobVerificationProof); } } diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 5ddc15791..2b7ad4a95 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -288,7 +288,7 @@ contract DeployL1Script is Script { function deployEigenDAVerifier() internal { bytes memory bytecode = abi.encodePacked( type(EigenDAVerifier).creationCode, - abi.encode(config.contracts.eigenServiceManager) + abi.encode(config.deployerAddress,config.contracts.eigenServiceManager) ); address contractAddress = deployViaCreate2(bytecode); console.log("EigenDAVerifier deployed at:", contractAddress); From d07c7a6a83c9bc9e90fe1627c3674eca132f7921 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 7 Oct 2024 11:34:05 -0300 Subject: [PATCH 08/14] Return bool on verify blob --- l1-contracts/contracts/eigenda/EigenDAVerifier.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol index 0b960a270..8ef7384d1 100644 --- a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol +++ b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol @@ -25,8 +25,9 @@ contract EigenDAVerifier is Ownable { function verifyBlob( BlobInfo calldata blobInfo - ) external view { + ) external view returns (bool) { require(address(EIGEN_DA_SERVICE_MANAGER) != address(0), "EigenDAVerifier: EIGEN_DA_SERVICE_MANAGER not set"); EigenDARollupUtils.verifyBlob(blobInfo.blobHeader, EIGEN_DA_SERVICE_MANAGER, blobInfo.blobVerificationProof); + return true; } } From 9f98e7bb8973c59f280c4bf177fdafff8cbfb477 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 7 Oct 2024 11:36:09 -0300 Subject: [PATCH 09/14] Format code --- l1-contracts/contracts/eigenda/EigenDAVerifier.sol | 5 +---- l1-contracts/deploy-scripts/DeployL1.s.sol | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol index 8ef7384d1..591b5bac8 100644 --- a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol +++ b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol @@ -6,7 +6,6 @@ import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDA import "@openzeppelin/contracts/access/Ownable.sol"; contract EigenDAVerifier is Ownable { - struct BlobInfo { IEigenDAServiceManager.BlobHeader blobHeader; EigenDARollupUtils.BlobVerificationProof blobVerificationProof; @@ -23,9 +22,7 @@ contract EigenDAVerifier is Ownable { EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager); } - function verifyBlob( - BlobInfo calldata blobInfo - ) external view returns (bool) { + function verifyBlob(BlobInfo calldata blobInfo) external view returns (bool) { require(address(EIGEN_DA_SERVICE_MANAGER) != address(0), "EigenDAVerifier: EIGEN_DA_SERVICE_MANAGER not set"); EigenDARollupUtils.verifyBlob(blobInfo.blobHeader, EIGEN_DA_SERVICE_MANAGER, blobInfo.blobVerificationProof); return true; diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 2b7ad4a95..bd56126ff 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -288,7 +288,7 @@ contract DeployL1Script is Script { function deployEigenDAVerifier() internal { bytes memory bytecode = abi.encodePacked( type(EigenDAVerifier).creationCode, - abi.encode(config.deployerAddress,config.contracts.eigenServiceManager) + abi.encode(config.deployerAddress, config.contracts.eigenServiceManager) ); address contractAddress = deployViaCreate2(bytecode); console.log("EigenDAVerifier deployed at:", contractAddress); From 3adf2e24b9301dd954fc30ca441cdfc875c8d674 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 10 Oct 2024 16:19:00 -0300 Subject: [PATCH 10/14] Initial blob decode --- .../contracts/eigenda/EigenDAVerifier.sol | 98 ++++++++++++++++++- .../chain-deps/facets/Executor.sol | 2 + 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol index 591b5bac8..fe84cf5b9 100644 --- a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol +++ b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.9; import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import {BN254} from "eigenlayer-middleware/libraries/BN254.sol"; contract EigenDAVerifier is Ownable { struct BlobInfo { @@ -22,9 +23,102 @@ contract EigenDAVerifier is Ownable { EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager); } - function verifyBlob(BlobInfo calldata blobInfo) external view returns (bool) { + function decodeBlobHeader(bytes calldata blobHeader) internal pure returns (IEigenDAServiceManager.BlobHeader memory) { + uint32 offset = 0; + // Decode x + uint32 xLen = uint32(bytes4(blobHeader[0:4])); + uint256 x = uint256(bytes32(blobHeader[4:4 + xLen])); + offset += 4 + xLen; + // Decode y + uint32 yLen = uint32(bytes4(blobHeader[offset:4 + offset])); + uint256 y = uint256(bytes32(blobHeader[4 + offset:4 + offset + yLen])); + offset += 4 + yLen; + + BN254.G1Point memory commitment = BN254.G1Point(x, y); + // Decode dataLength + uint32 dataLength = uint32(bytes4(blobHeader[offset:offset + 4])); + offset += 4; + + // Decode quorumBlobParams + uint32 quorumBlobParamsLen = uint32(bytes4(blobHeader[offset:offset + 4])); + IEigenDAServiceManager.QuorumBlobParam[] memory quorumBlobParams = new IEigenDAServiceManager.QuorumBlobParam[](quorumBlobParamsLen); + offset += 4; + for (uint256 i = 0; i < quorumBlobParamsLen; i++) { + quorumBlobParams[i].quorumNumber = uint8(uint32(bytes4(blobHeader[offset:offset + 4]))); + quorumBlobParams[i].adversaryThresholdPercentage = uint8(uint32(bytes4(blobHeader[offset + 4: offset + 8]))); + quorumBlobParams[i].confirmationThresholdPercentage = uint8(uint32(bytes4(blobHeader[offset + 8: offset + 12]))); + quorumBlobParams[i].chunkLength = uint32(bytes4(blobHeader[offset + 12: offset + 16])); + offset += 16; + } + return IEigenDAServiceManager.BlobHeader(commitment, dataLength, quorumBlobParams); + } + + function decodeBatchHeader(bytes calldata batchHeader) internal pure returns (IEigenDAServiceManager.BatchHeader memory) { + uint32 offset = 0; + // Decode blobHeadersRoot + bytes32 blobHeadersRoot = bytes32(batchHeader[offset:offset + 32]); + offset += 32; + // Decode quorumNumbers + uint32 quorumNumbersLen = uint32(bytes4(batchHeader[offset:offset + 4])); + bytes memory quorumNumbers = batchHeader[offset + 4:offset + 4 + quorumNumbersLen]; + offset += 4 + quorumNumbersLen; + // Decode signedStakeForQuorums + uint32 signedStakeForQuorumsLen = uint32(bytes4(batchHeader[offset:offset + 4])); + bytes memory signedStakeForQuorums = batchHeader[offset + 4:offset + 4 + signedStakeForQuorumsLen]; + offset += 4 + signedStakeForQuorumsLen; + // Decode referenceBlockNumber + uint32 referenceBlockNumber = uint32(bytes4(batchHeader[offset:offset + 4])); + return IEigenDAServiceManager.BatchHeader(blobHeadersRoot, quorumNumbers, signedStakeForQuorums, referenceBlockNumber); + } + + function decodeBatchMetadata(bytes calldata batchMetadata) internal pure returns (IEigenDAServiceManager.BatchMetadata memory) { + uint32 offset = 0; + // Decode batchHeader + uint32 batchHeaderLen = uint32(bytes4(batchMetadata[offset:offset + 4])); + IEigenDAServiceManager.BatchHeader memory batchHeader = decodeBatchHeader(batchMetadata[offset + 4:offset + 4 + batchHeaderLen]); + offset += 4 + batchHeaderLen; + // Decode signatoryRecordHash + bytes32 signatoryRecordHash = bytes32(batchMetadata[offset:offset + 32]); + offset += 32; + // Decode confirmationBlockNumber + uint32 confirmationBlockNumber = uint32(bytes4(batchMetadata[offset:offset + 4])); + return IEigenDAServiceManager.BatchMetadata(batchHeader, signatoryRecordHash, confirmationBlockNumber); + } + + function decodeBlobVerificationProof(bytes calldata blobVerificationProof) internal pure returns (EigenDARollupUtils.BlobVerificationProof memory) { + // Decode batchId + uint32 batchId = uint32(bytes4(blobVerificationProof[:4])); + // Decode blobIndex + uint32 blobIndex = uint32(bytes4(blobVerificationProof[4:8])); + // Decode batchMetadata + uint32 batchMetadataLen = uint32(bytes4(blobVerificationProof[8:12])); + IEigenDAServiceManager.BatchMetadata memory batchMetadata = decodeBatchMetadata(blobVerificationProof[12:batchMetadataLen]); + uint32 offset = 12 + batchMetadataLen; + // Decode inclusionProof + uint32 inclusionProofLen = uint32(bytes4(blobVerificationProof[offset:offset + 4])); + bytes memory inclusionProof = blobVerificationProof[offset + 4:offset + 4 + inclusionProofLen]; + offset += 4 + inclusionProofLen; + // Decode quorumIndexes + uint32 quorumIndexesLen = uint32(bytes4(blobVerificationProof[offset:offset + 4])); + bytes memory quorumIndexes = blobVerificationProof[offset + 4:offset + 4 + quorumIndexesLen]; + + return EigenDARollupUtils.BlobVerificationProof(batchId,blobIndex,batchMetadata,inclusionProof,quorumIndexes); + } + + function decodeBlobInfo(bytes calldata blobInfo) internal pure returns (BlobInfo memory) { + uint32 blobHeaderLen = uint32(bytes4(blobInfo[:4])); + IEigenDAServiceManager.BlobHeader memory blobHeader = decodeBlobHeader(blobInfo[4:blobHeaderLen]); + EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof = decodeBlobVerificationProof(blobInfo[blobHeaderLen:]); + return BlobInfo(blobHeader,blobVerificationProof); + } + + function verifyBlob(bytes calldata blobInfo) external view { + BlobInfo memory blob = decodeBlobInfo(blobInfo); + this._verifyBlob(blob); + } + + function _verifyBlob(BlobInfo calldata blobInfo) external view { require(address(EIGEN_DA_SERVICE_MANAGER) != address(0), "EigenDAVerifier: EIGEN_DA_SERVICE_MANAGER not set"); EigenDARollupUtils.verifyBlob(blobInfo.blobHeader, EIGEN_DA_SERVICE_MANAGER, blobInfo.blobVerificationProof); - return true; } } diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 3c3aa6ee8..76f1e5a58 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -15,6 +15,8 @@ import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; // While formally the following import is not used, it is needed to inherit documentation from it import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol"; +//import {EigenDAVerifier} from "../../../eigenda/EigenDAVerifier.sol"; + /// @title zkSync hyperchain Executor contract capable of processing events emitted in the zkSync hyperchain protocol. /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev From 739a6e8aebf424fa029b572bca41544d5a2ff38b Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:04:42 -0300 Subject: [PATCH 11/14] Add verify blob to executor --- .../contracts/state-transition/chain-deps/facets/Executor.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 76f1e5a58..566fd6732 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -15,7 +15,7 @@ import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; // While formally the following import is not used, it is needed to inherit documentation from it import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol"; -//import {EigenDAVerifier} from "../../../eigenda/EigenDAVerifier.sol"; +import {EigenDAVerifier} from "../../../eigenda/EigenDAVerifier.sol"; /// @title zkSync hyperchain Executor contract capable of processing events emitted in the zkSync hyperchain protocol. /// @author Matter Labs @@ -55,6 +55,7 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { // In this scenario, pubdataCommitments has the data of the commitment and the pubdataSource, so the len should be higher or equal than 1 require(_newBatch.pubdataCommitments.length >= 1, "EF: v0l"); + EigenDAVerifier.verifyBlob(_newBatch.pubdataCommitments[1:]); for (uint8 i = uint8(SystemLogKey.BLOB_ONE_HASH_KEY); i <= uint8(SystemLogKey.BLOB_SIX_HASH_KEY); i++) { logOutput.blobHashes[i - uint8(SystemLogKey.BLOB_ONE_HASH_KEY)] = bytes32(0); } From 3e1b3c26cad6e667a2058f347e6d91b1c704f866 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:06:53 -0300 Subject: [PATCH 12/14] Format code --- .../contracts/eigenda/EigenDAVerifier.sol | 57 +++++++++++++------ .../chain-deps/facets/Executor.sol | 1 - 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol index fe84cf5b9..d21d4e9b2 100644 --- a/l1-contracts/contracts/eigenda/EigenDAVerifier.sol +++ b/l1-contracts/contracts/eigenda/EigenDAVerifier.sol @@ -23,7 +23,9 @@ contract EigenDAVerifier is Ownable { EIGEN_DA_SERVICE_MANAGER = IEigenDAServiceManager(_eigenDAServiceManager); } - function decodeBlobHeader(bytes calldata blobHeader) internal pure returns (IEigenDAServiceManager.BlobHeader memory) { + function decodeBlobHeader( + bytes calldata blobHeader + ) internal pure returns (IEigenDAServiceManager.BlobHeader memory) { uint32 offset = 0; // Decode x uint32 xLen = uint32(bytes4(blobHeader[0:4])); @@ -41,19 +43,25 @@ contract EigenDAVerifier is Ownable { // Decode quorumBlobParams uint32 quorumBlobParamsLen = uint32(bytes4(blobHeader[offset:offset + 4])); - IEigenDAServiceManager.QuorumBlobParam[] memory quorumBlobParams = new IEigenDAServiceManager.QuorumBlobParam[](quorumBlobParamsLen); + IEigenDAServiceManager.QuorumBlobParam[] memory quorumBlobParams = new IEigenDAServiceManager.QuorumBlobParam[]( + quorumBlobParamsLen + ); offset += 4; - for (uint256 i = 0; i < quorumBlobParamsLen; i++) { + for (uint256 i = 0; i < quorumBlobParamsLen; i++) { quorumBlobParams[i].quorumNumber = uint8(uint32(bytes4(blobHeader[offset:offset + 4]))); - quorumBlobParams[i].adversaryThresholdPercentage = uint8(uint32(bytes4(blobHeader[offset + 4: offset + 8]))); - quorumBlobParams[i].confirmationThresholdPercentage = uint8(uint32(bytes4(blobHeader[offset + 8: offset + 12]))); - quorumBlobParams[i].chunkLength = uint32(bytes4(blobHeader[offset + 12: offset + 16])); + quorumBlobParams[i].adversaryThresholdPercentage = uint8(uint32(bytes4(blobHeader[offset + 4:offset + 8]))); + quorumBlobParams[i].confirmationThresholdPercentage = uint8( + uint32(bytes4(blobHeader[offset + 8:offset + 12])) + ); + quorumBlobParams[i].chunkLength = uint32(bytes4(blobHeader[offset + 12:offset + 16])); offset += 16; } return IEigenDAServiceManager.BlobHeader(commitment, dataLength, quorumBlobParams); } - function decodeBatchHeader(bytes calldata batchHeader) internal pure returns (IEigenDAServiceManager.BatchHeader memory) { + function decodeBatchHeader( + bytes calldata batchHeader + ) internal pure returns (IEigenDAServiceManager.BatchHeader memory) { uint32 offset = 0; // Decode blobHeadersRoot bytes32 blobHeadersRoot = bytes32(batchHeader[offset:offset + 32]); @@ -68,14 +76,24 @@ contract EigenDAVerifier is Ownable { offset += 4 + signedStakeForQuorumsLen; // Decode referenceBlockNumber uint32 referenceBlockNumber = uint32(bytes4(batchHeader[offset:offset + 4])); - return IEigenDAServiceManager.BatchHeader(blobHeadersRoot, quorumNumbers, signedStakeForQuorums, referenceBlockNumber); + return + IEigenDAServiceManager.BatchHeader( + blobHeadersRoot, + quorumNumbers, + signedStakeForQuorums, + referenceBlockNumber + ); } - function decodeBatchMetadata(bytes calldata batchMetadata) internal pure returns (IEigenDAServiceManager.BatchMetadata memory) { + function decodeBatchMetadata( + bytes calldata batchMetadata + ) internal pure returns (IEigenDAServiceManager.BatchMetadata memory) { uint32 offset = 0; // Decode batchHeader uint32 batchHeaderLen = uint32(bytes4(batchMetadata[offset:offset + 4])); - IEigenDAServiceManager.BatchHeader memory batchHeader = decodeBatchHeader(batchMetadata[offset + 4:offset + 4 + batchHeaderLen]); + IEigenDAServiceManager.BatchHeader memory batchHeader = decodeBatchHeader( + batchMetadata[offset + 4:offset + 4 + batchHeaderLen] + ); offset += 4 + batchHeaderLen; // Decode signatoryRecordHash bytes32 signatoryRecordHash = bytes32(batchMetadata[offset:offset + 32]); @@ -85,14 +103,18 @@ contract EigenDAVerifier is Ownable { return IEigenDAServiceManager.BatchMetadata(batchHeader, signatoryRecordHash, confirmationBlockNumber); } - function decodeBlobVerificationProof(bytes calldata blobVerificationProof) internal pure returns (EigenDARollupUtils.BlobVerificationProof memory) { + function decodeBlobVerificationProof( + bytes calldata blobVerificationProof + ) internal pure returns (EigenDARollupUtils.BlobVerificationProof memory) { // Decode batchId uint32 batchId = uint32(bytes4(blobVerificationProof[:4])); // Decode blobIndex uint32 blobIndex = uint32(bytes4(blobVerificationProof[4:8])); // Decode batchMetadata uint32 batchMetadataLen = uint32(bytes4(blobVerificationProof[8:12])); - IEigenDAServiceManager.BatchMetadata memory batchMetadata = decodeBatchMetadata(blobVerificationProof[12:batchMetadataLen]); + IEigenDAServiceManager.BatchMetadata memory batchMetadata = decodeBatchMetadata( + blobVerificationProof[12:batchMetadataLen] + ); uint32 offset = 12 + batchMetadataLen; // Decode inclusionProof uint32 inclusionProofLen = uint32(bytes4(blobVerificationProof[offset:offset + 4])); @@ -101,15 +123,18 @@ contract EigenDAVerifier is Ownable { // Decode quorumIndexes uint32 quorumIndexesLen = uint32(bytes4(blobVerificationProof[offset:offset + 4])); bytes memory quorumIndexes = blobVerificationProof[offset + 4:offset + 4 + quorumIndexesLen]; - - return EigenDARollupUtils.BlobVerificationProof(batchId,blobIndex,batchMetadata,inclusionProof,quorumIndexes); + + return + EigenDARollupUtils.BlobVerificationProof(batchId, blobIndex, batchMetadata, inclusionProof, quorumIndexes); } function decodeBlobInfo(bytes calldata blobInfo) internal pure returns (BlobInfo memory) { uint32 blobHeaderLen = uint32(bytes4(blobInfo[:4])); IEigenDAServiceManager.BlobHeader memory blobHeader = decodeBlobHeader(blobInfo[4:blobHeaderLen]); - EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof = decodeBlobVerificationProof(blobInfo[blobHeaderLen:]); - return BlobInfo(blobHeader,blobVerificationProof); + EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof = decodeBlobVerificationProof( + blobInfo[blobHeaderLen:] + ); + return BlobInfo(blobHeader, blobVerificationProof); } function verifyBlob(bytes calldata blobInfo) external view { diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 566fd6732..521a30ef0 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -52,7 +52,6 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { bytes32[] memory blobCommitments = new bytes32[](MAX_NUMBER_OF_BLOBS); if (pricingMode == PubdataPricingMode.Validium) { - // In this scenario, pubdataCommitments has the data of the commitment and the pubdataSource, so the len should be higher or equal than 1 require(_newBatch.pubdataCommitments.length >= 1, "EF: v0l"); EigenDAVerifier.verifyBlob(_newBatch.pubdataCommitments[1:]); From 65bac4e24ec0e07f78eedcd11f954a59a561c397 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:22:24 -0300 Subject: [PATCH 13/14] Add eigenda verifier address --- .../contracts/dev-contracts/test/ExecutorProvingTest.sol | 3 +++ .../contracts/dev-contracts/test/TestExecutor.sol | 2 ++ .../state-transition/chain-deps/facets/Executor.sol | 8 +++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol index 50bccb744..796d9276e 100644 --- a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol @@ -8,6 +8,9 @@ import {LogProcessingOutput} from "../../state-transition/chain-interfaces/IExec import {LogProcessingOutput} from "../../state-transition/chain-interfaces/IExecutor.sol"; contract ExecutorProvingTest is ExecutorFacet { + + constructor() ExecutorFacet(address(0)) {} + function getBatchProofPublicInput( bytes32 _prevBatchCommitment, bytes32 _currentBatchCommitment diff --git a/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol b/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol index 8da6425b3..263be1eab 100644 --- a/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol +++ b/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol @@ -5,6 +5,8 @@ import {ExecutorFacet} from "../../state-transition/chain-deps/facets/Executor.s pragma solidity 0.8.24; contract TestExecutor is ExecutorFacet { + + constructor() ExecutorFacet(address(0)) {} /// @dev Since we want to test the blob functionality we want mock the calls to the blobhash opcode. function _getBlobVersionedHash(uint256 _index) internal view virtual override returns (bytes32 versionedHash) { (bool success, bytes memory data) = s.blobVersionedHashRetriever.staticcall(abi.encode(_index)); diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 521a30ef0..b59dbeff4 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -27,6 +27,12 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { /// @inheritdoc IZkSyncHyperchainBase string public constant override getName = "ExecutorFacet"; + EigenDAVerifier immutable public eigenDAVerifier; + + constructor(address _eigenDAVerifier) { + eigenDAVerifier = EigenDAVerifier(_eigenDAVerifier); + } + /// @dev Process one batch commit using the previous batch StoredBatchInfo /// @dev returns new batch StoredBatchInfo /// @notice Does not change storage @@ -54,7 +60,7 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { if (pricingMode == PubdataPricingMode.Validium) { // In this scenario, pubdataCommitments has the data of the commitment and the pubdataSource, so the len should be higher or equal than 1 require(_newBatch.pubdataCommitments.length >= 1, "EF: v0l"); - EigenDAVerifier.verifyBlob(_newBatch.pubdataCommitments[1:]); + eigenDAVerifier.verifyBlob(_newBatch.pubdataCommitments[1:]); for (uint8 i = uint8(SystemLogKey.BLOB_ONE_HASH_KEY); i <= uint8(SystemLogKey.BLOB_SIX_HASH_KEY); i++) { logOutput.blobHashes[i - uint8(SystemLogKey.BLOB_ONE_HASH_KEY)] = bytes32(0); } From b3e1673b962453dca5ad481dbf16474bd7f78e45 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:25:33 -0300 Subject: [PATCH 14/14] Add address to executor in deploy script --- l1-contracts/deploy-scripts/DeployL1.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index bd56126ff..85549ccc8 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -362,7 +362,7 @@ contract DeployL1Script is Script { } function deployStateTransitionDiamondFacets() internal { - address executorFacet = deployViaCreate2(type(ExecutorFacet).creationCode); + address executorFacet = deployViaCreate2(abi.encodePacked(type(ExecutorFacet).creationCode,abi.encode(addresses.eigendaVerifier))); console.log("ExecutorFacet deployed at:", executorFacet); addresses.stateTransition.executorFacet = executorFacet;