reth-primitives-traits 0.2.0

Common types in reth.
Documentation

Commonly used types and traits in Reth.

Overview

This crate defines various traits and types that form the foundation of the reth stack. The top-level trait is [Block] which represents a block in the blockchain. A [Block] is composed of a [Header] and a [BlockBody]. A [BlockBody] contains the transactions in the block and additional data that is part of the block. In ethereum, this includes uncle headers and withdrawals. For optimism, uncle headers and withdrawals are always empty lists.

The most common types you'll use are:

  • [Block] - A basic block with header and body
  • [SealedBlock] - A block with its hash cached
  • [SealedHeader] - A header with its hash cached
  • [RecoveredBlock] - A sealed block with sender addresses recovered

Feature Flags

  • arbitrary: Adds proptest and arbitrary support for primitive types.
  • op: Implements the traits for various op-alloy types.
  • reth-codec: Enables db codec support for reth types including zstd compression for certain types.
  • rpc-compat: Adds RPC compatibility functions for the types in this crate, e.g. rpc type conversions.
  • serde: Adds serde support for all types.
  • secp256k1: Adds secp256k1 support for transaction signing/recovery. (By default the no-std friendly k256 is used)
  • rayon: Uses rayon for parallel transaction sender recovery in [BlockBody] by default.
  • serde-bincode-compat provides helpers for dealing with the bincode crate.

Sealing (Hashing)

The block hash is derived from the [Header] and is used to uniquely identify the block. This operation is referred to as sealing in the context of this crate. Sealing is an expensive operation. This crate provides various wrapper types that cache the hash of the block to avoid recomputing it: [SealedHeader] and [SealedBlock]. All sealed types can be downgraded to their unsealed counterparts.

Recovery

The raw consensus transactions that make up a block don't include the sender's address. This information is recovered from the transaction signature. This operation is referred to as recovery in the context of this crate and is an expensive operation. The [RecoveredBlock] represents a [SealedBlock] with the sender addresses recovered. A [SealedBlock] can be upgraded to a [RecoveredBlock] by recovering the sender addresses: [SealedBlock::try_recover]. A [RecoveredBlock] can be downgraded to a [SealedBlock] by removing the sender addresses: [RecoveredBlock::into_sealed_block].

Naming

The types in this crate support multiple recovery functions, e.g. [SealedBlock::try_recover] and [SealedBlock::try_recover_unchecked]. The _unchecked suffix indicates that this function recovers the signer without ensuring that the signature has a low s value, in other words this rule introduced in EIP-2 is ignored. Hence this function is necessary when dealing with pre EIP-2 transactions on the ethereum mainnet. Newer transactions must always be recovered with the regular recover functions, see also recover_signer.

Error Handling

Most operations that can fail return Result types:

  • RecoveryError - Transaction signature recovery failed
  • BlockRecoveryError - Block-level recovery failed
  • [GotExpected] / [GotExpectedBoxed] - Generic error for mismatched values

Recovery errors typically indicate invalid signatures or corrupted data. The block recovery error preserves the original block for further inspection.

Example

# use reth_primitives_traits::{SealedBlock, RecoveredBlock};
# use reth_primitives_traits::block::error::BlockRecoveryError;
# fn example<B: reth_primitives_traits::Block>(sealed_block: SealedBlock<B>) -> Result<(), BlockRecoveryError<SealedBlock<B>>>
# where B::Body: reth_primitives_traits::BlockBody<Transaction: reth_primitives_traits::SignedTransaction> {
// Attempt to recover senders from a sealed block
match sealed_block.try_recover() {
    Ok(recovered) => {
        // Successfully recovered all senders
        println!("Recovered {} senders", recovered.senders().len());
        Ok(())
    }
    Err(err) => {
        // Recovery failed - the block is returned in the error
        println!("Failed to recover senders for block");
        // You can still access the original block
        let block = err.into_inner();
        let hash = block.hash();
        Err(BlockRecoveryError::new(block))
    }
}
# }

Performance Considerations

  • Hashing: Block hashing is expensive. Use [SealedBlock] to cache hashes.
  • Recovery: Sender recovery is CPU-intensive. Use [RecoveredBlock] to cache results.
  • Parallel Recovery: Enable the rayon feature for parallel transaction recovery.