Overview
Register read-write checking ensures that register values are consistent throughout program execution. Every register read must return the value from the most recent write to that register, and initial register values must be zero (except the stack pointer).Role in the Proving System
Register checking is a critical component of memory consistency:- Stage: Part of Stage 3 (Register and Bytecode checking)
- Input: Execution trace with register reads/writes per instruction
- Output: Opening claims proving register consistency
- Integration: Feeds into final claim reductions (Stage 7)
Register Architecture
RISC-V Register File
Jolt supports the RISC-V register file:- 32 integer registers (x0-x31) for RV32
- 32 integer registers (x0-x31) for RV64 (64-bit values)
- Special registers:
x0: Hardwired to zero (all writes ignored)x2(sp): Stack pointer (initialized to top of memory)x1(ra): Return address
Register Traces
Each instruction cycle records:- RS1 read: Source register 1 (address and value)
- RS2 read: Source register 2 (address and value)
- RD write: Destination register (address and value)
lui only writes RD).
Memory Checking Protocol
Jolt uses an offline memory checking protocol based on multiset equality:Multiset Representation
Reads multisetR:
W:
Fingerprinting via Polynomial Evaluation
Multiset equality is proved via random fingerprinting:- Verifier samples random challenge
γ - Prover computes polynomial products:
- Read fingerprint:
∏_{r ∈ R} (γ - hash(r)) - Write fingerprint:
∏_{w ∈ W} (γ - hash(w))
- Read fingerprint:
- Check: Read fingerprint divides write fingerprint
Sumcheck Structure
Stage 3a: Register Val Evaluation
Purpose: Compute multilinear extension of register values at each cycle. Sumcheck claim:reg_val(x): Register value at cycle x (derived from trace)r: Random evaluation pointclaimed_eval: Value to be verified
RegisterValues: Virtual polynomial from execution traceRegisterAddresses: Which register is accessedEqPolynomial: Equality check at challenge point
Stage 3b: Register Read-Write Checking
Purpose: Verify read/write consistency via fingerprint sumcheck. Sumcheck claim:write_fingerprint(x): Product of (γ - hash(write)) for all writes up to cycle xread_fingerprint(x): Product of (γ - hash(read)) for all reads up to cycle xfinal_ratio: Should equal 1 if R ⊆ W
Read-After-Final (RAF) Polynomial
Jolt uses a Read-After-Final (RAF) polynomial to detect invalid reads:Definition
Purpose
RAF detects two error cases:- No writes: Register never written but is read
- Stale reads: Read after execution ends (shouldn’t happen in valid trace)
Sumcheck Integration
RAF is checked via a separate sumcheck:Initial and Final States
Initial Register State
Most registers: Initialize to 0W.
Final Register State
Not checked: Register values at program end are not constrained (only consistency during execution matters). Termination: Detected by heuristic (PC stops changing) rather than explicit register state.Implementation Details
Module Structure
val_evaluation.rs:- Computes register value evaluations at challenge points
- Uses multilinear polynomial evaluation over trace
- Implements fingerprint-based memory checking sumcheck
- Handles incremental fingerprint computation
- Verifies RAF polynomial is zero
Key Types
RegisterValEvaluationParams:Performance Characteristics
Prover Time
Register Val Evaluation:- O(trace_length · log(trace_length)) field operations
- ~5-10% of total proving time
- O(trace_length) field operations per round
- ~10-15% of total proving time
- Incremental fingerprint updates are efficient
Memory Usage
- No materialized polynomials: Register values derived on-the-fly from trace
- Streaming: Uses streaming sumcheck windows for memory efficiency
- Typical usage: ~10-20MB for 10⁶ cycles
Verifier Time
- O(log(trace_length)) field operations
- Verifies sumcheck round polynomials
- ~0.1-1ms for typical traces
Comparison with RAM Checking
Register checking is simpler than RAM checking:| Aspect | Register Checking | RAM Checking |
|---|---|---|
| Address space | 32 registers | 2^K memory words |
| Initialization | All zeros + sp | Bytecode + inputs |
| Read-after-final | Simple RAF check | Complex RAF with advice |
| Performance | ~10-15% proving time | ~30-40% proving time |
Key Files
jolt-core/src/zkvm/registers/val_evaluation.rs: Register value evaluation sumcheckjolt-core/src/zkvm/registers/read_write_checking.rs: Fingerprint-based consistency checkingjolt-core/src/zkvm/claim_reductions/: Final claim aggregation
Next Steps
- RAM Checking: Memory consistency verification (similar protocol)
- Instruction Execution: How instruction outputs are verified
- Opening Proofs: Batched commitment openings