TimelineProof & StateProof Chain
vest intermediate 6 min read
ELI5
A ship’s logbook: each voyage (StateProof) records how many miles sailed and a map of checkpoints (MerkleProof chain). The captain’s logbook (TimelineProof) collects all voyages and is signed on the cover (root_signature). To verify the whole voyage history, check each entry is internally consistent, then verify the cover signature.
Technical Deep Dive
StateProof
StateProof (src/timeline_proof.rs) proves the state of a timeline at a specific point:
| Field | Type | Validity constraint |
|---|---|---|
timeline_id | String | none |
state_hash | Vec<u8> | non-empty, exactly 32 bytes |
operation_count | u64 | must be > 0 |
timestamp_ms | u64 | none |
proof_chain | Vec<MerkleProof> | all proofs must pass MerkleProof::verify() |
verify() returns true iff !state_hash.is_empty() && state_hash.len() == 32 && operation_count > 0 && proof_chain.iter().all(|p| p.verify()).
size_bytes() = 32 (state_hash) + sum of all MerkleProof sizes.
TimelineProof
TimelineProof collects ordered StateProof objects and anchors them with a root AuditSignature:
classDiagram class TimelineProof { +timeline_id: String +state_proofs: Vec~StateProof~ +root_signature: AuditSignature +proof_depth: u32 +add_state_proof(StateProof) Result +verify_chain() bool +hash() Vec~u8~ +size_bytes() usize } class StateProof { +timeline_id: String +state_hash: Vec~u8~ +operation_count: u64 +timestamp_ms: u64 +proof_chain: Vec~MerkleProof~ +verify() bool +add_proof(MerkleProof) } TimelineProof "1" *-- "0..*" StateProofadd_state_proof rejects an invalid StateProof (returns Err("Invalid state proof")); otherwise pushes it and updates proof_depth = state_proofs.len().max(proof_depth).
verify_chain = root_signature.verify_chain() && all state_proofs pass verify().
Sealing Sequence
sequenceDiagram participant C as Caller participant TP as TimelineProof participant SP as StateProof
C->>SP: new(timeline_id, state_hash[32], op_count>0, ts) SP->>SP: verify() → true C->>TP: add_state_proof(sp) TP->>SP: verify() SP-->>TP: true TP->>TP: push, proof_depth = max(len, depth) TP-->>C: Ok(())
C->>TP: verify_chain() TP->>TP: root_signature.verify_chain() TP->>SP: verify() for each TP-->>C: trueSize Accounting
TimelineProof::size_bytes() = sum of all StateProof sizes + 96 (fixed overhead for root_signature and timeline_id). This 96-byte constant is hard-coded; the proto wire size will differ.
Timeline Hash
TimelineProof::hash() XOR-folds state_hash bytes from each StateProof, then XOR-folds root_signature.proof.signature_bytes — a 32-byte deterministic fingerprint of the complete timeline.
Key Terms
- StateProof → snapshot proof: (state_hash, operation_count, MerkleProof chain) at a point in time
- TimelineProof → ordered collection of StateProofs anchored by root_signature
- proof_depth → high-water mark of state_proofs.len(); updated via
.max()on each add - verify_chain → validates root_signature chain AND every StateProof.verify()
- SealedTimeline → production proto type; adds final_root, witnesses, and seal_reason
Q&A
Q: Can proof_depth ever decrease after add_state_proof calls?
A: No. It is updated with .max(self.proof_depth) so it only grows.
Q: What happens if add_state_proof is called with operation_count = 0?
A: StateProof::verify() returns false, causing add_state_proof to return Err("Invalid state proof"). The proof is not added and proof_depth does not change.
Q: Does TimelineProof::hash() include timestamps or operation counts from the StateProofs?
A: No — only state_hash bytes and root_signature.proof.signature_bytes are folded in.
Examples
Building and verifying a two-state timeline:
let sig_proof = SignatureProof::new("alice".into(), vec![1u8;64], vec![2u8;32], 0);let root_sig = AuditSignature::new(sig_proof, vec![3u8;32], 1);let mut tp = TimelineProof::new("tl-001".into(), root_sig);
let sp1 = StateProof::new("tl-001".into(), vec![1u8;32], 10, 1000);let sp2 = StateProof::new("tl-001".into(), vec![2u8;32], 20, 2000);tp.add_state_proof(sp1).unwrap();tp.add_state_proof(sp2).unwrap();
assert_eq!(tp.proof_depth, 2);assert!(tp.verify_chain());assert!(tp.size_bytes() > 96);neighbors on the map
- VEST Protocol Architecture Overview onboarding to the VEST codebase for the first time
- ProofVerifier Engine & VerificationResult reading verification counters after a batch signature check to determine failure rate
- Hybrid Logical Clock deciding ordering between concurrent operations
- Timeline Reconstruction implementing a new timeline UI control