From 512a220079e67b6b8b53a43d6dd7e407a5575369 Mon Sep 17 00:00:00 2001 From: JordyRo1 Date: Sun, 3 Nov 2024 19:49:13 +0100 Subject: [PATCH] feat: PragmaDecoder.sol smol refactoring --- solidity/src/PragmaDecoder.sol | 101 ++++++++++++++------------------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/solidity/src/PragmaDecoder.sol b/solidity/src/PragmaDecoder.sol index ffdf804..f424a5c 100644 --- a/solidity/src/PragmaDecoder.sol +++ b/solidity/src/PragmaDecoder.sol @@ -50,22 +50,20 @@ abstract contract PragmaDecoder { } } - function extractMetadataFromheader(bytes calldata updateData) internal pure returns (uint256 encodedOffset) { + function extractMetadataFromheader(bytes calldata updateData, uint256 offset) internal pure returns (uint256) { unchecked { - encodedOffset = 0; - { - uint8 majorVersion = UnsafeCalldataBytesLib.toUint8(updateData, encodedOffset); + uint8 majorVersion = UnsafeCalldataBytesLib.toUint8(updateData, offset); - encodedOffset += 1; + offset += 1; if (majorVersion != ConstantsLib.MAJOR_VERSION) { revert ErrorsLib.InvalidVersion(); } - uint8 minorVersion = UnsafeCalldataBytesLib.toUint8(updateData, encodedOffset); + uint8 minorVersion = UnsafeCalldataBytesLib.toUint8(updateData, offset); - encodedOffset += 1; + offset += 1; // Minor versions are forward compatible, so we only check // that the minor version is not less than the minimum allowed @@ -75,67 +73,49 @@ abstract contract PragmaDecoder { // This field ensure that we can add headers in the future // without breaking the contract (future compatibility) - uint8 trailingHeaderSize = UnsafeCalldataBytesLib.toUint8(updateData, encodedOffset); - encodedOffset += 1; - - // We use another encodedOffset for the trailing header and in the end add the - // encodedOffset by trailingHeaderSize to skip the future headers. - // - // An example would be like this: - // uint trailingHeaderOffset = encodedOffset - // uint x = UnsafeBytesLib.ToUint8(updateData, trailingHeaderOffset) - // trailingHeaderOffset += 1 - - encodedOffset += trailingHeaderSize; + uint8 trailingHeaderSize = UnsafeCalldataBytesLib.toUint8(updateData, offset); + offset += 1; + + offset += trailingHeaderSize; } - if (updateData.length < encodedOffset) { + if (updateData.length < offset) { revert ErrorsLib.InvalidUpdateData(); } } + return offset; } - function extractCheckpointRootAndNumUpdates(bytes calldata updateData, uint256 encodedOffset) + function extractCheckpointRootAndNumUpdates(bytes calldata updateData, uint256 offset) internal view - returns (uint256 offset, bytes32 checkpointRoot, uint8 numUpdates, bytes calldata encoded) + returns (uint256, bytes32 checkpointRoot, uint8 numUpdates) { unchecked { - encoded = UnsafeCalldataBytesLib.slice(updateData, encodedOffset, updateData.length - encodedOffset); - offset = 0; - - uint16 hyMsgSize = UnsafeCalldataBytesLib.toUint16(encoded, offset); + // Get the size of the hyperlane message + uint16 hyMsgSize = UnsafeCalldataBytesLib.toUint16(updateData, offset); offset += 2; - { - bytes memory encodedPayload; - { - (HyMsg memory hyMsg, uint256 index, bytes32 root) = - parseAndVerifyHyMsg(UnsafeCalldataBytesLib.slice(encoded, offset, hyMsgSize)); - checkpointRoot = root; - encodedPayload = hyMsg.payload; - offset += index; - } + // Extract and verify the hyperlane message + bytes calldata hyMsgData = UnsafeCalldataBytesLib.slice(updateData, offset, hyMsgSize); + (HyMsg memory hyMsg, uint256 index, bytes32 root) = parseAndVerifyHyMsg(hyMsgData); - uint256 payloadOffset = 0; + // Set the checkpoint root and get the payload + checkpointRoot = root; + bytes memory encodedPayload = hyMsg.payload; + offset += index; - { - // We don't check equality to enable future compatibility. - if (payloadOffset > encodedPayload.length) { - revert ErrorsLib.InvalidUpdateData(); - } - numUpdates = UnsafeBytesLib.toUint8(encodedPayload, payloadOffset); - offset += encodedOffset + 1; - payloadOffset += 1; - } - } + // Extract the number of updates from the payload + numUpdates = UnsafeBytesLib.toUint8(encodedPayload, 0); + offset += 1; } + return (offset, checkpointRoot, numUpdates); } function _isProofValid(bytes calldata encodedProof, uint256 offset, bytes32 root, bytes calldata leafData) internal virtual - returns (bool valid, uint256 endOffset) + returns (bool valid, uint256) { // TODO: The proof is ignored for now until we figure out how to get it from Hyperlane. @@ -143,7 +123,7 @@ abstract contract PragmaDecoder { return (true, offset); } - function extractDataInfoFromUpdate(bytes calldata encoded, uint256 offset, bytes32 checkpointRoot) + function extractDataInfoFromUpdate(bytes calldata updateData, uint256 offset, bytes32 checkpointRoot) internal returns (uint256 endOffset, ParsedData memory parsedData, bytes32 feedId, uint64 publishTime) { @@ -153,19 +133,22 @@ abstract contract PragmaDecoder { bytes calldata fulldataFeed; offset += 2; - uint16 proofSize = UnsafeCalldataBytesLib.toUint16(encoded, offset); + uint16 proofSize = UnsafeCalldataBytesLib.toUint16(updateData, offset); offset += 2; { - encodedProof = UnsafeCalldataBytesLib.slice(encoded, offset, proofSize); + encodedProof = UnsafeCalldataBytesLib.slice(updateData, offset, proofSize); uint256 encodedUpdateIndex = offset + proofSize; - encodedUpdate = - UnsafeCalldataBytesLib.slice(encoded, encodedUpdateIndex, encoded.length - 40 - encodedUpdateIndex); // 32 bytes for feedId, 8 bytes for publishTime + encodedUpdate = UnsafeCalldataBytesLib.slice( + updateData, encodedUpdateIndex, updateData.length - 40 - encodedUpdateIndex + ); // 32 bytes for feedId, 8 bytes for publishTime fulldataFeed = - UnsafeCalldataBytesLib.slice(encoded, encodedUpdateIndex, encoded.length - encodedUpdateIndex); + UnsafeCalldataBytesLib.slice(updateData, encodedUpdateIndex, updateData.length - encodedUpdateIndex); } + // For now, no proof check // bool valid; - // (valid, offset) = _isProofValid(encoded, offset, checkpointRoot, encodedUpdate); + // (valid, offset) = _isProofValid(updateData, offset, checkpointRoot, encodedUpdate); // if (!valid) revert ErrorsLib.InvalidHyperlaneCheckpointRoot(); + offset += proofSize; (parsedData, feedId, publishTime) = parseDataFeed(fulldataFeed); endOffset = offset + fulldataFeed.length; @@ -186,15 +169,15 @@ abstract contract PragmaDecoder { } function updateDataInfoFromUpdate(bytes calldata updateData) internal returns (uint8 numUpdates) { - // Extract header metadata - uint256 encodedOffset = extractMetadataFromheader(updateData); + uint256 offset = 0; + // Extract header metadata + offset = extractMetadataFromheader(updateData, offset); // Extract merkle root and number of updates from update data. - uint256 offset; + // uint256 offset; bytes32 checkpointRoot; - bytes calldata encoded; - (offset, checkpointRoot, numUpdates, encoded) = extractCheckpointRootAndNumUpdates(updateData, encodedOffset); + (offset, checkpointRoot, numUpdates) = extractCheckpointRootAndNumUpdates(updateData, offset); unchecked { for (uint256 i = 0; i < numUpdates; i++) { ParsedData memory parsedData;