Home / Input Output / ouroboros-leios-sim
May 29, 11-12 PM (0)
May 29, 12-1 PM (0)
May 29, 1-2 PM (0)
May 29, 2-3 PM (0)
May 29, 3-4 PM (1)
May 29, 4-5 PM (0)
May 29, 5-6 PM (0)
May 29, 6-7 PM (0)
May 29, 7-8 PM (0)
May 29, 8-9 PM (0)
May 29, 9-10 PM (1)
May 29, 10-11 PM (2)
May 29, 11-12 AM (0)
May 30, 12-1 AM (0)
May 30, 1-2 AM (0)
May 30, 2-3 AM (0)
May 30, 3-4 AM (0)
May 30, 4-5 AM (0)
May 30, 5-6 AM (0)
May 30, 6-7 AM (0)
May 30, 7-8 AM (0)
May 30, 8-9 AM (0)
May 30, 9-10 AM (0)
May 30, 10-11 AM (0)
May 30, 11-12 PM (0)
May 30, 12-1 PM (0)
May 30, 1-2 PM (0)
May 30, 2-3 PM (0)
May 30, 3-4 PM (0)
May 30, 4-5 PM (0)
May 30, 5-6 PM (0)
May 30, 6-7 PM (0)
May 30, 7-8 PM (0)
May 30, 8-9 PM (0)
May 30, 9-10 PM (0)
May 30, 10-11 PM (0)
May 30, 11-12 AM (0)
May 31, 12-1 AM (0)
May 31, 1-2 AM (0)
May 31, 2-3 AM (0)
May 31, 3-4 AM (0)
May 31, 4-5 AM (0)
May 31, 5-6 AM (0)
May 31, 6-7 AM (0)
May 31, 7-8 AM (0)
May 31, 8-9 AM (0)
May 31, 9-10 AM (0)
May 31, 10-11 AM (0)
May 31, 11-12 PM (0)
May 31, 12-1 PM (0)
May 31, 1-2 PM (0)
May 31, 2-3 PM (0)
May 31, 3-4 PM (0)
May 31, 4-5 PM (0)
May 31, 5-6 PM (0)
May 31, 6-7 PM (0)
May 31, 7-8 PM (0)
May 31, 8-9 PM (0)
May 31, 9-10 PM (0)
May 31, 10-11 PM (0)
May 31, 11-12 AM (0)
Jun 01, 12-1 AM (0)
Jun 01, 1-2 AM (0)
Jun 01, 2-3 AM (0)
Jun 01, 3-4 AM (0)
Jun 01, 4-5 AM (0)
Jun 01, 5-6 AM (0)
Jun 01, 6-7 AM (0)
Jun 01, 7-8 AM (0)
Jun 01, 8-9 AM (0)
Jun 01, 9-10 AM (0)
Jun 01, 10-11 AM (0)
Jun 01, 11-12 PM (0)
Jun 01, 12-1 PM (0)
Jun 01, 1-2 PM (0)
Jun 01, 2-3 PM (0)
Jun 01, 3-4 PM (0)
Jun 01, 4-5 PM (1)
Jun 01, 5-6 PM (0)
Jun 01, 6-7 PM (0)
Jun 01, 7-8 PM (0)
Jun 01, 8-9 PM (0)
Jun 01, 9-10 PM (0)
Jun 01, 10-11 PM (0)
Jun 01, 11-12 AM (0)
Jun 02, 12-1 AM (0)
Jun 02, 1-2 AM (0)
Jun 02, 2-3 AM (0)
Jun 02, 3-4 AM (0)
Jun 02, 4-5 AM (0)
Jun 02, 5-6 AM (0)
Jun 02, 6-7 AM (0)
Jun 02, 7-8 AM (0)
Jun 02, 8-9 AM (0)
Jun 02, 9-10 AM (1)
Jun 02, 10-11 AM (1)
Jun 02, 11-12 PM (0)
Jun 02, 12-1 PM (2)
Jun 02, 1-2 PM (5)
Jun 02, 2-3 PM (5)
Jun 02, 3-4 PM (0)
Jun 02, 4-5 PM (0)
Jun 02, 5-6 PM (0)
Jun 02, 6-7 PM (0)
Jun 02, 7-8 PM (0)
Jun 02, 8-9 PM (0)
Jun 02, 9-10 PM (0)
Jun 02, 10-11 PM (0)
Jun 02, 11-12 AM (0)
Jun 03, 12-1 AM (0)
Jun 03, 1-2 AM (0)
Jun 03, 2-3 AM (0)
Jun 03, 3-4 AM (0)
Jun 03, 4-5 AM (0)
Jun 03, 5-6 AM (5)
Jun 03, 6-7 AM (0)
Jun 03, 7-8 AM (0)
Jun 03, 8-9 AM (0)
Jun 03, 9-10 AM (3)
Jun 03, 10-11 AM (0)
Jun 03, 11-12 PM (0)
Jun 03, 12-1 PM (1)
Jun 03, 1-2 PM (0)
Jun 03, 2-3 PM (0)
Jun 03, 3-4 PM (0)
Jun 03, 4-5 PM (0)
Jun 03, 5-6 PM (0)
Jun 03, 6-7 PM (0)
Jun 03, 7-8 PM (0)
Jun 03, 8-9 PM (0)
Jun 03, 9-10 PM (0)
Jun 03, 10-11 PM (0)
Jun 03, 11-12 AM (0)
Jun 04, 12-1 AM (0)
Jun 04, 1-2 AM (0)
Jun 04, 2-3 AM (0)
Jun 04, 3-4 AM (0)
Jun 04, 4-5 AM (0)
Jun 04, 5-6 AM (0)
Jun 04, 6-7 AM (0)
Jun 04, 7-8 AM (0)
Jun 04, 8-9 AM (0)
Jun 04, 9-10 AM (0)
Jun 04, 10-11 AM (0)
Jun 04, 11-12 PM (0)
Jun 04, 12-1 PM (0)
Jun 04, 1-2 PM (0)
Jun 04, 2-3 PM (0)
Jun 04, 3-4 PM (0)
Jun 04, 4-5 PM (0)
Jun 04, 5-6 PM (0)
Jun 04, 6-7 PM (0)
Jun 04, 7-8 PM (0)
Jun 04, 8-9 PM (0)
Jun 04, 9-10 PM (0)
Jun 04, 10-11 PM (0)
Jun 04, 11-12 AM (0)
Jun 05, 12-1 AM (0)
Jun 05, 1-2 AM (0)
Jun 05, 2-3 AM (0)
Jun 05, 3-4 AM (0)
Jun 05, 4-5 AM (0)
Jun 05, 5-6 AM (0)
Jun 05, 6-7 AM (0)
Jun 05, 7-8 AM (0)
Jun 05, 8-9 AM (0)
Jun 05, 9-10 AM (0)
Jun 05, 10-11 AM (0)
Jun 05, 11-12 PM (0)
28 commits this week May 29, 2026 - Jun 05, 2026
demo: simplify network emulation variables and align proto-devnet to bridge topology
Collapse the 8 per-direction RATE/DELAY variables in demo/burst into a
single RATE and DELAY, matching the convention in demo/proto-devnet.
Replace associative arrays with simple PEERS lists.

Switch demo/proto-devnet from point-to-point veths with IFB-based
ingress delay to the same bridge topology used in demo/burst: a shared
bridge in ns-br with prio+netem on the bridge-side veths for delay and
HTB on the node-side for rate limiting.

Also: use bash arithmetic instead of bc for jitter, add namespace
cleanup trap in demo/burst run.sh.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
net-core: log the resolved peer IP per connection
Carry the concrete socket address the TCP connection landed on
(`resolved_addr`) on `Connection`/`DuplexConnection`, and log it with
the peer_id at connect time:

  peer connected (duplex) peer_id=peer-0
    host=leios-node.play.dev.cardano.org:3001 resolved_ip=52.29.179.71:3001

The host is often a round-robin DNS name, so each (re)connection can
land on a different backend.  Since the per-peer Leios trace logs are
keyed by peer_id, this one line lets a given EB's activity be
attributed to the specific IP that served it.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
net-core: trace Leios client EB/vote activity with full hashes
Add client-side tracing to the per-peer LeiosNotify and LeiosFetch
sub-tasks so a follower's logs can be cross-referenced against a peer's
(e.g. a relay's) server-side logs:

  - leios_notify: EB offered / EB txs offered (slot + full eb_hash),
    votes received (count; per-vote slot/eb_hash/voter_id/sig at debug),
    EB announcement (header size).
  - leios_fetch: requesting EB / EB received (slot, full eb_hash,
    manifest bytes); requesting EB txs / received (requested index
    count + first indices); request-failed warnings carry the same
    fields so a disconnect is attributable to a specific EB.

EB hashes are logged in full (32 bytes) — the natural correlation key
against a relay's logs.  info level for the per-EB events, debug for
per-vote detail.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
net: align LeiosFetch with the prototype CDDL
Bring the LeiosFetch mini-protocol up to the cardano-blueprint
leios-prototype CDDL, fixing the live `leios_fetch block: expected
bytes, got map` disconnect when fetching an EB from the dev relay.

Wire changes:
  - msgLeiosBlock = [1, endorser_block] where
    endorser_block = { tx_hash => tx_size } (a CBOR map, previously
    decoded as an opaque bytestring).  The codec now captures/splices
    the map's raw CBOR verbatim (minicbor input()/writer_mut()), so the
    `block: Vec<u8>` plumbing is unchanged — the bytes simply *are* the
    manifest map.
  - msgLeiosBlockTxs = [3, point, bitmaps, tx_list] (was [3, tx_list]);
    the server now echoes the request's point + bitmap.  Each tx in
    tx_list is carried as raw CBOR (opaque pass-through), so a
    structured `tx.tx` from a real peer round-trips.
  - Removed the block-range sub-protocol (msgLeiosBlockRangeRequest [6],
    msgLeiosNext/LastBlockAndTxsInRange [7]/[8], StBlockRange,
    fetch_block_range) — gone from the spec.

net-node: encode/decode_overflow_eb now (de)serialise the
`{ hash => size }` manifest map (sizes 0 on the produce path; the EB
blob's slot is dropped — it was never read).  Callers/tests updated.

Verified against the live Leios dev relay (magic 164): an EB is fetched,
the manifest decodes, an election is created (phase CertEligible), and
an EB-tx fetch is issued — zero CBOR decode errors.  Tests: net-core
318, net-node 112, shared-consensus 297, net-cli green.

Known follow-up: the relay sends a TCP RST shortly after our
MsgLeiosBlockTxsRequest (bitmap EB-tx fetch); no decode error on our
side, connection reconnects and resyncs.  Separate behavioural item.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
shared-consensus: remove the now-dead VoteFetchPolicy
Votes are delivered inline (previous commit), so the vote offer→fetch
machinery has no callers.  Remove it across the workspace:

  - shared-consensus fetch.rs: drop the VoteFetchPolicy trait, its
    LowestRttFirst/BroadcastN/NoFetch impls, VoteCandidateLookup, and
    the CandidateTracker vote_offers / pending_vote_fetches fields plus
    note_vote_offered / vote_candidates / start_vote_fetch /
    finish_vote_fetch.  state_sizes() drops its two vote counters.
    VoteId stays as a generic (slot, voter_id) tuple (sim-rs keys its
    own vote state on it).
  - shared-consensus leios.rs: drop the vote_policy field, the
    with_fetch vote_policy param, and set_vote_policy.
  - net-node / sim-rs: drop the `votes` fetch-policy config field,
    into_vote_policy, and the set_vote_policy wiring; drop the
    fetch_policy.votes doc from mainnet.toml.

EB / EB-tx fetch policies are untouched.  Tests: shared-consensus 297,
net-core 322, net-node 112, net-cli 57 pass.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
leios: deliver votes inline, remove the offer→fetch round-trip
CIP-0164's prototype (cardano-blueprint leios-prototype) delivers Leios
votes inline in LeiosNotify rather than offering vote ids to be pulled
over LeiosFetch.  This reworks net-rs + shared-consensus to match and
makes the prototype vote shape drive quorum natively.

Wire (net-core):
  - msgLeiosBlockOffer = [2, point, eb_size]  (gained eb_size: word32)
  - msgLeiosVotes      = [4, [vote, ...]]      (replaces msgLeiosVotesOffer)
      vote = [slot, eb_hash, voter_id: word16, vote_signature: bool]
  Decoders now read the declared array length and skip trailing
  elements, so a future field addition degrades gracefully instead of
  desyncing the mux stream (the bug that dropped the dev-relay link).
  Captured dev-relay frames are pinned as codec test vectors.  Removed
  the LeiosFetch votes-request/delivery messages (gone from the spec).

shared-consensus:
  - New canonical types::Vote (re-exported); CBOR codec stays in the
    net I/O layer so this crate remains format-agnostic.
  - Deterministic u16<->node_id voter index (Elections::voter_index /
    voter_id_at: position in the sorted stake registry, identical on
    every node) lets inline votes resolve to a committee weight.
  - on_votes_received now takes Vec<Vote> and feeds aggregation
    directly (mocked bool signatures need no ledger validation step);
    removed on_votes_offered, LeiosEffect::FetchLeiosVotes /
    ValidateVotes, and the vote behaviour-offer hooks.

Plumbing / node:
  - PeerEvent/NetworkEvent::LeiosVotesReceived carry Vec<Vote>; the
    coordinator dedups (peer, slot, eb_hash, voter_id) and re-injects
    into LeiosStore for epidemic gossip.  Self-vote production emits a
    structured Vote with the node's own index.  Removed the opaque
    VoteBody codec and the vote ledger-validation command/outcome.

Verified: shared-consensus 298, net-core 322, net-node 112, net-cli 57
tests pass.  Interop vs the live Leios dev relay (magic 164) no longer
drops on LeiosNotify decode.  A 30-node StakeCentile cluster reaches
stake-weighted LeiosQuorumReached purely from inline votes, no fetch.

Out of scope (follow-ups): LeiosFetch is a further CDDL revision behind
(endorser_block is now a {hash => size} map, done moved to [9],
block-txs gained bitmaps); the vestigial VoteFetchPolicy.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
shared-consensus: never anchor a BlockFetch range at Origin
A standard Cardano BlockFetch server resets the bearer when it
receives a MsgRequestRange whose lower bound is the genesis point:
Origin carries no block, so the range cannot be resolved.

On first connect the ChainSync intersection is at Origin, and both
FetchBlockRange emit sites could surface it as the range's `from`:

  - issue_fetch_internal used `anchor_point` (the intersection) as the
    lower bound, which is Some(Origin) for a genesis intersection.
  - the gap-bridge retry fell back to `unwrap_or(Point::Origin)` when
    there was no adopted tip.

Both now require a real block point: issue_fetch_internal falls back
to the oldest missing block when the anchor is Origin, and the
gap-bridge only fires when an adopted tip provides a lower bound.

Found via interop testing net-node against a live Leios dev relay
(leios-node.play.dev.cardano.org): the relay RST the connection
immediately after our RequestRange(Origin, <first header>). With the
fix the node syncs cleanly (handshake -> ChainSync -> BlockFetch ->
validation, no resets). Mainnet never exercised this path because its
Byron-era genesis headers aren't parsed, so no fetch was ever issued
from Origin.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
net-node: restore MemorySizes per-slot telemetry dropped in main merge
The per-slot memory telemetry added in 8bc4da50e was silently lost when
resolving conflicts during the "Merged with github main" merge
(da54b615c): the NodeEvent enum and main.rs took main's side, discarding
the MemorySizes additions. The shared-consensus state_sizes() snapshots
and LeiosStoreStats survived, but nothing assembled them into an event,
so scripts/memory-report.py reported "no MemorySizes events found".

Re-applies the net-node / net-core wiring against the post-merge tree:

  - telemetry.rs: NodeEvent::MemorySizes(Box<MemorySizesPayload>) plus
    the MemorySizesPayload and FragmentSizes structs and their test.
  - consensus/mod.rs: praos_state_sizes() / leios_state_sizes() wrappers.
  - coordinator.rs: per-peer fragment_sizes snapshot, kept in sync on
    every fragment mutation (intersection, header announce, rollback,
    add/remove peer); exposed through the handle.
  - mod.rs: CoordinatorHandle gains leios_store + fragment_sizes so the
    app can read sizes without a command round-trip.
  - main.rs: emit one MemorySizes event per slot.
  - Cargo.lock: reflect net-core's existing serde dependency.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>