sumeragi.md
May 5, 2026 · View on GitHub
Sumeragi: Current Implementation (v1)
For a granular view of the remaining migration work, see
sumeragi_npos_task_breakdown.md.
Overview
- Roles and rotation: the ordered topology partitions peers into roles —
Leader,ValidatingPeer,ProxyTail, andSetBValidator. Before each leader selection, the roster is canonicalized by sorting peer IDs to keep ordering deterministic across nodes. In permissioned mode the roster is deterministically shuffled per block height using PRF(seed, height) (seeded by the epoch PRF/VRF state), and view changes rotate the shuffled topology to advance the leader; previous-block-hash rotation is no longer used for leader selection. In NPoS mode the active validator roster is canonicalized (sorted) before PRF leader selection so signer indices remain consistent across peers, and the PRF-derived leader index rotates the view-aligned topology so signatures and collectors agree on who is index 0.rotated_for_prev_block_hash(prev_hash)innetwork_topology.rsremains as a legacy deterministic helper. - Fault tolerance and quorum: for validator roster size
n, the runtime derivesf = floor((n-1)/3)and uses commit quorum2f+1forn >= 4(seecommit_quorum_from_leninnetwork_topology.rs); forn <= 3the quorum isn(all validators). Set A is alwaysmin_votes_for_commit(); to changef, adjust the validator roster size viatrusted_peersor the NPoS stake roster. - K‑collector mode: per height/view, the topology designates K collectors via PRF selection from the canonical roster, excluding the leader. When a PRF seed is unavailable, the system falls back to the wraparound slice starting at
proxy_tail_index()(inclusive), skipping the leader and filling at least the commit quorum size (bounded by non-leader peers). Setting K=1 selects a single PRF collector; when PRF is unavailable the fallback still fills at least the commit quorum (starting at the proxy tail). Validators can also send commit votes to a small parallel topology fanout (collectors.parallel_topology_fanout) to reduce collector hop latency. - Commit certificates: validators sign the block header and send a
CommitVoteto the deterministic collector set (PRF-selected, excluding the leader); when collectors are disabled or local-only, votes fall back to the full commit topology. Any collector that reaches quorum (2f+1 in permissioned mode, or ≥2/3 total stake in NPoS) gossips aCommitCertificate; peers commit on the certificate + payload. Prepare/NewView certificates and availability evidence remain for pacemaker/telemetry but do not gate commit.
Safety and Liveness (Proof Sketch)
This is a proof sketch for the current v1 implementation (not a formal proof).
It summarizes the invariants enforced by the code paths in
crates/iroha_core/src/sumeragi/main_loop/{proposal_handlers,commit,qc,votes}.rs.
Assumptions (both modes)
- Partial synchrony after GST (eventual bounded message delays).
- Cryptography is secure (BLS signatures unforgeable; hash functions collision resistant).
- Deterministic roster selection and view alignment are consistent across honest peers.
- Payload dissemination eventually succeeds (BlockCreated + block sync and/or RBC).
Safety (permissioned)
- Quorum intersection: for
n = 3f+1, the commit quorum is2f+1; any two quorums intersect in at leastf+1validators, so at least one honest validator is in the intersection. - Single-vote rule: a validator records at most one commit vote per
(height, view, epoch)and will not sign a conflicting block at the same height/view (seeemit_precommit_vote). - Locked-QC rule: a validator only accepts proposals and emits votes that extend the locked
QC (
qc_extends_locked_with_lookup), preventing honest validators from signing conflicting chains once they are locked. - Therefore, two conflicting commit certificates at the same height would require an honest validator to sign both branches, which is excluded by the single-vote + locked-QC rules.
Safety (NPoS)
- Quorum is defined by stake: a commit QC requires ≥2/3 of total stake in the active roster
(
stake_quorum_reached_for_peers). - If <1/3 of stake is Byzantine, any two ≥2/3 stake quorums intersect in >1/3 stake that must include honest validators.
- The same single-vote and locked-QC rules apply, so honest stake will not sign conflicting branches at the same height/view, ruling out two conflicting commit certificates.
Liveness (permissioned)
- The pacemaker advances views on timeouts and missing-payload/validation failures; view
changes are monotonically increasing for a height (see
trigger_view_change_with_cause). - Once the network is synchronous and an honest leader is selected for a view, proposals and
commit votes propagate to collectors/topology;
2f+1votes produce a commit QC and the block is committed when the payload is available. - If payloads are missing, block sync/RBC recovery retries; persistent failure triggers a view change, ensuring the protocol does not stall on a single leader or payload.
Liveness (NPoS)
- The pacemaker logic is the same, but commit QCs require ≥2/3 stake; liveness holds when ≥2/3 of stake (by the active roster) is online and able to exchange votes.
- Deterministic PRF leader selection plus view changes ensure that an honest leader is eventually chosen after GST, allowing a commit QC to form.
DA/RBC note
- Data availability is tracked and recovered (RBC + block sync), but commit does not wait for availability evidence; it only requires the local payload. Missing payloads are handled by retries and view changes so the protocol keeps making progress.
NPoS mode configuration (operators)
- Choose the roster source.
sumeragi.npos.use_stake_snapshot_roster = truetells the validator to hydrate the epoch roster from the staking snapshot provider (required for production NPoS). Leaving itfalsecontinues to mirrortrusted_peersso small devnets can stage upgrades without the staking sidecar. When stake records are missing for some roster peers, NPoS assigns the minimum self-bond (or 1 when unset) to the missing entries; if no public-lane stake records exist, every roster peer receives the same fallback stake for quorum checks. If the commit topology omits active validators, the epoch roster widens to include the active set before filtering so validator elections and quorum checks retain the full active roster. - Define epoch cadence.
sumeragi.npos.epoch_length_blockscontrols how long a validator set lives. Within each epoch,sumeragi.npos.vrf.commit_window_blocksand.reveal_window_blocksfence the VRF commit/reveal RPCs (when omitted, VRF windows and deadlines are derived fromepoch_length_blocks), and the on-chainSumeragiParameters.block_time_mstarget (scaled bypacing_factor_bps) informs telemetry dashboards and the pacemaker expectation. Whensumeragi_npos_parametersis present on-chain (genesis or governance), its collector fan-out,epoch_length_blocks, VRF commit/reveal windows, and election/reconfig knobs are authoritative and override the local config values. Pacemaker timeouts are derived fromSumeragiParameters.block_time_msscaled bypacing_factor_bps(basis points, >= 10_000), clamped bymin_finality_ms, plus anysumeragi.advanced.npos.timeoutsoverrides. - Calibrate collector fan-out.
sumeragi.collectors.kdecides how many collectors assemble votes per slot.sumeragi.collectors.redundant_send_rcaps how many additional collectors a validator targets when local timeouts expire.sumeragi.collectors.parallel_topology_fanoutadds a small topology fanout alongside collectors to reduce hop latency (0 disables).sumeragi.advanced.npos.timeouts.*_msprovide the per-phase pacemaker budget (proposal, prevote, precommit, commit, DA, aggregator). These values are milliseconds in the user config and are mirrored directly into the runtime;exec/witnesstimeouts remain reserved for future witness pacing and do not influence the pacemaker today. Unset fields derive from the on-chain effective block time (SumeragiParameters.block_time_msscaled bypacing_factor_bps).
- Record election and reconfiguration policy.
sumeragi.npos.election.*sets self‑bond minimums and the guardrails for nominator concentration, seat variance, and validator correlation.sumeragi.npos.reconfig.{evidence_horizon_blocks,activation_lag_blocks,slashing_delay_blocks}govern how long evidence is retained, how long it takes for a newly scheduled validator set to activate, and how long consensus slashing is delayed before it applies.
Minimal TOML scaffold:
[sumeragi]
consensus_mode = "npos"
[sumeragi.collectors]
k = 3
redundant_send_r = 3 # example for 4 validators (2f+1)
[sumeragi.npos]
epoch_length_blocks = 7200
use_stake_snapshot_roster = true
# advanced.npos.timeouts.*_ms derive from the effective block time when omitted
## Optional: override derived VRF windows.
#[sumeragi.npos.vrf]
# commit_window_blocks = 120
# reveal_window_blocks = 60
[sumeragi.npos.election]
min_self_bond = 10_000
max_nominator_concentration_pct = 20
seat_band_pct = 10
max_entity_correlation_pct = 25
[sumeragi.npos.reconfig]
evidence_horizon_blocks = 7200
activation_lag_blocks = 1
slashing_delay_blocks = 259200
The same knobs exist in iroha_config::parameters::actual, so runtime overrides and the /configuration surface use the exact field names referenced above.
Configuration audit & evidence
iroha --output-format text ops sumeragi paramsprints the effectiveconsensus_mode, stake-roster toggle, epoch length, and collector knobs that the binary loaded. Capture the output (with timestamp + peer id) before enabling traffic so release packets can prove which consensus mode was activated.iroha --output-format json ops sumeragi params > artifacts/sumeragi-params-<height>.jsonemits the raw Norito-parsed structure, including nestedsumeragi.npos.*fields. Store this alongside theconfig.tomlthat was deployed so audits can diff the intent vs. runtime configuration without scraping logs.curl -s "$TORII/v1/configuration" | jq '.sumeragi'(orGET /v1/configurationvia the SDKToriiClient.getConfiguration) returns the live parameters as seen by Torii. Compare the JSON stanza across validators to ensure the sameconsensus_mode, redundant-send policy, and epoch cadence are in effect everywhere before declaring the lane healthy.- Record the evidence bundle inside your lane hand-off (CLI summary,
/configurationsnapshot, and the signed config file). Governance requires these attachments before approving an NPoS cut-over, and the artefacts double as rollback proof whenever parameters change.
Operator readiness checklist (NPoS)
- Confirm configuration — run
iroha --output-format text ops sumeragi params(or inspect/configuration) before rolling validators. The summary prints the liveconsensus_mode, stake-roster toggle, epoch length, and collector knobs so you can prove the binary loadednposwith the intended redundancy (redundant_send_r). Capture the output in the lane hand-off packet. - Check runtime state —
iroha --output-format text ops sumeragi statusexposes the active leader/view, epoch tuple, RBC backlog, DA retry counters, and pacemaker deferrals. Pair it withiroha --output-format text ops sumeragi collectorsto show which peers are acting as collectors on the current height, andiroha --output-format text ops sumeragi rbc statusto confirm RBC sessions and throughput match expectations before enabling external traffic. - Validate randomness & evidence — follow {doc}
sumeragi_randomness_evidence_runbookto pull the VRF epoch snapshot (iroha ops sumeragi vrf-epoch --epoch <height>), enumerate penalties (iroha ops sumeragi vrf-penalties --epoch <height>), and record the telemetry gauges (sumeragi_vrf_commits_emitted_total,sumeragi_vrf_reveals_late_total,sumeragi_vrf_non_reveal_penalties_total,sumeragi_vrf_no_participation_total, etc.). The runbook also covers/v1/sumeragi/evidence{,/count}and the CLI wrappers so NPoS slashing evidence is mirrored into the GA bundle. - Archive evidence — every readiness rehearsal must attach the CLI summaries, JSON snapshots, and SSE capture referenced in the runbook plus the generated Markdown reports (
docs/source/generated/sumeragi_*_report.md). Keep the artefact directory path recorded instatus.mdanddocs/source/project_tracker/npos_sumeragi_phase_a.mdso governance reviewers can re-download the same run.
Mode selection validation flow
Operators must prove every validator actually booted into npos before the lane
accepts traffic:
- Run
iroha --output-format json ops sumeragi params > artifacts/<lane>/mode_check.jsonimmediately after restarting each peer. Compare the capturedconsensus_mode,use_stake_snapshot_roster,k_aggregators, andredundant_send_rvalues against the hand-off manifest; mismatches require redeploying the config or re-running genesis. - Capture
iroha --output-format text ops sumeragi status(and optionallyiroha --output-format json ops sumeragi status > artifacts/<lane>/status.json) to prove the pacemaker view matches the intended epoch and that RBC backlog/backpressure counters are zero before opening Torii to clients. - Query
/v1/statusand/v1/sumeragi/statusviacurl -s "$TORII/status"and archive the payload in the same artefact directory. The JSON includes the VRF commit/reveal schedule andprf_epoch_seed; store it alongside the CLI output so auditors can cross-check the CLI and HTTP surfaces. - Keep the artefacts under version control (or a signed object store) next to the chaos/performance captures referenced later in this document. Doing so satisfies the roadmap requirement for deterministic evidence of mode selection without adding a separate runbook.
Telemetry, metrics, and evidence checkpoints
/v1/sumeragi/statusnow reportscommit_quorum/commit_qcsummaries alongsideworker_loop.queue_diagnostics(blocked/dropped enqueues per queue),dedup_evictions,bg_post_drop_{post,broadcast}_total, andcommit_inflight(active commit id/height/view, elapsed/timeout, and pause/resume queue depths) so stalled commit jobs and channel backpressure are visible without log scraping./v1/sumeragi/statusincludes the effective timing snapshot (effective_min_finality_ms,effective_block_time_ms,effective_commit_time_ms,effective_pacing_factor_bps, andeffective_npos_timeoutsin NPoS) so operators can validate on-chain timing and scaling in one place./v1/sumeragi/commit_qc/{hash}returns the full commit QC record (when available), includingparent_state_root,post_state_root, and the aggregate signature payload needed for independent verification.- Prometheus metrics provide the same signals for fleet monitoring:
sumeragi_epoch_length_blocks,sumeragi_epoch_commit_deadline_offset,sumeragi_epoch_reveal_deadline_offset— confirm the node loaded the intended VRF schedule.sumeragi_prf_epoch_seed_hex— last seed published by the VRF pipeline (pairs with/v1/sumeragi/status.prf_epoch_seed).sumeragi_npos_collector_selected_totalandsumeragi_npos_collector_assignments_by_idx{collector_idx}— sanity check collector rotation.
sumeragi_da_gate_block_total{reason}andsumeragi_rbc_da_reschedule_total— monitor DA availability warnings on missing local payloads; reschedule counters are legacy and should remain zero now that DA is advisory.sumeragi_missing_block_fetch_total{outcome}plussumeragi_missing_block_fetch_target_total{target="signers|topology|none"}confirm missing-block fetch cadence and whether signer targeting fell back to the full topology.sumeragi_rbc_store_pressure,sumeragi_rbc_backpressure_deferrals_total,sumeragi_rbc_persist_drops_total,sumeragi_rbc_store_evictions_total, and the per‑dataspace gauges (sumeragi_rbc_dataspace_*) — highlight on‑disk RBC congestion.mode_tag,staged_mode_tag,staged_mode_activation_height, andmode_activation_lag_blocks(also exposed via/v1/sumeragi/status) surface staged flips; non-zero lag means the activation height passed but the runtime mode hasn’t flipped yet and should trigger an alert.- Live cutover guardrails:
mode_flip_kill_switchmirrorssumeragi.mode_flip_enabled;mode_flip_blockedplus the{success,failure,blocked}_totalcounters,last_mode_flip_timestamp_ms, andlast_mode_flip_errorshow whether the node applied or rejected the staged flip. When the kill switch is false the node keeps exporting the staged mode but refuses to flip until the switch is restored. - Runtime flips are deferred while a commit is in flight or a pending block is actively processing;
mode_flip_blockedrecordspending_processing/commit_inflightto explain the lag until the pipeline drains. - Runtime flips flush mode-sensitive caches (pending blocks/RBC sessions/certificate and proposal caches) and reset pacemaker/view-change trackers to the base pacemaker interval at flip time so post-flip timers/leaders are recomputed deterministically.
sumeragi_rbc_deliver_defer_{ready,chunks}_totaland the/v1/sumeragi/status.pending_rbc+rbc_backlogsnapshots expose READY quorum vs chunk-gate stalls, stash totals by reason (pending_rbc.stash_*), stash age/drops, and pending session counts so dashboards can alarm on stuck RBC sessions before DA/commit stalls.sumeragi_rbc_mismatch_total{peer,kind}and/v1/sumeragi/status.rbc_mismatchtrack per-peer chunk digest/payload hash/chunk root mismatches; mismatched payloads are dropped (no penalties) and logs are throttled per peer/kind to keep behavior deterministic.sumeragi_consensus_message_handling_total{kind,outcome,reason}and/v1/sumeragi/status.consensus_message_handlingcapture drop/deferral reasons for BlockCreated, BlockSyncUpdate, ProposalHint, Proposal, QcVote, Qc, VrfCommit, VrfReveal, ExecWitness, RbcInit, RbcChunk, RbcReady, RbcDeliver, FetchPendingBlock, and Evidence to triage missing-payload warnings and backpressure drops.
- Block-sync roster telemetry:
/v1/sumeragi/status.block_sync_roster(Norito) and/v1/sumeragi/status.block_sync.roster(JSON) expose drop counters (drop_missing_total,drop_unsolicited_share_blocks_total) plus source gauges (commit_roster_journal,roster_sidecar, pairedcommit+checkpointhints, single cert/checkpoint history). Prometheus mirrors the same labels viasumeragi_block_sync_roster_source_total{source}andsumeragi_block_sync_roster_drop_total{reason}, and counts dropped unsolicited ShareBlocks viasumeragi_block_sync_share_blocks_unsolicited_total. Roster selection orders persisted snapshots (journal → sidecar) ahead of hints/history, and rejectsBlockSyncUpdatepayloads unless they carry a certified roster (commit certificate and/or validator checkpoint). Validator checkpoints embed the view index plus parent/post state roots in the signed preimage, so they validate without requiring commit-QC history. In NPoS, commit-certificate validation prefers a matching stake snapshot; when one is missing it derives a deterministic snapshot from local stake records (falling back to the minimum self-bond for missing peers) and only drops hints on roster or snapshot mismatch. Cached precommit signer records carry the stake snapshot so locally derived block-sync QCs still satisfy stake quorum. Block-sync share responses now propagate roster metadata so fresh peers can verify updates without waiting on local snapshots. Missing-block payload hydration usesBlockCreatedreplies instead of block-sync updates, removing the need for uncertified roster sources. Config parsing rejects incomplete PoP maps; if a mismatch still slips through, PoP filtering is skipped and the BLS baseline roster is used to avoid divergent topologies. - View-change causes:
/v1/sumeragi/status.view_change_causesreports per-cause counters (commit failure/quorum timeout/stake quorum timeout/censorship evidence/missing payload/missing commit certificate (missing_qc_total)/validation reject; DA availability is reserved for compatibility) and the last labeled timestamp to help operators triage view changes; Prometheus mirrors these timestamps insumeragi_view_change_cause_last_timestamp_ms{cause}. - Pending-block replay: after a view change installs, the leader rebroadcasts the highest pending
BlockCreatedpayload on a cadence derived fromblock_time(small floor, 2x base multiplier for >=1s block times, 1x for sub-1s, plus the 2x payload multiplier) so peers missing the payload hydrate without waiting for hints/sidecars. - View-change pruning: once a higher view is installed for a height, stale pending blocks/RBC sessions/missing-block requests for lower views of that height are dropped to prevent rebroadcast storms; missing payloads are re-requested only for the active view.
- Validation gate rejects:
/v1/sumeragi/status.validation_rejectssurfaces totals by reason plus the last rejected block hash/height/view/reason/timestamp. Prometheus mirrors the rejects viasumeragi_validation_reject_total{reason}with gaugessumeragi_validation_reject_last_reason,_last_height,_last_view, and_last_timestamp_ms(all zero when unset) so alerts can distinguish stateless vs execution vs prev-hash/height/topology failures before voting. - Evidence helpers:
/v1/sumeragi/evidence,/v1/sumeragi/evidence/count, and/v1/sumeragi/evidence/submitcarry the same DTOs surfaced in the JS/Python SDKs, so the CLI and automation can inspect or upload observer/fault evidence without recomputing payload formats.- View‑change telemetry is mirrored via
view_change_proof_{accepted,stale,rejected}_total;/v1/sumeragi/statusexposes the same counters for ad‑hoc audits.
Quick reference
| Surface | Signal | Expectation | Operator action |
|---|---|---|---|
CLI iroha --output-format text ops sumeragi params | consensus_mode, block_time_ms, commit_time_ms, min_finality_ms, pacing_factor_bps, k_aggregators, redundant_send_r, VRF windows | Match governance manifest; only change via tracked config updates | Re-deploy config or regenerate genesis when values drift |
CLI iroha --output-format text ops sumeragi collectors / HTTP /v1/sumeragi/collectors | Collector indices, epoch/view tuple, k_aggregators slice | Current collectors rotate deterministically; no gaps or duplicate indices | If a peer is missing or duplicated, re-run the staking snapshot sync, verify epoch_length_blocks, and restart collectors after confirming randomness evidence |
CLI iroha --output-format text ops sumeragi vrf-epoch, iroha --output-format text ops sumeragi vrf-penalties | finalized=true, participant count equals roster size, penalty lists reflect drills only | Every epoch emits a seed and penalty set that matches the staking roster/governance intent | When counts drift or unexpected penalties appear, follow {doc}sumeragi_randomness_evidence_runbook to resubmit commits/reveals and capture artefacts for governance |
| Prometheus | sumeragi_phase_latency_ms{phase="commit"} and phase-specific histograms | P95 < 0.8 * sumeragi.advanced.npos.timeouts.<phase>_ms | Trigger chaos harness + perf runbook if exceeded; investigate collector fan-out |
| Prometheus | sumeragi_da_gate_block_total{reason="missing_local_data"}, sumeragi_rbc_store_evictions_total, sumeragi_rbc_persist_drops_total | Flat line in steady state; spikes indicate missing local payloads or RBC churn | Verify BlockCreated delivery/RBC backlog, then capture artefacts |
| Prometheus | sumeragi_vrf_no_participation_total, sumeragi_vrf_reveals_late_total | 0 outside planned drills | Follow {doc}sumeragi_randomness_evidence_runbook; page affected validators |
HTTP /v1/sumeragi/evidence/count and CLI iroha ops sumeragi evidence count | Monotonic growth when faults occur; zero drift between peers | If counts diverge, re-run evidence submit/list checks and inspect Alertmanager snapshots |
Troubleshooting checklist
- Epoch/VRF drift: If collectors or leaders look stuck, compare the operator intent with
sumeragi_epoch_length_blocksandsumeragi_prf_epoch_seed_hex. A zero epoch length indicates the node never switched into NPoS mode.- Capture
iroha --output-format text ops sumeragi paramsplus/v1/status. - Diff the values against the governance manifest and the most recent
mode_check.json. - Restart the peer with the corrected config and re-run the validation flow above.
- Capture
- RBC or DA bottlenecks: Spikes in
sumeragi_da_gate_block_total{reason="missing_local_data"}orstatus.rbc_store.pressure_level > 0mean payload recovery is lagging (consensus continues, but DA payloads are missing locally). Confirmsumeragi.collectors.redundant_send_rand the DA timeouts are sized for the hardware, then inspect/v1/sumeragi/rbc/sessionsfor the offending chunk.- Use
iroha --output-format text ops sumeragi rbc statusto capture backlog depth. - Fetch
/v1/sumeragi/rbc/sessionsto identify the stuck height/hash pair. - Increase redundancy (
sumeragi.collectors.redundant_send_r) temporarily, restart impacted collectors, and attach the run’ssummary.jsonartefact to the incident report.
- Use
- View-change storms: Rising
view_change_proof_rejected_totalorgossip_fallback_totalusually trace back to mismatched VRF windows or collectors. Cross-check the VRF commit/reveal windows andepoch_commit_deadline_offset/epoch_reveal_deadline_offset.- Poll
iroha --output-format text ops sumeragi vrf-epoch --epoch <current>to verify the recorded windows. - Confirm
/v1/sumeragi/collectorsmatches the expected roster, then run the VRF portion of the randomness runbook.
- Poll
- Roster activation delays: When slashing or onboarding validators,
view_change_proof_accepted_totalshould continue increasing. If not, verifysumeragi.npos.reconfig.activation_lag_blocks, confirm the governance evidence is visible via/v1/sumeragi/evidence, and account for thesumeragi.npos.reconfig.slashing_delay_blockswindow.- Use
iroha --output-format text ops sumeragi evidence listto confirm the slashing payload propagated. - Inspect
/v1/sumeragi/status.mode_activation_lag_blocksto ensure the window has elapsed. - Confirm
slashing_delay_blocksiniroha --output-format text ops sumeragi paramsand whether governance cancelled the penalty before the delay expires. - Only re-run admission once both checks succeed; otherwise escalate governance/persistence issues.
- Use
- Evidence ingestion stalls: Diverging
iroha ops sumeragi evidence countoutputs or a flatsumeragi_evidence_records_totaltime series indicates the HTTP ingest path is failing.- Compare
evidence countacross at least two validators. - Tail the Torii logs for
/v1/sumeragi/evidence/submiterrors and re-submit a known fixture. - If the retry also fails, capture the
countoutput and Alertmanager silence IDs, then roll back to the last known-good build.
- Compare
Node Roles (config)
validator(default): participates in consensus according to its current topology role.observer: excluded from the consensus topology (role becomesUndefined); does not propose, vote, or collect even if its position would otherwise be a collector. It fully syncs via block gossip and can commit using received commit certificates.- Observers listed in
trusted_peersremain in the P2P dial set so they keep receiving gossip and block sync, but they never enter the consensus roster. - Note: Set B validators remain in the topology and are full validators; they are not the
observerrole.
- Observers listed in
Validator Key Requirements
- Validators must use BLS-Normal public keys and present a proof-of-possession (PoP). In NPoS, the consensus roster is filtered to the active public-lane validator set whenever stake records are available (including after commit-topology updates); if the commit topology omits active validators, the roster is widened with the active set before PoP filtering so the full validator set participates. When no active validators are present it falls back to
trusted_peersafter filtering out peers without BLS-Normal keys (the legacytrusted_peers_blsmapping no longer exists). Iftrusted_peers_popis empty, the BLS trusted-peer set remains the validator roster. Whentrusted_peers_popis present, it defines the validator subset among trusted BLS peers: peers with valid PoPs participate in consensus, while trusted peers without PoPs remain network-trusted observers and are excluded from consensus. Invalid PoP entries are rejected, non-BLS peers are always excluded, and the nodepublic_key/private_keypair must be BLS-Normal for transport and consensus. - Commit certificates carry a mandatory BLS aggregate signature over same-message signatures, along with a compact signer bitmap. Receivers verify the aggregate signature against the signer set and reject certificates with mismatched aggregates or out-of-range bitmap bits. Explicit votes remain the source of truth for quorum accounting and evidence, but aggregates are no longer advisory.
- Transaction admission uses
crypto.allowed_signing/allowed_curve_ids; consensus vote signatures do not. Leavingallowed_signingat the Ed25519/secp defaults is fine for BLS validators—addbls_normalonly if you intend to accept BLS-signed transactions. The BLS feature must be compiled in (--features bls) andsignature_batch_max_blskept > 0 for validator nodes.
Message Flow (steady state)
- Leader: when a block is expected (transactions queued) and the deadline elapses, the leader sends
BlockCreatedto the commit topology (validators); when there is no queued work the pacemaker stays idle (no heartbeat proposals). - Proposal assembly defers when consensus block-payload/RBC chunk queues are saturated, when relay backpressure is active, when unresolved RBC sessions exist for the active tip, when the highest QC block is missing locally (it first schedules a missing-block fetch using QC-history rosters if needed), or when pending blocks extend the tip and have not been quorum-rescheduled; if no proposal is observed, the liveness override uses
min(commit_quorum_timeout, 4 * propose_interval)to allow proposals/view changes, and once a proposal is seen it waits the full commit quorum timeout before overriding backlog. Idle view-change fallbacks pause while a commit is inflight so local execution cannot be preempted by a new view. - Validators: validate, emit Availability votes, and send
CommitVote(block header signature) to the deterministic collector set; votes fall back to the full commit topology only when collectors are disabled or local-only. Prepare/NewView certificates remain for pacemaker/telemetry but do not gate commit. On local timeout in view 0, the node may fan out to additional collectors up tor, plus any configured parallel topology fanout. - Collectors: collectors aggregate
CommitVotesignatures and gossip aCommitCertificateonce quorum is reached; collector ordering is PRF-derived per height/view (leader excluded) with fallback to the full commit topology only when collectors are disabled or local-only. Collectors may still aggregate availability evidence and prepare/new-view certificates for view-change hints. - Set B validators: vote/sign under the same rules as Set A; routing/collection still prioritizes Set A for throughput, but any quorum of validators is accepted.
- Receivers: verify
CommitCertificate, update highest/locked QC tracking (highest_qc/locked_qcfields), and attempt commit whenever the certificate and block payload are present. If a certificate arrives before the payload, peers request the missing block via block sync (signer-first with topology fallback), retry on the rebroadcast cadence (block-time aligned), and force a view change after the missing-payload window (quorum timeout) so consensus does not stall indefinitely. Missing-payload dwell tracking is scoped to the current view, so when the view advances the dwell window resets and a still-missing payload can trigger another view change; locally retained payloads (including aborted pending payloads in DA mode) suppress redundant missing-block fetches to prevent view-change churn. Once a block commits, outstanding missing-block requests at or below that height are cleared as obsolete (including conflicting hashes) so stale retries do not accumulate. Missing-block fetches can also come from RBC reconstruction or missing-parent detection; consensus-priority requests override background windows, but background requests can still trigger a view change when a one-block gap persists. - Missing-parent recovery: if a block arrives ahead of local height and its parent is unknown, peers request the parent immediately and sweep pending gaps; when the gap is exactly one height the request arms the view-change window, while larger gaps keep retrying without forcing a view change while the node catches up.
- Block-sync updates: peers gossip
BlockSyncUpdatepayloads to a capped fanout (block_gossip_size) after commits and for vote/backfill so stragglers and observers can sync without relying on full broadcast. Updates are only broadcast when they carry verifiable roster metadata (commit QC or validator checkpoint; in NPoS the roster evidence must include a matching stake snapshot or be derivable from local stake records); otherwise the sender falls back toBlockCreatedpayload broadcasts to avoid dropped updates. Validator checkpoints include the signed view index plus parent/post state roots so receivers can verify them without cached commit-QC roots. Receivers only apply block-sync payloads when they include commit evidence (commit quorum signatures, a validated commit QC/certificate, or a validator checkpoint), except for explicit permissioned missing-block requests: next-height requests can proceed with any valid signer, while farther-ahead requests still require commit-quorum signatures. To keep the main loop responsive, receivers process commit votes and missing-block bookkeeping immediately but defer the heavy roster/signature/block-validation path while commit or validation work is inflight, replaying the update once the pipeline is idle. Relay ingress enqueues updates with backpressure; when the block-payload queue is fullBlockSyncUpdatewaits for capacity instead of dropping, while other block messages remain best-effort and rely on rebroadcasts for retries. Attached availability evidence, prepare/new-view certificates, and commit certificates are only applied when their height and block hash match the payload; mismatches are ignored. In permissioned mode, commit QCs must also match the block header view before they can be treated as valid evidence. Block-sync share filtering only keeps commit QCs that pass full validation, so invalid QCs cannot bypass signature checks.ShareBlocksresponses are accepted only after aGetBlocksAfterrequest; unsolicited batches are dropped before they hit Sumeragi. Requests or responses that claim a differentpeer_idthan the transport sender are dropped at the relay. - Commit-conflict handling (strict finality): if a commit QC arrives for a different hash at an already-committed height, the node validates the QC and rejects it as conflicting finality. The local committed block is never rewound or replaced; the conflicting QC is treated as invalid and recorded/gossiped as
InvalidQcevidence (commit_conflict_finality) so operators/governance can slash/evict in a later epoch. - Availability votes: peers gossip
AvailabilityVoteframes to a capped fanout (block_gossip_size) so availability evidence can converge without full broadcast when collector routing is sparse. - View-change counters:
view_change_suggest_totalincrements when the local node triggers a view change (timeouts, missing payloads, validation rejects).view_change_install_totalincrements when the node installs a higher view for a height after observing higher-view traffic or its own triggers;view_change_indexreports the currently tracked view.
Commit rule (commit certificate)
- Each validator tracks
highest_qc/locked_qccertificate references for view-change safety (highest may be Prepare or Commit), but commits are driven byCommitCertificates rather than child certificates. - Validators sign the proposed block header and send
CommitVoteto the deterministic collector set; votes fall back to the full commit topology only when collectors are disabled or local-only. Any collector that reaches quorum aggregates2f+1signatures (permissioned) or ≥2/3 total stake (NPoS) into aCommitCertificateand gossips it. - A block finalises when a valid
CommitCertificatefor(height,hash)is available and the block payload is known locally. Peers that receive the certificate first request the payload via block sync and commit once it arrives. - Commit QCs always bind
parent_state_rootandpost_state_root; there is no separate execution QC gate. Whensumeragi.da.enabled=true, availability evidence is tracked but does not gate commit.
Pacemaker (view changes)
- View‑0 voting follows the same rules for Set A and Set B validators. On local timeout in view 0, nodes suggest a view change (no widen‑before‑rotate). Timing is driven by on‑chain parameters:
SumeragiParameters(BlockTimeMs/CommitTimeMs/MinFinalityMs/PacingFactorBps) set the base for both modes; the pacing factor scales the block/commit targets (basis points, >= 10_000), and NPoS derives per‑phase timeouts from the scaled block time with optionalsumeragi.advanced.npos.timeoutsoverrides. Leader proposal is roughly at 1/3 and expected commit at 2/3 of the pipeline time. - View-change proofs advance once
f+1validators raise suspicion (commit failure or quorum timeout); a full commit quorum is not required for a view change.
Deterministic pacing governor (always enabled)
- Config keys live under
sumeragi.advanced.pacing_governor. - Each block evaluates the last
window_blocksheaders and computes view-change pressure (average view-change index delta per block, permille) plus commit spacing pressure (average inter-block spacing vs target block time, permille). - If either pressure exceeds its threshold, increase
SumeragiParameters.pacing_factor_bpsbystep_up_bps. If both pressures fall below their clear thresholds, decrease bystep_down_bps. - Clamp
pacing_factor_bpsto[min_factor_bps, max_factor_bps](min >= 10_000). If a block explicitly setspacing_factor_bps, the governor skips that height. - Updates apply only at block boundaries and emit configuration events; the result is
deterministic because it is derived solely from committed headers. Monitor
effective_pacing_factor_bpsvia/v1/sumeragi/status.
K / r Parameters
- Config keys:
sumeragi.collectors.k: usize(collectors per height; default 1 in config) andsumeragi.collectors.redundant_send_r: u8(redundant send fanout; tooling may seed on-chain defaults as2f+1from the validator count, and the config fallback is 3 (2f+1 for 4 validators) when parameters are absent). - On-chain: K and r live in
SumeragiParametersand are authoritative for collector planning andConsensusParamsadverts; config values seed the genesis defaults. When peers advertise different K/r, the node logs a mismatch but keeps the on-chain values. - Fallbacks: if
kyields no collectors, votes fall back to the full commit topology;redundant_send_ris clamped to at least the commit quorum size (subject to the available collectors). - Determinism: primary/next collector order is a pure function of the canonical roster, PRF seed, and
(height, view); when the PRF seed is unavailable the fallback is the wraparound slice starting atproxy_tail_index()(skipping the leader) until at least commit quorum size, with no per-node randomness.
NPoS Tunables (sumeragi.npos.* + sumeragi.advanced.npos.timeouts.*)
advanced.npos.timeouts.{propose_ms, prevote_ms, precommit_ms, exec_ms, witness_ms, commit_ms, da_ms, aggregator_ms}(optional): each value must be > 0 when set. Unset fields derive from the on‑chain effective block time (SumeragiParameters.block_time_msscaled bypacing_factor_bps) using the 1s ratios350/450/550/150/150/850/750/120. The pacemaker currently consumes propose/collect_da/collect_prevote/collect_precommit/commit;exec_ms/witness_msare reserved for future witness pacing andcollect_aggregatorremains observability-only.- Collector fan-out is configured under
sumeragi.collectors.{k,redundant_send_r}(shared with permissioned). Both must be > 0; invalid values are rejected during config parsing. vrf.{commit_window_blocks, reveal_window_blocks}(optional): length of the commit and reveal windows inside an epoch; both must be > 0 when set. Unset values derive fromepoch_length_blocksusing the 3600-block ratios100/40.vrf.commit_deadline_offset_blocksdefaults tocommit_window_blocksandvrf.reveal_deadline_offset_blocksdefaults tocommit_window_blocks + reveal_window_blockswhen omitted.election.{min_self_bond, max_nominator_concentration_pct, seat_band_pct, max_entity_correlation_pct}with defaults1000,25,5, and25. Percentages are clamped to the 0–100 range, andmin_self_bondmust be > 0.- Candidates failing these staking constraints are excluded from the election; the entity correlation cap limits how many winners can share the same validator account.
election.finality_margin_blocksdelays activation of the newly elected roster until the chain has advanced by the configured number of blocks after the election snapshot, preventing premature swaps before finality.reconfig.{evidence_horizon_blocks, activation_lag_blocks, slashing_delay_blocks}default to7200,1, and259200. All three knobs must be > 0 to prevent unusable governance/evidence windows.- Joint-consensus staging guard: proposals must stage
next_modeandmode_activation_heighttogether; manifests and governance packets missing either field are rejected, block application fails if a block sets only one of them, and handshake fingerprints derive from the effective runtime mode (configured mode until the activation height, staged mode after crossing it). Capture both values in cutover runbooks so peers agree on the pre‑activation fingerprint and the post‑activation mode tag. The runtime error surfaces as:mode_activation_height requires next_mode to be set in the same block. - Configuration parsing now validates all tunables and produces a clear
Invalid Sumeragi consensus configurationerror if any constraint is violated (e.g., zero timeout or percentages above 100). Nodes will refuse to start with invalid NPoS settings rather than silently falling back.
Genesis manifests now seed Sumeragi::NextMode and the sumeragi_npos_parameters custom payload in the parameters block; normalization/signing injects the corresponding SetParameter instructions so the WSV persists, and Sumeragi loads, the live values during startup. Regenerate manifests via kagami genesis generate (add --consensus-mode npos for NPoS networks) to pick up the updated parameters and fingerprint.
Kagami NPoS devnets (local + Docker)
- Sora profile localnets use NPoS for the global merge ledger and disallow staged cutovers; run permissioned Iroha3 localnets without
--sora-profile. - Bare-metal (Iroha3 NPoS):
kagami localnet --peers 4 --out-dir ./npos-local --consensus-mode npos --seed demowrites genesis/configs/start scripts with BLS keys/PoPs and a stable NPoS fingerprint; start with./npos-local/start.sh. - Sora Nexus localnet:
kagami localnet --sora-profile nexus --peers 4 --out-dir ./sora-nexus-localgenerates a 4-node NPoS localnet and startsirohad --sorafor Nexus dataspaces. - Sora dataspace localnet:
kagami localnet --sora-profile dataspace --peers 4 --out-dir ./sora-ds-localkeeps Sora multi-lane defaults under NPoS; use--consensus-mode permissionedonly without--sora-profile. - Bare-metal (Iroha2 staged cutover):
kagami localnet --build-line iroha2 --peers 4 --out-dir ./npos-local --consensus-mode permissioned --next-consensus-mode npos --mode-activation-height 5 --seed demostages a permissioned→NPoS cutover at height 5 and keeps the advertised fingerprint on the permissioned mode until activation. - Localnet defaults to a fast 1s pipeline (block/commit split), shortens transaction gossip cadence (
transaction_gossip_period_ms = 100,transaction_gossip_resend_ticks = 1, target reshuffle cadence = 100ms), raisessumeragi.advanced.rbc.chunk_max_bytesto 256 KiB, lifts queue capacity to 262,144, setsnexus.fusion.exit_teu = 1,000,000andsumeragi.block.proposal_queue_scan_multiplier = 4to bound proposal assembly, relaxes Torii tx rate limiting (torii.tx_rate_per_authority_per_sec = 1,000,000,torii.tx_burst_per_authority = 2,000,000,torii.api_high_load_tx_threshold = 262,144), disables Kura fsync (kura.fsync_mode = "off"), clamps the pacing governor to 1.0x so effective block/commit timing stays aligned with the pipeline, and bumps redundant-send fanout when DA is enabled; for NPoS localnets it seeds XOR stake, activates validators in genesis, and rewritesSumeragiParameterstiming fields (block_time_ms,commit_time_ms) to match the selected pipeline. Override with--block-time-ms,--commit-time-ms, or--redundant-send-rif you need slower timings. When only one of the block/commit values is set, Kagami mirrors it to the other to keep the pipeline balanced; set both to decouple them. - Localnet soak (permissioned, thousands of blocks/tx):
cargo test -p integration_tests --test consensus_and_da sumeragi_localnet_smoke::permissioned_localnet_soak_thousands -- --ignored --exact --nocapture(long-running). - Docker Compose: point
--config-dirat the same localnet output and runkagami docker --peers 4 --config-dir ./npos-local --image hyperledger/iroha:dev --out-file docker-compose.npos.yml --consensus-mode npos --no-banner --printto emit a Compose file that re-signs genesis in-container withGENESIS_CONSENSUS_MODEoverrides (add theGENESIS_NEXT_CONSENSUS_MODE/GENESIS_MODE_ACTIVATION_HEIGHTpair only on Iroha2 staged networks). - Rosters/PoPs: re-sign custom topologies with
kagami genesis sign --topology '<peers_json>' --peer-pop <public_key=pop_hex>...(swarm’s inline signer accepts the same flags). Reuse the same--seedwhen regenerating localnet output so BLS/Ed25519 keys and PoPs stay deterministic for VRF sampling. - Genesis signing (NPoS): when no public-lane validators are present in the manifest,
kagami genesis signinjects a bootstrap transaction that registers the defaultnexus/ivmdomains, mintsxor#nexus, and stakes/activates each topology peer in the public lane. - Guardrails:
--mode-activation-heightrequires--next-consensus-mode(height > 0) and--consensus-modecontinues to advertise the pre‑activation mode for fingerprints; omit both flags to stay in the configured mode, or pair them to stage a permissioned→NPoS cutover on Iroha2 only.
Deterministic Collector Selection (helpers)
collector_indices_k(k) -> Vec<usize>: contiguous indices fromproxy_tail_index()up tok(no wraparound).collector_indices_k_fallback(k) -> Vec<usize>: wraparound indices fromproxy_tail_index()(skipping the leader) until at least commit quorum size, bounded by non-leader peers.collectors_k(k) -> Vec<&PeerId>: peer IDs for those indices.is_collector(peer, k) -> bool: membership test for collector duty at a given height.
Commit Certificate Content and Rotation Hint
- Commit certificates include the subject block hash, height/view/epoch, and a signer bitmap plus BLS-normal aggregate. For genesis NEW_VIEW frames, the highest certificate is a deterministic stub (zero bitmap, empty aggregate) accepted only when the hash matches the local genesis block. Receivers rotate their local topology to the certificate’s view before aggregate verification for deterministic checks.
Observer Fast‑Path (pending certificates)
- Observers retain commit certificates (phase
Commit) keyed by block hash; once the matching block body arrives via gossip/RBC they validate and wait for aCommitCertificatebefore finalizing.
Actor Model
- The Sumeragi main loop owns explicit subcomponents (commit, propose/pacemaker, DA/RBC, VRF, merge/lane relay) with isolated mutable state and focused helpers, while shared consensus state (pending blocks, certificate caches, locks) stays in the core actor.
Backpressure & Telemetry
- Scheduler: with
sumeragi.advanced.worker.parallel_ingress = true, per-queue worker threads feed a ticketed gate (one actor at a time, FIFO by ticket) instead of the single-thread priority mailbox; the priority mailbox (Votes → RBC chunks → blocks → block payloads → consensus control → lane relay → background) with starvation guards (non_vote_starve_max,block_rx_starve_max) is used only whenparallel_ingress = false. - Pre-tick drain is bounded by the next tick deadline (with a tick-min-gap grace when the deadline is immediate) so pacemaker ticks are not delayed by long queue backlogs; remaining messages drain after the tick within the iteration budget.
- Commit pipeline work runs on the tick path; inbound handlers only request a wakeup so heavy commit processing does not block mailbox drain. The tick path still runs on the max-gap cadence so commits continue without starving message drain.
- Pre-vote block validation is offloaded to background workers; the main loop schedules validation jobs and applies results on tick to keep drain latency bounded under backlog.
- Proposal,
BlockCreated,RbcInit, andRbcChunkbroadcasts bypass the background post queue and send inline so bulk RBC traffic cannot delay proposal delivery or chunk dissemination. - Drops: relay ingress uses non-blocking enqueues for block/control messages, so full queues drop and increment
sumeragi_dropped_block_messages_total/sumeragi_dropped_control_messages_total;BlockSyncUpdateplus proposal payloads (Proposal) bypass the non-blocking path and block until space is available in the block-payload queue to preserve commit/QC evidence and payload delivery, whileBlockCreated,FetchPendingBlock, andRbcInitblock on the block queue to avoid missing-block stalls. RBC READY/DELIVER also bypass the non-blocking path but are queued with votes to avoid payload backlog; they still travel on the high-priority consensus topic in the relay, while RBC chunks use the dedicatedConsensusChunktopic with low-priority P2P routing and best-effort ingress (drops are allowed when the chunk queue is saturated so relays do not stall). Blocking backpressure remains for explicitincoming_*calls (internal producers). When relay drops spike (subscriber queues full, network post/broadcast drops, per-peer post overflows, or topic-cap violations), consensus rebroadcasts (votes/block sync/RBC payloads) and idle view-change triggers pause for one rebroadcast cooldown to avoid message storms. Unresolved RBC payloads also pause proposal assembly (subject to the pacemaker RBC backlog soft limits); if no proposal arrives, idle view changes and backpressure overrides are bounded bymin(commit_quorum_timeout, 4 * propose_interval)so leader loss does not stall liveness. Consensus ingress guardrails still apply: standard caps cover regular consensus/control traffic, critical caps cover recovery/coordination and payload delivery (BlockCreated,FetchPendingBlock,ProposalHint,Proposal,QcVote,Qc,VrfCommit,VrfReveal,RbcInit,RbcReady,RbcDeliver, plus control-flow evidence) and skip penalty cooldowns, and bulk caps cover payload frames (BlockSyncUpdate,ExecWitness,RbcChunk,BlockSync) scaled by block_time vs 2s while tracking RBC session limits. Payload-topic drops are counted inconsensus_ingress_drop_total{topic,reason}withtopicin {ConsensusPayload,ConsensusChunk,BlockSync}. - Dedup caches: vote + block-payload/RBC chunk deduplication uses bounded LRU+TTL caches partitioned by message kind;
/v1/sumeragi/status.dedup_evictionsexposes capacity vs TTL evictions for votes, proposals, block-created, block-sync updates, RBC READY/DELIVER payloads, and RBC chunks. - Collector metrics: gauges for
collectors_k/redundant_send_r, counters for redundant sends (with per‑collector/per‑peer breakdowns), a gauge for collectors targeted in the current round, and a histogram for collectors targeted per committed block. Certificate size is tracked viasumeragi_cert_size. - Transaction queue backpressure:
sumeragi_tx_queue_depth/sumeragi_tx_queue_capacitygauge the mempool, whilesumeragi_tx_queue_saturatedflips to 1 when Torii reports saturation. When saturated, validators skip redundant collector fan-out (behaving asredundant_send_r = 1) to shed load and expedite commit of queued transactions. - Proposal assembly scans a bounded snapshot of the queue (derived from
max_in_block * sumeragi.block.proposal_queue_scan_multiplier) so sustained admission traffic cannot stall block creation; newly arrived transactions remain queued for the next proposal. - Fast-finality cap: when
effective_commit_time_ms <= 1000, proposal assembly clamps the gas budget tomin(ivm_gas_limit_per_block, sumeragi.block.fast_gas_limit_per_block)(optional) and selects transactions by gas to keep validation within a 1s finality budget. - Background post saturation:
sumeragi_bg_post_overflow_total{kind="Post|Broadcast"}increments when the bounded background-post queue is full; the sender does not block and can fall back to inline network posts.sumeragi_bg_post_drop_total{kind}and/v1/sumeragi/status.bg_post_drop_{post,broadcast}_totalcount drops when the queue is missing or disconnected. Sustained overflow suggests a slow background worker or network pressure; drops indicate lost network posts. - For deterministic testing (e.g., CI or chaos harnesses), set
sumeragi.debug.disable_background_worker = trueto disable the worker and dispatch background posts inline (synchronous, no extra thread, no queue drops). - READY gossip fallback:
gossip_fallback_totalstill records the number of collector plans that exhausted the deterministic fan-out and had to fall back to gossip broadcasts. Correlate with the background metrics above: if both are rising, the node is likely CPU or network bound and will delay RBC convergence. - See
docs/source/telemetry.mdand the README “Consensus metrics (Sumeragi)” section for metric names and example PromQL.
Consensus Parameter Advert (pinning)
- At startup and when collector plans refresh, nodes broadcast a compact
ConsensusParamsadvert carrying(collectors_k, redundant_send_r)plus the current membership snapshot{ height, view, epoch, view_hash }. The epoch is derived from the advertised height using the finalized VRF epoch schedule so epoch-length changes do not invalidate historical messages and replays across epoch boundaries remain deterministic. - Receivers verify the advert against their effective parameters and membership view hash. Mismatches increment the Prometheus counter
sumeragi_membership_mismatch_total{peer,height,view}and mark the offending peer insumeragi_membership_mismatch_active{peer}so operators can wire alerts directly. Any mismatch is logged and flagged locally; consensus semantics are unchanged. Effective values are taken from on‑chainSumeragiParameterswhen present (preferred over local config).
Configuration (example)
[sumeragi]
role = "validator" # or "observer" (sync-only)
consensus_mode = "permissioned"
[sumeragi.collectors]
k = 3 # three collectors per height
redundant_send_r = 3 # example for 4 validators (2f+1)
[sumeragi.advanced.queues]
votes = 8192 # vote channel capacity (commit votes + RBC READY/DELIVER)
block_payload = 128 # block payload capacity (Proposal/BlockSyncUpdate)
rbc_chunks = 1024 # RBC chunk capacity
blocks = 256 # block message capacity (BlockCreated/FetchPendingBlock/RbcInit/etc.)
control = 1024 # control/background/lane channel capacity
[sumeragi.advanced.worker]
iteration_budget_cap_ms = 2000 # cap worker loop time budget per iteration
iteration_drain_budget_cap_ms = 2000 # cap mailbox drain per iteration
tick_work_budget_cap_ms = 500 # cap per-tick proposal/commit work (0 disables)
parallel_ingress = true # run per-queue ingress threads with a ticketed gate
validation_worker_threads = 1 # pre-vote validation worker threads
validation_work_queue_cap = 4 # validation work queue per worker
validation_result_queue_cap = 4 # validation result queue
validation_pending_cap = 8192 # deferred vote-validation backlog cap
[sumeragi.advanced.pacemaker]
pending_stall_grace_ms = 250 # grace before pending progress counts as stalled
active_pending_soft_limit = 1 # allow proposals with <= N blocking pending blocks (0 = strict)
rbc_backlog_session_soft_limit = 8 # allow proposals with <= N backlog sessions (0 = strict)
rbc_backlog_chunk_soft_limit = 256 # allow proposals with <= N missing chunks (0 = strict)
[sumeragi.da]
enabled = true # enable DA + RBC; availability evidence tracked (commit does not wait)
[sumeragi.advanced.rbc]
chunk_fanout = null # RBC chunk fanout cap (null = full roster minus local)
[sumeragi.persistence]
kura_retry_interval_ms = 1000 # retry failed kura persistence with exponential backoff
kura_retry_max_attempts = 5 # abort and requeue the block payload after repeated failures
commit_inflight_timeout_ms = 30000
commit_work_queue_cap = 1 # commit worker queue capacity
commit_result_queue_cap = 1 # commit worker result queue capacity
[sumeragi.recovery]
missing_block_signer_fallback_attempts = 1 # fetch from certificate signers this many times, then try full topology
view_change_backlog_extension_factor = 1.5 # extend quorum-reschedule grace only when backlog signals are active
view_change_backlog_extension_cap_ms = 200 # max extra grace added by backlog extension logic
deferred_qc_ttl_ms = 2000 # missing-payload/deferred-QC TTL before forced fetch/escalation
[network]
deferred_send_ttl_ms = 1500 # drop deferred outbound frames after this age
deferred_send_max_per_peer = 256 # cap deferred outbound frames retained per peer
[sumeragi.gating]
membership_mismatch_alert_threshold = 1 # consecutive mismatches before alert/fail-closed
membership_mismatch_fail_closed = false # drop consensus messages from mismatched peers
Notes
- Consensus thresholds and signature validation are unchanged by K/r; only the set of eligible aggregators expands. With K=1, behavior matches the single‑collector path.
- All paths remain deterministic across hardware. BLS aggregation is over the same message and does not introduce non‑determinism; consensus accepts only certificates whose explicit signatures validate against the current topology.
- RBC READY/DELIVER quorum uses the commit topology’s
min_votes_for_commit(). - RBC INIT carries the session roster snapshot and its
roster_hash; READY/DELIVER include the sameroster_hashso signatures are bound to a single roster. - RBC INIT also carries the per‑chunk SHA‑256 digest list; receivers validate each chunk against the digest at its index and drop mismatches without invalidating the session.
- Per‑peer RBC mismatch counters (digest/payload/root) surface in
status.rbc_mismatchandsumeragi_rbc_mismatch_total{peer,kind}; mismatches are drop‑only (no penalties/quarantine) to preserve deterministic behavior, and mismatch logs are throttled per peer/kind. - RBC INIT that conflicts with an existing session’s payload hash, chunk count, digest list, or chunk root is dropped to avoid poisoning an in‑flight session.
- RBC sessions cache the roster from INIT as unverified until a derived commit-topology roster is available; derived rosters are authoritative for READY/DELIVER validation and local signing, and INIT rosters that conflict with a derived roster are rejected. In permissioned mode, if no derived roster can be computed yet (far-ahead heights), INIT rosters are treated as a provisional authority for READY/DELIVER so availability does not stall; derived rosters still supersede INIT snapshots once available.
- READY/DELIVER received before an authoritative roster is available are stashed, trigger missing
BlockCreatedfetches (falling back to the effective commit topology when needed), and replay once the derived roster is cached; mismatchedroster_hashvalues are dropped once an authoritative roster is cached, while derived roster mismatches trigger a fresh derived-roster lookup and are re-stashed until INIT arrives if the roster still mismatches, resetting cached READY/DELIVER state. Local READY/DELIVER emission waits for an authoritative roster and a chunk root unless permissioned fallback to INIT is active; READY/INIT rebroadcasts reuse the cached roster only when the roster hash matches to avoid liveness stalls. - When READY/DELIVER or chunks arrive before INIT, the node stashes them and immediately requests the missing
BlockCreatedpayload (subject to the missing-block backoff). If the session roster is empty, the request falls back to the effective commit topology. Missing-block responses in DA mode include RBC INIT + chunks so the requester can hydrate through the chunk queue; responders with an RBC session will serve INIT/chunks even if the full block is not yet available. - Empty payloads are represented as a single empty RBC chunk so sessions never advertise a zero chunk count.
- RBC chunk broadcasts pick a deterministic, per-session target set sized to at least the commit quorum; the default (
rbc_chunk_fanout = null) targets the full roster minus local so READY quorums can form even with f faulty peers. Payload rebroadcasts send cached chunks to the full roster to recover missed fanout. - RBC payload rebroadcasts and outbound chunk flushes pause while block-payload/RBC chunk queues are backpressured so the worker can drain before sending more chunks.
- When a block payload is known locally and the height remains in the current epoch, RBC may fall back to the active topology even if the height is ahead of the committed tip so READY quorum can form without waiting on roster snapshots.
- Idle view changes are suppressed while unresolved RBC backlog, relay backpressure, or consensus queue backpressure (block-payload/RBC chunk queues saturated) is active; the pacemaker resumes view-change timers once the backlog clears.
- Idle view-change timers reset when the transaction queue transitions from empty to non-empty so fresh work gets a full proposal window before leader rotation.
- RBC payload rebroadcasts always include INIT even when no chunks are cached once a roster snapshot is cached, so peers can learn the roster snapshot and request missing chunks; derived rosters may rebroadcast but remain guarded by roster-hash checks, the background rebroadcast loop does not synthesize roster snapshots on its own, cached chunks continue to rebroadcast while any chunks are still missing even after READY quorum is reached, and only a deterministic f+1 subset of the roster performs payload rebroadcasts per session to limit message storms.
- RBC READY rebroadcasts use the same deterministic f+1 sender subset (leader always included) to cap message volume; skipped rebroadcasts increment
sumeragi_rbc_rebroadcast_skipped_total{kind="payload|ready"}. - RBC payloads carry canonical block payload bytes only; if delivery completes before
BlockCreatedarrives, the node requests the signed block header/body from peers so validation and voting can proceed. - RBC INIT/READY/DELIVER must carry the epoch derived from the advertised height; mismatched epochs are rejected to prevent cross-epoch availability drift.
- RBC READY must reference the expected chunk root for the session; mismatched roots are rejected so quorum only counts votes for the same payload. When the expected root is missing, READY/DELIVER seed it from the message (validated against any computed root) so restored sessions still enforce root consistency.
- RBC DELIVER carries the sender-observed READY signature bundle (sender index + signature). Receivers validate and record those signatures to recover READY quorum when READY messages were missed.
- Persisted RBC sessions include the authoritative roster snapshot so restarts validate READY/DELIVER against the original topology even if the live roster changes; derived fallback rosters are not persisted.
- Vote/certificate signature checks use the roster snapshot tied to the block when available, falling back to the live commit topology so roster changes do not invalidate late votes or certificates; when the parent hash is known, history-derived rosters must match the known chain or the vote is dropped.
- When the commit topology changes at block commit, the node clears pending consensus caches (pending blocks, vote logs, RBC sessions, DA bundles) so stale votes from the old roster cannot stall the pipeline.
- Vote/QC/deferred/roster caches are pruned to a bounded height/view window around the active round to prevent unbounded growth during view-change storms.
- In DA mode, view changes still prune stale pending blocks but retain RBC sessions and missing-block requests while the payload is unavailable so availability can finish after a view change.
- NEW_VIEW tracker entries are retained within the configured future-view window so late quorum receipts can still unblock proposal assembly after a timeout.
- Timing uses on‑chain
SumeragiParameters(BlockTimeMs/CommitTimeMs/MinFinalityMs/PacingFactorBps) for both modes; the pacing factor scales the block/commit targets, and NPoS derives per‑phase timeouts from the scaled block time with optionalsumeragi.advanced.npos.timeoutsoverrides. Both affect pacing but not semantics. - DA-enabled runs derive the quorum timeout as
3 * (block_time + 3 * commit_time)to leave headroom for RBC/availability-evidence propagation on slower hosts. - Quorum timeouts are evaluated against the last observed progress for the pending block (RBC chunks/READY/DELIVER or votes); the fast-path view-change window is suppressed while pre-vote validation is inflight, and in DA mode the fast-path shortcut is disabled so timeouts always use the full DA commit window. If progress stalls, the timeout still fires to recover.
- Availability timeouts use
2 * max(quorum_timeout, 2s)in DA mode to tolerate payload hydration before logging/rebroadcast; whenMissingLocalDatais recorded, quorum reschedules are deferred until the availability timeout so payload recovery can complete. Once the availability timeout elapses, quorum reschedules and idle view changes are allowed even if RBC backlog persists to avoid deadlocks. - Stale-view guards drop old-view consensus traffic; with DA enabled, RBC payload and BlockCreated traffic is still accepted when it matches an active pending/inflight block, and stale-view RBC INIT/READY/DELIVER for uncommitted heights are stashed even before INIT (including when the payload is only present via an aborted pending block) so availability can finish without perfectly synchronized views while stale floods are suppressed.
- Future-window guards drop consensus messages that arrive far ahead of the active round (height/view). View gating applies only to the active round and relaxes after the local commit-quorum timeout so lagging nodes can catch up;
BlockSyncUpdaterespects the same window unless the block is already tracked (pending/explicit missing-block request) or its parent payload is known locally, keeping catch-up traffic bounded without stalling sync. - Repeated invalid Vote/READY/DELIVER signatures from the same signer trigger a temporary suppression window so verification storms do not saturate the worker.
Sumeragi (commit-certificate pipeline)
Overview
- Prepare/Commit votes and certificates remain for pacemaker/telemetry and lock tracking; commits are driven by
CommitCertificates (proxy‑tail quorum) rather than child certificates. Historical BlockSigned/BlockCommitted frames have been removed. - NEW_VIEW gating: the leader proposal is gated in views ≥ 1 by commit quorum (≥
min_votes_for_commit(), i.e., 2f+1) NEW_VIEW receipts for the tuple (height, view). View 0 remains optimistic‑propose. The actor tracks deduplicated NEW_VIEW counts and adopts the highest certificate (highest_qc) monotonically; on view change it sends NEW_VIEW votes to the view-aligned collector set and always includes the leader, falling back to the full commit topology only when collectors are disabled or local-only to keep quorum formation reliable without N^2 broadcast storms. - NEW_VIEW freshness: highest certificate heights that lag the local locked certificate are still accepted and counted toward view-change quorum; the locked‑certificate rule is enforced when proposing or validating blocks, not when tallying view-change receipts.
- NEW_VIEW stale handling: stale NEW_VIEW frames do not advance the local view, but their highest certificate is still processed to seed missing-block fetch and cache late certificates.
- NEW_VIEW height sanity: frames are accepted when
height == highest_qc.height + 1for commit or prepare highest QCs so view changes cannot skip heights. - NEW_VIEW height floor: cached NEW_VIEW entries below the active round height (highest QC height + 1 or committed tip + 1) are discarded so proposals cannot regress after a higher commit certificate is observed.
- NEW_VIEW highest certificate epoch: votes and QCs are rejected when
highest_qc.epochdoes not match the height-derived epoch forhighest_qc.height. - NEW_VIEW highest certificate phase: outbound NEW_VIEW frames carry a commit certificate or a prepare certificate for the parent height (
height - 1); when the available highest QC does not match the target height, peers fall back to the latest committed commit certificate (or the genesis stub) before gossiping. - NEW_VIEW highest certificate view: when the referenced parent block is known locally, NEW_VIEW votes/QCs are rejected if
highest_qc.height/viewdo not match the stored header; cached NEW_VIEW entries are reconciled to the local header view when the parent becomes available. - NEW_VIEW roster selection: NEW_VIEW votes/QCs for the next height use the active commit topology (post-commit state) so roster changes are honored; gaps beyond the next height roll forward from commit-certificate history.
- NEW_VIEW roster history: when rolling forward from commit-certificate history, certificates that contradict a locally known block hash at the same height are ignored to avoid using a forked roster snapshot.
- NEW_VIEW highest certificate roster: highest certificate verification uses the roster snapshot for the referenced block when available so topology changes do not invalidate late highest-certificate payloads.
- Highest certificate: peers update
(height, view, hash)on incoming NEW_VIEW and on commit-certificate receipts; this informs leader’s proposal header and pacemaker.
Messages (Norito‑encoded)
- Control:
ControlFlow::{NewView, Evidence}are carried on the control topic and route through the consolidated control flow.NEW_VIEWframes include a signature over(height, view, highest_qc, sender)and the highest certificate itself; peers verify it against the commit topology and drop unauthenticated frames (the genesis highest certificate is the stub described above). - Block:
CommitVote(phasePrepare/Commit),AvailabilityVote, and the correspondingCommitCertificate(phasePrepare/Commit) plus availability evidence.
Commit rules (scaffold wiring)
- DA availability: when
SumeragiParameter::DaEnabled = true, availability evidence is tracked locally via RBCREADYquorum (>=min_votes_for_commit()) and availability vote aggregation. Commit/finalize does not wait for availability evidence, but still requires the local payload; RBCDELIVERor block sync can satisfy it. - Availability votes: validators emit
AvailabilityVoteafter proposal validation whenever DA is enabled and they have not already voted; vote emission does not wait for RBC delivery. This avoids circular waits between payload transport and voting. Collectors may aggregate availability evidence even when the payload is still missing locally; missing-block fetch runs in parallel so availability status updates once evidence is observed. Nodes continue to accept late availability votes for pending blocks even after a view change so DA quorums can still form, and in DA mode stale availability votes are recorded even if the payload has not been hydrated yet. If the collector target set is empty after filtering the local peer, the vote sender falls back to the commit topology to avoid a no-op broadcast. - Commit votes: nodes accept late commit votes even after a view change so commit certificates can still form; in DA mode stale commit votes are recorded even if the payload is not yet known, and in DA-off runs the same holds when a missing-block fetch is in flight so the certificate can be reconstructed after payload arrival. The local validator gossips a block-sync update (fanout‑capped) after emitting its commit vote to propagate cached votes.
- Payload recovery: nodes that observe availability evidence (RBC
READYquorum or availability votes) without the payload deterministically fetch it from the certificate signers forsumeragi.recovery.missing_block_signer_fallback_attemptsattempts, then fall back to the full commit topology (and still fall back immediately when the signer set is empty). Payload hashes are verified before applying the block. - Empty commit-topology defers are bounded: proposer/finalize paths now use a staged recovery flow (refresh topology, targeted fetch, bounded wait, then deterministic view-change escalation) and suppress repeated identical defer logs within a cooldown window.
- Availability timeout on idle views (NPoS/DA-only): pending blocks with
MissingLocalDatalog and rebroadcast availability evidence after the availability timeout even if no fresh traffic arrives; whileMissingLocalDatais set, quorum reschedules are deferred until the availability timeout, andManifestGuardremains advisory (warnings only). Permissioned/DA-off paths skip DA availability tracking but still benefit from the prevote-only fallback above. - Prepare-only fallback: if only a prepare certificate reaches quorum and no commit votes arrive by the quorum timeout, the actor requeues the block’s transactions, rebroadcasts the block + block-sync update + prepare certificate, resets a highest certificate reference that pointed at the stalled block, and triggers a view change so the next round can propose a fresh block without stalling (applies to both DA-off permissioned runs and DA-off NPoS smoke tests).
- Commit vote lock: once any commit vote is observed at a height, proposal assembly for that height is deferred until the committed block resolves, and quorum reschedules skip requeueing that block’s transactions to avoid conflicting proposals.
- Aborted pending retention: when a commit inflight timeout or quorum reschedule marks a pending block aborted, the payload is retained for a bounded window (derived from quorum timeout and missing-block fallback attempts) so late commit certificates and missing-block fetches can still finalize; entries are evicted once committed or when the retention window expires without votes or fetches.
- Timer-driven commit path: if any pending block exists, the pacemaker tick runs
process_commit_candidateseven when no new messages arrive, and message handlers request the tick when commit evidence lands. This keeps quorum timeouts, Kura retries, and DA availability tracking advancing on quiet networks (permissioned and NPoS). Operators can confirm this path viastatus_snapshot().commit_pipeline_tick_totalandsumeragi_commit_pipeline_tick_total{mode,outcome}(outcome="active"when pending blocks existed,outcome="idle"otherwise). - Tick cadence: when there is no pending consensus work and the transaction queue is empty, ticks are suppressed and the worker sleeps on the wake channel (with a periodic shutdown poll); scheduled tasks (missing‑block retries, quorum reschedule/aborted‑retention windows, RBC rebroadcast/TTL maintenance, idle view‑change timeouts, and commit‑inflight timeouts) drive a next‑deadline sleep instead of fixed‑interval polling; once work appears, ticks are throttled to a block/commit-derived minimum gap while preserving the maximum-gap liveness guarantees, and queued transactions force immediate tick scheduling even when pending blocks exist to keep commit/DA work moving.
- Worker wake: inbound consensus queues, transaction enqueue paths, and async commit/RBC-persist workers signal a wake channel so the worker blocks until new work or the next tick deadline instead of fixed-interval polling.
- Kura persistence retry/backoff: when
kura.store_blockreturns an error the block stays pending and retries with exponential backoff derived fromsumeragi.persistence.kura_retry_interval_ms. Aftersumeragi.persistence.kura_retry_max_attemptsthe actor aborts the payload and requeues its transactions so new proposals can make progress. Status counters (status_snapshot().kura_store.*) and telemetry (sumeragi_kura_store_failures_total{outcome="retry|abort"}) surface failures for alerting, and WSV remains untouched until persistence succeeds.- Gauges
sumeragi_kura_store_last_retry_attemptandsumeragi_kura_store_last_retry_backoff_msexport the most recent retry decision so alerting can page on stuck backoffs or exhausted budgets. /v1/sumeragi/status.kura_storemirrors the same snapshot (failures/abort totals plus the last failed height/view/hash) in both JSON and Norito responses so operators can audit persistence stalls without shell access.- Staging is atomic: pipeline events and WSV deltas are buffered until
kura.store_blocksucceeds. The status surface reportsstage_total/stage_last_*for staged blocks,rollback_total/rollback_last_*with the last reason (store_failureorstate_commit_failure) when a stage is dropped before WSV apply, andlock_reset_total/lock_reset_last_*when highest/locked certificates are reset to the latest committed tip after a kura abort.
- Gauges
- Availability status is data driven: every availability-evidence update (RBC
READYquorum or availability votes) orNEW_VIEWupdate re-evaluates tracking. Blocks finalize based onCommitCertificates plus payload validation; when DA is enabled, availability evidence is tracked alongside the commit pipeline (seeprocess_commit_candidatesinmain_loop.rs). - RBC worker recovery: background fan-out uses a bounded channel. If the queue is full the sender blocks and
sumeragi_bg_post_overflow_total{kind}increments; if the queue is missing or disconnected the message is dropped andsumeragi_bg_post_drop_total{kind}increments. RBC sessions themselves are persisted and markedrecovered: trueon restart; the integration scenariossumeragi_rbc_recovers_after_peer_restartandsumeragi_rbc_session_recovers_after_cold_restartassert this behaviour end-to-end. - State roots: commit votes bind
parent_state_rootandpost_state_rootderived from execution witness snapshots. Commit uses the commit certificate plus payload; there is no separate execution QC gate or WSV requirement. - Commit certificate safety: validators only commit one block per height/epoch (re-votes across views must target the same block). Collectors skip commit-certificate aggregation for blocks that do not extend the locked chain, and receivers drop conflicting commit certificates (emitting invalid-QC evidence) instead of caching them for finalize.
Commit certificate verification (basic)
- Receivers perform bitmap/topology shape checks on the new certificates: signer bitmaps must not reference indices ≥ N and must have at least
min_votes_for_commit()bits set. The BLS aggregate signature is verified against the signer set; certificates with mismatched aggregates are rejected.
Determinism
- All additional checks are pure functions of local state and message contents. The pipeline preserves deterministic commit semantics while enabling the pacemaker path and certificates.
Proposal header validation
- Validators cache full proposals (header + payload hash) and may cache proposal hints (height/view/highest certificate metadata). When hints are missing, the cached proposal is used to derive the highest-QC context for
BlockCreated. OnBlockCreatedingress they enforce:- proposals are dropped if their embedded
highest_qcdoes not targetheight - 1, does not match the height-derived epoch, does not match the proposalparent_hash, or (when the parent block is known) does not match the parent block view; - hint metadata must match the
BlockCreatedheader(height, view, parent); when the parent block is known, the hinthighest_qc.viewmust match the parent view; BlockCreatedwithout cached hints are rejected when locally known ancestry proves they do not extend the locked chain; if ancestry is missing, the payload is kept while parents are fetched;- if the locked block itself is missing, the validator retains the lock, requests the payload, and defers accepting non-extending certificates until the lock resolves;
- the cached proposal header’s
parent_hashandtx_rootmust equal the block header; - the cached proposal payload hash must equal the recomputed canonical payload hash (header + transactions + DA bundles, without signatures or execution results).
- proposals are dropped if their embedded
- Header/payload mismatches immediately drop the block. Proposal mismatches emit
Evidence::InvalidProposal(broadcast on the control topic) so collectors can quarantine faulty leaders. Hint-only mismatches are dropped without evidence because the full proposal may still arrive later in the view. - When the proposal has not arrived yet, the node logs a trace entry and accepts the block after standard validation; the sanity checks re-run if the proposal subsequently appears.
Validation gate telemetry
- The pre-vote validation gate increments
sumeragi_validation_reject_total{reason}and/v1/sumeragi/statussurfacesvalidation_reject_total,validation_reject_reason, andvalidation_rejects.*(per-reason counters plus last height/view/block/timestamp) whenever validation fails before sending votes. Reasons are bucketed asstateless,execution,prev_hash,prev_height, ortopology; view-change cause telemetry includes avalidation_rejectbucket to show how often rejects force a view bump. - Blocks rejected by the gate requeue their transactions and emit invalid-proposal evidence when a parent certificate is available so view-change recovery can proceed without advancing highest/locked certificates; highest/locked certificates realign to the last committed chain if they pointed at the rejected block.
Large payload simulations
-
Integration helpers
sumeragi_rbc_da_large_payload_four_peersand_six_peers(seedocs/source/sumeragi_da.md) exercise ≥10 MiB payloads withsumeragi.da.enabled = trueand confirm that availability evidence forms (or an RBCREADYquorum is recorded) and commit progresses without deadlocking. RBC delivery typically completes before commit, but commit is not gated on availability evidence or localDELIVER. -
DA availability timeout: while availability evidence is still missing (RBC
READYquorum not met), the actor logs and rebroadcasts availability evidence after the timeout. The reschedule counters (sumeragi_rbc_da_reschedule_totalandstatus_snapshot().da_reschedule_total) are legacy and should remain zero now that DA is advisory. Nodes missing payload fetch it from certificate signers first, then fall back to the full commit topology after the configured retry budget. -
The helpers capture per-peer Prometheus counters and
/v1/sumeragi/rbc/sessionssnapshots; automation can watch theirsumeragi_da_summary::*output. -
Performance budgets are enforced by the helpers: RBC delivery ≤ 3.6 s, commit ≤ 4.0 s, throughput ≥ 2.7 MiB/s, background-post queue depth ≤ 32, and P2P queue drops = 0. Violations fail the tests and should alert operators in production runs.
-
Use
cargo run -p build-support --bin sumeragi_da_reportagainst the latest.summary.jsonartifacts to capture measured numbers. The generated Markdown now includesBG queue maxandP2P drops maxcolumns mirroring the budgets. -
The generated summary under
docs/source/generated/sumeragi_da_report.mdis updated byscripts/run_sumeragi_da.py --report-dest …and is included here to surface the most recent measurements. -
Baseline (1 s block, k=3) metrics rely on a discrete harness run; see
docs/source/generated/sumeragi_baseline_report.mdfor the latest report. The current measurements were captured on an Apple M2 Ultra (24 cores, 192 GB RAM, macOS 15.0). Reproduce with:SUMERAGI_BASELINE_ARTIFACT_DIR=artifacts/sumeragi-baseline-live \ python3 scripts/run_sumeragi_baseline.py \ --fail-on-fixture \ --report-dest docs/source/generated/sumeragi_baseline_report.mdThe harness writes Norito summary JSON alongside topology snapshots so the Markdown report and fixtures remain in sync.
-
For chaos/performance validation, run the targeted stress scenarios via
scripts/run_sumeragi_stress.py. The helper executes thesumeragi_npos_performance.rsfault-injection tests individually (queue backpressure, RBC overflow, redundant fan-out, jitter, chunk loss) and saves per-test logs plus asummary.jsonmanifest for later analysis. Example:python3 scripts/run_sumeragi_stress.py \ --artifacts artifacts/sumeragi-stress-$(date +%Y%m%d-%H%M)See
docs/source/sumeragi_chaos_performance_runbook.mdfor the complete Milestone A6 checklist covering baseline captures, soak-matrix runs, telemetry validation, and evidence packaging.
For the multi-peer soak matrix (4/6/8 peers) and the corresponding operator sign-off bundle, run:
python3 scripts/run_sumeragi_soak_matrix.py \
--artifacts-root artifacts/sumeragi-soak-$(date +%Y%m%d-%H%M) \
--pack artifacts/sumeragi-soak-$(date +%Y%m%d-%H%M)/signoff.zip
See sumeragi_soak_matrix.md for the default matrix
and sign-off checklist.
Run the suite on dedicated hardware; scenarios intentionally exercise
backpressure saturation and may take several minutes. Inspect the emitted log
files when a test fails and cross-reference the metrics with the VRF and DA
dashboards above. The helper appends results to summary.json inside the
artifacts directory so operators can confirm each scenario succeeded without
re-running the full suite; each entry records the exit status plus stdout/
stderr log paths for postmortems. Use scripts/render_sumeragi_stress_report.py --output-format text <path> to turn the manifest into a Markdown table with clickable log
links for runbooks or incident retrospectives.
Collector telemetry runbook
Stalled collectors or slow commit assembly manifest as missing
availability-evidence records, prolonged DA collection, or commit_ms /
pipeline_total_ms spikes. Operators should wire the following telemetry to
detect and triage issues before commits approach the configured commit-time
budget (permissioned CommitTimeMs or NPoS effective_npos_timeouts.commit_ms).
Key dashboards
sum(rate(sumeragi_da_votes_ingested_by_collector[1m])) by (collector_idx)— identify collectors that are not ingesting votes.sumeragi_qc_last_latency_ms{kind="availability"}and the histogramsumeragi_qc_assembly_latency_ms{kind="availability"}— last observed and recent latency for building availability evidence.sumeragi_phase_latency_ms{phase="collect_da"}andsumeragi_phase_latency_ms{phase="collect_precommit"}(P95 over 5 minutes) — view-level time spent collecting availability votes and precommit QCs.sumeragi_phase_latency_ms{phase="collect_aggregator"}— redundant collector fan-out latency; correlate spikes with collector backlog and adjustsumeragi.collectors.redundant_send_r/timeouts as needed. Track fallback frequency withsumeragi_gossip_fallback_totaland monitor rejected proposals viablock_created_dropped_by_lock_total,block_created_hint_mismatch_total,block_created_proposal_mismatch_total, andpacemaker_backpressure_deferrals_total(the latter highlights queues saturated enough to stall proposal assembly).sumeragi_phase_latency_ema_ms{phase="propose|collect_da|collect_prevote|collect_precommit|commit"}— smoothed per-phase latency (EMA). The pacemaker consumes these phases; track drift between the EMA and raw histogram to catch sudden latency spikes./v1/sumeragi/telemetry(oriroha_cli --output-format text ops sumeragi status) — compact JSON snapshot with per-collector vote counts, certificate latency, RBC backlog, and the latest highest/locked certificate hashes (highest_qc/locked_qc) (CLI output truncates hashes for readability)./v1/sumeragi/status/sse— SSE stream mirroring/v1/sumeragi/statusfor live dashboards (≈1s cadence)./v1/sumeragi/phases(oriroha_cli --output-format text ops sumeragi phases) — latest{ propose_ms, collect_da_ms, collect_prevote_ms, collect_precommit_ms, collect_aggregator_ms, commit_ms, pipeline_total_ms }plus anema_msobject mirroring all phases (includingpipeline_total_ms) for dashboards tracking drift between spot and smoothed latencies. The pipeline total aggregates the pacemaker-controlled phases (propose → commit), providing a single end-to-end latency signal.- Import
docs/source/grafana_sumeragi_overview.jsonfor a ready-made Grafana dashboard visualising certificate height drift, BlockCreated drop counters, and VRF participation/penalty trends.
Alert thresholds
- Availability evidence latency: alert when
sumeragi_qc_last_latency_msforkind="availability"exceeds0.6 * commit_time_msfor two consecutive windows, or when the histogram P95 crosses0.7 * commit_time_ms(permissionedCommitTimeMs, NPoSeffective_npos_timeouts.commit_ms). - Vote ingress stagnation: alert when
sum(rate(sumeragi_da_votes_ingested_total[2m])) == 0whilesumeragi_rbc_backlog_sessions_pending > 0(collectors are not making progress despite active RBC sessions). - Commit latency: alert when
commit_msor the P95 ofsumeragi_phase_latency_ms{phase="commit"}exceeds0.75 * commit_time_ms(permissionedCommitTimeMs, NPoSeffective_npos_timeouts.commit_ms), or when it remains zero for ≥3 consecutive rounds while new blocks arrive (commit pipeline stalled). - Collector fan-out: alert when
collect_aggregator_msexceeds0.5 * sumeragi.advanced.npos.timeouts.aggregator_msfor three consecutive rounds, or when redundant sends occur more thansumeragi.collectors.redundant_send_rtimes in a single view (watchsumeragi_redundant_sends_total), gossip fallback fires repeatedly (monitorrate(sumeragi_gossip_fallback_total[5m]) > 0), or proposals are dropped at the locked certificate gate (increase(block_created_dropped_by_lock_total[5m]) > 0), fail header checks (increase(block_created_hint_mismatch_total[5m]) > 0,increase(block_created_proposal_mismatch_total[5m]) > 0), or stall due to proposal backpressure (queue saturation, relay/RBC backlog, or blocking pending blocks;increase(pacemaker_backpressure_deferrals_total[5m]) > 0). Sustained breaches indicate that the primary collector is lagging or network backpressure is throttling vote flow.
Redundant fan-out counters tick when the DA retry loop re-broadcasts cached RBC
payloads to additional collectors. The integration harness exercises this path
via npos_redundant_send_retries_update_metrics to keep dashboards aligned with
the consensus backoff contract.
Triage checklist
- Confirm collector assignments via
iroha_cli --output-format text ops sumeragi collectorsand ensure the stalled peer is still designated. - Query
/v1/sumeragi/telemetryto pinpoint the collector index with a flatvotes_ingestedcounter. If only one collector is stalled, increasesumeragi.collectors.redundant_send_rtemporarily so validators fan out to the next collector while investigating networking issues. - Inspect
sumeragi_bg_post_queue_depthandp2p_*_throttled_totalmetrics to determine whether bounded queues or transport caps are delaying vote or payload propagation. - For FASTPQ/prover stalls, check
/v1/torii/zk/prover/reports(when the prover is enabled) and the Torii logs for failed witness uploads; recover or restart the affected prover workers. - If both collectors are idle, inspect RBC backlog gauges to confirm payloads
are still circulating. A growing backlog together with DA stagnation
indicates collectors are wedged; restart the affected peers and investigate
for mismatched manifests or disk pressure flagged in
sumeragi_rbc_store_*metrics.sumeragi_rbc_store_evictions_totalspikes when TTL or capacity limits prune sessions, whilesumeragi_rbc_persist_drops_totalclimbs when the async persist queue saturates; both signal that the persisted backlog is shedding load and warrants operator attention./v1/sumeragi/statusnow exposes the most recent(block_hash, height, view)tuples inrbc_store.recent_evictionsso operators can correlate evictions with specific payloads and epochs. Example excerpt:
{
"rbc_store": {
"sessions": 3,
"bytes": 1048576,
"pressure_level": 1,
"backpressure_deferrals_total": 5,
"persist_drops_total": 2,
"evictions_total": 12,
"recent_evictions": [
{ "block_hash": "deadbeefcafebabe", "height": 4201, "view": 7 }
]
}
}
iroha --output-format text ops sumeragi status mirrors the same data, including current
session/byte utilisation, aggregated governance-seal counters
(lane_governance_sealed_total, lane_governance_sealed_aliases), and the
active epoch scheduling tuple (epoch_len, epoch_commit, epoch_reveal), so
operators can eyeball backlog pressure, spot sealed lanes, and review
pacemaker timing without parsing JSON. Pair the view with
iroha_cli app nexus lane-report --only-missing --fail-on-sealed during upgrades
to exit pipelines when governance manifests are still missing.
6. Once service resumes, document the incident and restore redundant-send and
collector parameters to their baseline values.
Pacemaker & RBC telemetry surfaces
Operators can pull deterministic telemetry snapshots over Torii or via the CLI.
CLI and HTTP reference
iroha --output-format text ops sumeragi telemetryhitsGET /v1/sumeragi/telemetryand reports availability votes, collector counts, VRF penalties, and RBC backlog figures in a single line suitable for shift notes.iroha --output-format text ops sumeragi pacemaker(GET /v1/sumeragi/pacemaker) exposes the current view timeout, backoff window, jitter configuration, and RTT floor used by the EMA-based pacemaker. Capture this before and after incidents to prove pacing adjustments.iroha --output-format text ops sumeragi phases(GET /v1/sumeragi/phases) prints per-phase latencies together with EMA totals so you can distinguish between DA/collector stalls and proposal throughput regressions.iroha --output-format text ops sumeragi rbc status(GET /v1/sumeragi/rbc) tracks session counts, ready/deliver broadcasts, rebroadcast skips, and payload bytes delivered. Useiroha --output-format text ops sumeragi rbc sessions(GET /v1/sumeragi/rbc/sessions) when you need the chunk-level breakdown for a specific payload.- For automation, hit the same endpoints from SDKs (
ToriiClient.getSumeragiTelemetryet al.) and log the JSON payloads alongside Prometheus scrapes so governance artefacts include both machine-readable metrics and operator-facing evidence.
Key metrics
| Metric | Meaning | Operator action |
|---|---|---|
sumeragi_pacemaker_backpressure_deferrals_total | Pacemaker skipped a proposal because the transaction queue is saturated, consensus block-payload/RBC chunk queues are saturated, relay/RBC backpressure is active, or a pending block still blocks proposal assembly. | Inspect iroha --output-format text ops sumeragi status for rbc_store.pressure_level, drain gossip/RBC queues, and consider temporarily raising the per-queue caps (especially sumeragi.advanced.queues.rbc_chunks/sumeragi.advanced.queues.block_payload) or reducing incoming traffic before resuming. |
sumeragi_commit_pipeline_tick_total{mode,outcome} | Pacemaker tick invoked the commit pipeline (outcome="active" when pending blocks existed, "idle" when empty). | Pair with status_snapshot().commit_pipeline_tick_total to prove timer-driven commits on quiet networks; alert if idle climbs while transactions are queued, or if active climbs without matching inbound votes. |
sumeragi_pacemaker_backoff_ms / sumeragi_pacemaker_view_timeout_target_ms | Current view timeout vs. target window derived from the on-chain effective block time (block_time_ms scaled by pacing_factor_bps). Sustained values far above the block time indicate repeated view changes or retries. | Run iroha --output-format text ops sumeragi pacemaker, compare with the on-chain block time, and audit p2p_*_throttled_total plus RBC backlog metrics to find which stage is stretching the view timer. |
sumeragi_phase_latency_ema_ms{phase="collect_da_ms",…} / sumeragi_phase_total_ema_ms | EMA latency per phase and across the full pipeline as rendered by iroha --output-format text ops sumeragi phases. | Trigger alerts when EMA totals exceed the configured view timeout, then correlate the offending phase with Torii/RBC logs to determine whether DA, vote-collection, or aggregator legs are stalling. |
sumeragi_rbc_store_sessions / sumeragi_rbc_store_pressure / sumeragi_rbc_store_bytes | Persisted RBC sessions and pressure level. pressure=2 means the store is shedding sessions to remain within bounds. | Take iroha --output-format text ops sumeragi telemetry plus iroha ops sumeragi rbc status snapshots, prune stale payloads, and review disk I/O. If pressure stays high, increase the per-session cap or speed up delivery via sumeragi.collectors.redundant_send_r. |
sumeragi_rbc_store_evictions_total / sumeragi_rbc_backpressure_deferrals_total | Sessions evicted due to TTL/capacity enforcement and proposals deferred because the store refused new payloads. | Use /v1/sumeragi/status.rbc_store.recent_evictions and the CLI summary to pinpoint the affected height/view, re-ingest the payload if needed, and adjust sumeragi.collectors.redundant_send_r or store caps to avoid repeated evictions. |
sumeragi_rbc_persist_drops_total | Persist requests dropped because the async RBC persist queue is full. | Check disk throughput and queue saturation, then tune RBC store caps or reduce incoming load to avoid prolonged in-memory growth. |
sumeragi_rbc_backlog_sessions_pending / sumeragi_rbc_backlog_chunks_total / sumeragi_rbc_backlog_chunks_max | Number of payloads still missing chunks and the highest per-session backlog. | When pending_sessions or chunks_total plateaus, inspect iroha --output-format text ops sumeragi rbc sessions to find the stuck block hash, then check network logs for throttling or mismatched manifests. |
| `sumeragi_rbc_rebroadcast_skipped_total{kind="payload | ready"}` | Local peer skipped a payload/READY rebroadcast because it was not in the deterministic f+1 sender subset. |
sumeragi_rbc_da_reschedule_total | Legacy counter for DA deadline reschedules (no longer incremented when DA is advisory). | Keep at zero; use sumeragi_da_gate_block_total{reason="missing_local_data"} to monitor missing local payloads. |
sumeragi_membership_mismatch_total / sumeragi_membership_mismatch_active | Peers disagree on roster membership for a (height,view) tuple. | Compare /v1/sumeragi/status.membership hashes across peers, run iroha --output-format text ops sumeragi params per node, and halt the rollout until every validator reports the same ordered_peer_ids. |
RBC rebroadcast budget
RBC payload recovery is capped per tick by sumeragi.advanced.rbc.rebroadcast_sessions_per_tick to avoid
rebroadcast storms when many sessions are missing chunks. Increase it on well-provisioned
networks to speed recovery, or lower it if P2P queues saturate during soak tests.
Pending RBC stash bounds
Before INIT arrives, RBC frames are bounded by per-session caps
(sumeragi.advanced.rbc.pending_max_chunks, sumeragi.advanced.rbc.pending_max_bytes) and the
session cap sumeragi.advanced.rbc.pending_session_limit (default 256). Entries also
expire after sumeragi.advanced.rbc.pending_ttl_ms when the session is not yet active;
once a session exists, pending READY/DELIVER frames are retained until the
session is cleared so roster delays do not drop availability evidence.
Session-cap evictions skip active sessions; if the cap is reached by active
sessions, new pending frames are dropped and recorded as session_cap drops.
The worst-case buffered payload before INIT is:
When pending frames are dropped (cap, TTL, or session-cap), the node
deterministically requests the missing BlockCreated from the cached roster
to preserve liveness; retries respect the standard backoff and roster-hash
checks.
sumeragi.advanced.rbc.pending_session_limit
* min(sumeragi.advanced.rbc.pending_max_bytes, sumeragi.advanced.rbc.chunk_max_bytes * RBC_MAX_TOTAL_CHUNKS)
Size sumeragi.advanced.rbc.pending_max_bytes to at least one chunk (sumeragi.advanced.rbc.chunk_max_bytes), and
set sumeragi.advanced.rbc.chunk_max_bytes to a positive value (0 is rejected by config
validation) so payloads can always split into at least one chunk. Then
use the bound above to keep memory budgets deterministic. Drops and evictions
are surfaced via /v1/sumeragi/telemetry.pending_rbc.{drops_cap_total,drops_cap_bytes_total,drops_ttl_total,drops_ttl_bytes_total,drops_bytes_total,evicted_total,max_*}
and iroha --output-format text ops sumeragi status; sustained movement should trigger alerts
and a manifest/collector audit. Stash counters (/v1/sumeragi/status.pending_rbc.stash_*)
track READY/DELIVER/chunk frames parked before INIT or roster verification and
help correlate missing-block fetch retries with roster hydration. Evictions never mark availability on their own—
availability still requires availability evidence (RBC READY quorum or availability votes) even when
pending stash frames are discarded.
At runtime, sumeragi.advanced.rbc.chunk_max_bytes is clamped so a serialized RbcChunk (including
headers and length prefix) fits within the consensus payload plaintext cap derived
from network.max_frame_bytes_block_sync.
Adaptive observability
Enable sumeragi.adaptive_observability to let the actor temporarily widen
collector fan-out and pacemaker intervals when telemetry shows stalls:
- Trigger sources: certificate latency over
qc_latency_alert_msor bursts of missing availability warnings whenstatus.da_gate.missing_local_data_totaladvances byda_reschedule_burst(legacy name) between ticks. - Mitigation: raise redundant collector fan-out to
collector_redundant_r.max(baseline)and addpacemaker_extra_msto the proposal interval; the actor logs the decision with the measured metrics. - Reset: once counters stabilise for
cooldown_ms, the collector limit and pacemaker interval snap back to baseline. - Defaults: disabled; 400 ms certificate latency threshold, DA burst of 2, +100 ms pacemaker interval, redundant fan-out of 3, 5 s cooldown.
VRF Randomness Pipeline
Sumeragi’s NPoS pacemaker drives leader and collector rotation from a verifiable
random function (VRF). Each epoch (epoch_length_blocks) is split into two
windows:
- Commit window (
vrf_commit_deadline_offsetblocks) — validators submitVrfCommitpayloads with a hash of their reveal. - Reveal window (
vrf_reveal_deadline_offsetblocks) — validators disclose the reveal (VrfReveal). The actor verifies it against the prior commit and records the 32-byte reveal.
The commit/reveal ingestion path is synchronous and deterministic:
- Validators automatically post
VrfCommitandVrfRevealframes to the commit topology when the commit/reveal windows open and the node is part of the active validator set. Manual submissions remain available via Torii for recovery/override flows:POST /v1/sumeragi/vrf/commitwith{ "epoch": <u64>, "signer": <u32>, "commitment_hex": "<0x…>" }.POST /v1/sumeragi/vrf/revealwith{ "epoch": <u64>, "signer": <u32>, "reveal_hex": "<0x…>" }.
- Torii rate-limits the requests, validates the 32-byte hex payload, and forwards
the message to the
SumeragiHandle. - The main-loop actor (
handle_vrf_commit/handle_vrf_reveal) checks the local epoch, window, and commitment binding, then snapshots the in-progress epoch state into WSV (world.vrf_epochs) for durability and observability. - The PRF seed stays fixed for the current epoch; snapshots update participation only and do not change leader/collector selection until the next epoch boundary.
When the epoch boundary is reached (block height multiple of
epoch_length_blocks), the actor:
- Computes penalties (
committed_no_reveal,no_participation). - Mixes valid reveals into the next epoch seed
S_e. - Persists a finalized
VrfEpochRecord(with penalties populated). - Updates
epoch_report::VrfPenaltiesReport, status counters, and telemetry.
The refreshed seed flows back into deterministic collector selection through
deterministic_collectors, and /v1/sumeragi/collectors reports the active
plan alongside the (height, view) the pacemaker is evaluating.
If a node restarts after finalizing an epoch record but before persisting the seed-only snapshot for the next epoch, it recomputes the next-epoch seed from the finalized record (seed + ordered reveals) when selecting PRF values. This keeps deterministic rotation consistent across peers even if the seed-only record is missing at restart.
CLI and operator workflow
-
iroha_cli --output-format text ops sumeragi vrf-epoch --epoch <n>prints the persisted seed, participation table, and penalty breakdown together with the recordedcommit_deadline_offset/reveal_deadline_offsetfor that epoch. Omit--output-format textfor the full JSON payload (found,finalized, counts, offsets). -
iroha_cli --output-format text ops sumeragi telemetryshows the latest availability vote totals, RBC backlog, and VRF participation summary (reveals_total,late_reveals_total,committed_no_reveal,no_participation). Drop--output-format textto inspect the full JSON payload. -
iroha_cli --output-format text ops sumeragi paramsprints the active consensus parameters pulled from WSV, includingevidence_horizon_blocks,activation_lag_blocks, andslashing_delay_blocks, so operators can verify staged values before and after governance decisions. -
Use the Torii POST endpoints directly when you need to submit commits or reveals manually (automation should drive them during normal operations). Example:
curl -X POST "$TORII/v1/sumeragi/vrf/commit" \ -H "Content-Type: application/json" \ -d '{"epoch":42,"signer":1,"commitment_hex":"0x..."}' curl -X POST "$TORII/v1/sumeragi/vrf/reveal" \ -H "Content-Type: application/json" \ -d '{"epoch":42,"signer":1,"reveal_hex":"0x..."}' -
Automation can poll
/v1/sumeragi/collectorsto confirm the collector set matches expectations (collectors[*].peer_id), and/v1/sumeragi/statusforprf_epoch_seed,prf_height,vrf_late_reveals_total, and penalty totals.
Randomness runbook (operator checklist)
-
Monitor
iroha_cli --output-format text ops sumeragi statusafter each block; ifvrf_penalty_epochjumps orcommitted_no_revealgrows, open the per-epoch snapshot withiroha_cli --output-format text ops sumeragi vrf-epoch --epoch <n>to identify missing validators. -
During the commit window validate that each validator submitted a commitment:
iroha_cli --output-format text ops sumeragi telemetryexposescommitments_total, while/v1/sumeragi/telemetrylists the per-signer map undervrf.commitments. -
Before the reveal deadline, watch
vrf.reveals_totalandvrf_late_reveals_total. If a reveal is missing, page the validator and be ready to post it manually viaPOST /v1/sumeragi/vrf/reveal(see curl example above) with a hex-encoded payload captured from the validator. -
Cross-check the epoch’s recorded
commit_deadline_offset/reveal_deadline_offsetagainst your expected schedule; mismatches indicate a configuration drift or stale genesis snapshot and should trigger incident response before the pacemaker advances to the next epoch. -
When a reveal lands late, follow the recovery flow below: capture the current seed, confirm the late reveal is recorded under
vrf.late_reveals, and verify thatprf.epoch_seedremains unchanged. -
At epoch rollover confirm penalties cleared:
vrf_committed_no_reveal_totalshould drop to zero for the signer that supplied the late reveal, and/v1/sumeragi/vrf/epoch/{n}should showfinalized: true. -
Healthy NPoS runs keep the RBC data plane inside the budgets enforced by CI (
integration_tests/tests/sumeragi_npos_happy_path.rs):sumeragi_rbc_deliver_broadcasts_totalshould advance each block, whilesumeragi_bg_post_queue_depthand the per-peersumeragi_bg_post_queue_depth_by_peergauges remain ≤ 16. Sustained breaches point to collectors that are stuck or to transport backpressure throttling vote/reveal propagation. -
Integration tests
npos_rbc_store_backpressure_records_metricsandnpos_rbc_chunk_loss_fault_reports_backlogcapture RBC store pressure and chunk-loss telemetry end-to-end (integration_tests/tests/sumeragi_npos_performance.rs:633and:760). -
Nodes emit a rate-limited log when RBC store pressure transitions (warn on elevated pressure, info when back to normal). Repeated elevated logs are throttled to one per minute.
Metrics and alerts
Telemetry surfaces the VRF lifecycle so operators can wire alerts:
sumeragi_vrf_commit_emitted_total/sumeragi_vrf_reveal_emitted_total— accepted submissions.sumeragi_vrf_non_reveal_total/sumeragi_vrf_no_participation_total— epoch penalties (incremented once per epoch).sumeragi_prf_epoch_seed(status endpoint) — the current seed; can be graphed by decoding the hex string to validate changes.sumeragi_prf_context_height/_view— the(height, view)used when sampling collectors or leaders.
Combine these with /v1/sumeragi/vrf/epoch/{epoch} to audit individual epochs
and /v1/sumeragi/telemetry’s vrf section for dashboards.
- Torii exposes
/v1/sumeragi/vrf/epoch/{epoch}for persisted randomness snapshots. The response includes the epoch seed (seed_hex), commit/reveal participation, and penalty tallies. Useiroha_cli --output-format text ops sumeragi vrf-epoch --epoch <n>for a human-friendly view; omit--output-format textto print the full Norito payload. /v1/sumeragi/telemetrynow returns avrfsection with the latest epoch summary:{ found, epoch, finalized, seed_hex, roster_len, participants_total, commitments_total, reveals_total, late_reveals_total, committed_no_reveal[], no_participation[], late_reveals[] }. The CLI summary mirrors these fields so dashboards can track reveal participation in real time./v1/sumeragi/statusexposes aggregate penalty counters (vrf_penalty_epoch,vrf_committed_no_reveal_total,vrf_no_participation_total,vrf_late_reveals_total) so operators can monitor participation drift alongside highest/locked certificate telemetry while confirming that late reveals do not mutate the active PRF seed (prf.epoch_seed).- The status payload now includes a deterministic roster hash under
membership { height, view, epoch, view_hash }and the last mismatch context undermembership_mismatch { active_peers, last_peer, last_height, last_view, last_epoch, last_local_hash, last_remote_hash, last_timestamp_ms }. Compare this block across peers— either via/v1/sumeragi/statusor the Norito payload—to confirm validator alignment and identify which peer diverged. Hashes are derived from(chain_id, height, view, epoch, ordered_peer_ids)using Blake2b-256. - Late reveals: validators may submit reveals after the configured window (
vrf_reveal_deadline_offset) to clear penalties. The actor verifies the reveal against the stored commitment, records it underlate_reveals, and incrementssumeragi_vrf_reveals_late_total. Late submissions never remix the epoch seed—only on-time reveals participate in the Blake2b accumulator—but they do remove the validator from thecommitted_no_revealset. Late entries are persisted inworld.vrf_epochs[*].late_revealsso operators can audit the height at which the reveal landed.
VRF alert thresholds
- Page when
increase(sumeragi_vrf_no_participation_total[epoch_window]) > 0. Any increment means at least one validator missed both commit and reveal windows for the tracked epoch. Use a window length matchingvrf_commit_deadline_offset + vrf_reveal_deadline_offset(for the defaults,epoch_window = 140mon a one‑second block cadence). - Warn on
increase(sumeragi_vrf_non_reveal_penalties_total[epoch_window]) > 0and includesumeragi_vrf_non_reveal_by_signerin the alert labels to pinpoint the validator that skipped the reveal. - Alert when
increase(sumeragi_vrf_rejects_total_by_reason{reason!="late"}[5m]) > 0. Non‑late reject reasons (stale,invalid_signature,bad_epoch, etc.) indicate malformed payloads or a validator running stale parameters. - Notify when
rate(sumeragi_vrf_commits_emitted_total[5m]) == 0for the entire commit window while the cluster continues finalising blocks (increase(sumeragi_blocks_committed_total[5m]) > 0). The combination signals that commitments are not being produced even though the epoch is active. - Track
increase(sumeragi_vrf_reveals_late_total[epoch_window]) > 0as a warning; frequent late reveals imply validators are missing the reveal deadline and may slip into non‑reveal penalties.
VRF alert response (runbook)
- Capture the current epoch context from
/v1/sumeragi/status(prf_height,prf_view,vrf_penalty_epoch,vrf_committed_no_reveal_total,vrf_no_participation_total) to confirm the alerting epoch and whether penalties were already applied. - Inspect the detailed participation table with
iroha_cli --output-format text ops sumeragi vrf-epoch --epoch <n>. When multiple validators are missing, rerun without--output-format textto list per-signer commitments, reveals, and penalty flags. - For
no_participationincrements, contact the affected validator and verify that the corresponding Torii ingress logs show VRF submissions. If the validator was offline, stage a joint reconfiguration or jailing proposal before the next epoch to keep quorum guarantees intact. - For
non_revealincrements, collect the stored commitment from the epoch snapshot (commitments[*].commitment_hex) and have the validator resend the reveal viaPOST /v1/sumeragi/vrf/reveal(see the curl example above). Confirmsumeragi_vrf_reveals_late_totalincrements andvrf_committed_no_reveal_totaldrops back to zero after the late submission. - When
sumeragi_vrf_rejects_total_by_reasonfires, inspect thereasonlabel to determine root cause.invalid_signatureandbad_epochrequire the validator to refresh its configuration;staleimplies the payload was replayed and should be discarded. Record the offending payload hash in the incident notes. - After remediation, wait for the next block and re-check
/v1/sumeragi/statusplus/v1/sumeragi/telemetry.vrfto ensure counters stabilise and the PRF seed (seed_hex) matches the value captured before the intervention. If penalties remain non-zero across an epoch boundary, escalate to governance to slash or rotate the validator.
Recovery: Late Reveals and Zero-Participation Epochs
- Capture the baseline seed. Before acting on a reveal gap, record the
current PRF seed from
/v1/sumeragi/status.prf.epoch_seed(oriroha_cli --output-format text ops sumeragi status). The seed must remain unchanged if a reveal arrives late. - Submit or observe the late reveal. Once the validator broadcasts the
payload,
/v1/sumeragi/telemetry.vrf.late_reveals_totalincrements and/v1/sumeragi/status.vrf_late_reveals_totalmirrors the count even before the epoch finalizes. The per-epoch snapshot/v1/sumeragi/vrf/epoch/{n}lists the signer, reveal bytes, and the height at which the late message was accepted. - Verify the PRF seed is stable. Compare the cached seed with the current
prf.epoch_seedin/v1/sumeragi/status. A mismatch indicates an invalid reveal flow and should trigger incident response; late reveals must never remix epoch entropy. - Confirm penalties clear at epoch rollover. After the epoch boundary,
/v1/sumeragi/statusreportsvrf_committed_no_reveal_total = 0for the late signer while retaining thevrf_late_reveals_totalhistory. Telemetry counters (sumeragi_vrf_committed_no_reveal_total,sumeragi_vrf_reveals_late_total) also reset accordingly. - Handle zero-participation epochs. If no validator submits commitments or
reveals, expect
/v1/sumeragi/status.vrf_no_participation_totalto equal the roster length andvrf_late_reveals_total = 0. The epoch snapshot still exposes the derived seed so operators can audit deterministic leader selection for the next epoch.
DA availability matrix (sumeragi.da.enabled, advisory)
Build-line policy: v3 uses sumeragi.da.enabled (on-chain SumeragiParameters.da_enabled) as the single DA/RBC switch. In this first release, Iroha v3 deployments must keep DA/RBC enabled; the runtime honors the on-chain value and applies no override, and the node refuses to start if sumeragi.da.enabled is false.
- DA/RBC enabled (
sumeragi.da.enabled=true) — availability evidence is tracked (advisory); commits proceed without waiting for evidence:- Missing local payload sets
status.da_gate.reason = missing_local_data;status.da_gate.missing_local_data_totalincrements on every transition into this state. The gate clears once the payload is available locally (viaBlockCreatedor RBC delivery). - Manifest guard: when a block carries DA commitments but the corresponding manifest is missing or mismatched,
status.da_gate.reasonbecomes one ofmanifest_missing/manifest_hash_mismatch/manifest_read_failed/manifest_spool_scanandstatus.da_gate.manifest_guard_totalincrements. Audit-only lanes still log the warning; strict lanes report the same reason but do not block commit.
- Missing local payload sets
- DA/RBC disabled (
sumeragi.da.enabled=false) — unsupported in v3; the node refuses to start when DA/RBC is disabled. status.da_gate.last_satisfiedrecordsmissing_data_recoveredwhen the local payload becomes available. Commit does not depend on local RBC delivery; RBC is transport/recovery and is tracked separately via the RBC endpoints and metrics.- Implementation note: commit certificates are cached by
(phase, hash, height, view, epoch)so availability evidence cannot overwrite prepare/commit certificates. When certificates arrive before the payload, the node replays cached certificates once the payload is available so message reordering cannot strand availability tracking.
| Build line | Availability status | Status fields to watch | Typical remediation |
|---|---|---|---|
Iroha v3 (sumeragi.da.enabled=true) | Local payload availability (advisory) | status.da_gate.reason, status.da_gate.missing_local_data_total, status.da_gate.last_satisfied, legacy status.sumeragi.da_reschedule_total | Verify BlockCreated broadcasts and RBC payload recovery, inspect /v1/sumeragi/status.rbc_store and RBC backlog for stuck payloads, and restart collectors if quorum cannot form. |
DA availability transitions also emit structured debug logs when the reason changes or when a requirement is satisfied. The logs carry reason, satisfied, da_enabled, and delivered fields so operators can align missing-availability evidence with the corresponding telemetry counters without scraping Prometheus.
Troubleshooting quick reference
| Symptom | Detection | Remediation |
|---|---|---|
| Pacemaker keeps extending views beyond the configured block time | iroha --output-format text ops sumeragi pacemaker shows backoff_ms / view_timeout_target_ms climbing, sumeragi_pacemaker_backpressure_deferrals_total and sumeragi_pacemaker_backpressure_deferrals_by_reason_total{reason=...} increment, and iroha --output-format text ops sumeragi phases lists inflated EMA totals. | Inspect sumeragi_phase_latency_* to locate the slow phase, check sumeragi_pacemaker_backpressure_deferral_age_ms{reason=...} plus sumeragi_bg_post_queue_depth{,_by_peer} and p2p_*_throttled_total, and clear RBC backlog pressure before restoring the original pacemaker multipliers. |
| DA availability missing with payloads pending | sumeragi_rbc_backlog_sessions_pending or sumeragi_rbc_backlog_chunks_total plateau, iroha --output-format text ops sumeragi rbc sessions shows chunks missing, and DA availability counters (sumeragi_da_gate_block_total{reason="missing_local_data"}) increase. | Verify the manifest hash and chunk availability, restart collectors that stopped ingesting votes, temporarily increase sumeragi.collectors.redundant_send_r, and document the stalled block hash (/v1/sumeragi/status.rbc_store.recent_evictions). |
| Collector stops ingesting votes | iroha --output-format text ops sumeragi telemetry reports flat availability.collectors[*].votes_ingested for a single index and sumeragi_bg_post_queue_depth_by_peer spikes for that collector. | Use iroha --output-format text ops sumeragi collectors to confirm the assignments, bump sumeragi.collectors.redundant_send_r to fan out to another collector, and debug the peer’s networking (firewall, queue saturation) before restoring the baseline redundancy. |
| Membership mismatch alert | sumeragi_membership_mismatch_active gauges flip to 1 and /v1/sumeragi/status.membership.view_hash differs between peers. | Compare /v1/configuration.sumeragi snapshots, ensure trusted_peers/stake snapshots are identical, restart any validator that failed to apply the latest config, and keep the lane quiesced until every peer reports the same roster hash. |
| VRF penalties creeping up | Prometheus alerts on increase(sumeragi_vrf_no_participation_total) / increase(sumeragi_vrf_non_reveal_penalties_total) or CLI telemetry shows growing penalties. | Follow {doc}sumeragi_randomness_evidence_runbook to pull the per-epoch participation table, contact the validator, collect the late reveal via POST /v1/sumeragi/vrf/reveal, and confirm the prf.epoch_seed remained stable. |
| RBC store evicts sessions faster than expected | sumeragi_rbc_store_pressure=2, sumeragi_rbc_store_evictions_total increases, and iroha --output-format text ops sumeragi status lists recent evictions for nearby heights. | Expand disk allowance, confirm sumeragi.advanced.rbc.store_max_bytes and sumeragi.collectors.redundant_send_r match the production template, and re-ingest the affected payload once collectors are healthy. |
Governance Checklist: Reconfiguration & Slashing
- Collect evidence via
/v1/sumeragi/evidenceoriroha_cli ops sumeragi evidence listwhile the height remains withinevidence_horizon_blocks. - Stage the penalty (e.g.,
Unregister::peer) and let the old validator set commit the block. - Cancel if needed by submitting
CancelConsensusEvidencePenaltywith the evidence payload beforeslashing_delay_blockselapses; the record is markedpenalty_cancelledandpenalty_cancelled_at_height, and no slashing applies. - Schedule activation by committing
SetParameter::Sumeragi::NextModeandSetParameter::Sumeragi::ModeActivationHeighttogether. The activation height must exceed the current height by at leastactivation_lag_blocks. - Verify the schedule with
iroha_cli --output-format text ops sumeragi params(or/v1/sumeragi/params) to confirm the stagednext_mode,mode_activation_height, andslashing_delay_blocksvalues. - Observe the switchover via
iroha_cli --output-format text ops sumeragi statusonce the activation height is committed;next_modeclears and the new set becomes active one block later.
Evidence API & CLI quick reference
- List —
iroha_cli --output-format text ops sumeragi evidence list(JSON via/v1/sumeragi/evidence) surfaces the total count and the most recent records; drop--output-format textfor the full Norito payload. - Filter — refine the snapshot with
--kind DoublePrepare/DoubleCommit/InvalidQc/InvalidProposal/Censorshipand paginate via--limit/--offsetwhen auditing large incident windows. - Count —
iroha_cli ops sumeragi evidence count(orGET /v1/sumeragi/evidence/count) reports the deduplicated total so operators can confirm that rejected payloads did not persist. - Submit —
iroha_cli ops sumeragi evidence submit --evidence-hex <0x…>(or--evidence-hex-file forged_evidence.hex) wrapsPOST /v1/sumeragi/evidencewith a hex-encoded Norito payload. Torii validates structure and signatures (vote signatures against the commit topology and chain ID), emitsinvalid consensus evidenceon mismatch, and never stores the entry. - Horizon audit —
iroha_cli --output-format text ops sumeragi paramsshows the activeevidence_horizon_blocks; governance updates flow throughSetParameter::Custom(SumeragiNposParameters)and tests guard short horizons to prevent stale replays from succeeding.
Evidence runbook (operator checklist)
- Record the current count via
iroha_cli ops sumeragi evidence countbefore submitting slashing material; the value should increase only after valid payloads are accepted. - When ingesting evidence manually, inspect the payload locally (for example with the Norito tooling or a staging node) to avoid propagating malformed votes before calling
iroha_cli ops sumeragi evidence submit. - After submission, poll
iroha_cli --output-format text ops sumeragi evidence listand confirm the new record’srecorded_at_heightequals the subject height (or the fallback height if horizon pruning applied). - Use
iroha_cli ops sumeragi evidence list --kind <Kind>to isolate double votes versus invalid QC/proposal reports; reconcile the paginated output (--limit,--offset) across peers to ensure the in-memory snapshot matches before/after governance actions. - If a payload is rejected with
invalid consensus evidence, inspect the CLI’s structured error and cross-check the underlying votes or proposal. No state change should occur; the count remains unchanged by design. - Periodically compare
/v1/sumeragi/evidence/countacross peers. Divergence indicates a horizon mismatch or a node that failed to persist the record and should trigger incident response. - Submit payloads with
iroha_cli ops sumeragi evidence submit --evidence-hex <0x…>or--evidence-hex-file forged_evidence.hex. Use--output-format textto surface the{kind, status}line; omit it to return the full JSON payload. - For pacemaker queue issues, run
python3 scripts/sumeragi_backpressure_log_scraper.py <logfile>(or pipejournalctl -f … | python3 scripts/sumeragi_backpressure_log_scraper.py -) to correlatepacemaker_backpressure_deferrals_totalspikes with "DA availability still missing (advisory)" logs and RBC backlog logs. Add--statuswhen you have a/v1/sumeragi/statussnapshot to include counter baselines; seescripts/sumeragi_backpressure_log_scraper.py --helpand the telemetry runbook for details.
CI coverage keeps the evidence pipeline honest:
integration_tests/tests/sumeragi_negative_paths.rsposts forged double-vote payloads with mismatched signer/height/view/epoch/signature metadata, invalid kind/payload pairings, and stale heights; each permutation must yieldinvalid consensus evidenceand leave the persisted count untouched.crates/iroha_core/src/sumeragi/evidence.rsround-trips every negative mutation through the Norito codec before feeding it to the validator so encode/decode cannot “heal” malformed payloads. The fuzz-style loop jitters signatures and block hashes to guard the deduplication keys.- The helper
set_evidence_horizonin the integration suite stages short horizons and proves that stale evidence sourced from old heights is ignored even when the network replays it later.