feat: implement compression for ContractStorageAccount values - #594
S0naliThakur wants to merge 1 commit into
Conversation
Adds functionality to compress and decompress storage values in the ContractStorageAccount, improving space efficiency by storing values as compressed binary instead of hex strings. feat: enhance handling of ContractStorageAccount values Implements logic to compress and decompress ContractStorageAccount values, ensuring efficient storage management. Additionally, updates transaction state handling to account for empty storage slots, improving robustness in RLP decoding. This change optimizes data retrieval and storage efficiency across the application. refactor: simplify account data handling by removing compression logic refactor: streamline RLP decoding logic in transaction state management
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
| const compressedLength = stream.readUInt8() | ||
| let compressedValue: Uint8Array | ||
| if (compressedLength > 0) { | ||
| const buffer = stream.readBuffer() | ||
| compressedValue = new Uint8Array(buffer) | ||
| } else { | ||
| compressedValue = new Uint8Array([0]) | ||
| } | ||
| const value = decompressValue(compressedValue) |
There was a problem hiding this comment.
Suggestion: The current code does not verify that the length of the buffer read matches the expected compressedLength, which could allow malformed or truncated data to be accepted. Add a check to ensure the buffer length matches compressedLength and throw an error if it does not. [possible issue, importance: 7]
| const compressedLength = stream.readUInt8() | |
| let compressedValue: Uint8Array | |
| if (compressedLength > 0) { | |
| const buffer = stream.readBuffer() | |
| compressedValue = new Uint8Array(buffer) | |
| } else { | |
| compressedValue = new Uint8Array([0]) | |
| } | |
| const value = decompressValue(compressedValue) | |
| const compressedLength = stream.readUInt8() | |
| let compressedValue: Uint8Array | |
| if (compressedLength > 0) { | |
| const buffer = stream.readBuffer() | |
| if (buffer.length !== compressedLength) { | |
| throw new Error('Compressed value length mismatch') | |
| } | |
| compressedValue = new Uint8Array(buffer) | |
| } else { | |
| compressedValue = new Uint8Array([0]) | |
| } | |
| const value = decompressValue(compressedValue) |
| function fromMinimalHex(hex: string): Uint8Array { | ||
| if (!hex.startsWith('0x')) { | ||
| throw new Error('Hex string must start with 0x') | ||
| } | ||
|
|
||
| const cleanHex = hex.slice(2) | ||
| if (cleanHex.length === 0 || cleanHex === '0') { | ||
| return new Uint8Array([0]) | ||
| } | ||
|
|
||
| // Pad odd length hex strings | ||
| const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : '0' + cleanHex | ||
|
|
||
| const bytes = new Uint8Array(paddedHex.length / 2) | ||
| for (let i = 0; i < paddedHex.length; i += 2) { | ||
| bytes[i / 2] = parseInt(paddedHex.substring(i, i + 2), 16) | ||
| } | ||
|
|
||
| return bytes | ||
| } |
There was a problem hiding this comment.
Suggestion: The function does not check for invalid hex characters, which could result in NaN values in the output array. Add a check after parsing each byte to ensure it is a valid number, and throw an error if not. [possible issue, importance: 8]
| function fromMinimalHex(hex: string): Uint8Array { | |
| if (!hex.startsWith('0x')) { | |
| throw new Error('Hex string must start with 0x') | |
| } | |
| const cleanHex = hex.slice(2) | |
| if (cleanHex.length === 0 || cleanHex === '0') { | |
| return new Uint8Array([0]) | |
| } | |
| // Pad odd length hex strings | |
| const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : '0' + cleanHex | |
| const bytes = new Uint8Array(paddedHex.length / 2) | |
| for (let i = 0; i < paddedHex.length; i += 2) { | |
| bytes[i / 2] = parseInt(paddedHex.substring(i, i + 2), 16) | |
| } | |
| return bytes | |
| } | |
| function fromMinimalHex(hex: string): Uint8Array { | |
| if (!hex.startsWith('0x')) { | |
| throw new Error('Hex string must start with 0x') | |
| } | |
| const cleanHex = hex.slice(2) | |
| if (cleanHex.length === 0 || cleanHex === '0') { | |
| return new Uint8Array([0]) | |
| } | |
| // Pad odd length hex strings | |
| const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : '0' + cleanHex | |
| const bytes = new Uint8Array(paddedHex.length / 2) | |
| for (let i = 0; i < paddedHex.length; i += 2) { | |
| const byte = parseInt(paddedHex.substring(i, i + 2), 16) | |
| if (isNaN(byte)) { | |
| throw new Error('Invalid hex string') | |
| } | |
| bytes[i / 2] = byte | |
| } | |
| return bytes | |
| } |
User description
Adds functionality to compress and decompress storage values in the ContractStorageAccount, improving space efficiency by storing values as compressed binary instead of hex strings. feat: enhance handling of ContractStorageAccount values
Implements logic to compress and decompress ContractStorageAccount values, ensuring efficient storage management. Additionally, updates transaction state handling to account for empty storage slots, improving robustness in RLP decoding. This change optimizes data retrieval and storage efficiency across the application. refactor: simplify account data handling by removing compression logic
refactor: streamline RLP decoding logic in transaction state management
PR Type
Enhancement, Tests
Description
Implements compression for
ContractStorageAccountstorage values.Updates serialization/deserialization to use compressed binary format.
Adds robust conversion between hex strings and Uint8Array.
Expands and adapts unit tests for new compression logic.
Changes walkthrough 📝
ContractStorageAccount.ts
Add compressed binary storage and enhanced serialization forContractStorageAccountsrc/types/ContractStorageAccount.ts
prefix.
formats.
contractStorageCompression.ts
Add contract storage value compression/decompression utilitiessrc/storage/contractStorageCompression.ts
storage values.
accountStorage.ts
Simplify account query result structuresrc/storage/accountStorage.ts
ContractStorageAccount.test.ts
Update and expand tests for compressed ContractStorageAccount valuestest/unit/src/types/ContractStorageAccount.test.ts