observe / @flop-lab/finality
Finality monitor
Suite entry: flop finality. The README below lists the package options.
Reading progress
Finality
Is the chain producing and finalizing blocks on time? flop finality measures intervals between linked consecutive blocks and compares the public API's reported finalized lag with pinned yellowpaper rules. Missing finality stays unavailable.
Quick start
Run from the repository root with Node 22 and pnpm:
pnpm install
pnpm --filter @flop-lab/finality build
node packages/finality/dist/cli.js snapshot --recordedRead or record
node packages/finality/dist/cli.js snapshot --json
node packages/cli/dist/cli.js finality snapshot --recorded
node packages/finality/dist/cli.js snapshot --out finality.json
node packages/finality/dist/cli.js snapshot --input finality.json --jsonBuild the suite CLI before using its command. --out creates a replayable JSON file and refuses to overwrite it. It never writes a transaction. Exit codes: 0 for a normal lag comparison with timing data, 1 for a warn/freeze/escape result and 2 for missing data, parameter drift or invalid input.
How the measurements work
One flop_indexer_query requests the latest block window and stats.finality through @flop-lab/mcp. A window is capped at 24 blocks. Calls use an eight-second attempt timeout and one retry with backoff on retryable errors. No discovery loop or RPC host scan runs during a snapshot. createMonitor() coalesces callers and caches successes and failures for 15 seconds after completion.
Every recording retains the raw tool text, query, source URL, response time, duration and request count. Sort blocks by height. Only adjacent heights with matching parent hashes and increasing non-future millisecond timestamps contribute an interval. Missing heights are not averaged away. Median is the middle value or the mean of the middle pair. Nulls, duplicates and malformed fields never become zero. The count above the paper's 1000 ms interval is descriptive, not a consensus violation verdict.
Finality lag is bestBlock - finalizedBlock within the reported finality object. It must equal finalizedLag. The indexed strip can trail that object's best head. The strip is never substituted into that formula. No conversion of lag into elapsed stall time is made.
Quoted rules
Source: yellowpaper at 2a2cc821. Raw excerpts and their line numbers are in test/fixtures/paper.json.
- R2.1: "Blocks MUST be authored by BABE at a fixed 1 s interval."
finality_lag_warn: 30 blocks. "Finality lag above which the detector reports Lagging (alert only; finality-clocked deadlines pause naturally)." The comparison is strictly greater than 30.finality_freeze_threshold: 120 blocks. "Finality lag at/above which the channel enters Stalled: new finality-dependent opens are rejected fail-closed (ensure_finality_open_allowed); additive top-up/cancel paths stay open."max_finality_stall: 3600 blocks. "Finality lag at/above which the chain is EscapeEligible (safe mode): restore AlephBFT finality or ratify a checkpoint recovery through the hard-fork runbook."
These are pinned paper values. API-reported thresholds are compared separately. Neither agreement nor an API state label proves deployed runtime enforcement. Section 2 specifies no finality latency target. Escape eligibility never authorizes treating best blocks as finalized.
Validators and rotation
The captured tool list and indexer schema expose no active validator membership, session keys, committee identities or rotation events. activeOperators, price-source miners and trust-root committee entries are not substitutes for the validator set.
Section 15 distinguishes the authoring set from the selected finality committee. Registration enters ValidatorQueue; rotation promotes into ActiveValidators. Section 15.5 describes interval-based and manual rotation with a stake gate, churn cap and minimum active-set guard. This tool quotes the rule but cannot observe its execution from the inspected public fields. The site links the recorder's dated height history. Sparse recorder points are not consecutive-block timing measurements.
Library and checks
import { collect, analyzeRecording } from "@flop-lab/finality";
const report = analyzeRecording(await collect());
console.log(report.production, report.lagState);Run pnpm --filter @flop-lab/finality check. The default tests replay real responses and make no network calls. pnpm --filter @flop-lab/finality capture deliberately refreshes the small research fixtures through public read-only sources. Tests cover threshold boundaries, gaps, parent mismatches, malformed heads, offline cache behavior and empty input.
What this does not verify
The tool does not verify AlephBFT signatures, finalized-prefix storage, canonical chain membership, validator identities, rotation execution, deployed thresholds or runtime safe mode. MCP block lookup and indexer queries share an indexer and are not independent proofs. A normal reported lag is not an uptime or finality guarantee. The devnet can reset. Dated recordings are not current network state. The recorder archive does not contain a finalized-head series yet. No latency SLA or stall duration is inferred from block lag.