Skip to main content

Module chain_freshness

Module chain_freshness 

Source
Expand description

Liveness of the node’s chain-derived compliance state (ADR 011 § Serving while chain-stale).

Every serve-path guard that reads on-chain state — the blacklist deny-set, the pool-solvency recheck, the per-signer capability cap — answers from a projection that only advances while the chain watchers can reach the RPC. During an RPC outage each of those guards silently passes on stale data: a takedown, a drained pool, or a spent capability that landed on-chain during the blind window is invisible, so the node keeps signing serve and probe responses it can no longer vouch for. Serving a hash past its compliance window is slashable (ADR 011 § Slashing), and the offense is exactly a signed StreamResponse{ok:true} or ProbeResponse{has_blob:true} — the node produces its own evidence.

ChainFreshness is the single backstop over that whole family: it holds the wall-clock time of the blacklist watcher’s last successful poll tick and answers one question — has the node been unable to reach the chain for longer than the operator’s grace window? While it has, the serve and probe paths refuse rather than sign. The signal is the successful tick, not the last event: a quiet chain produces no blacklist events for hours legitimately, and keying on events would take every node dark on any quiet stretch. The tick stamps on every successful poll including idle ones (the same liveness the decdn_blacklist_watcher_last_tick_timestamp_seconds gauge exports), and the boot enumeration stamps it too, so a freshly-booted node that has just vetted its deny-set is never treated as stale.

Grace, not a switch. There is one knob — the grace window in seconds — and it is always evaluated. An operator who wants the old fail-open behavior sets the window large (a year); there is no separate enable flag, so there is no “enabled but zero-grace” state to reason about.

Unwired = fail-open. A node with no chain configured (dev/test) has no blacklist watcher to stamp the cell, so the runtime wires no ChainFreshness at all and the guards read None — the same fail-open shape the pool-view guards use when no chain is present.

Structs§

ChainFreshness
Shared liveness of the node’s chain reads. Cloned into the blacklist watcher (which stamps it) and the serve and probe handlers (which read it); every clone shares one cell.