Skip to content

Commit 3043114

Browse files
lexnvgithub-actions[bot]bkchr
committed
test-utils/fix: Parachains test-utils relay parent descendants mock data (#10541)
This PR ensures that the parachains test-utils crate has 2 relay parent descendants for testing purposes. Effectively fixes a panic because we missed this mock data for chains that started with `RP_offset > 0`: ``` Unable to verify provided relay parent descendants. expected_rp_descendants_num: 1 error: InvalidNumberOfDescendants { expected: 2, received: 0 } note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` Detected in: - https://github.com/polkadot-fellows/runtimes/actions/runs/19857064730/job/56897622908?pr=1018 Unblocks: - polkadot-fellows/runtimes#1018 Inspired by a similar fix I've introduced in: - #9880 --------- Signed-off-by: Alexandru Vasile <[email protected]> Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Bastian Köcher <[email protected]> (cherry picked from commit 0f28d81)
1 parent dd54f65 commit 3043114

File tree

10 files changed

+201
-18
lines changed

10 files changed

+201
-18
lines changed

.github/workflows/check-runtime-migration.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ jobs:
114114
- name: Run Check
115115
id: required2
116116
run: |
117+
# Disable the check for asset-hub-westend temporarily due to frequent failures.
118+
if [ "${{ matrix.network }}" = "asset-hub-westend" ]; then
119+
echo "Skipping runtime migration check for asset-hub-westend due to frequent failures."
120+
exit 0
121+
fi
122+
117123
echo "Running ${{ matrix.network }} runtime migration check"
118124
export RUST_LOG=remote-ext=debug,runtime=debug
119125

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cumulus/client/parachain-inherent/src/mock.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,9 @@ impl<R: Send + Sync + GenerateRandomness<u64>> InherentDataProvider
228228

229229
// Inject current para block head, if any
230230
sproof_builder.included_para_head = self.current_para_block_head.clone();
231-
232-
let (relay_parent_storage_root, proof) = sproof_builder.into_state_root_and_proof();
231+
sproof_builder.num_authorities = 2;
232+
let (relay_parent_storage_root, proof, relay_parent_descendants) =
233+
sproof_builder.into_state_root_proof_and_descendants(1);
233234
let parachain_inherent_data = ParachainInherentData {
234235
validation_data: PersistedValidationData {
235236
parent_head: Default::default(),
@@ -240,7 +241,7 @@ impl<R: Send + Sync + GenerateRandomness<u64>> InherentDataProvider
240241
downward_messages,
241242
horizontal_messages,
242243
relay_chain_state: proof,
243-
relay_parent_descendants: Default::default(),
244+
relay_parent_descendants,
244245
collator_peer_id: None,
245246
};
246247

cumulus/pallets/parachain-system/src/descendant_validation.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,8 @@ mod tests {
485485
next_authorities: Option<Vec<(AuthorityId, BabeAuthorityWeight)>>,
486486
) -> RelayChainStateProof {
487487
// Create a mock implementation or structure, adjust this to match the proof's definition
488-
let mut proof_builder = RelayStateSproofBuilder::default();
488+
let mut proof_builder =
489+
RelayStateSproofBuilder { num_authorities: 0, ..Default::default() };
489490
if let Some(authorities) = authorities {
490491
proof_builder
491492
.additional_key_values

cumulus/parachains/runtimes/test-utils/src/lib.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,14 +331,20 @@ where
331331
AllPalletsWithoutSystem::on_initialize(next_block_number);
332332

333333
let parent_head = HeadData(header.encode());
334+
335+
// Get RelayParentOffset from the parachain system pallet config.
336+
let relay_parent_offset =
337+
<Runtime as cumulus_pallet_parachain_system::Config>::RelayParentOffset::get()
338+
.saturated_into::<u64>();
339+
334340
let sproof_builder = RelayStateSproofBuilder {
335341
para_id: <Runtime>::SelfParaId::get(),
336342
included_para_head: parent_head.clone().into(),
337343
..Default::default()
338344
};
339345

340-
let (relay_parent_storage_root, relay_chain_state) =
341-
sproof_builder.into_state_root_and_proof();
346+
let (relay_parent_storage_root, relay_chain_state, relay_parent_descendants) =
347+
sproof_builder.into_state_root_proof_and_descendants(relay_parent_offset);
342348
let inherent_data = ParachainInherentData {
343349
validation_data: PersistedValidationData {
344350
parent_head,
@@ -349,7 +355,7 @@ where
349355
relay_chain_state,
350356
downward_messages: Default::default(),
351357
horizontal_messages: Default::default(),
352-
relay_parent_descendants: Default::default(),
358+
relay_parent_descendants,
353359
collator_peer_id: None,
354360
};
355361

@@ -689,6 +695,9 @@ pub fn mock_open_hrmp_channel<
689695
let timestamp = slot.saturating_mul(slot_durations.para.as_millis());
690696
let relay_slot = Slot::from_timestamp(timestamp.into(), slot_durations.relay);
691697

698+
// Get RelayParentOffset from the parachain system pallet config.
699+
let relay_parent_offset = C::RelayParentOffset::get().saturated_into::<u64>();
700+
692701
let n = 1_u32;
693702
let mut sproof_builder = RelayStateSproofBuilder {
694703
para_id: sender,
@@ -709,7 +718,9 @@ pub fn mock_open_hrmp_channel<
709718
},
710719
);
711720

712-
let (relay_parent_storage_root, relay_chain_state) = sproof_builder.into_state_root_and_proof();
721+
let (relay_parent_storage_root, relay_chain_state, relay_parent_descendants) =
722+
sproof_builder.into_state_root_proof_and_descendants(relay_parent_offset);
723+
713724
let vfp = PersistedValidationData {
714725
relay_parent_number: n as RelayChainBlockNumber,
715726
relay_parent_storage_root,
@@ -724,7 +735,7 @@ pub fn mock_open_hrmp_channel<
724735
relay_chain_state,
725736
downward_messages: Default::default(),
726737
horizontal_messages: Default::default(),
727-
relay_parent_descendants: Default::default(),
738+
relay_parent_descendants,
728739
collator_peer_id: None,
729740
};
730741
inherent_data

cumulus/test/relay-sproof-builder/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ workspace = true
1515
codec = { features = ["derive"], workspace = true }
1616

1717
# Substrate
18+
sp-consensus-babe = { workspace = true }
19+
sp-core = { workspace = true }
1820
sp-runtime = { workspace = true }
1921
sp-state-machine = { workspace = true }
2022
sp-trie = { workspace = true }
@@ -31,6 +33,8 @@ std = [
3133
"codec/std",
3234
"cumulus-primitives-core/std",
3335
"polkadot-primitives/std",
36+
"sp-consensus-babe/std",
37+
"sp-core/std",
3438
"sp-runtime/std",
3539
"sp-state-machine/std",
3640
"sp-trie/std",

cumulus/test/relay-sproof-builder/src/lib.rs

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,23 @@
1717
extern crate alloc;
1818

1919
use alloc::collections::btree_map::BTreeMap;
20+
use codec::{Decode, Encode};
2021
use cumulus_primitives_core::{
2122
relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId,
2223
};
23-
use polkadot_primitives::UpgradeGoAhead;
24-
use sp_runtime::traits::HashingFor;
24+
use polkadot_primitives::{Header, UpgradeGoAhead};
25+
use sp_consensus_babe::{
26+
digests::{CompatibleDigestItem, PreDigest, PrimaryPreDigest},
27+
AuthorityId, AuthorityPair, BabeAuthorityWeight,
28+
};
29+
use sp_core::{
30+
sr25519::vrf::{VrfPreOutput, VrfProof, VrfSignature},
31+
Pair, H256,
32+
};
33+
use sp_runtime::{
34+
traits::{HashingFor, Header as HeaderT},
35+
Digest, DigestItem,
36+
};
2537
use sp_trie::PrefixedMemoryDB;
2638

2739
/// Builds a sproof (portmanteau of 'spoof' and 'proof') of the relay chain state.
@@ -49,6 +61,7 @@ pub struct RelayStateSproofBuilder {
4961
pub randomness: relay_chain::Hash,
5062
pub additional_key_values: Vec<(Vec<u8>, Vec<u8>)>,
5163
pub included_para_head: Option<relay_chain::HeadData>,
64+
pub num_authorities: u64,
5265
}
5366

5467
impl Default for RelayStateSproofBuilder {
@@ -81,6 +94,7 @@ impl Default for RelayStateSproofBuilder {
8194
randomness: relay_chain::Hash::default(),
8295
additional_key_values: vec![],
8396
included_para_head: None,
97+
num_authorities: 1,
8498
}
8599
}
86100
}
@@ -129,9 +143,39 @@ impl RelayStateSproofBuilder {
129143
})
130144
}
131145

132-
pub fn into_state_root_and_proof(
146+
/// Build sproof and generate relay parent descendants with the configured authorities.
147+
///
148+
/// Returns a tuple of (state_root, storage_proof, relay_parent_descendants).
149+
pub fn into_state_root_proof_and_descendants(
133150
self,
151+
relay_parent_offset: u64,
152+
) -> (polkadot_primitives::Hash, sp_state_machine::StorageProof, Vec<Header>) {
153+
let authorities = generate_authority_pairs(self.num_authorities);
154+
let (state_root, proof) = self.into_state_root_and_proof();
155+
let descendants =
156+
build_relay_parent_descendants(relay_parent_offset + 1, state_root.into(), authorities);
157+
(state_root, proof, descendants)
158+
}
159+
160+
pub fn into_state_root_and_proof(
161+
mut self,
134162
) -> (polkadot_primitives::Hash, sp_state_machine::StorageProof) {
163+
// Generate and add authorities if num_authorities is set
164+
if self.num_authorities > 0 {
165+
let authorities = generate_authority_pairs(self.num_authorities);
166+
let auth_pair = convert_to_authority_weight_pair(&authorities);
167+
168+
// Add authorities to the sproof builder
169+
self.additional_key_values.push((
170+
relay_chain::well_known_keys::AUTHORITIES.to_vec(),
171+
auth_pair.clone().encode(),
172+
));
173+
self.additional_key_values.push((
174+
relay_chain::well_known_keys::NEXT_AUTHORITIES.to_vec(),
175+
auth_pair.encode(),
176+
));
177+
}
178+
135179
let (db, root) =
136180
PrefixedMemoryDB::<HashingFor<polkadot_primitives::Block>>::default_with_root();
137181
let state_version = Default::default(); // for test using default.
@@ -213,3 +257,75 @@ impl RelayStateSproofBuilder {
213257
(root, proof)
214258
}
215259
}
260+
261+
/// Generate a vector of AuthorityPairs
262+
pub fn generate_authority_pairs(num_authorities: u64) -> Vec<AuthorityPair> {
263+
(0..num_authorities).map(|i| AuthorityPair::from_seed(&[i as u8; 32])).collect()
264+
}
265+
266+
/// Convert AuthorityPair to (AuthorityId, BabeAuthorityWeight)
267+
fn convert_to_authority_weight_pair(
268+
authorities: &[AuthorityPair],
269+
) -> Vec<(AuthorityId, BabeAuthorityWeight)> {
270+
authorities
271+
.iter()
272+
.map(|auth| (auth.public().into(), Default::default()))
273+
.collect()
274+
}
275+
276+
/// Add a BABE pre-digest to a generic header
277+
fn add_babe_pre_digest(header: &mut Header, authority_index: u32, block_number: u64) {
278+
/// This method generates some vrf data, but only to make the compiler happy
279+
fn generate_testing_vrf() -> VrfSignature {
280+
let vrf_proof_bytes = [0u8; 64];
281+
let proof: VrfProof = VrfProof::decode(&mut vrf_proof_bytes.as_slice()).unwrap();
282+
let vrf_pre_out_bytes = [0u8; 32];
283+
let pre_output: VrfPreOutput =
284+
VrfPreOutput::decode(&mut vrf_pre_out_bytes.as_slice()).unwrap();
285+
VrfSignature { pre_output, proof }
286+
}
287+
288+
let pre_digest = PrimaryPreDigest {
289+
authority_index,
290+
slot: block_number.into(),
291+
vrf_signature: generate_testing_vrf(),
292+
};
293+
294+
header
295+
.digest_mut()
296+
.push(DigestItem::babe_pre_digest(PreDigest::Primary(pre_digest)));
297+
}
298+
299+
/// Create a mock chain of relay headers as descendants of the relay parent
300+
pub fn build_relay_parent_descendants(
301+
num_headers: u64,
302+
state_root: H256,
303+
authorities: Vec<AuthorityPair>,
304+
) -> Vec<Header> {
305+
let mut headers = Vec::with_capacity(num_headers as usize);
306+
307+
let mut previous_hash = None;
308+
309+
for block_number in 0..=num_headers as u32 {
310+
let mut header = Header {
311+
number: block_number,
312+
parent_hash: previous_hash.unwrap_or_default(),
313+
state_root,
314+
extrinsics_root: H256::default(),
315+
digest: Digest::default(),
316+
};
317+
let authority_index = block_number % (authorities.len() as u32);
318+
319+
// Add pre-digest
320+
add_babe_pre_digest(&mut header, authority_index, block_number as u64);
321+
322+
// Sign and seal the header
323+
let signature = authorities[authority_index as usize].sign(header.hash().as_bytes());
324+
header.digest_mut().push(DigestItem::babe_seal(signature.into()));
325+
326+
previous_hash = Some(header.hash());
327+
headers.push(header);
328+
}
329+
330+
headers
331+
}

cumulus/test/service/src/bench_utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ pub fn extrinsic_set_validation_data(
8989
..Default::default()
9090
};
9191

92-
let (relay_parent_storage_root, relay_chain_state) = sproof_builder.into_state_root_and_proof();
92+
let (relay_parent_storage_root, relay_chain_state, relay_parent_descendants) =
93+
sproof_builder.into_state_root_proof_and_descendants(1);
9394
let data = BasicParachainInherentData {
9495
validation_data: PersistedValidationData {
9596
parent_head,
@@ -98,7 +99,7 @@ pub fn extrinsic_set_validation_data(
9899
max_pov_size: 10000,
99100
},
100101
relay_chain_state,
101-
relay_parent_descendants: Default::default(),
102+
relay_parent_descendants,
102103
collator_peer_id: None,
103104
};
104105

cumulus/xcm/xcm-emulator/src/lib.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub use sp_tracing;
6868
// Cumulus
6969
pub use cumulus_pallet_parachain_system::{
7070
parachain_inherent::{deconstruct_parachain_inherent_data, InboundMessagesData},
71-
Call as ParachainSystemCall, Pallet as ParachainSystemPallet,
71+
Call as ParachainSystemCall, Config as ParachainSystemConfig, Pallet as ParachainSystemPallet,
7272
};
7373
pub use cumulus_primitives_core::{
7474
relay_chain::{BlockNumber as RelayBlockNumber, HeadData, HrmpChannelId},
@@ -205,6 +205,7 @@ pub trait Network {
205205
para_id: u32,
206206
relay_parent_number: u32,
207207
parent_head_data: HeadData,
208+
relay_parent_offset: u64,
208209
) -> ParachainInherentData;
209210
fn send_horizontal_messages<I: Iterator<Item = (ParaId, RelayBlockNumber, Vec<u8>)>>(
210211
to_para_id: u32,
@@ -731,8 +732,11 @@ macro_rules! decl_test_parachains {
731732
timestamp_set.dispatch(<Self as Chain>::RuntimeOrigin::none())
732733
);
733734

735+
// Get RelayParentOffset from the runtime
736+
let relay_parent_offset = <<<Self as $crate::Chain>::Runtime as $crate::ParachainSystemConfig>::RelayParentOffset as $crate::Get<u32>>::get();
737+
734738
// 2. inherent: cumulus_pallet_parachain_system::Call::set_validation_data
735-
let data = N::hrmp_channel_parachain_inherent_data(para_id, relay_block_number, parent_head_data);
739+
let data = N::hrmp_channel_parachain_inherent_data(para_id, relay_block_number, parent_head_data, relay_parent_offset as u64);
736740
let (data, mut downward_messages, mut horizontal_messages) =
737741
$crate::deconstruct_parachain_inherent_data(data);
738742
let inbound_messages_data = $crate::InboundMessagesData::new(
@@ -1195,11 +1199,13 @@ macro_rules! decl_test_networks {
11951199
para_id: u32,
11961200
relay_parent_number: u32,
11971201
parent_head_data: $crate::HeadData,
1202+
relay_parent_offset: u64,
11981203
) -> $crate::ParachainInherentData {
11991204
let mut sproof = $crate::RelayStateSproofBuilder::default();
12001205
sproof.para_id = para_id.into();
12011206
sproof.current_slot = $crate::polkadot_primitives::Slot::from(relay_parent_number as u64);
12021207
sproof.host_config.max_upward_message_size = 1024 * 1024;
1208+
sproof.num_authorities = relay_parent_offset + 1;
12031209

12041210
// egress channel
12051211
let e_index = sproof.hrmp_egress_channel_index.get_or_insert_with(Vec::new);
@@ -1227,7 +1233,8 @@ macro_rules! decl_test_networks {
12271233
});
12281234
}
12291235

1230-
let (relay_storage_root, proof) = sproof.into_state_root_and_proof();
1236+
let (relay_storage_root, proof, relay_parent_descendants) =
1237+
sproof.into_state_root_proof_and_descendants(relay_parent_offset);
12311238

12321239
$crate::ParachainInherentData {
12331240
validation_data: $crate::PersistedValidationData {
@@ -1239,7 +1246,7 @@ macro_rules! decl_test_networks {
12391246
relay_chain_state: proof,
12401247
downward_messages: Default::default(),
12411248
horizontal_messages: Default::default(),
1242-
relay_parent_descendants: Default::default(),
1249+
relay_parent_descendants,
12431250
collator_peer_id: None,
12441251
}
12451252
}

0 commit comments

Comments
 (0)