Skip to content

xcm-emulator: advance relay block number by relay_blocks_per_para_block#11031

Merged
sigurpol merged 6 commits intomasterfrom
sigurpol-fix-emulated-integration-tests
Feb 10, 2026
Merged

xcm-emulator: advance relay block number by relay_blocks_per_para_block#11031
sigurpol merged 6 commits intomasterfrom
sigurpol-fix-emulated-integration-tests

Conversation

@sigurpol
Copy link
Copy Markdown
Contributor

@sigurpol sigurpol commented Feb 10, 2026

After AuraDigestProvider was introduced, emulated integration tests for parachains with slot_duration != relay_slot_duration (e.g. 12s Polkadot/Kusama chains) panic because FixedVelocityConsensusHook derives a parachain slot that doesn't match CurrentSlot.

Fix by advancing the relay block number by slot_duration / RELAY_CHAIN_SLOT_DURATION_MILLIS per parachain block (instead of always +1), and computing the aura digest slot inline using both durations.
This removes the DigestProvider associated type from the Parachain trait and the AuraDigestProvider struct — the emulator now handles the digest automatically.

Downstream users must remove DigestProvider: AuraDigestProvider, from their decl_test_parachains! invocations.

AuraDigestProvider sets CurrentSlot = relay_block_number, but the
sproof builder was also setting current_slot = relay_block_number.
For parachains with slot duration != relay slot duration (e.g. 12s
Polkadot/Kusama chains), FixedVelocityConsensusHook derives a
different para_slot and panics.

Scale sproof.current_slot by slot_duration / RELAY_CHAIN_SLOT_DURATION
so the hook's derivation matches CurrentSlot for any slot duration.
@sigurpol sigurpol added T10-tests This PR/Issue is related to tests. A4-backport-stable2512 Pull request must be backported to the stable2512 release branch labels Feb 10, 2026
@sigurpol
Copy link
Copy Markdown
Contributor Author

/cmd prdoc --audience runtime_dev --bump patch

@sigurpol
Copy link
Copy Markdown
Contributor Author

sigurpol commented Feb 10, 2026

This is needed to unlock runtime 2.1.0 PR where all integration emulated tests are currently failing see polkadot-fellows/runtimes#1065 (comment)

I've locally patched the 2.1.0 PR to contain this fix and integration emulated tests pass now.

@skunert
Copy link
Copy Markdown
Contributor

skunert commented Feb 10, 2026

Hey, thanks for looking into this.

Your fix should work. However thought about it a bit and propose to use this: 7f240f1

I would consider it more in line with our logic in the dev mode.

@sigurpol
Copy link
Copy Markdown
Contributor Author

Your fix should work. However thought about it a bit and propose to use this:

let me cherry-pick that and run tests in the runtime with your fix. Keep you posted (and thx)

@sigurpol sigurpol changed the title xcm-emulator: scale relay slot by parachain slot duration xcm-emulator: advance relay block number by relay_blocks_per_para_block Feb 10, 2026
@sigurpol
Copy link
Copy Markdown
Contributor Author

Hey, thanks for looking into this.

Your fix should work. However thought about it a bit and propose to use this: 7f240f1

I would consider it more in line with our logic in the dev mode.

@skunert thanks for the reply. I went for your approach and tested in the runtime.
With my original commit - no changes were needed in the runtime beside relying on the new xcm-emulator pallet.

With your neater approach, I need to replace in the test AuraDigestProvider with an ad-hoc one like below:

pub struct SlotAdjustedDigestProvider<const PARA_SLOT_MS: u64>;

impl<const PARA_SLOT_MS: u64> Convert<(u32, u32), Digest>
	for SlotAdjustedDigestProvider<PARA_SLOT_MS>
{
	fn convert((_block_number, relay_block_number): (u32, u32)) -> Digest {
		let slot: Slot =
			(relay_block_number as u64 * RELAY_CHAIN_SLOT_DURATION_MILLIS / PARA_SLOT_MS).into();
		let mut digest = Digest::default();
		digest.logs.push(DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()));
		digest
	}
}

which is perfectly fine by me as well. Wdyt?
With your SDK fix + test using AuraDigestProvider as digest provider:

  • relay_block_number = 3 (first para block: initial 1 + 2)
  • AuraDigestProvider sets digest slot = 3 (it uses relay_block_number
    directly)
  • on_initialize reads digest → CurrentSlot = 3
  • timestamp = 3 * 6000 = 18000
  • pallet_aura::OnTimestampSet asserts: timestamp / slot_duration = 18000 / 12000 = 1
  • 1 ≠ 3 → panic

They diverge because AuraDigestProvider puts the raw relay block number in the digest, but the timestamp now uses RELAY_CHAIN_SLOT_DURATION_MILLIS (6000) instead of slot_duration (12000).

In the SDK, this works because the SDK's test chains have slot_duration = 6000. In the runtime repo, Polkadot/Kusama parachains have slot_duration = 12000, so we need a DigestProvider that divides accordingly: slot = relay_block_number * 6000 / 12000. Does it make sense?

@skunert
Copy link
Copy Markdown
Contributor

skunert commented Feb 10, 2026

Hey, thanks for looking into this.
Your fix should work. However thought about it a bit and propose to use this: 7f240f1
I would consider it more in line with our logic in the dev mode.

@skunert thanks for the reply. I went for your approach and tested in the runtime. With my original commit - no changes were needed in the runtime beside relying on the new xcm-emulator pallet.

With your neater approach, I need to replace in the test AuraDigestProvider with an ad-hoc one like below:

pub struct SlotAdjustedDigestProvider<const PARA_SLOT_MS: u64>;

impl<const PARA_SLOT_MS: u64> Convert<(u32, u32), Digest>
	for SlotAdjustedDigestProvider<PARA_SLOT_MS>
{
	fn convert((_block_number, relay_block_number): (u32, u32)) -> Digest {
		let slot: Slot =
			(relay_block_number as u64 * RELAY_CHAIN_SLOT_DURATION_MILLIS / PARA_SLOT_MS).into();
		let mut digest = Digest::default();
		digest.logs.push(DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()));
		digest
	}
}

which is perfectly fine by me as well. Wdyt? With your SDK fix + test using AuraDigestProvider as digest provider:

* relay_block_number = 3 (first para block: initial 1 + 2)

* AuraDigestProvider sets digest slot = 3 (it uses relay_block_number
  directly)

* on_initialize reads digest → CurrentSlot = 3

* timestamp = 3 * 6000 = 18000

* pallet_aura::OnTimestampSet asserts: timestamp / slot_duration = 18000 / 12000 = 1

* 1 ≠ 3 → panic

They diverge because AuraDigestProvider puts the raw relay block number in the digest, but the timestamp now uses RELAY_CHAIN_SLOT_DURATION_MILLIS (6000) instead of slot_duration (12000).

In the SDK, this works because the SDK's test chains have slot_duration = 6000. In the runtime repo, Polkadot/Kusama parachains have slot_duration = 12000, so we need a DigestProvider that divides accordingly: slot = relay_block_number * 6000 / 12000. Does it make sense?

Yes, fine by me. You could make the default AuraDigestProvider do this. Then it would be fixed automatically.

Maybe I shouldn't even have introduced the DigestProvider but directly add the digest in xcm-emulator, in the end we have both slot durations available there already. But fine for now.

@sigurpol
Copy link
Copy Markdown
Contributor Author

Maybe I shouldn't even have introduced the DigestProvider but directly add the digest in xcm-emulator, in the end we have both slot durations available there already. But fine for now.

Good point @skunert - removed here 8c05dc2

Copy link
Copy Markdown
Member

@ggwpez ggwpez left a comment

Choose a reason for hiding this comment

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

(approving to unblock 2.1.0)

@sigurpol sigurpol enabled auto-merge February 10, 2026 13:14
@sigurpol sigurpol added this pull request to the merge queue Feb 10, 2026
Merged via the queue into master with commit a20ac9b Feb 10, 2026
224 of 227 checks passed
@sigurpol sigurpol deleted the sigurpol-fix-emulated-integration-tests branch February 10, 2026 13:54
paritytech-release-backport-bot bot pushed a commit that referenced this pull request Feb 10, 2026
…ck (#11031)

After `AuraDigestProvider` was introduced, emulated integration tests
for parachains with `slot_duration != relay_slot_duration` (e.g. 12s
Polkadot/Kusama chains) panic because `FixedVelocityConsensusHook`
derives a parachain slot that doesn't match `CurrentSlot`.
Fix by advancing the relay block number by `slot_duration /
RELAY_CHAIN_SLOT_DURATION_MILLIS` per parachain block (instead of always
+1), and computing the aura digest slot inline using both durations.
This removes the `DigestProvider` associated type from the `Parachain`
trait and the `AuraDigestProvider` struct — the emulator now handles the
digest automatically.
Downstream users must remove `DigestProvider: AuraDigestProvider,` from
their `decl_test_parachains!` invocations.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit a20ac9b)
@paritytech-release-backport-bot
Copy link
Copy Markdown

Successfully created backport PR for stable2512:

sigurpol added a commit that referenced this pull request Feb 10, 2026
Backport #11031 into `stable2512` from sigurpol.

Note that the two changes marked as `major` come from xcm-emulator and a
test pallet so they have zero impact on real production runtimes, only
on integrated emulation test @EgorPopelyaev

See the
[documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md)
on how to use this bot.

<!--
  # To be used by other automation, do not modify:
  original-pr-number: #${pull_number}
-->

---------

Co-authored-by: Paolo La Camera <paolo@parity.io>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
arturgontijo pushed a commit to moonbeam-foundation/polkadot-sdk that referenced this pull request Apr 1, 2026
Backport paritytech#11031 into `stable2512` from sigurpol.

Note that the two changes marked as `major` come from xcm-emulator and a
test pallet so they have zero impact on real production runtimes, only
on integrated emulation test @EgorPopelyaev

See the
[documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md)
on how to use this bot.

<!--
  # To be used by other automation, do not modify:
  original-pr-number: #${pull_number}
-->

---------

Co-authored-by: Paolo La Camera <paolo@parity.io>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A4-backport-stable2512 Pull request must be backported to the stable2512 release branch T10-tests This PR/Issue is related to tests.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants