Skip to content

Conversation

@schrink
Copy link

@schrink schrink commented Nov 28, 2025

Description:
This PR refactors migrate_pparams_version to handle non-sequential protocol version requests (e.g., requesting a migration from v1 directly to v3) by iteratively applying the necessary intermediate hard fork transitions.

Context / The Problem:
While syncing the Vector chain, Dolos encountered a panic at slot 864000:
not implemented: don't know how to bump from version 1 to 3.
Investigation showed that while the chain history itself is sequential (v1 -> v2 -> v3), Dolos's internal state machine seemingly missed the v2 update trigger. When the v3 transition occurred, it attempted to migrate from its last known state (v1) directly to the new target (v3).

The Solution:
Instead of panicking on non-adjacent version jumps, the migration logic is now iterative.
If asked to go from v1 to v3, it will:

  • Apply transition v1 -> v2 (e.g., from_shelley_genesis)
  • Apply transition v2 -> v3 (e.g., intra_era_hardfork)

This makes the PParams migration logic robust against missed internal updates or potential future chains that might genuinely skip versions.

Changes:

  • Refactored migrate_pparams_version to use a while loop.
  • The logic sequentially applies standard transitions (from_shelley_genesis, into_alonzo, intra_era_hardfork, etc.) until the target version is reached.

Testing:

  • Verified on Vector Mainnet.
  • Previously crashed at slot 864000.
  • With this fix, the node successfully migrated the parameters and is currently syncing past slot 1,200,000+ without issues.

Summary by CodeRabbit

  • Refactor
    • Enhanced protocol parameter migration logic to process version transitions incrementally through each intermediate step, ensuring more reliable and deterministic parameter updates during version upgrades.

✏️ Tip: You can customize this high-level summary in your review settings.

@schrink schrink requested a review from scarmuega as a code owner November 28, 2025 20:20
@coderabbitai
Copy link

coderabbitai bot commented Nov 28, 2025

Walkthrough

The migrate_pparams_version function is refactored to perform iterative, incremental parameter migrations through a loop, advancing one version at a time from current to target version, replacing the previous direct multi-version jump logic. Each transition step applies the same match cases sequentially until reaching the target version.

Changes

Cohort / File(s) Change Summary
Parameter migration refactoring
crates/cardano/src/forks.rs
Reworked migrate_pparams_version to use iterative loop-based version transitions instead of direct version jumping; maintains same per-step match cases but applies them sequentially to accumulate parameter updates

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify loop correctly iterates through all intermediate versions without off-by-one errors
  • Ensure parameter accumulation logic properly chains updates across each transition step
  • Confirm all version-to-version match cases remain functionally equivalent and complete

Possibly related PRs

Poem

🐰 Hop through versions, step by step so neat,
Where each migration makes the journey complete,
No more big jumps across the forks so wide—
Sequential steps keep protocols in stride!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: converting migrate_pparams_version to use iterative, incremental migrations instead of direct jumps, enabling robust handling of non-sequential protocol version upgrades.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
crates/cardano/src/forks.rs (2)

228-251: Per‑step match table aligns with era transitions; consider making the catch‑all more explicit

The explicit arms for (0→1)…(9→10) preserve the existing era transition semantics, now applied stepwise, which looks correct relative to the documented hard‑fork sequence. The catch‑all arm (_, target) => intra_era_hardfork(&params, target) is convenient for forward compatibility, but it will also silently treat any unhandled (v, next) pair (including a potential mistake in the table) as a plain intra‑era bump. For consensus‑critical code you may want to constrain this a bit—for example, only allow the catch‑all once v is at or above the highest known version, or at least emit a warn! with (v, next) so unexpected transitions are visible in logs.


257-267: force_pparams_version can now delegate to a single migrate_pparams_version call

Since migrate_pparams_version now handles arbitrary from → to upgrades by iterating internally, the for from in from..to loop here effectively duplicates that logic. If you don’t plan to add per‑step invariant checks in this helper, you could simplify it to a single call:

 pub fn force_pparams_version(
-    initial: &PParamsSet,
-    genesis: &Genesis,
-    from: u16,
-    to: u16,
-) -> Result<PParamsSet, BrokenInvariant> {
-    let mut pparams = initial.clone();
-
-    for from in from..to {
-        pparams = migrate_pparams_version(from, from + 1, &pparams, genesis);
-    }
-
-    Ok(pparams)
+    initial: &PParamsSet,
+    genesis: &Genesis,
+    from: u16,
+    to: u16,
+) -> Result<PParamsSet, BrokenInvariant> {
+    Ok(migrate_pparams_version(from, to, initial, genesis))
 }

Not required for this fix, but it removes duplication and makes the intended migration path clearer.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ac0844 and 24b84ad.

📒 Files selected for processing (1)
  • crates/cardano/src/forks.rs (1 hunks)
🔇 Additional comments (1)
crates/cardano/src/forks.rs (1)

222-227: Iterative loop correctly chains migrations; clarify from >= to behavior

The while v < to { next = v + 1; ... v = next; } flow does what you want for non‑sequential upgrades (e.g. 1→3) by forcing each intermediate step starting from a clone of current, which should address the Vector Mainnet panic. One edge case: when from >= to the loop is skipped and you just return a cloned current, which is probably intended for from == to but might hide a caller bug if downgrades are not supposed to happen. Consider tightening the precondition with a debug_assert!(from <= to) or an early return/error for from > to. A small test/property that compares a multi‑step call (e.g. 1→9) against chaining single‑step calls would also help guard this logic.

Also applies to: 252-255

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.

1 participant