Use latest remake cardano-node
Home /
Input Output /
ouroboros-leios
May 17, 9-10 AM (0)
May 17, 10-11 AM (0)
May 17, 11-12 PM (0)
May 17, 12-1 PM (0)
May 17, 1-2 PM (0)
May 17, 2-3 PM (0)
May 17, 3-4 PM (0)
May 17, 4-5 PM (0)
May 17, 5-6 PM (0)
May 17, 6-7 PM (0)
May 17, 7-8 PM (0)
May 17, 8-9 PM (0)
May 17, 9-10 PM (0)
May 17, 10-11 PM (0)
May 17, 11-12 AM (0)
May 18, 12-1 AM (0)
May 18, 1-2 AM (0)
May 18, 2-3 AM (0)
May 18, 3-4 AM (0)
May 18, 4-5 AM (0)
May 18, 5-6 AM (0)
May 18, 6-7 AM (0)
May 18, 7-8 AM (0)
May 18, 8-9 AM (1)
May 18, 9-10 AM (0)
May 18, 10-11 AM (1)
May 18, 11-12 PM (0)
May 18, 12-1 PM (0)
May 18, 1-2 PM (0)
May 18, 2-3 PM (0)
May 18, 3-4 PM (0)
May 18, 4-5 PM (0)
May 18, 5-6 PM (0)
May 18, 6-7 PM (0)
May 18, 7-8 PM (0)
May 18, 8-9 PM (0)
May 18, 9-10 PM (0)
May 18, 10-11 PM (0)
May 18, 11-12 AM (0)
May 19, 12-1 AM (0)
May 19, 1-2 AM (0)
May 19, 2-3 AM (0)
May 19, 3-4 AM (0)
May 19, 4-5 AM (0)
May 19, 5-6 AM (0)
May 19, 6-7 AM (0)
May 19, 7-8 AM (0)
May 19, 8-9 AM (2)
May 19, 9-10 AM (0)
May 19, 10-11 AM (0)
May 19, 11-12 PM (1)
May 19, 12-1 PM (0)
May 19, 1-2 PM (0)
May 19, 2-3 PM (1)
May 19, 3-4 PM (3)
May 19, 4-5 PM (0)
May 19, 5-6 PM (3)
May 19, 6-7 PM (0)
May 19, 7-8 PM (0)
May 19, 8-9 PM (0)
May 19, 9-10 PM (0)
May 19, 10-11 PM (0)
May 19, 11-12 AM (0)
May 20, 12-1 AM (0)
May 20, 1-2 AM (0)
May 20, 2-3 AM (0)
May 20, 3-4 AM (0)
May 20, 4-5 AM (0)
May 20, 5-6 AM (0)
May 20, 6-7 AM (0)
May 20, 7-8 AM (0)
May 20, 8-9 AM (0)
May 20, 9-10 AM (3)
May 20, 10-11 AM (2)
May 20, 11-12 PM (0)
May 20, 12-1 PM (0)
May 20, 1-2 PM (4)
May 20, 2-3 PM (0)
May 20, 3-4 PM (88)
May 20, 4-5 PM (6)
May 20, 5-6 PM (0)
May 20, 6-7 PM (0)
May 20, 7-8 PM (0)
May 20, 8-9 PM (0)
May 20, 9-10 PM (1)
May 20, 10-11 PM (0)
May 20, 11-12 AM (0)
May 21, 12-1 AM (0)
May 21, 1-2 AM (0)
May 21, 2-3 AM (0)
May 21, 3-4 AM (0)
May 21, 4-5 AM (0)
May 21, 5-6 AM (0)
May 21, 6-7 AM (0)
May 21, 7-8 AM (0)
May 21, 8-9 AM (0)
May 21, 9-10 AM (0)
May 21, 10-11 AM (2)
May 21, 11-12 PM (1)
May 21, 12-1 PM (5)
May 21, 1-2 PM (0)
May 21, 2-3 PM (0)
May 21, 3-4 PM (0)
May 21, 4-5 PM (1)
May 21, 5-6 PM (0)
May 21, 6-7 PM (0)
May 21, 7-8 PM (0)
May 21, 8-9 PM (0)
May 21, 9-10 PM (0)
May 21, 10-11 PM (0)
May 21, 11-12 AM (0)
May 22, 12-1 AM (0)
May 22, 1-2 AM (0)
May 22, 2-3 AM (0)
May 22, 3-4 AM (0)
May 22, 4-5 AM (1)
May 22, 5-6 AM (1)
May 22, 6-7 AM (1)
May 22, 7-8 AM (0)
May 22, 8-9 AM (1)
May 22, 9-10 AM (0)
May 22, 10-11 AM (0)
May 22, 11-12 PM (0)
May 22, 12-1 PM (0)
May 22, 1-2 PM (0)
May 22, 2-3 PM (1)
May 22, 3-4 PM (0)
May 22, 4-5 PM (0)
May 22, 5-6 PM (0)
May 22, 6-7 PM (0)
May 22, 7-8 PM (0)
May 22, 8-9 PM (3)
May 22, 9-10 PM (4)
May 22, 10-11 PM (4)
May 22, 11-12 AM (0)
May 23, 12-1 AM (0)
May 23, 1-2 AM (0)
May 23, 2-3 AM (0)
May 23, 3-4 AM (0)
May 23, 4-5 AM (0)
May 23, 5-6 AM (0)
May 23, 6-7 AM (1)
May 23, 7-8 AM (0)
May 23, 8-9 AM (0)
May 23, 9-10 AM (0)
May 23, 10-11 AM (0)
May 23, 11-12 PM (0)
May 23, 12-1 PM (0)
May 23, 1-2 PM (0)
May 23, 2-3 PM (0)
May 23, 3-4 PM (0)
May 23, 4-5 PM (0)
May 23, 5-6 PM (0)
May 23, 6-7 PM (0)
May 23, 7-8 PM (0)
May 23, 8-9 PM (0)
May 23, 9-10 PM (0)
May 23, 10-11 PM (0)
May 23, 11-12 AM (0)
May 24, 12-1 AM (0)
May 24, 1-2 AM (0)
May 24, 2-3 AM (0)
May 24, 3-4 AM (0)
May 24, 4-5 AM (0)
May 24, 5-6 AM (0)
May 24, 6-7 AM (0)
May 24, 7-8 AM (0)
May 24, 8-9 AM (0)
May 24, 9-10 AM (0)
142 commits this week
May 17, 2026
-
May 24, 2026
demo/burst: tolerate missing data.mux_at in load_sendrecv_node
ouroboros-network's LogFormatting for TraceSendRecv was discarding the bearer Time argument carried by TraceSendMsg/TraceRecvMsg, so the node-side trace events have no data.mux_at. Every record then hit the bare 'except Exception: continue' guard and the node frame came back empty. Fall back to the outer 'at' when data.mux_at is absent so the table renders against logs from binaries that don't emit the field. Once cardano-node is rebuilt against the ouroboros-network change that exposes mux_at, the field populates and the send/transport/recv latency columns work.
Tx-centrifuge without cooldown
Fix an exception in analyse.py
Update demo/burst setup to Dijkstra and new data
The new dataset was recored with the demo/proto-devnet scenario and a TC=0 setting allows to quickly iterate without requiring sudo.
IDEA-NeighborhoodFarPeers.md: add very concrete Appendix
Tx-centrifuge without cooldown
Remade traces in cardano-node
IDEA-NeighborhoodFarPeers.md: fix typo
Bump to latest remake cardano-node
Update demo/burst setup to Dijkstra and new data
The new dataset was recored with the demo/proto-devnet scenario and a TC=0 setting allows to quickly iterate without requiring sudo.
Hard-fork into Dijkstra in proto-devnet
WIP: demo/burst setup
WIP: demo/burst setup
WIP: demo/burst setup
WIP: demo/burst setup
WIP: demo/burst setup
net-rs: dynamic attack trigger from the UI
Lets researchers install (and stop) a per-node behaviour spec at runtime on a subset of nodes, instead of fixing it at cluster startup, so they can observe the network's reaction to misbehaviour without losing chain state to a restart. net-node remembers the BehaviourSpec it materialised at startup and gains a behaviour_reset stdin path that walks the handle back to it; net-cluster gains a per-child targeted send_config_update_to and three /api/attack routes (GET / POST / POST stop) driven by the existing BehaviourSelection enum, with the main-loop arm resetting any prior set before applying a new one and clearing the active attack across restarts. The new AttackPanel and orange-explosion toolbar icon let the UI install/stop attacks; attacking nodes are tinted dark red in the topology graph (bgColor only, leaving border flashes intact) and surfaced in the node inspector. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Make the haskell simulation buildable
net-rs: wire tcp-congestion-control param to TcpConnection
Previously use_tcp was hardcoded to false on every LinkConfiguration. Now RawParameters::tcp_congestion_control (default true) is propagated to all links during SimConfiguration::build, so users can disable the TCP congestion-window model via yaml with `tcp-congestion-control: false`. Update config.schema.json to reflect Rust support and add default: true. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
net-rs: implement TcpConnection (Chan.TCP port)
Port the Haskell `Chan/TCP.hs` channel abstraction to Rust. `TcpConnection<TMessage>` models one direction of a full-duplex TCP link using `forecast_tcp_msg_send` for timing. Key design decisions: - Backpressure via `send_cursor`: the effective send time is `max(now, send_cursor)`, so overlapping sends queue behind their predecessor — the same role the one-slot `TMVar` plays in Haskell. - Idle reset (RFC 6298 RTO): when the link has been quiet for longer than `max(1 s, RTT)` and all in-flight ACKs have returned, the congestion window is reset to the initial value. - Messages are queued with arrival time = `recv_trailing_edge` (the receiver needs the complete message, not just the leading edge). Integration: - `ConnectionKind<TP, TM>` enum wraps both `Connection` (bandwidth- sharing) and `TcpConnection` with a uniform interface so the rest of the network layer is unchanged. - `LinkConfiguration` and `EdgeConfig` gain a `use_tcp: bool` flag (default `false`); both the actor and sequential engines route through `ConnectionKind::from_config`. - `TcpState::all_acks_arrived` added to support the idle-reset check. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
net-rs: add TCP congestion-window model
Port the Haskell `ModelTCP` module to Rust as `sim-core/src/tcp.rs`.
The model forecasts send timing for a stream of messages over a single
TCP connection, accounting for serialisation delay, one-way propagation
latency, and the congestion window (slow-start through to steady state).
Key design points:
- `forecast_tcp_msg_send` is a pure function: takes props + state + now
+ message size, returns the overall forecast, per-fragment forecasts,
and the updated state. No IO, easy to test.
- ACKs are anchored to the *receive leading edge* ("strategic cheat"):
approximates per-segment ACK pipelining without modelling individual
segments, preventing the model from understating throughput.
- `merge_adjacent_fragments` collapses contiguous window-fill chunks so
the fragment count stays bounded across long sends.
- Six unit tests cover: small message timing, per-fragment invariants,
large-message fragmentation, fragment merging, and the trace helper.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
net-core: stop dispatch-loop stall from disconnecting healthy peers
A 25-node smoke cluster at p=0.1 RB generation accumulated 62
"peer command channel full" disconnects over ~16 minutes, with
lagging nodes ~100s behind the leaders. Tip distribution fragmented
into 8 chains spanning 9 blocks even though all nodes shared
ancestry — not a partition, just receive-side starvation.
Root cause: each peer task has small sub-channels feeding the
client protocol sub-tasks (fetch=16, peer_share=4, tx_submit=16,
cs_reintersect=4, leios_fetch=16). The shared command-dispatch
loop uses `.send().await` on each, so when any sub-channel fills,
the dispatch loop blocks. While blocked, no commands move from
the per-peer `commands` channel (cap 4096) — which then fills under
high `ProvideTxs` traffic and trips the coordinator's "command
channel full" disconnect via try_send. Healthy peers were being
torn down for downstream slowness.
The `ProvideTxs { txs: Vec<…> }` path unspools one tx per
`.send().await`, so a single 30-tx batch already consumed nearly
twice tx_submit's capacity.
Fix:
- Bump sub-channel caps to match expected burst sizes: fetch and
leios_fetch to 256, tx_submit to 1024, the small signal channels
(peer_share, cs_reintersect) to 16. Applied symmetrically in
peer_task.rs and duplex_task.rs.
- Switch `tx_submit` from `.send().await` to `try_send` with a
drop-and-warn on Full. Tx propagation is best-effort gossip —
another peer will re-broadcast — so dropping is preferable to
stalling the dispatch loop and tearing down the connection.
Fetches (FetchBlocks, FetchLeios*) keep `.send().await` since
those are correctness-critical.
Verified live: rebuilt cluster at p=0.1 holds a single tip across
all 25 nodes with zero "command channel full" disconnects through
block 30 of the new run.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
shared-consensus: cert targets parent RB's EB only, drop sticky-cert API
CIP-0164 Linear Leios specifies that the cert in an RB endorses the EB announced by the immediately preceding RB. sim-rs's `linear_leios.rs` implements it that way: `latest_rb_id()` → `ebs_by_rb.get(rb_id)` → quorum + pipeline-timing check → `Some(Endorsement)` or `None`. shared-consensus instead exposed `has_certified_eb()` / `certified_eb_slot()` — global queries across the elections map that returned whichever quorum-reached EB happened to be in CertEligible right now. Under high RB generation rates this produced ~100% endorsement: every RB found *some* older EB in the 10-slot CertEligible window and attached its cert, regardless of whether that EB belonged to the parent RB. Fix: - New `ChainTree::announced_eb_hash_by(rb_hash)`. Already stored on every `ChainNode`; just needed an accessor. - New `Elections::eb_certifiable_slot(eb_hash) -> Option<u64>` — returns the announced slot iff *that specific* election is at quorum and in CertEligible. Replaces both `has_certified_eb()` and `certified_eb_slot()`, which are gone. - New `LeiosState::eb_certifiable_slot(eb_hash)` delegate. - New `Consensus::cert_for_parent()` on the net-node facade: composes `praos.adopted_tip_announced_eb()` and `leios.eb_certifiable_slot()` so the producer can ask, "is the parent RB's EB certifiable?" in one call. - `main.rs` producer uses `cert_for_parent()` instead of the two retired methods. Verified live: at rb_generation_probability=0.25 (mean gap ≈4 slots, well below the 13-slot CertEligible floor), the rebuilt cluster produces zero certs — correct under this rule, parent's EB never matures in time. At p=0.1 (mean gap ≈10 slots), certs appear when the inter-RB gap exceeds 13 and not otherwise — observed live as gaps 1→2 and 3→4 (long) producing certs, gap 2→3 (short) not. Tests updated: `eb_certifiable_slot_targets_specific_hash` in net-node's leios facade exercises a per-hash lookup with two elections at different stages; the elections.rs unit test asserts the new accessor on a single hash and that unrelated hashes return None. Old `certified_eb_slot_returns_latest_quorum_election` deleted (it asserted the wrong protocol semantics). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
shared-consensus: accept genesis as common ancestor in select_chain
When two RB producers won the same slot-1 lottery and their blocks
both reached the cluster, every node would lock onto the variant it
saw first, classify the rival chain as `OrphanCandidate`, never fetch
it, and the partition would persist indefinitely. Observed in a
25-node smoke cluster: 13:12 split rooted at block 1, both halves
extending independently for tens of blocks despite being connected
by 13 cross-partition peers.
Root cause: `select_chain_once`'s common-ancestor search refused to
accept genesis as the ancestor unless the local node was at genesis
itself:
None => {
if self.adopted_tip_hash.is_none() {
ancestor = Some([0u8; 32]);
}
}
So a fork at block 1 (peer's oldest entry has `prev_hash = None`)
gave no ancestor, and the candidate was tagged orphan. Genesis is
a universal common ancestor — every valid chain descends from it —
and the validator still re-applies each replayed block, so accepting
it is safe. Drop the `is_none()` gate.
Tests:
- shared-consensus: new `select_chain_genesis_rooted_fork_is_not_orphan`
asserts `WaitingForBlocks { ancestor: [0; 32], .. }` when a peer's
block 1 has `prev_hash = None` and beats the local tip on the
lower-hash tie-break.
- net-node: `select_chain_accepts_genesis_ancestor_for_adopted_node`
was previously asserting `OrphanCandidate` despite its docstring
promising the opposite (a "regression test for the Origin-as-
ancestor fix" that locked in the bug). Flipped the assertion to
`WaitingForBlocks { ancestor: [0; 32], .. }`.
Verified live: 25-node cluster converges to a single tip immediately
where it previously held a 13:12 split for the full run.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>