Skip to main content

Module checkpoint

Module checkpoint 

Source
Expand description

Checkpoints — a serialized fold at a frontier (slice B4 of docs/proposals/multi-device-sync.md, §“Snapshots: bounding the oplog”).

A Checkpoint is exactly what the proposal specs: “a serialized folded state at a frontier F, content-addressed” — the crate::fold::SyncState a device folded from every op at or below the frontier, plus the bookkeeping a truncated log needs to stay verifiable:

  • frontier — per device, the {seq, hlc, head} of the last op the checkpoint covers. Because crate::oplog::verify_log enforces HLC-monotone chains, “hlc ≤ F” is always a per-device chain prefix, so the frontier is a clean cut.
  • head — the covered chain tail’s op_id. After truncation the first retained op’s prev must link to it: the checkpoint IS the anchored chain head, which upgrades the A9-style truncation-honesty story (a truncated log + its checkpoint prove that nothing was dropped silently — the cut is signed into the anchor). verify_anchored checks the whole composition; crate::oplog::verify_log alone already accepts chains that don’t start at seq 0 (designed for this).
  • state_hashcrate::fold::state_hash of the stored state, the proposal’s divergence invariant (“same frontier ⇒ same snapshot hash”).
  • checkpoint_hash — the content address, covering the WHOLE record (frontier + scopes + state), not just the state. This is load-bearing: the fold DEDUPS (e.g. the same conversation turn emitted by two devices), so two checkpoints with different frontiers can fold to the same SyncState — a state-only address would give them one file name, the relay (B3) would dedup-keep the wrong one, and resume_anchored would seed next_seq from the wrong frontier — a permanent duplicate-seq chain fork. Addressing the whole record makes “same file ⇒ same checkpoint” true (and gives B6 a correct thing to sign); “same frontier ⇒ same file” still holds because the fold is deterministic.

Scopes, honestly: the proposal tracks frontiers per scope, but B1’s DeviceLog stamps ONE seq/prev chain across all scopes (personal and shared ops interleave in a single device chain), so a per-scope truncation would punch unverifiable holes in the chain. B4 therefore checkpoints a device log whole-chain and records the Checkpoint::scopes it covers; true per-scope frontiers arrive when B3/B6 split the relay streams (and with them the chains) by scope.

Durability discipline: Checkpoint::save writes temp + atomic rename (fsync’d file, best-effort fsync’d dir); Checkpoint::load re-derives BOTH hashes from the stored content — state_hash from the state, checkpoint_hash from the whole record — and cross-checks the file name against the content address, rejecting any mismatch loudly (CheckpointError::HashMismatch / CheckpointError::ContentMismatch / CheckpointError::AddressMismatch) — a tampered or bit-rotted snapshot (including a tampered frontier) never folds and never anchors.

Structs§

Checkpoint
A serialized fold at a frontier — see the module docs for the design.
FrontierEntry
Per-device frontier bookkeeping: the last op the checkpoint covers for one device — its chain position (seq), stamp (hlc), and op_id (head, the anchor a truncated log’s first retained prev links to).

Enums§

AnchorError
A failure composing a checkpoint with a (truncated) tail.
CheckpointError
A checkpoint load/verify failure.

Functions§

resume_anchored
Resume a device’s append chain from a checkpoint + retained tail — the truncated-journal sibling of DeviceLog::resume. Without this, a device whose ops were ALL below the frontier would resume at seq 0 and permanently fork its own chain (the same hazard DeviceLog::resume’s journal-durable-before-transmit contract guards). Verifies the composition first, seeds seq/prev from the frontier anchor, and advances the hybrid clock past every stamp the checkpoint or tail covers (the frontier holds each device’s max covered HLC, so it bounds everything folded into the state). The resumed log defaults to the logical (always-0) wall source — attach the real one with DeviceLog::set_wall_clock.
verify_anchored
Verify the composition checkpoint + retained tail — the truncated-log analogue of verify_log: