Skip to content

fix: update the Leios setup to the latest prototype - #3706

Merged
mkoura merged 5 commits into
masterfrom
update_leios_rel_0921
Sep 22, 2026
Merged

mkoura merged 5 commits into
masterfrom
update_leios_rel_0921

Conversation

@mkoura

@mkoura mkoura commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Bumps cardonnay to 0.4.7 and turns on POOLS_IN_GENESIS for the Leios
testrun, then fixes the test fallout of that setup and of the latest
leios-prototype node.

POOLS_IN_GENESIS

Pool re-registration fails on a testnet that starts in Dijkstra, because the
Dijkstra POOL rule expects every registered pool's VRF key hash in
psVRFKeyHashes and genesis staking injection records none. POOLS_IN_GENESIS
(cardonnay 0.4.7) sidesteps it by writing the full pool parameters into the
genesis instead of submitting a registration transaction.

That puts the pools - BLS keys included - in the initial ledger state, which
changes when the Leios voting committee is seated.

test_no_voting_before_committee_epoch

The test checks that no EB is voted on before the committee becomes active in
VOTING_START_EPOCH. With the pools in the genesis there is no such window:
all three pools voted in epoch 0 and no pool ever reported NotOnCommittee, so
the test failed on a premise that no longer holds.

The genesis always lists the pools created by genesis create-staked --gen-pools, so their presence says nothing; the BLS key in their entries is
what separates a genesis-seated pool from one registered by a transaction. The
new _is_committee_seated_in_genesis reads it from extraConfig.stakePools,
or from staking.pools before cardano-cli 11.2, and the test skips on it as
its first act - before the wait that can otherwise burn a whole epoch.

Checked against the genesis of five local clusters: True for the three
leios_fast ones, False for both local_fast ones.

Stake snapshots

test_stake_snapshot failed with:

KeyError: "Neither 'activeStake' nor 'stake' found in stake snapshot"

The pstakeMark, pstakeSet and pstakeGo entries of esSnapshots are no
longer the stake distribution itself - it moved under a snapShot key, next to
the new epochNo and leiosCommitteeSize fields.

unwrap_snapshot returns the snapShot value when there is one and the entry
itself otherwise, and get_stake_rec and get_snapshot_delegations read the
entries through it. The older layouts keep working, with or without the
wrapper: activeStake of cardano-node 10.7+, and stake / delegations
before it. cardano-cli query stake-snapshot is unaffected; it only gained a
leiosCommittee key.

NoLedgerView under Tx load

Teardowns failed on Forge.Loop.NoLedgerView in a node log. The forge loop
forecasts the ledger view from the tip of the chain the node has selected, and
ledgerViewForecastAt reaches only stabilityWindow = 3k/f slots past that
tip - 240 slots on leios_fast, at k=4, f=0.05 and a 1 s slot. A node kept busy
by tx-firehose or tx-centrifuge can fall further behind than that. It then
skips the slot it was about to forge and recovers as soon as it catches up, so
nothing is wrong with the node; the trace only lands in whatever test happens
to be in teardown and is reported as that test's failure.

_get_ignored_error_regexes now ignores it, gated on ENABLE_TX_CENTRIFUGE or
ENABLE_TX_FIREHOSE, next to the existing GITHUB_ACTIONS and testnet gates.
Without a Tx load generator a node falling that far behind is still reported.

This silences the noise, it does not change the odds. The 240-slot window holds
only about 10.7 expected blocks at the measured chain density of 0.045, so the
tail is fat; the underlying fix would be a larger k in the testnet variant.
Raising k is cheap for this repo - every test reads it from the genesis, and
clusterlib_utils.get_stability_window already derives 3k/f - but it belongs
in cardonnay, not here.

Deselect list

Every entry of scripts/deselected_leios_tests.txt was there for one cause,
the missing PlutusV2 cost model in the Dijkstra genesis, which the node no
longer has - query protocol-parameters now reports a PlutusV2 entry in
costModels.

The list and its wiring are gone, together with the skip_deselect workflow
input, which only existed to clear a DESELECT_FROM_FILE coming from an env
file and no env file sets one anymore. The generic deselect machinery in
runner/run_tests.sh and the tcache path stay.

Testing

  • Unit tests: 427 passed, 1 xfailed. Includes 12 new ones covering all three
    snapshot layouts, both helpers and both KeyError paths, and a new case on
    test_get_ignored_error_regexes for the Tx load gate.
  • test_stake_snapshot passes against a local Dijkstra + Leios cluster whose
    ledger state does carry the snapShot wrapper.
  • The last regression run had a result for all 107 tests of the deselect list:
    48 passed, 59 were collected but not reached before the end of the session,
    none failed. The 48 cover 13 of the 18 affected modules and every
    sub-pattern - raw and build minting and spending, the mix_v1_v2 and
    mix_v2_v1 two-script cases, secp256k1 ecdsa and schnorr, inline datum and
    reference script visibility, and reference inputs. Five more were rerun
    locally and pass.

test_no_voting_before_committee_epoch is verified only on the skip path; the
setup where the committee is not seated in the genesis needs a run on a testnet
variant without POOLS_IN_GENESIS.

`test_no_voting_before_committee_epoch` checks that no EB is voted on
before the Leios voting committee becomes active in `VOTING_START_EPOCH`.
The premise no longer holds on the `leios_fast` testnet variant, where
every pool votes from the first slot, so the test failed with a vote,
a peer vote and a certificate reported by all three pools in epoch 0.

The committee is drawn from a stake distribution snapshot. A pool
registered by a transaction on a freshly started cluster instance gets
into one only in `VOTING_START_EPOCH`, but cardonnay's `POOLS_IN_GENESIS`
writes the pool parameters, BLS key included, straight into the genesis
to avoid `VRFKeyHashAlreadyRegistered` on testnets that start in
Dijkstra. Such a pool is in the initial ledger state and therefore on
the committee from slot 0.

The genesis always lists the pools created by `genesis create-staked
--gen-pools`, so their presence doesn't tell the two setups apart, while
the BLS key in their entries does. Add `_is_committee_seated_in_genesis`,
which reads it from `extraConfig` or, before cardano-cli 11.2, from
`staking`, and skip on it as the first thing the test does, before the
wait that can otherwise burn a whole epoch.
`test_stake_snapshot` fails on a Leios enabled node with:

  KeyError: "Neither 'activeStake' nor 'stake' found in stake snapshot"

The `pstakeMark`, `pstakeSet` and `pstakeGo` entries of `esSnapshots`
are no longer the stake distribution itself. The distribution moved
under a `snapShot` key, next to the new `epochNo` and
`leiosCommitteeSize` fields, so `get_stake_rec` and
`get_snapshot_delegations` no longer find the record they look for.

Add `unwrap_snapshot`, which returns the `snapShot` value when there is
one and the entry itself otherwise, and read the entries through it.
The older layouts, `activeStake` of cardano-node 10.7+ and the `stake`
and `delegations` of the versions before it, are kept working, with or
without the wrapper. The `cardano-cli query stake-snapshot` output is
not affected; it only gained a `leiosCommittee` key.

Cover all three layouts with unit tests.
Every entry of `scripts/deselected_leios_tests.txt` was there for one
cause, the missing PlutusV2 cost model in the Dijkstra genesis, which
the node no longer has - `query protocol-parameters` reports a PlutusV2
entry in `costModels`.

The latest regression run in `run_workdir` ran without the list and
has a result for all 107 of its tests: 48 passed, 59 were collected but
not reached before the end of the session, none failed. The 48 cover 13
of the 18 affected modules and every sub-pattern of the list - raw and
build minting and spending, the `mix_v1_v2` and `mix_v2_v1` two-script
cases, secp256k1 ecdsa and schnorr, inline datum and reference script
visibility, and reference inputs.

Drop the list and its wiring in `runner/env_leios`, the launcher and
the docs. The `skip_deselect` workflow input goes with it: it existed
only to clear a `DESELECT_FROM_FILE` coming from an env file, and no
env file sets one anymore. The generic deselect machinery in
`runner/run_tests.sh` and the tcache path stay.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The pre-committee path lacks verified coverage, and 54 formerly deselected tests remain unverified.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Low severity

Open (1)
What changed in this PR

Updates the Leios setup for cardonnay 0.4.7, genesis-seated pools, and the latest snapshot format.

Changes:

  • Enables POOLS_IN_GENESIS and updates dependencies.
  • Adds wrapped snapshot support and committee detection.
  • Removes obsolete deselection configuration.
File Summary / review note
uv.lock Locks cardonnay 0.4.7.
scripts/​test_leios.sh Removes obsolete deselection guidance. Moderate (1 vote): 54 formerly deselected tests remain unverified.
scripts/​deselected_leios_tests.txt Removes obsolete Leios deselection entries.
runner/​run_tests.sh Updates deselection comments while retaining generic machinery.
runner/​env_leios Enables POOLS_IN_GENESIS. Nit (1 vote): documentation should describe this requirement and the removed skip_deselect input.
pyproject.toml Raises the minimum cardonnay version.
framework_tests/​test_clusterlib_utils.py Adds snapshot helper and layout coverage.
doc/​leios_tests.md Documents Leios setup and CI inputs. Nit (2 votes): the setup variable and removed workflow input remain stale.
cardano_node_tests/​utils/​clusterlib_utils.py Supports wrapped Leios stake snapshots.
cardano_node_tests/​tests/​test_leios_blocks.py Detects genesis-seated committees. Moderate (1 vote): the pre-committee path lacks verified coverage for modern and legacy layouts.
.github/​workflows/​regression-leios.yaml Removes the obsolete workflow input.
.github/​workflows/​regression_reusable.yaml Removes deselection override handling.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread doc/leios_tests.md
The forge loop forecasts the ledger view from the tip of the chain the
node has selected, and the forecast reaches only `3k/f` slots past that
tip. On `leios_fast` that is 240 slots at k=4 and f=0.05. A node kept
busy by a standalone Tx load generator can fall further behind than
that, and then it just skips the slot it was about to forge and recovers
as soon as it catches up.

The trace lands in whatever test happens to be in teardown, so it is
reported as a failure of an unrelated test. Ignore it, but only when
`ENABLE_TX_CENTRIFUGE` or `ENABLE_TX_FIREHOSE` is set - without the
load, a node falling that far behind is worth reporting.
@mkoura
mkoura merged commit 1ee6775 into master Sep 22, 2026
4 checks passed
@mkoura
mkoura deleted the update_leios_rel_0921 branch September 22, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants