Skip to content

Fix Chopsticks runtime-upgrade test panic (InvalidNumberOfDescendants) - #3800

Merged
arturgontijo merged 2 commits into
masterfrom
artur/chopsticks-fork-block-fix
Jun 22, 2026
Merged

arturgontijo merged 2 commits into
masterfrom
artur/chopsticks-fork-block-fix

Conversation

@arturgontijo

@arturgontijo arturgontijo commented Jun 20, 2026 •

Copy link
Copy Markdown
Contributor

What does it do?

Fixes the chopsticks-upgrade-test CI job (moonbeam / moonriver / moonbase) which
was failing during block production after the runtime upgrade with:

Runtime has aborted: "panicked at .../cumulus/pallets/parachain-system/src/lib.rs:623:
Unable to verify provided relay parent descendants.
expected_rp_descendants_num: 1 error: InvalidNumberOfDescendants { expected: 2, received: 0 }"

Root cause. The upgraded runtime wires parachain-system's RelayParentOffset
to pallet_async_backing, whose RelayParentOffset storage value now defaults to 1.
With the offset > 0, set_validation_data verifies that the inherent carries
RelayParentOffset + 1 = 2 relay-parent descendant headers. Chopsticks mocks the
relay chain and builds the setValidationData inherent with 0 descendants, so every
block built under the new runtime panics. beforeAll passes because those blocks still
run under the old (live) runtime, which does not enforce the check; the first block
built under the new runtime (C01T1) is the one that fails.

Fix. After the upgrade is applied, force AsyncBacking::RelayParentOffset to 0
in the forked chain (set_validation_data skips the descendant check when the offset
is 0). This is a Chopsticks-only accommodation; the real network is unaffected
because real collators source the descendant headers from the live relay chain.

This also reverts the earlier, ineffective workarounds for the same panic:

  • Removed the block-production retry helpers in test-upgrade-chain.ts (added in Reduce CI runner cost and make CI less flaky (pass 2) #3757).
    The panic is deterministic, so retrying never helped — it just exhausted attempts and
    then failed the height assertion.
  • Removed test/scripts/select-chopsticks-fork-block.ts, the CI step that ran it, and the
    block: ${env.CHOPSTICKS_BLOCK} config entries (added in Make Chopsticks runtime upgrade tests less flaky in CI #3765). Fork-block selection
    is irrelevant here: the failing inherent is fabricated fresh for each new block,
    independent of the fork block. Chopsticks now forks from the latest finalized block again.

What important points should reviewers know?

  • The fix lives entirely in the Chopsticks test setup; no runtime/node code changes.
  • disableRelayParentOffset writes the raw u32 value 0x00000000. Passing a falsy
    value (e.g. 0) to moonwall's setStorage would delete the key and fall back to the
    default of 1, so the explicit little-endian hex is intentional.
  • The override is applied after dev_newBlock({ count: 3 }) so the new runtime's metadata
    (which contains asyncBacking.relayParentOffset) is already active when the storage is set.
  • Applies to all three networks (moonbeam, moonriver, moonbase), which all map
    RelayParentOffset = AsyncBacking.

Is there something left for follow-up PRs?

  • If/when Chopsticks gains the ability to synthesize relay-parent descendant headers,
    the offset override could be dropped to exercise the feature end-to-end in the fork test.

What alternative implementations were considered?

  • Upgrading Chopsticks (1.2.8 → ≥1.3.1/1.4.x): the 1.3.1 fix only corrects descendant
    state roots when descendants are already populated; it does not synthesize the missing
    descendants, so it would not resolve InvalidNumberOfDescendants { received: 0 }.
  • Selecting a fork block with ≥2 descendants: not possible — production Moonbeam blocks
    currently carry 0 descendants, and descendants of the fork block don't propagate into the
    freshly built inherents anyway.

Are there relevant PRs or issues in other repositories (Substrate, Polkadot, Frontier, Cumulus)?

What value does it bring to the blockchain users?

  • Restores the Chopsticks runtime-upgrade test as a reliable pre-release safety net, ensuring
    runtime upgrades that change relay-parent-offset behavior are validated in CI before shipping.

@arturgontijo arturgontijo self-assigned this Jun 20, 2026
@arturgontijo arturgontijo added B0-silent Changes should not be mentioned in any release notes D3-trivial PR contains trivial changes in a runtime directory that do not require an audit not-breaking Does not need to be mentioned in breaking changes labels Jun 20, 2026
@coderabbitai

coderabbitai Bot commented Jun 20, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9aec9047-702b-49c8-a948-de569c7076a0

📥 Commits

Reviewing files that changed from the base of the PR and between 77065ab and eb3e274.

📒 Files selected for processing (6)
  • .github/workflows/build.yml
  • test/configs/alphanet.yml
  • test/configs/moonbeam.yml
  • test/configs/moonriver.yml
  • test/scripts/select-chopsticks-fork-block.ts
  • test/suites/chopsticks/test-upgrade-chain.ts
💤 Files with no reviewable changes (5)
  • test/configs/moonriver.yml
  • test/configs/moonbeam.yml
  • .github/workflows/build.yml
  • test/configs/alphanet.yml
  • test/scripts/select-chopsticks-fork-block.ts

📝 Walkthrough

Walkthrough

The fork-block selection script gains an anchored relay-chain state proof requirement enforced via blake2AsHex hashing and proof validation. Test configurations remove environment-based block selection, the CI workflow replaces the fork-block selection step with a direct install step, and the test suite adds a helper to disable relay-parent offset after runtime upgrade, switching from retry-based to direct block creation.

Changes

Anchored proof gate and test suite adaptation

Layer / File(s) Summary
Config and workflow cleanup
test/configs/alphanet.yml, test/configs/moonbeam.yml, test/configs/moonriver.yml, .github/workflows/build.yml
Removes block: ${env.CHOPSTICKS_BLOCK} from all three test configuration files; replaces the fork-block selection script invocation in the CI workflow with a pnpm install step, eliminating the separate block-selection phase.
Fork-block selection script with anchored relay-chain proof validation
test/scripts/select-chopsticks-fork-block.ts
Imports blake2AsHex; adds SetValidationDataMetrics type; implements toU8a (trie node → bytes) and isProofAnchored (checks trie node hashes against relayParentStorageRoot); replaces descendants-only extraction with getSetValidationDataMetrics computing descendantsLength, relayChainTrieNodes, and proofAnchored; adds isStableForkBlock requiring anchored proof then branching on legacy (descendantsLength >= minDescendants) vs. production (descendantsLength === 0) format; updates --min-descendants CLI description and main scan loop to use the new metrics; updates terminal error to reflect anchored-proof and descendants requirements.
Test suite adaptation: relay-parent offset disabling and direct block creation
test/suites/chopsticks/test-upgrade-chain.ts
Introduces disableRelayParentOffset helper that sets asyncBacking.relayParentOffset to 0 after runtime upgrade to avoid descendant-header verification failures; updates upgradeRuntime to call the helper immediately after the upgrade event; replaces all retry-helper-based block creation in test cases T1 and T2 with direct context.createBlock() calls (batched or per-iteration), removing the previous retry utilities.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • moonbeam-foundation/moonbeam#3740: The test suite changes adding disableRelayParentOffset directly exercise the runtime behavior where relay_parent_offset is sourced dynamically from AsyncBacking instead of a fixed constant.
  • moonbeam-foundation/moonbeam#3757: Overlaps in test/suites/chopsticks/test-upgrade-chain.ts with modifications to block-production logic and retry-helper removal.
  • moonbeam-foundation/moonbeam#3765: Directly precedes this PR — it introduced the original relayParentDescendants.length >= --min-descendants check that this PR extends with the anchored relay-chain state proof requirement.

Suggested labels

ci, D2-notlive

Suggested reviewers

  • librelois
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main fix: resolving the Chopsticks runtime-upgrade test panic caused by InvalidNumberOfDescendants error.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the root cause, solution, and implementation details of the fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch artur/chopsticks-fork-block-fix

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.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 20, 2026
@arturgontijo arturgontijo changed the title Fix Chopsticks fork-block selection for Moonbeam/Moonriver Fix Chopsticks runtime-upgrade test panic (InvalidNumberOfDescendants) Jun 20, 2026
@arturgontijo
arturgontijo merged commit 8d4a50b into master Jun 22, 2026
40 checks passed
@arturgontijo
arturgontijo deleted the artur/chopsticks-fork-block-fix branch June 22, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B0-silent Changes should not be mentioned in any release notes D3-trivial PR contains trivial changes in a runtime directory that do not require an audit not-breaking Does not need to be mentioned in breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants