CometBFT Liveness and the x/slashing Downtime Window
signed_blocks_window, min_signed_per_window, and the jail-unjail-tombstone distinction in the Cosmos SDK.
§ IFrame
Last Saturday's cert lesson took the validator's signature apart: the three vote types CometBFT asks for, the PrivValidator interface that decides who answers, and the x/evidence and x/slashing path that convicts a validator on its own duplicated signature. That lesson was the safety half of slashing. A validator that signs two conflicting blocks at one height is convicted by cryptography, tombstoned, and barred forever. Today is the liveness half, and the protocol treats it as a different category of failure with a different mechanism, a different cost, and a different ending.
The distinction is not a matter of degree. Double-sign is a fault of commission, proven by evidence a third party submits, punished by a large slash and a permanent tombstone. Downtime is a fault of omission, detected by the chain itself with no evidence transaction at all, punished by a small slash and a recoverable jail. The same module, x/slashing, holds both, but it reaches them through entirely separate code paths: one driven by submitted evidence, the other by a counter the module updates on every single block. An operator who studies only the evidence path knows half the module and the less common half.
The liveness path matters more for daily operations precisely because it is the one that fires. The Interchain Dev credential tests it because a Cosmos engineer ships and operates chains where these parameters are governance-set values that shape every validator's risk. Understanding signed_blocks_window and min_signed_per_window is not exam trivia; it is the difference between setting a chain's liveness policy deliberately and inheriting whatever the scaffolding defaulted to.
tome_refs: [] — the Cosmos / CometBFT / Tendermint tome shelf is empty in the Atrium Lattice (known R-010 acquisition gap). Lattice queries for the liveness-window, downtime-jail, and tombstone phrases returned only prior synthesis-lesson chunks, zero canonical doc_type=tome hits. Acquisition priority surfaced to the Fajr brief §IV.
§ IIDomain Foundations — How the Chain Counts Absence
The x/slashing module keeps, for every validator, a small running record called the validator signing info. It holds three fields that matter for liveness: the index into a sliding window, a counter of missed blocks in that window, and the jailed-until timestamp. On every block, the module looks at whether each bonded validator's signature appeared in the block's commit, and it updates that validator's record accordingly.
The sliding window is a bit-array of fixed length, the signed_blocks_window parameter. Picture it as a ring of bits, one per recent block, each bit recording signed-or-missed for that block. As each new block arrives the ring advances one position, the oldest bit ages out, and the newest bit is written. The missed_blocks_counter is the running count of missed bits currently in the ring, maintained incrementally: when a new block is missed the counter goes up, and when an old missed bit ages out of the window the counter comes back down. This incremental maintenance is why the chain can evaluate liveness on every block without rescanning the whole window each time.
The jail condition is a single comparison. The module computes the maximum misses it will tolerate as the window size minus the required signed count, where the required signed count is signed_blocks_window multiplied by min_signed_per_window. When missed_blocks_counter exceeds that maximum, the validator is below the floor, and the module jails it in the same block. Two parameters, one derived threshold, one comparison per block per validator. The whole liveness regime reduces to keeping that counter under that threshold.
§ IIIThe signed_blocks_window and min_signed_per_window Parameters
These two parameters are the chain's liveness policy, and they are set by governance, which means a Cosmos engineer either proposes their values or inherits someone else's. Reading them correctly is the first competence the cert tests.
The signed_blocks_window sets how far back the chain remembers. A larger window is more forgiving of a long single outage in absolute block terms but also slower to forget past misses, so a validator that stumbles repeatedly accumulates misses across a wider span. A common mainnet value is ten thousand blocks. At a block time of roughly six seconds that window spans about seventeen hours of wall-clock, though the protocol counts blocks and not time, so a chain that slows down stretches the wall-clock span of the same window.
The min_signed_per_window is a decimal fraction, the floor. A value of five-hundredths means the validator must sign at least five percent of the window. Combined with a ten-thousand-block window, the validator must sign at least five hundred of the last ten thousand blocks, which means it may miss up to ninety-five hundred before the jail fires. That headroom looks enormous, and for an intermittent flapping failure it is, but for a continuous outage it is spent linearly: a fully dark validator adds one missed bit per block and crosses ninety-five hundred misses after ninety-five hundred consecutive dark blocks, a single uninterrupted outage.
The interaction of the two is the subtlety the cert probes. The floor is a fraction of the window, so changing the window changes the absolute miss-tolerance even if the fraction stays fixed. Double the window at a fixed five-percent floor and the validator may now miss twice as many blocks in absolute terms, which is more forgiving of one long outage but holds a grudge over a longer history. There is no free parameter here; a chain's choice of window and floor is a choice about which failure shape it punishes hardest.
§ IVThe Jail, the Unjail, and the Tombstone
When the floor breaks, three things happen in the jailing block, and then a fourth thing waits on the operator. The module applies the downtime slash, a fraction of the validator's bonded stake set by slash_fraction_downtime, typically a hundredth of a percent or a tenth of a percent. It sets the validator jailed and records a jailed_until timestamp equal to now plus the downtime_jail_duration, often ten minutes. It removes the validator from the active set so it stops being asked to sign. And it resets the signing-info window, so the validator starts its post-jail life with a clean counter rather than re-jailing instantly on the misses that caused the first jail.
The fourth thing is the unjail, and the protocol makes it a deliberate operator action rather than an automatic return. After jailed_until has passed, the operator submits a MsgUnjail from the validator's operator account. The module checks several conditions before accepting: the jail duration must have elapsed, the validator must still have self-delegation above the minimum, and it must not be tombstoned. If the checks pass, the validator rejoins the active set at the next block and resumes signing. The protocol deliberately does not auto-unjail, because an automatic return would re-jail a validator whose underlying problem is unfixed, burning stake in a loop; the manual step forces a human to assert the validator is healthy.
The tombstone is the line between this lesson and last week's. A downtime jail is recoverable: serve the duration, fix the node, unjail, continue. A double-sign conviction sets the tombstone flag, and a tombstoned validator can never unjail, because the tombstone check in the unjail path fails permanently. This is the protocol encoding the moral difference the two faults carry. Absence is forgiven because it harms only the absent validator's rewards and the chain's momentary throughput. Equivocation is not forgiven because it attacks the chain's safety, and the consensus key that did it is barred for life. Same module, same jail flag, opposite endings, and the tombstone is the field that decides which.
§ VPractice Scenario — Reading a Chain's Liveness Policy
Suppose a Cosmos engineer inherits a new chain whose genesis sets signed_blocks_window to thirty thousand, min_signed_per_window to ten-hundredths, slash_fraction_downtime to a thousandth, and downtime_jail_duration to ten minutes. Block time is one second. What does this policy actually say?
The window is thirty thousand blocks at one second, roughly eight hours of wall-clock. The floor of ten percent means the validator must sign at least three thousand of the last thirty thousand blocks, so it may miss up to twenty-seven thousand before jailing, which at one second a block is about seven and a half hours of continuous darkness. This is a forgiving liveness policy: a validator can be down most of a working day before it jails. The slash of a thousandth, one-tenth of one percent, is on the higher side for downtime but still small next to a double-sign. The ten-minute jail duration means recovery is fast once the operator acts.
The engineering read is that this chain has prioritized validator forgiveness over tight liveness, which suits a young chain still stabilizing its validator set, and would be reconsidered as the chain matures and wants tighter uptime guarantees. The operational read, the one that feeds the paired Ops lesson, is that the watchdog's page threshold should sit far below twenty-seven thousand misses, somewhere around a thousand to two thousand, so the operator is woken with hours of margin rather than minutes. The parameters set the chain's tolerance; the monitoring threshold is the operator's much tighter private tolerance inside it.
§ VIConnection to Today's Ops and Dev Lessons
The Ops lesson watches three things, and §II of this lesson is what those three things are made of at the protocol level. The missed-block meter the Ops lesson polls is reading the missed_blocks_counter field this module maintains. The jail event it catches is the jailed flag and jailed_until timestamp this module sets. The unjail gate it describes is the MsgUnjail path and its checks. The Ops lesson treats these as an interface; this lesson shows the implementation behind the interface, so the operator who tunes a watchdog threshold knows exactly what counter the threshold is comparing against.
The Dev lesson's auto-unjail guard maps onto the protocol's deliberate refusal to auto-unjail. The protocol forces a manual MsgUnjail precisely because an automatic return against an unhealthy validator re-jails in a loop, and the Bash guard's confirm-caught-up-then-unjail ordering is the operator-side enforcement of the same principle the protocol enforces by requiring the manual message. The script and the protocol agree: returning a broken validator to the set is worse than leaving it out a little longer.
§ VIIPractice Questions
signed_blocks_window of ten thousand and min_signed_per_window of five-hundredths. Is it jailed?MsgUnjail rather than auto-unjailing once jailed_until passes?signed_blocks_window while holding min_signed_per_window fixed at five percent. How does each validator's absolute miss-tolerance change, and what is the trade-off?x/slashing itself on every block, by checking whether the validator's signature appears in the block commit and updating the missed-block counter, with no external transaction involved. A double-sign is detected from an x/evidence submission that any node can broadcast, carrying the two conflicting signed votes. One is a self-driven counter; the other is third-party-submitted evidence.§ VIIIClosing
A Cosmos validator lives or dies by two numbers a third party set in governance and a counter the chain updates on every block. The signed_blocks_window decides how long absence is remembered, the min_signed_per_window decides how much absence is tolerated, and the missed_blocks_counter against the derived threshold decides, block by block, whether the validator stays in the set. Learn to read a chain's liveness parameters as a policy statement rather than as defaults, and learn the one field that separates the recoverable jail from the permanent tombstone. Study the MsgUnjail checks until it is obvious why the protocol refuses to bring a validator back without a human saying it is ready.
Paired Ops → δ-Chain/Synthesis-Lessons/2026-06-20-validator-liveness-monitoring-and-the-downtime-slashing-defense
Paired Dev → Polyglot-Dev/Bash/2026-06-20-bash-for-validator-liveness-watchdogs-polling-the-sign-info-endpoint-missed-block-threshold-alerting-and-the-idempotent-auto-unjail-guard
Cert-Prep Lesson · Interchain Dev (Cosmos) · 2026-06-20 · ROD v3