Fix flaky ProposeNewConstitution test#6601
Open
carbolymer wants to merge 1 commit into
Open
Conversation
Open
4 tasks
2064644 to
0e48d61
Compare
Base automatically changed from
mgalazyn/feature/update-cardano-rpc-11.0
to
master
June 19, 2026 12:45
d9fddec to
0020a36
Compare
0020a36 to
29c0245
Compare
There was a problem hiding this comment.
Pull request overview
This PR aims to make the ProposeNewConstitution governance integration test deterministic by avoiding a transient “proposal-with-votes-but-not-yet-ratified” window caused by low (0%) voting thresholds and pulsing snapshot lag.
Changes:
- Overrides Conway genesis in the test to raise
dvtUpdateToConstitution(to 51%) and extendgovActionLifetime, and updates theconfiguration.yamlgenesis hash accordingly. - Splits DRep voting into two rounds and replaces “wait then assert” logic with
retryUntilJustMpolling guards that wait for exact expected vote counts in ledger state and CLI output. - Updates several golden query outputs (notably PlutusV3 cost model parameter values) and adds
.serena/to.gitignore.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs | Reworks the test setup (genesis override + rehash), voting flow (two rounds), and assertion strategy (exact-count polling) to eliminate flakiness. |
| cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersOut.txt | Updates expected protocol parameter output (PlutusV3 cost model values). |
| cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersFileOut.json | Updates expected protocol parameter JSON output (PlutusV3 cost model values). |
| cardano-testnet/test/cardano-testnet-test/files/golden/queries/govStateOut.json | Updates expected governance state JSON output (PlutusV3 cost model values). |
| cardano-testnet/changelog.d/20260629_103800_mgalazyn_fix_flaky_propose_new_constitution.md | Documents the test flake fix and new strategy. |
| .gitignore | Ignores .serena/ directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+73
to
+75
| -- Generate model for votes in two rounds. | ||
| -- Round 1: 3 yes votes = 33.3% of active DRep stake, below 51% threshold - proposal stays alive. | ||
| -- Round 2: +1 yes, +3 no, +2 abstain. New ratio is 4/7 participating = 57.1%, triggers ratification. |
Comment on lines
+329
to
+330
| -- Round 1: submit 3 yes votes (33.3% of active DRep stake, below 51% threshold). | ||
| -- The proposal cannot be ratified, so it persists across epoch boundaries. |
| stakePoolVotes <- H.evalMaybe $ cliProposal ^? Aeson.key "stakePoolVotes" . Aeson._Object | ||
| stakePoolVotes === mempty | ||
|
|
||
| -- Round 2: submit +1 yes, +3 no, +2 abstain. New ratio is 4/7 = 57.1% > 51%, triggers ratification. |
|
|
||
| - Fixed flaky `ProposeNewConstitution` test by raising `dvtUpdateToConstitution` to 51% and splitting voting into two rounds. | ||
| The old test submitted all votes at once with the default threshold of 0%, so any single yes-vote could trigger instant ratification; combined with pulsing snapshot lag, the "proposal with votes" state was transient and assertions failed non-deterministically. | ||
| The new test uses `createTestnetEnv` + genesis override to set a meaningful threshold, then votes in two rounds: round 1 (3 yes, below threshold) keeps the proposal alive for deterministic assertions, round 2 (+1 yes, +3 no, +2 abstain = 57.1%) triggers ratification. |
Comment on lines
403
to
407
| 7305, | ||
| -900, | ||
| 1716, | ||
| 960, | ||
| 549, | ||
| 57, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dvtUpdateToConstitutionto 51% (from the default 0%) via Conway genesis override, so a minority of yes-votes cannot trigger instant ratification.waitForGovActionVotes+ immediate assertions withretryUntilJustMpolling that exits only when the exact expected vote count appears in both ledger state and CLI output.govActionLifetimeto 4 epochs and ratification timeout to epoch 20 so the proposal survives the pulsing snapshot refresh cycle.query proposalsassertion before voting so the proposal structure is verified while it has zero votes (deterministic).Root cause
The default
dvtUpdateToConstitution = 0%means any single DRep yes-vote immediately satisfies the ratification threshold.Combined with the pulsing snapshot lag (the snapshot only picks up new votes at epoch boundaries), the window where the proposal exists with votes but is not yet ratified is extremely narrow.
The old test submitted all 9 votes at once and then asserted on the transient "proposal with votes" state, which was a race condition.
Approach
Structure the test so that the states we are interested in are longer-lived (addressing review feedback):
Test plan
DISABLE_RETRIES=1(4/4 runs, ~75-96s each)