From 08a41ef1619256a23ed2b55f90ef474f8f0adbc6 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:53:15 -0300 Subject: [PATCH 1/7] Add real MerkleProofInput --- .../da-layers/eigenda/DummyEigenDABridge.sol | 2 +- .../eigenda/EigenDAAttestationLib.sol | 2 +- .../da-layers/eigenda/EigenDAL1Validator.sol | 6 ++-- .../da-layers/eigenda/IEigenDABridge.sol | 36 +++---------------- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index 6cb5cc986..92e6299b7 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -17,7 +17,7 @@ contract DummyEigenDABridge is IEigenDABridge { return implementationContract; } - function verifyBlobLeaf(bytes calldata) external view returns (bool) { + function verifyBlobLeaf(MerkleProofInput calldata) external view returns (bool) { return true; } } diff --git a/da-contracts/contracts/da-layers/eigenda/EigenDAAttestationLib.sol b/da-contracts/contracts/da-layers/eigenda/EigenDAAttestationLib.sol index 4399ac1c6..5bb1fe070 100644 --- a/da-contracts/contracts/da-layers/eigenda/EigenDAAttestationLib.sol +++ b/da-contracts/contracts/da-layers/eigenda/EigenDAAttestationLib.sol @@ -24,7 +24,7 @@ abstract contract EigenDAAttestationLib { implementation = bridge.implementation(); } - function _attest(bytes memory input) internal virtual { + function _attest(IEigenDABridge.MerkleProofInput memory input) internal virtual { if (!bridge.verifyBlobLeaf(input)) revert InvalidAttestationProof(); /*attestations[input.leaf] = AttestationData( implementation.rangeStartBlocks(input.rangeHash) + uint32(input.dataRootIndex) + 1, diff --git a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol index cb9b40295..7cee06dec 100644 --- a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol +++ b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol @@ -29,10 +29,10 @@ contract EigenDAL1Validator is IL1DAValidator, EigenDAAttestationLib { output.stateDiffHash = stateDiffHash; - /*IEigenDABridge.MerkleProofInput memory input = abi.decode(operatorDAInput[32:], (IEigenDABridge.MerkleProofInput)); - if (l2DAValidatorOutputHash != keccak256(abi.encodePacked(output.stateDiffHash, input.leaf))) + IEigenDABridge.MerkleProofInput memory input = abi.decode(operatorDAInput[32:], (IEigenDABridge.MerkleProofInput)); + /*if (l2DAValidatorOutputHash != keccak256(abi.encodePacked(output.stateDiffHash, input.leaf))) revert InvalidValidatorOutputHash();*/ //TODO: Maybe we don't need this - _attest(operatorDAInput[32:]); + _attest(input); output.blobsLinearHashes = new bytes32[](maxBlobsSupported); output.blobsOpeningCommitments = new bytes32[](maxBlobsSupported); diff --git a/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol index bfcd3d300..11947e045 100644 --- a/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/IEigenDABridge.sol @@ -5,42 +5,14 @@ import {IImplementation} from "./IImplementation.sol"; interface IEigenDABridge { // solhint-disable-next-line gas-struct-packing - struct Message { - // single-byte prefix representing the message type - bytes1 messageType; - // address of message sender - bytes32 from; - // address of message receiver - bytes32 to; - // origin chain code - uint32 originDomain; - // destination chain code - uint32 destinationDomain; - // data being sent - bytes data; - // nonce - uint64 messageId; - } struct MerkleProofInput { - // proof of inclusion for the data root - bytes32[] dataRootProof; - // proof of inclusion of leaf within blob/bridge root - bytes32[] leafProof; - // abi.encodePacked(startBlock, endBlock) of header range commitment on implementation - bytes32 rangeHash; - // index of the data root in the commitment tree - uint256 dataRootIndex; - // blob root to check proof against, or reconstruct the data root - bytes32 blobRoot; - // bridge root to check proof against, or reconstruct the data root - bytes32 bridgeRoot; - // leaf being proven + bytes32 batchRoot; bytes32 leaf; - // index of the leaf in the blob/bridge root tree - uint256 leafIndex; + uint256 index; + bytes inclusionProof; } function implementation() external view returns (IImplementation implementation); - function verifyBlobLeaf(bytes calldata input) external view returns (bool); + function verifyBlobLeaf(MerkleProofInput calldata input) external view returns (bool); } From 14b6fc6aabc78e77358a86c17426ee34059c6fab Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:59:43 -0300 Subject: [PATCH 2/7] Update DummyEigenDABridge.sol --- .../da-layers/eigenda/DummyEigenDABridge.sol | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index 92e6299b7..6ae3d3c95 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -17,7 +17,29 @@ contract DummyEigenDABridge is IEigenDABridge { return implementationContract; } - function verifyBlobLeaf(MerkleProofInput calldata) external view returns (bool) { - return true; + function verifyBlobLeaf(MerkleProofInput calldata merkleProof) external view returns (bool) { + uint256 index = merkleProof.index; + require(merkleProof.inclusionProof.length % 32 == 0, "DummyEigenDABridge VerifyBlobLeaf: proof length should be a multiple of 32"); + bytes32 computedHash = merkleProof.leaf; + for (uint256 i = 32; i <= merkleProof.inclusionProof.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(merkleProof.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(merkleProof.inclusionProof, i))) + mstore(0x20, computedHash) + computedHash := keccak256(0x00, 0x40) + index := div(index, 2) + } + } + } + require(computedHash == merkleProof.batchRoot, "DummyEigenDABridge VerifyBlobLeaf: invalid proof"); } } From 97842d6f974ad946502e954df3c8bae8c94baf5a Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:53:05 -0300 Subject: [PATCH 3/7] Fix merkle proof --- .../contracts/da-layers/eigenda/DummyEigenDABridge.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index 6ae3d3c95..b8d0a40de 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -19,21 +19,22 @@ contract DummyEigenDABridge is IEigenDABridge { function verifyBlobLeaf(MerkleProofInput calldata merkleProof) external view returns (bool) { uint256 index = merkleProof.index; - require(merkleProof.inclusionProof.length % 32 == 0, "DummyEigenDABridge VerifyBlobLeaf: proof length should be a multiple of 32"); + bytes memory inclusionProof = merkleProof.inclusionProof; + require(inclusionProof.length % 32 == 0, "DummyEigenDABridge VerifyBlobLeaf: proof length should be a multiple of 32"); bytes32 computedHash = merkleProof.leaf; - for (uint256 i = 32; i <= merkleProof.inclusionProof.length; i += 32) { + for (uint256 i = 32; i <= inclusionProof.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(merkleProof.inclusionProof, i))) + 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(merkleProof.inclusionProof, i))) + mstore(0x00, mload(add(inclusionProof, i))) mstore(0x20, computedHash) computedHash := keccak256(0x00, 0x40) index := div(index, 2) @@ -41,5 +42,6 @@ contract DummyEigenDABridge is IEigenDABridge { } } require(computedHash == merkleProof.batchRoot, "DummyEigenDABridge VerifyBlobLeaf: invalid proof"); + return true; } } From 44811c48ed2eabd7c34d21dd12cbda1ab1ca629f Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:40:32 -0300 Subject: [PATCH 4/7] Fix comments --- .../contracts/da-layers/eigenda/DummyEigenDABridge.sol | 7 ++++--- .../contracts/da-layers/eigenda/EigenDAL1Validator.sol | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index b8d0a40de..bbb12255e 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -20,9 +20,10 @@ contract DummyEigenDABridge is IEigenDABridge { function verifyBlobLeaf(MerkleProofInput calldata merkleProof) external view returns (bool) { uint256 index = merkleProof.index; bytes memory inclusionProof = merkleProof.inclusionProof; - require(inclusionProof.length % 32 == 0, "DummyEigenDABridge VerifyBlobLeaf: proof length should be a multiple of 32"); + require(inclusionProof.length % 32 == 0, "proof length not multiple of 32"); bytes32 computedHash = merkleProof.leaf; - for (uint256 i = 32; i <= inclusionProof.length; i += 32) { + 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 { @@ -41,7 +42,7 @@ contract DummyEigenDABridge is IEigenDABridge { } } } - require(computedHash == merkleProof.batchRoot, "DummyEigenDABridge VerifyBlobLeaf: invalid proof"); + require(computedHash == merkleProof.batchRoot, "invalid proof"); return true; } } diff --git a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol index 7cee06dec..a2d5bbbbe 100644 --- a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol +++ b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol @@ -15,7 +15,7 @@ contract EigenDAL1Validator is IL1DAValidator, EigenDAAttestationLib { function checkDA( uint256, // _chainId uint256, // _batchNumber - bytes32 l2DAValidatorOutputHash, // TODO: Maybe we don't need this + bytes32 // _l2DAValidatorOutputHash, // TODO: Maybe we don't need this bytes calldata operatorDAInput, uint256 maxBlobsSupported ) external override returns (L1DAValidatorOutput memory output) { From 72f1980c6b7e7592a38cd7d4cd8658ae1670d9dd Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:42:22 -0300 Subject: [PATCH 5/7] Fix compilation --- da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol index a2d5bbbbe..45b19ce93 100644 --- a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol +++ b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol @@ -15,7 +15,7 @@ contract EigenDAL1Validator is IL1DAValidator, EigenDAAttestationLib { function checkDA( uint256, // _chainId uint256, // _batchNumber - bytes32 // _l2DAValidatorOutputHash, // TODO: Maybe we don't need this + bytes32, // _l2DAValidatorOutputHash, // TODO: Maybe we don't need this bytes calldata operatorDAInput, uint256 maxBlobsSupported ) external override returns (L1DAValidatorOutput memory output) { From 9dde738cc6c9abda0559b9bdddddc4b13b09dead Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:46:06 -0300 Subject: [PATCH 6/7] Add inspired comment --- da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol index bbb12255e..dd893253b 100644 --- a/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol +++ b/da-contracts/contracts/da-layers/eigenda/DummyEigenDABridge.sol @@ -18,6 +18,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; require(inclusionProof.length % 32 == 0, "proof length not multiple of 32"); From 9cc2eb1d289b327836cbbb1265a62aad1eb0a5df Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:49:45 -0300 Subject: [PATCH 7/7] Format code --- .../contracts/da-layers/eigenda/EigenDAL1Validator.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol index 45b19ce93..75f8c5d87 100644 --- a/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol +++ b/da-contracts/contracts/da-layers/eigenda/EigenDAL1Validator.sol @@ -29,7 +29,10 @@ contract EigenDAL1Validator is IL1DAValidator, EigenDAAttestationLib { output.stateDiffHash = stateDiffHash; - IEigenDABridge.MerkleProofInput memory input = abi.decode(operatorDAInput[32:], (IEigenDABridge.MerkleProofInput)); + IEigenDABridge.MerkleProofInput memory input = abi.decode( + operatorDAInput[32:], + (IEigenDABridge.MerkleProofInput) + ); /*if (l2DAValidatorOutputHash != keccak256(abi.encodePacked(output.stateDiffHash, input.leaf))) revert InvalidValidatorOutputHash();*/ //TODO: Maybe we don't need this _attest(input);