From b34c12c8b873e98528e79889f214af2137959bb3 Mon Sep 17 00:00:00 2001 From: julink-eth Date: Thu, 2 May 2024 10:57:18 +0200 Subject: [PATCH] feat: apply minor changes to SparseMerkleProof lib --- .../linea-verifier/lib/SparseMerkleProof.sol | 37 +++++++++---------- .../contracts/lib/SparseMerkleProof.sol | 37 +++++++++---------- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/packages/l1-contracts/contracts/linea-verifier/lib/SparseMerkleProof.sol b/packages/l1-contracts/contracts/linea-verifier/lib/SparseMerkleProof.sol index 9f8c3872d..9508acb76 100644 --- a/packages/l1-contracts/contracts/linea-verifier/lib/SparseMerkleProof.sol +++ b/packages/l1-contracts/contracts/linea-verifier/lib/SparseMerkleProof.sol @@ -25,6 +25,7 @@ library SparseMerkleProof { error WrongBytesLength(uint256 expectedLength, uint256 bytesLength); uint256 internal constant TREE_DEPTH = 40; + bytes32 internal constant ZERO_HASH = 0x0; /** * @notice Format input and verify sparse merkle proof @@ -162,23 +163,24 @@ library SparseMerkleProof { bytes[] calldata _rawProof ) private pure returns (bytes32, bytes32, bytes32[] memory) { uint256 rawProofLength = _rawProof.length; + uint256 formattedProofLength = rawProofLength - 2; - bytes32[] memory proof = new bytes32[](rawProofLength - 2); + bytes32[] memory proof = new bytes32[](formattedProofLength); bytes32 nextFreeNode = bytes32(_rawProof[0][:32]); bytes32 leafHash = Mimc.hash(_rawProof[rawProofLength - 1]); - for (uint256 i = 1; i < rawProofLength - 2; ) { - proof[rawProofLength - 2 - i] = Mimc.hash(_rawProof[i]); + for (uint256 i = 1; i < formattedProofLength; ) { + proof[formattedProofLength - i] = Mimc.hash(_rawProof[i]); unchecked { ++i; } } - // If the neighboring leaf is equal to zero bytes we don't hash it - if (_isZeroBytes(_rawProof[rawProofLength - 2])) { - proof[0] = bytes32(0); + // If the sibling leaf (_rawProof[formattedProofLength]) is equal to zero bytes we don't hash it + if (_isZeroBytes(_rawProof[formattedProofLength])) { + proof[0] = ZERO_HASH; } else { - proof[0] = Mimc.hash(_rawProof[rawProofLength - 2]); + proof[0] = Mimc.hash(_rawProof[formattedProofLength]); } return (nextFreeNode, leafHash, proof); @@ -187,29 +189,28 @@ library SparseMerkleProof { /** * @notice Check if bytes contain only zero byte elements * @param _data Bytes to be checked - * @return {bool} true if bytes contain only zero byte elements, false otherwise + * @return isZeroBytes true if bytes contain only zero byte elements, false otherwise */ - function _isZeroBytes(bytes calldata _data) private pure returns (bool) { - bool allZero = true; + function _isZeroBytes( + bytes calldata _data + ) private pure returns (bool isZeroBytes) { + isZeroBytes = true; assembly { - let dataLength := _data.length let dataStart := _data.offset - let dataEnd := add(dataStart, dataLength) for { let currentPtr := dataStart - } lt(currentPtr, dataEnd) { + } lt(currentPtr, add(dataStart, _data.length)) { currentPtr := add(currentPtr, 0x20) } { let dataWord := calldataload(currentPtr) if eq(iszero(dataWord), 0) { - allZero := 0 + isZeroBytes := 0 break } } } - return allZero; } /** @@ -230,7 +231,7 @@ library SparseMerkleProof { bytes32 computedHash = _leafHash; uint256 currentIndex = _leafIndex; - for (uint256 height; height < TREE_DEPTH; ) { + for (uint256 height; height < TREE_DEPTH; ++height) { if ((currentIndex >> height) & 1 == 1) computedHash = Mimc.hash( abi.encodePacked(_proof[height], computedHash) @@ -239,10 +240,6 @@ library SparseMerkleProof { computedHash = Mimc.hash( abi.encodePacked(computedHash, _proof[height]) ); - - unchecked { - ++height; - } } return diff --git a/packages/linea-verifier/contracts/lib/SparseMerkleProof.sol b/packages/linea-verifier/contracts/lib/SparseMerkleProof.sol index 9f8c3872d..9508acb76 100644 --- a/packages/linea-verifier/contracts/lib/SparseMerkleProof.sol +++ b/packages/linea-verifier/contracts/lib/SparseMerkleProof.sol @@ -25,6 +25,7 @@ library SparseMerkleProof { error WrongBytesLength(uint256 expectedLength, uint256 bytesLength); uint256 internal constant TREE_DEPTH = 40; + bytes32 internal constant ZERO_HASH = 0x0; /** * @notice Format input and verify sparse merkle proof @@ -162,23 +163,24 @@ library SparseMerkleProof { bytes[] calldata _rawProof ) private pure returns (bytes32, bytes32, bytes32[] memory) { uint256 rawProofLength = _rawProof.length; + uint256 formattedProofLength = rawProofLength - 2; - bytes32[] memory proof = new bytes32[](rawProofLength - 2); + bytes32[] memory proof = new bytes32[](formattedProofLength); bytes32 nextFreeNode = bytes32(_rawProof[0][:32]); bytes32 leafHash = Mimc.hash(_rawProof[rawProofLength - 1]); - for (uint256 i = 1; i < rawProofLength - 2; ) { - proof[rawProofLength - 2 - i] = Mimc.hash(_rawProof[i]); + for (uint256 i = 1; i < formattedProofLength; ) { + proof[formattedProofLength - i] = Mimc.hash(_rawProof[i]); unchecked { ++i; } } - // If the neighboring leaf is equal to zero bytes we don't hash it - if (_isZeroBytes(_rawProof[rawProofLength - 2])) { - proof[0] = bytes32(0); + // If the sibling leaf (_rawProof[formattedProofLength]) is equal to zero bytes we don't hash it + if (_isZeroBytes(_rawProof[formattedProofLength])) { + proof[0] = ZERO_HASH; } else { - proof[0] = Mimc.hash(_rawProof[rawProofLength - 2]); + proof[0] = Mimc.hash(_rawProof[formattedProofLength]); } return (nextFreeNode, leafHash, proof); @@ -187,29 +189,28 @@ library SparseMerkleProof { /** * @notice Check if bytes contain only zero byte elements * @param _data Bytes to be checked - * @return {bool} true if bytes contain only zero byte elements, false otherwise + * @return isZeroBytes true if bytes contain only zero byte elements, false otherwise */ - function _isZeroBytes(bytes calldata _data) private pure returns (bool) { - bool allZero = true; + function _isZeroBytes( + bytes calldata _data + ) private pure returns (bool isZeroBytes) { + isZeroBytes = true; assembly { - let dataLength := _data.length let dataStart := _data.offset - let dataEnd := add(dataStart, dataLength) for { let currentPtr := dataStart - } lt(currentPtr, dataEnd) { + } lt(currentPtr, add(dataStart, _data.length)) { currentPtr := add(currentPtr, 0x20) } { let dataWord := calldataload(currentPtr) if eq(iszero(dataWord), 0) { - allZero := 0 + isZeroBytes := 0 break } } } - return allZero; } /** @@ -230,7 +231,7 @@ library SparseMerkleProof { bytes32 computedHash = _leafHash; uint256 currentIndex = _leafIndex; - for (uint256 height; height < TREE_DEPTH; ) { + for (uint256 height; height < TREE_DEPTH; ++height) { if ((currentIndex >> height) & 1 == 1) computedHash = Mimc.hash( abi.encodePacked(_proof[height], computedHash) @@ -239,10 +240,6 @@ library SparseMerkleProof { computedHash = Mimc.hash( abi.encodePacked(computedHash, _proof[height]) ); - - unchecked { - ++height; - } } return