Skip to content

✨ Rlp decoding + MPT proofs #1449

Open

Description

@0xClandestine

OZ is adding it to 5.5.0, would love a Solady alternative.

Useful for historical Ethereum proofs (block headers, accounts, account storage, txs, tx logs) which is particularly useful now given EIP-2935.

OpenZeppelin/openzeppelin-contracts#5680
https://eips.ethereum.org/EIPS/eip-2935

Activity

  1. 0xClandestine commented on Jul 4, 2025

    @0xClandestine
    ContributorAuthor
    function computeBlockHeader(
        bytes32 parentHash,
        bytes32 omnersHash,
        address beneficiary,
        bytes32 stateRoot,
        bytes32 transactionsRoot,
        bytes32 receiptsRoot,
        bytes memory logsBloom,
        uint256 difficulty,
        uint256 number,
        uint256 gasLimit,
        uint256 gasUsed,
        uint256 timestamp,
        bytes memory extraData,
        bytes32 mixHash,
        uint256 nonce,
        uint256 baseFeePerGas,
        bytes32 withdrawalsRoot,
        uint256 blobGasUsed,
        uint256 excessBlobGas,
        bytes32 parentBeaconBlockRoot,
        bytes32 requestsHash
    ) internal view returns (bytes32) {
        // forgefmt: disable-next-item
        return keccak256(LibRLP
            .p(uint256(parentHash))
            .p(uint256(omnersHash))
            .p(beneficiary)
            .p(uint256(stateRoot))
            .p(uint256(transactionsRoot))
            .p(uint256(receiptsRoot))
            .p(logsBloom)
            .p(uint256(mixHash))
            .p(nonce)
            .p(baseFeePerGas)
            .p(uint256(withdrawalsRoot))
            .p(blobGasUsed)
            .p(excessBlobGas)
            .p(uint256(parentBeaconBlockRoot))
            .p(uint256(requestsHash))
            .encode());
    }

    This throws stack-too-deep for obvious reasons...

  2. Vectorized commented on Jul 7, 2025

    @Vectorized
    Owner

    Good request.

    Thank you OZ once again for the reference!

  3. 0xClandestine commented on Jul 18, 2025

    @0xClandestine
    ContributorAuthor

    Can cheaply parse leading fields whose lengths are fixed.

    /// @notice Efficiently extracts one of the first 7 fields from an RLP-encoded Ethereum block header.
    /// @dev Optimized for extracting one of the first 7 fields (parentHash, ommersHash, etc.)
    ///      from a canonical RLP-encoded block header using precomputed offsets.
    ///      Much faster and cheaper than generic RLP decoding for these fields.
    function decodeLeadingField(bytes calldata header, uint256 field) internal pure returns (bytes memory) {
        unchecked {
            // Field 0: parentHash (32 bytes)
            // Field 1: ommersHash (32 bytes)
            // Field 2: beneficiary (20 bytes)
            // Field 3: stateRoot (32 bytes)
            // Field 4: transactionsRoot (32 bytes)
            // Field 5: receiptsRoot (32 bytes)
            // Field 6: logsBloom (259 bytes)
            uint8[7] memory offsets = [1, 34, 67, 88, 121, 154, 186];
            uint16[7] memory lengths = [32, 32, 20, 32, 32, 32, 259];
            uint256 start = 1 + (uint8(header[0]) - (LIST_LONG_START - 1)) + offsets[field];
            return header[start:start + lengths[field]];
        }
    }
  4. changed the title [-]Rlp decoding + MPT proofs[/-] [+]✨ Rlp decoding + MPT proofs[/+] on Aug 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions