Skip to main content

Recent History (ζH\zeta_H)

The Recent History state transition maintains a rolling window of the most recent block metadata, enabling the protocol to detect duplicate work-reports and verify historical commitments.

Purpose

The recent history component (β\beta) serves several critical functions:

  1. Duplicate Detection: Prevents the same work-report from being submitted multiple times across recent blocks
  2. State Integrity: Maintains Merkle commitments to recent block states for verification
  3. Accumulation Tracking: Records the accumulation output log using a Merkle Mountain Range (MMR) structure
  4. Work-Package History: Tracks which work-packages were reported in recent blocks

State Structure

The recent history state consists of two main components:

β ≡ ⟨h, b⟩  // Recent history tuple

h ∈ [BlockHistory;8] // Sequence of up to 8 recent block records
b ∈ MMR // Accumulation output MMR

Each block history entry contains:

BlockHistory {
header_hash: H, // Blake2b hash of the block header
state_root: H, // State trie root (corrected in next block)
beefy_root: H, // MMR super-peak (used for BEEFY finality proofs)
reported: {HH} // Map: work-package hash → segment root
}

The beefy_root is the MMR super-peak of the accumulation output log, used by the BEEFY finality gadget to provide concise finality proofs to third-party systems.

Constants:

  • Window size: 8 blocks (configurable via RECENT_HISTORY_SIZE)
  • Hashing: Keccak-256 for MMR operations (legacy compatibility)

How It Works

1. Parent State Root Correction

When a new block is processed, the first step updates the parent block's state root with the actual value:

if len(beta.h):
beta.h[-1].state_root = block.header.parent_state_root

This corrects the placeholder zero hash from the previous block's transition, ensuring historical state roots are accurate.

2. Accumulation Output MMR Update

The accumulation outputs from the current block are Merklized and appended to the MMR:

# Append accumulation root to MMR
beta.b = mmr_append(beta.b, acc_root, keccak256)

# Calculate MMR super-peak (Beefy root)
beefy_root = mmr_super_peak(beta.b)

The Beefy root is the MMR super-peak, providing a succinct commitment to all historical accumulation outputs.

3. Work-Package Tracking

For each guarantee in the block, we extract and store the work-package hash and its segment root:

def package(guarantees: GuaranteesExtrinsic) -> dict:
package_dict = {}
for g in guarantees:
spec = g.report.package_spec
package_dict[spec.hash] = spec.exports_root
return package_dict

This mapping allows the protocol to verify that a work-package hasn't been reported in recent history.

4. New Block History Entry

Finally, a new history entry is created and appended (with the state root initially set to zero):

new_entry = BlockHistory(
header_hash=header_hash,
state_root=Bytes[32]([0] * 32), # Placeholder, corrected next block
beefy_root=beefy_root,
reported=package(block.extrinsic.guarantees)
)

beta.h.append(new_entry)
beta.h = beta.h[-8:] // Keep only last 8 entries

State Transition Equation

The recent history transition updates both components:

β' = ⟨h', b'⟩

Where:
h' = (h† + n) [last 8 elements]
b' = MMR-append(b, acc_root, Keccak)
  • h† is the history after parent state root correction
  • n is the new block history entry
  • acc_root is the accumulation output root for this block

Implementation Details

Location: tessera/jam/state/transitions/recent_history/recent_history.py

Key Functions:

  • RecentHistory.transition(): Main state transition function
  • package(): Transforms guarantees into segment root lookup dictionary
  • MMRFunctions.append_fn(): Appends to Merkle Mountain Range
  • MMRFunctions.super_peak(): Computes MMR commitment

Dependencies:

  • Keccak-256 hashing for MMR operations
  • Blake2b for header hashing
  • MMR utilities from jam.utils.merkle

Usage in Protocol

Recent history is consulted during:

  1. Work-Report Validation: Checking that a work-package hash hasn't appeared in recent blocks
  2. State Proofs: Verifying historical state commitments
  3. Accumulation Verification: Validating accumulation output sequences via the MMR

Example

When block at slot 1000 is processed:

  1. Update block 999's state root: h[7].state_root = parent_state_root
  2. Append accumulation output to MMR: b' = MMR-append(b, acc_root)
  3. Record work-packages: reported = {pkg_hash_1 → seg_root_1, ...}
  4. Add new entry: h[8] = {header_hash, 0x00...00, beefy_root, reported}
  5. Trim to last 8: h' = h[1:9]

References

  • Gray Paper: Section on Recent History
  • Specification: Equations defining β\beta, hh, and bb
  • Implementation: tessera/jam/state/transitions/recent_history/

Next: SAFROLE | Authorization