Skip to content

Commit

Permalink
Starlight: Wire ContainerRegistrar and Registrar pallets (#653)
Browse files Browse the repository at this point in the history
* first steps

* refactor and test

* add tuple conversion for ParaRegistrationParams in tests

* add changes for mark_valid_for_collating and deregister

* modify RegistrarHandler trait and add more tests

* add TS test

* add more TS tests

* fix syntax

* remove clone

* modify MaxEncodedGenesisDataSize

* add BufferedParasToDeregister

* fix deregistration rust test

* TS tests now working

* fmt

* TS lint

* use run_block() instead

* at the end run_block is not needed in test

* PR suggestions in pallet_registrar

* add comment

* account for proper weight inside on_initialize()

* add test for deregistering two paras

* fmt

* make all trait functions to behave as hooks

* set MaxGenesisDataSize to 5MB again

* add head_data param to register functions

* fix tests

* fmt

* fix build

* fmt

* make trait functions fallible again

* fix rust tests

* fix dancebox and flashbox TS tests

* fix dev_tanssi_relay TS tests

* fix zombie tests

* clippy

* fmt

* generate new api-augment interfaces

* api-augment again

* add more docs

* fix core scheduling test

* add test for invalid wasm

* add registrar errors to ContainerRegistrar

* fmt

* cargo fmt

* api-augment

* add a way to test InnerRegistrar calls in pallet registrar

* adapt previous tests

* comment

* pr comments

* Avoid clone of genesis storage in dancebox

* fix mock

---------

Co-authored-by: Tomasz Polaczyk <tmpolaczyk@gmail.com>
  • Loading branch information
Agusrodri and tmpolaczyk committed Sep 4, 2024
1 parent 944c771 commit bbb45d0
Show file tree
Hide file tree
Showing 41 changed files with 2,249 additions and 746 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion pallets/registrar/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ mod benchmarks {
create_funded_user::<T>("caller", 0, T::DepositAmount::get());

#[extrinsic_call]
Pallet::<T>::register(RawOrigin::Signed(caller), Default::default(), storage);
Pallet::<T>::register(RawOrigin::Signed(caller), Default::default(), storage, None);

// verification code
assert_eq!(pending_verification_len::<T>(), 1usize);
Expand Down Expand Up @@ -165,6 +165,7 @@ mod benchmarks {
proof,
signature,
storage,
None,
);

// verification code
Expand All @@ -188,6 +189,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
// Do not call mark_valid_for_collating, to ensure that the deregister call also executes the cleanup hooks
Expand Down Expand Up @@ -224,6 +226,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
// Call mark_valid_for_collating to ensure that the deregister call
Expand Down Expand Up @@ -273,6 +276,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
// Do not call mark_valid_for_collating, to ensure that the deregister call also executes the cleanup hooks
Expand Down Expand Up @@ -326,6 +330,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
// Call mark_valid_for_collating to ensure that the deregister call
Expand Down Expand Up @@ -393,6 +398,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
}
Expand All @@ -406,6 +412,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
k.into(),
storage.clone(),
None,
)
.unwrap();
T::RegistrarHooks::benchmarks_ensure_valid_for_collating(k.into());
Expand Down Expand Up @@ -445,6 +452,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
k.into(),
storage.clone(),
None,
)
.unwrap();
T::RegistrarHooks::benchmarks_ensure_valid_for_collating(k.into());
Expand All @@ -461,6 +469,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
T::RegistrarHooks::benchmarks_ensure_valid_for_collating(i.into());
Expand Down Expand Up @@ -509,6 +518,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
k.into(),
storage.clone(),
None,
)
.unwrap();
T::RegistrarHooks::benchmarks_ensure_valid_for_collating(k.into());
Expand All @@ -525,6 +535,7 @@ mod benchmarks {
RawOrigin::Signed(caller.clone()).into(),
i.into(),
storage.clone(),
None,
)
.unwrap();
T::RegistrarHooks::benchmarks_ensure_valid_for_collating(i.into());
Expand Down Expand Up @@ -568,6 +579,7 @@ mod benchmarks {
Default::default(),
slot_frequency,
storage,
None,
);

// verification code
Expand Down Expand Up @@ -596,6 +608,7 @@ mod benchmarks {
i.into(),
slot_frequency.clone(),
storage.clone(),
None,
)
.unwrap();
T::RegistrarHooks::benchmarks_ensure_valid_for_collating(i.into());
Expand Down
119 changes: 113 additions & 6 deletions pallets/registrar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub use weights::WeightInfo;
pub use pallet::*;

use {
cumulus_primitives_core::relay_chain::HeadData,
dp_chain_state_snapshot::GenericStateProof,
dp_container_chain_genesis_data::ContainerChainGenesisData,
frame_support::{
Expand All @@ -64,8 +65,8 @@ use {
sp_std::{collections::btree_set::BTreeSet, prelude::*},
tp_traits::{
GetCurrentContainerChains, GetSessionContainerChains, GetSessionIndex, ParaId,
ParathreadParams as ParathreadParamsTy, RelayStorageRootProvider, SessionContainerChains,
SlotFrequency,
ParathreadParams as ParathreadParamsTy, RegistrarHandler, RelayStorageRootProvider,
SessionContainerChains, SlotFrequency,
},
};

Expand Down Expand Up @@ -175,6 +176,14 @@ pub mod pallet {

type RegistrarHooks: RegistrarHooks;

/// External manager that takes care of executing specific operations
/// when register-like functions of this pallet are called.
///
/// Mostly used when we are in a relay-chain configuration context (Starlight)
/// to also register, deregister and upgrading paraIds in polkadot's
/// paras_registrar pallet.
type InnerRegistrar: RegistrarHandler<Self::AccountId>;

type WeightInfo: WeightInfo;
}

Expand Down Expand Up @@ -235,6 +244,27 @@ pub mod pallet {
ValueQuery,
>;

/// This storage aims to act as a 'buffer' for paraIds that must be deregistered at the
/// end of the block execution by calling 'T::InnerRegistrar::deregister()' implementation.
///
/// We need this buffer because when we are using this pallet on a relay-chain environment
/// like Starlight (where 'T::InnerRegistrar' implementation is usually the
/// 'paras_registrar' pallet) we need to deregister (via 'paras_registrar::deregister')
/// the same paraIds we have in 'PendingToRemove<T>', and we need to do this deregistration
/// process inside 'on_finalize' hook.
///
/// It can be the case that some paraIds need to be downgraded to a parathread before
/// deregistering on 'paras_registrar'. This process usually takes 2 sessions,
/// and the actual downgrade happens when the block finalizes.
///
/// Therefore, if we tried to perform this relay deregistration process at the beginning
/// of the session/block inside ('on_initialize') initializer_on_new_session() as we do
/// for this pallet, it would fail due to the downgrade process could have not taken
/// place yet.
#[pallet::storage]
pub type BufferedParasToDeregister<T: Config> =
StorageValue<_, BoundedVec<ParaId, T::MaxLengthParaIds>, ValueQuery>;

pub type DepositBalanceOf<T> =
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;

Expand Down Expand Up @@ -311,6 +341,10 @@ pub mod pallet {
InvalidRelayManagerSignature,
/// Tried to deregister a parachain that was not deregistered from the relay chain
ParaStillExistsInRelay,
/// Tried to register a paraId in a relay context without specifying a proper HeadData.
HeadDataNecessary,
/// Tried to register a paraId in a relay context without specifying a wasm chain code.
WasmCodeNecessary,
}

#[pallet::composite_enum]
Expand All @@ -320,6 +354,17 @@ pub mod pallet {

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
// Account for on_finalize weight
let mut weight = Weight::zero().saturating_add(T::DbWeight::get().reads(1));

let buffered_paras = BufferedParasToDeregister::<T>::get();
for _ in 0..buffered_paras.len() {
weight += T::InnerRegistrar::deregister_weight();
}
weight
}

#[cfg(feature = "try-runtime")]
fn try_state(_n: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> {
use {scale_info::prelude::format, sp_std::collections::btree_set::BTreeSet};
Expand Down Expand Up @@ -421,6 +466,14 @@ pub mod pallet {

Ok(())
}

fn on_finalize(_: BlockNumberFor<T>) {
let buffered_paras = BufferedParasToDeregister::<T>::take();
for para_id in buffered_paras {
// Deregister (in the relay context) each paraId present inside the buffer.
T::InnerRegistrar::deregister(para_id);
}
}
}

#[pallet::call]
Expand All @@ -432,9 +485,10 @@ pub mod pallet {
origin: OriginFor<T>,
para_id: ParaId,
genesis_data: ContainerChainGenesisData,
head_data: Option<HeadData>,
) -> DispatchResult {
let account = ensure_signed(origin)?;
Self::do_register(account, para_id, genesis_data)?;
Self::do_register(account, para_id, genesis_data, head_data)?;
Self::deposit_event(Event::ParaIdRegistered { para_id });

Ok(())
Expand Down Expand Up @@ -538,9 +592,10 @@ pub mod pallet {
para_id: ParaId,
slot_frequency: SlotFrequency,
genesis_data: ContainerChainGenesisData,
head_data: Option<HeadData>,
) -> DispatchResult {
let account = ensure_signed(origin)?;
Self::do_register(account, para_id, genesis_data)?;
Self::do_register(account, para_id, genesis_data, head_data)?;
// Insert parathread params
let params = ParathreadParamsTy { slot_frequency };
ParathreadParams::<T>::insert(para_id, params);
Expand Down Expand Up @@ -605,6 +660,7 @@ pub mod pallet {
relay_storage_proof: sp_trie::StorageProof,
manager_signature: cumulus_primitives_core::relay_chain::Signature,
genesis_data: ContainerChainGenesisData,
head_data: Option<HeadData>,
) -> DispatchResult {
let account = T::RegisterWithRelayProofOrigin::ensure_origin(origin)?;
let relay_storage_root =
Expand Down Expand Up @@ -633,7 +689,7 @@ pub mod pallet {
return Err(Error::<T>::InvalidRelayManagerSignature.into());
}

Self::do_register(account, para_id, genesis_data)?;
Self::do_register(account, para_id, genesis_data, head_data)?;
// Insert parathread params
if let Some(parathread_params) = parathread_params {
ParathreadParams::<T>::insert(para_id, parathread_params);
Expand Down Expand Up @@ -750,7 +806,12 @@ pub mod pallet {
(T::Currency::minimum_balance() + T::DepositAmount::get()) * 2u32.into();
let account = create_funded_user::<T>("caller", 1000, new_balance).0;
let origin = RawOrigin::Signed(account);
assert_ok!(Self::register(origin.into(), *para_id, Default::default()));
assert_ok!(Self::register(
origin.into(),
*para_id,
Default::default(),
None
));
}

let deposit_info = RegistrarDeposit::<T>::get(para_id).expect("Cannot return signed origin for a container chain that was registered by root. Try using a different para id");
Expand All @@ -767,6 +828,7 @@ pub mod pallet {
account: T::AccountId,
para_id: ParaId,
genesis_data: ContainerChainGenesisData,
head_data: Option<HeadData>,
) -> DispatchResult {
let deposit = T::DepositAmount::get();
// Verify we can hold
Expand Down Expand Up @@ -805,6 +867,14 @@ pub mod pallet {
// Hold the deposit, we verified we can do this
T::Currency::hold(&HoldReason::RegistrarDeposit.into(), &account, deposit)?;

// Register the paraId also in the relay context (if any).
T::InnerRegistrar::register(
account.clone(),
para_id,
&genesis_data.storage,
head_data,
)?;

// Update DepositInfo
RegistrarDeposit::<T>::insert(
para_id,
Expand All @@ -828,6 +898,13 @@ pub mod pallet {
Self::deposit_event(Event::ParaIdDeregistered { para_id });
// Cleanup immediately
Self::cleanup_deregistered_para_id(para_id);
BufferedParasToDeregister::<T>::try_mutate(|v| v.try_push(para_id)).map_err(
|_e| {
DispatchError::Other(
"Failed to add paraId to deregistration list: buffer is full",
)
},
)?;
} else {
Self::schedule_paused_parachain_change(|para_ids, paused| {
// We have to find out where, in the sorted vec the para id is, if anywhere.
Expand All @@ -853,6 +930,18 @@ pub mod pallet {
})?;
// Mark this para id for cleanup later
Self::schedule_parachain_cleanup(para_id)?;

// If we have InnerRegistrar set to a relay context (like Starlight),
// we first need to downgrade the paraId (if it was a parachain before)
// and convert it to a parathread before deregistering it. Otherwise
// the deregistration process will fail in the scheduled session.
//
// We only downgrade if the paraId is a parachain in the context of
// this pallet.
if let None = ParathreadParams::<T>::get(para_id) {
T::InnerRegistrar::schedule_para_downgrade(para_id)?;
}

Self::deposit_event(Event::ParaIdDeregistered { para_id });
}

Expand Down Expand Up @@ -889,6 +978,15 @@ pub mod pallet {

T::RegistrarHooks::para_marked_valid_for_collating(para_id);

// If we execute mark_valid_for_collating, we automatically upgrade
// the paraId to a parachain (in the relay context) at the end of the execution.
//
// We only upgrade if the paraId is a parachain in the context of
// this pallet.
if let None = ParathreadParams::<T>::get(para_id) {
T::InnerRegistrar::schedule_para_upgrade(para_id)?;
}

Ok(())
}

Expand Down Expand Up @@ -1168,6 +1266,15 @@ pub mod pallet {
for para_id in new_paras {
Self::cleanup_deregistered_para_id(*para_id);
removed_para_ids.insert(*para_id);
if let Err(id) =
BufferedParasToDeregister::<T>::try_mutate(|v| v.try_push(*para_id))
{
log::error!(
target: LOG_TARGET,
"Failed to add paraId {:?} to deregistration list",
id
);
}
}
}

Expand Down
Loading

0 comments on commit bbb45d0

Please sign in to comment.