Skip to main content

Module slash_watcher

Module slash_watcher 

Source
Expand description

Daemon slash-detection watcher (#1032, G-NODE-05).

Surfaces every still-appealable slash minted against this node’s own operator so the operator can see it over the admin RPC (admin_v1_slashes) and file decdn appeal slash within the 30-day window without watching the chain directly. A counter metric (decdn_slashes_detected_total) mirrors it.

Shape follows the CapacityBond registry watcher (crate::dht::capacity_bond_registry) — enumerate at a snapshot block, follow the tail, re-read periodically as the backstop — rather than replaying logs:

  • Enumerate at boot. The in-memory store is rebuilt on every start from the authoritative CapacityBond.operatorSlash* enumeration (ADR 019), not by re-scanning the Slashed log tail from a block floor (#1108). Walking the append-only index backwards and stopping at the first closed record reads only the still-appealable tail. Offense and evidence come straight off the record; the enforced deadline is the record’s base appealWindowClose plus the global pausedTotal, all read at the snapshot block. A transient RPC failure retries on the shared boot budget, like the registry bootstrap on the same contract; a deterministic fault or an exhausted budget fails startup.
  • Follow SlashRecorded from the snapshot block. The route follows SlashRecorded on the shared multiplexed poller, seeded at the enumeration snapshot block, so there is no historical scan on any boot. SlashRecorded indexes operator as topic2, but the merged poller filter cannot scope topic2, so the route receives every operator’s SlashRecorded and decode_recorded’s operator == self guard filters out the rest. The event carries only the slashId; the offense/evidence/deadline are point-read from getSlashRecord.
  • Resync as the backstop. A missed tail event (reorg at the unstable tip, or a tick lost to RPC backoff) never self-heals otherwise, so the store is re-enumerated every SLASH_RESYNC_INTERVAL at the snapshot block; this also prunes slashes whose appeal window has since closed. A slash the tail saw above that block survives the resync (fold_resync). The store is deduped by slashId, so the enumeration/tail overlap is harmless.

Structs§

DetectedSlash
One slash detected against this node’s operator.

Functions§

bootstrap
Enumerate this operator’s still-appealable slashes from CapacityBond, then return the shared detected-slash store (for the admin surface) and the SlashRecorded Route the shared poller drives to keep it current.

Type Aliases§

SlashStore
Shared, in-memory detected-slash store: appended in detection order and deduped by slashId. Cloned into crate::admin::AdminState for the read-only admin_v1_slashes surface.