Skip to main content

Documentation Index

Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt

Use this file to discover all available pages before exploring further.

Try it Live

Run RLP examples in the interactive playground

    encodeArray vs encodeList

    encodeArray is functionally identical to encodeList - it’s provided as an alias for semantic clarity:
    import { Rlp } from 'tevm'
    
    const items = [new Uint8Array([1]), new Uint8Array([2])]
    
    // These are equivalent
    const encoded1 = Rlp.encodeArray(items)
    const encoded2 = Rlp.encodeList(items)
    // Both => Uint8Array([0xc4, 0x01, 0x02])
    
    Use encodeArray when thinking of the input as an array of values (e.g., transaction fields, block components). Use encodeList when thinking of the input as a list structure (e.g., nested lists, tree structures).

    Usage Patterns

    Transaction Encoding

    Encode transaction fields as array:
    import { Rlp } from 'tevm'
    
    interface LegacyTx {
      nonce: bigint
      gasPrice: bigint
      gasLimit: bigint
      to: Uint8Array
      value: bigint
      data: Uint8Array
      v: bigint
      r: Uint8Array
      s: Uint8Array
    }
    
    function encodeLegacyTx(tx: LegacyTx): Uint8Array {
      const fields = [
        bigintToBytes(tx.nonce),
        bigintToBytes(tx.gasPrice),
        bigintToBytes(tx.gasLimit),
        tx.to,
        bigintToBytes(tx.value),
        tx.data,
        bigintToBytes(tx.v),
        tx.r,
        tx.s
      ]
    
      return Rlp.encodeArray(fields)
    }
    
    const tx: LegacyTx = {
      nonce: 0n,
      gasPrice: 20000000000n,
      gasLimit: 21000n,
      to: new Uint8Array(20).fill(0x01),
      value: 1000000000000000000n,
      data: Bytes(),
      v: 27n,
      r: Bytes32().fill(0x02),
      s: Bytes32().fill(0x03)
    }
    
    const encoded = encodeLegacyTx(tx)
    

    Block Header Encoding

    Encode block header fields:
    import { Rlp } from 'tevm'
    
    interface BlockHeader {
      parentHash: Uint8Array
      uncleHash: Uint8Array
      coinbase: Uint8Array
      stateRoot: Uint8Array
      transactionsRoot: Uint8Array
      receiptsRoot: Uint8Array
      logsBloom: Uint8Array
      difficulty: bigint
      number: bigint
      gasLimit: bigint
      gasUsed: bigint
      timestamp: bigint
      extraData: Uint8Array
    }
    
    function encodeBlockHeader(header: BlockHeader): Uint8Array {
      const fields = [
        header.parentHash,
        header.uncleHash,
        header.coinbase,
        header.stateRoot,
        header.transactionsRoot,
        header.receiptsRoot,
        header.logsBloom,
        bigintToBytes(header.difficulty),
        bigintToBytes(header.number),
        bigintToBytes(header.gasLimit),
        bigintToBytes(header.gasUsed),
        bigintToBytes(header.timestamp),
        header.extraData
      ]
    
      return Rlp.encodeArray(fields)
    }
    

    Log Entry Encoding

    Encode event log entries:
    import { Rlp } from 'tevm'
    
    interface Log {
      address: Uint8Array
      topics: Uint8Array[]
      data: Uint8Array
    }
    
    function encodeLog(log: Log): Uint8Array {
      const fields = [
        log.address,
        log.topics,  // Nested array
        log.data
      ]
    
      return Rlp.encodeArray(fields)
    }
    
    const log: Log = {
      address: new Uint8Array(20).fill(0x01),
      topics: [
        Bytes32().fill(0x02),
        Bytes32().fill(0x03)
      ],
      data: new Uint8Array([0x04, 0x05, 0x06])
    }
    
    const encoded = encodeLog(log)
    

    Receipt Encoding

    Encode transaction receipts:
    import { Rlp } from 'tevm'
    
    interface Receipt {
      status: bigint
      gasUsed: bigint
      logsBloom: Uint8Array
      logs: Log[]
    }
    
    function encodeReceipt(receipt: Receipt): Uint8Array {
      const encodedLogs = receipt.logs.map(log => encodeLog(log))
    
      const fields = [
        bigintToBytes(receipt.status),
        bigintToBytes(receipt.gasUsed),
        receipt.logsBloom,
        encodedLogs
      ]
    
      return Rlp.encodeArray(fields)
    }
    

    Merkle Patricia Trie Node

    Encode trie nodes:
    import { Rlp } from 'tevm'
    
    type TrieNode =
      | { type: 'branch'; children: Uint8Array[]; value: Uint8Array }
      | { type: 'extension'; path: Uint8Array; child: Uint8Array }
      | { type: 'leaf'; path: Uint8Array; value: Uint8Array }
    
    function encodeTrieNode(node: TrieNode): Uint8Array {
      if (node.type === 'branch') {
        // Branch node: [child0, child1, ..., child15, value]
        return Rlp.encodeArray([...node.children, node.value])
      }
    
      if (node.type === 'extension') {
        // Extension node: [path, child]
        return Rlp.encodeArray([node.path, node.child])
      }
    
      // Leaf node: [path, value]
      return Rlp.encodeArray([node.path, node.value])
    }
    

    Schema-based Encoding

    Define typed schemas for RLP encoding:
    import { Rlp } from 'tevm'
    
    // Define schema
    interface AccountState {
      nonce: bigint
      balance: bigint
      storageRoot: Uint8Array
      codeHash: Uint8Array
    }
    
    // Encoder function
    function encodeAccountState(account: AccountState): Uint8Array {
      return Rlp.encodeArray([
        bigintToBytes(account.nonce),
        bigintToBytes(account.balance),
        account.storageRoot,
        account.codeHash
      ])
    }
    
    // Decoder function (see decodeArray)
    function decodeAccountState(bytes: Uint8Array): AccountState {
      const arr = Rlp.decodeArray(bytes)
      return {
        nonce: bytesToBigint(arr[0]),
        balance: bytesToBigint(arr[1]),
        storageRoot: arr[2],
        codeHash: arr[3]
      }
    }
    

    Performance

    Pre-calculate Sizes

    Calculate total size before encoding:
    import { Rlp } from 'tevm'
    
    const items = [
      new Uint8Array([1, 2, 3]),
      new Uint8Array([4, 5, 6])
    ]
    
    // Calculate size first
    const size = Rlp.getEncodedLength(items)
    console.log(`Array will encode to ${size} bytes`)
    
    // Then encode
    const encoded = Rlp.encodeArray(items)
    

    Batch Encoding

    Encode multiple arrays efficiently:
    import { Rlp } from 'tevm'
    
    const transactions = [
      [nonce1, gasPrice1, ...],
      [nonce2, gasPrice2, ...],
      [nonce3, gasPrice3, ...]
    ]
    
    // Encode each transaction
    const encodedTxs = transactions.map(tx => Rlp.encodeArray(tx))
    
    // Encode as list of transactions
    const block = Rlp.encodeArray(encodedTxs)
    

    Reusable Buffers

    For high-frequency encoding, consider pre-allocating buffers:
    import { Rlp } from 'tevm'
    
    class TxEncoder {
      private buffer = new Uint8Array(1024)  // Reusable buffer
    
      encode(tx: Transaction): Uint8Array {
        const fields = [
          bigintToBytes(tx.nonce),
          bigintToBytes(tx.gasPrice),
          // ...
        ]
    
        return Rlp.encodeArray(fields)
      }
    }
    

    See Also