Lines
100 %
Functions
Branches
// Copyright (C) Moondance Labs Ltd.
// This file is part of Tanssi.
// Tanssi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Tanssi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Tanssi. If not, see <http://www.gnu.org/licenses/>
#![cfg(test)]
use {
crate::{
tests::common::*, ContainerRegistrar, Paras, Registrar, RuntimeCall, SlotFrequency, System,
},
cumulus_primitives_core::relay_chain::HeadData,
frame_support::{assert_noop, assert_ok, BoundedVec},
pallet_registrar::Event as ContainerRegistrarEvent,
pallet_registrar_runtime_api::{
runtime_decl_for_registrar_api::RegistrarApi, ContainerChainGenesisData,
runtime_common::paras_registrar,
runtime_parachains::configuration as parachains_configuration,
sp_runtime::traits::Dispatchable,
sp_std::vec,
tp_traits::ParaId,
};
#[test]
fn registrar_needs_a_reserved_para_id() {
ExtBuilder::default()
.with_balances(vec![
// Alice gets 10k extra tokens for her mapping deposit
(AccountId::from(ALICE), 210_000 * UNIT),
(AccountId::from(BOB), 100_000 * UNIT),
(AccountId::from(CHARLIE), 100_000 * UNIT),
(AccountId::from(DAVE), 100_000 * UNIT),
])
.build()
.execute_with(|| {
run_to_block(2);
let validation_code =
vec![1u8; cumulus_primitives_core::relay_chain::MIN_CODE_SIZE as usize];
let genesis_data_2000 = ContainerChainGenesisData {
storage: BoundedVec::try_from(vec![
(b":code".to_vec(), validation_code.clone()).into()
.unwrap(),
name: Default::default(),
id: Default::default(),
fork_id: Default::default(),
extensions: BoundedVec::try_from(vec![]).unwrap(),
properties: Default::default(),
let genesis_data_no_code = ContainerChainGenesisData {
storage: BoundedVec::try_from(vec![(b":code".to_vec(), vec![1u8]).into()]).unwrap(),
let next_para_id = ParaId::from(2000);
assert_noop!(
ContainerRegistrar::register(
origin_of(ALICE.into()),
next_para_id,
genesis_data_2000.clone(),
Some(HeadData(vec![1u8, 1u8, 1u8])),
),
paras_registrar::Error::<Runtime>::NotReserved
);
// After a reservation, we can register
assert_ok!(Registrar::reserve(origin_of(ALICE.into())));
genesis_data_no_code,
paras_registrar::Error::<Runtime>::InvalidCode
let validation_code: cumulus_primitives_core::relay_chain::ValidationCode =
vec![1u8; cumulus_primitives_core::relay_chain::MIN_CODE_SIZE as usize].into();
assert_ok!(ContainerRegistrar::register(
));
assert!(Paras::lifecycle(next_para_id)
.expect("para should be onboarding")
.is_onboarding());
// Two sessions later the para should be a parathread
// But only if the pvf is accepted! which we havent done
run_to_session(2);
// Now let's accept the pvf, so that after 2 sesssions we have the chain onboarded
assert_ok!(Paras::add_trusted_validation_code(
root_origin(),
validation_code
run_to_session(4);
// PVF accepted and the para should be a parathread
.expect("para should be parathread")
.is_parathread());
});
}
fn register_para_via_container_registrar() {
.with_para_ids(vec![
(1001, empty_genesis_data(), u32::MAX, u32::MAX).into(),
(1002, empty_genesis_data(), u32::MAX, u32::MAX).into(),
// In this test we're gonna register a para via ContainerRegistrar,
// which will internally use the InnerRegistrar type to also register the para
// in the relay Registrar pallet.
assert_eq!(Runtime::registered_paras(), vec![1001.into(), 1002.into()]);
assert_eq!(Runtime::genesis_data(2000.into()).as_ref(), None);
assert_eq!(
parachains_configuration::ActiveConfig::<Runtime>::get().max_head_data_size,
20500
assert_ok!(
2000.into(),
Some(HeadData(vec![1u8, 1u8, 1u8]))
()
// Now let's check if the para was preoperly registered in the relay.
// Run to next session.
run_to_session(1);
assert!(Paras::lifecycle(2000.into())
// We need to accept the validation code, so that the para is onboarded after 2 sessions.
validation_code.into()
run_to_session(3);
// Now the para should be a parathread.
fn cannot_register_para_twice_in_relay() {
// In this test we're gonna confirm that a para cannot be registered in the relay
// after being already registered through ContainerRegistrar.
validation_code.clone().into()
// We shouldn't be able to register the para again
pallet_registrar::Error::<Runtime>::ParaIdAlreadyRegistered,
fn mark_valid_for_collating_converts_to_parachain() {
// In this test we're gonna check that inside mark_valid_for_collating(),
// if we are passing a parathread, this one will be upgraded to a parachain
// at the end of the execution.
set_dummy_boot_node(origin_of(ALICE.into()), 2000.into());
// Call mark_valid_for_collating.
ContainerRegistrar::mark_valid_for_collating(root_origin(), 2000.into()),
// The change should be applied after 2 sessions.
run_to_session(5);
.expect("para should be parachain")
.is_parachain());
fn deregister_calls_schedule_para_cleanup() {
// In this test we're gonna check that when calling ContainerRegistrar::deregister(),
// the para is also offboarded from the relay.
Runtime::genesis_data(2000.into()).as_ref(),
Some(&genesis_data_2000)
assert_ok!(ContainerRegistrar::deregister(root_origin(), 2000.into()));
// Assert that the ParaIdDeregistered event was properly deposited
System::assert_last_event(
ContainerRegistrarEvent::ParaIdDeregistered {
para_id: 2000.into(),
.into(),
run_to_session(7);
end_block();
// Para should be offboarding after 2 sessions.
// we need one more block to trigger the on_initialize of containerRegistrar
// which should fully clean everything
start_block();
.expect("para should be offboarding")
.is_offboarding());
fn deregister_two_paras_in_the_same_block() {
// two paraIds are properly offboarded from the relay.
assert_eq!(Runtime::genesis_data(2001.into()).as_ref(), None);
let genesis_data_2000_and_2001 = ContainerChainGenesisData {
// Register paraId 2000
genesis_data_2000_and_2001.clone(),
// Register paraId 2001
2001.into(),
// Now let's check if the paras were preoperly registered in the relay.
assert!(Paras::lifecycle(2001.into())
// We need to accept the validation code, so that paras are onboarded after 2 sessions.
// Now paras should be parathreads.
set_dummy_boot_node(origin_of(ALICE.into()), 2001.into());
ContainerRegistrar::mark_valid_for_collating(root_origin(), 2001.into()),
Some(&genesis_data_2000_and_2001)
Runtime::genesis_data(2001.into()).as_ref(),
assert_ok!(ContainerRegistrar::deregister(root_origin(), 2001.into()));
para_id: 2001.into(),
// Paras should be offboarding after 2 sessions.
fn test_register_parathread_not_allowed() {
.with_collators(vec![
(AccountId::from(ALICE), 210 * UNIT),
(AccountId::from(BOB), 100 * UNIT),
(AccountId::from(CHARLIE), 100 * UNIT),
(AccountId::from(DAVE), 100 * UNIT),
RuntimeCall::ContainerRegistrar(
pallet_registrar::Call::<Runtime>::register_parathread {
para_id: 3001.into(),
slot_frequency: SlotFrequency { min: 1, max: 1 },
genesis_data: empty_genesis_data(),
head_data: None
)
.dispatch(
<Runtime as frame_system::Config>::RuntimeOrigin::signed(AccountId::from(
ALICE
))
frame_system::Error::<Runtime>::CallFiltered
fn test_relay_registrar_through_extrinsic_not_allowed() {
RuntimeCall::Registrar(paras_registrar::Call::<Runtime>::register {
id: 3001.into(),
validation_code: cumulus_primitives_core::relay_chain::ValidationCode(
genesis_head: HeadData(vec![1u8, 1u8, 1u8]),
})
fn test_relay_registrar_deregister_through_extrinsic_not_allowed() {
RuntimeCall::Registrar(paras_registrar::Call::<Runtime>::deregister {
id: 3001.into()