Skip to content

RCache: missing PostState for pre-Byzantium receipts #20910

@sudeepdino008

Description

@sudeepdino008

Problem

MakeReceipt (execution/protocol/state_processor.go:160-165) only ever sets Status on the receipt, never PostState. So WriteReceiptCacheV2ReceiptForStorage only persists the 1-byte status.

For pre-Byzantium blocks (mainnet < 4,370,000), the canonical consensus receipt RLP is [postState (32 bytes), cumGas, bloom, logs] — see EIP-658 and Yellow Paper §4.3.1. Without PostState, RCache cannot reconstruct the canonical receipt root for those blocks: Receipt.statusEncoding() returns 1 byte where the original encoding had 32 bytes, so DeriveSha(receipts) produces a different root than the header.

Impact

  • The new ReceiptRootIntegrity check (PRs landing on dwightbot/receipt-root-range-opt, commits 7cceabe25e / 1eb5b2af3b) cannot validate pre-Byzantium blocks. As a workaround we now start it at ByzantiumBlock (commit 0b7381a8e9).
  • Any other consumer that needs to reconstruct pre-Byzantium consensus receipt encoding from RCache alone will be similarly blocked.
  • Today the only path that recovers PostState is rpc/jsonrpc/receipts/receipts_generator.go:421,625, which re-derives it by replaying the transaction and computing commitment from history — only works on datadirs with commitment history enabled.

Suggested fixes (not exhaustive)

  1. Compute and persist PostState per tx in MakeReceipt for pre-Byzantium blocks (cheap conceptually, but requires intermediate-state-root commitment per tx — currently only available via commitment history).
  2. Backfill PostState for pre-Byzantium ranges from snapshots once (one-shot migration), so RCache becomes complete.
  3. Document that RCache is only complete from Byzantium onwards, and gate any consumers (like the integrity check) on cc.IsByzantium(blockNum).

References

  • EIP-658: https://eips.ethereum.org/EIPS/eip-658
  • execution/types/receipt.go:342-350statusEncoding() returns r.PostState if non-empty, otherwise 1-byte status.
  • execution/protocol/state_processor.go:160-165MakeReceipt only sets Status.
  • db/integrity/rcache_receipt_root.go — current workaround skipping pre-Byzantium.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions