Skip to content

Commit

Permalink
Refactor do_register
Browse files Browse the repository at this point in the history
  • Loading branch information
tmpolaczyk committed Jan 31, 2024
1 parent ac2b511 commit 11af492
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 107 deletions.
168 changes: 62 additions & 106 deletions pallets/registrar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,58 +389,7 @@ pub mod pallet {
genesis_data: ContainerChainGenesisData<T::MaxLengthTokenSymbol>,
) -> DispatchResult {
let account = ensure_signed(origin)?;
let deposit = T::DepositAmount::get();

// Verify we can reserve
T::Currency::can_reserve(&account, deposit)
.then_some(true)
.ok_or(Error::<T>::NotSufficientDeposit)?;

// Check if the para id is already registered by looking at the genesis data
if ParaGenesisData::<T>::contains_key(para_id) {
return Err(Error::<T>::ParaIdAlreadyRegistered.into());
}

// Insert para id into PendingVerification
let mut pending_verification = PendingVerification::<T>::get();
match pending_verification.binary_search(&para_id) {
// This Ok is unreachable
Ok(_) => return Err(Error::<T>::ParaIdAlreadyRegistered.into()),
Err(index) => {
pending_verification
.try_insert(index, para_id)
.map_err(|_e| Error::<T>::ParaIdListFull)?;
}
}

// The actual registration takes place 2 sessions after the call to
// `mark_valid_for_collating`, but the genesis data is inserted now.
// This is because collators should be able to start syncing the new container chain
// before the first block is mined. However, we could store the genesis data in a
// different key, like PendingParaGenesisData.
// TODO: for benchmarks, this call to .encoded_size is O(n) with respect to the number
// of key-values in `genesis_data.storage`, even if those key-values are empty. And we
// won't detect that the size is too big until after iterating over all of them, so the
// limit in that case would be the transaction size.
let genesis_data_size = genesis_data.encoded_size();
if genesis_data_size > T::MaxGenesisDataSize::get() as usize {
return Err(Error::<T>::GenesisDataTooBig.into());
}

// Reserve the deposit, we verified we can do this
T::Currency::reserve(&account, deposit)?;

// Update DepositInfo
RegistrarDeposit::<T>::insert(
para_id,
DepositInfo {
creator: account,
deposit,
},
);
ParaGenesisData::<T>::insert(para_id, genesis_data);
PendingVerification::<T>::put(pending_verification);

Self::do_register(account, para_id, genesis_data)?;
Self::deposit_event(Event::ParaIdRegistered { para_id });

Ok(())
Expand Down Expand Up @@ -616,64 +565,11 @@ pub mod pallet {
slot_frequency: SlotFrequency,
genesis_data: ContainerChainGenesisData<T::MaxLengthTokenSymbol>,
) -> DispatchResult {
// TODO: refactor register and register_parathread, extract common path to `do_register`.
let account = ensure_signed(origin)?;
let deposit = T::DepositAmount::get();

// Verify we can reserve
T::Currency::can_reserve(&account, deposit)
.then_some(true)
.ok_or(Error::<T>::NotSufficientDeposit)?;

// Check if the para id is already registered by looking at the genesis data
if ParaGenesisData::<T>::contains_key(para_id) {
return Err(Error::<T>::ParaIdAlreadyRegistered.into());
}

// Insert para id into PendingVerification
let mut pending_verification = PendingVerification::<T>::get();
match pending_verification.binary_search(&para_id) {
// This Ok is unreachable
Ok(_) => return Err(Error::<T>::ParaIdAlreadyRegistered.into()),
Err(index) => {
pending_verification
.try_insert(index, para_id)
.map_err(|_e| Error::<T>::ParaIdListFull)?;
}
}

// The actual registration takes place 2 sessions after the call to
// `mark_valid_for_collating`, but the genesis data is inserted now.
// This is because collators should be able to start syncing the new container chain
// before the first block is mined. However, we could store the genesis data in a
// different key, like PendingParaGenesisData.
// TODO: for benchmarks, this call to .encoded_size is O(n) with respect to the number
// of key-values in `genesis_data.storage`, even if those key-values are empty. And we
// won't detect that the size is too big until after iterating over all of them, so the
// limit in that case would be the transaction size.
let genesis_data_size = genesis_data.encoded_size();
if genesis_data_size > T::MaxGenesisDataSize::get() as usize {
return Err(Error::<T>::GenesisDataTooBig.into());
}

// Reserve the deposit, we verified we can do this
T::Currency::reserve(&account, deposit)?;

// Update DepositInfo
RegistrarDeposit::<T>::insert(
para_id,
DepositInfo {
creator: account,
deposit,
},
);
ParaGenesisData::<T>::insert(para_id, genesis_data);
PendingVerification::<T>::put(pending_verification);

Self::do_register(account, para_id, genesis_data)?;
// Insert parathread params
let params = ParathreadParamsTy { slot_frequency };
ParathreadParams::<T>::insert(para_id, params);

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

Ok(())
Expand Down Expand Up @@ -760,6 +656,66 @@ pub mod pallet {
Ok(deposit_info.creator)
}

fn do_register(
account: T::AccountId,
para_id: ParaId,
genesis_data: ContainerChainGenesisData<T::MaxLengthTokenSymbol>,
) -> DispatchResult {
let deposit = T::DepositAmount::get();

// Verify we can reserve
T::Currency::can_reserve(&account, deposit)
.then_some(true)
.ok_or(Error::<T>::NotSufficientDeposit)?;

// Check if the para id is already registered by looking at the genesis data
if ParaGenesisData::<T>::contains_key(para_id) {
return Err(Error::<T>::ParaIdAlreadyRegistered.into());
}

// Insert para id into PendingVerification
let mut pending_verification = PendingVerification::<T>::get();
match pending_verification.binary_search(&para_id) {
// This Ok is unreachable
Ok(_) => return Err(Error::<T>::ParaIdAlreadyRegistered.into()),
Err(index) => {
pending_verification
.try_insert(index, para_id)
.map_err(|_e| Error::<T>::ParaIdListFull)?;
}
}

// The actual registration takes place 2 sessions after the call to
// `mark_valid_for_collating`, but the genesis data is inserted now.
// This is because collators should be able to start syncing the new container chain
// before the first block is mined. However, we could store the genesis data in a
// different key, like PendingParaGenesisData.
// TODO: for benchmarks, this call to .encoded_size is O(n) with respect to the number
// of key-values in `genesis_data.storage`, even if those key-values are empty. And we
// won't detect that the size is too big until after iterating over all of them, so the
// limit in that case would be the transaction size.
let genesis_data_size = genesis_data.encoded_size();
if genesis_data_size > T::MaxGenesisDataSize::get() as usize {
return Err(Error::<T>::GenesisDataTooBig.into());
}

// Reserve the deposit, we verified we can do this
T::Currency::reserve(&account, deposit)?;

// Update DepositInfo
RegistrarDeposit::<T>::insert(
para_id,
DepositInfo {
creator: account,
deposit,
},
);
ParaGenesisData::<T>::insert(para_id, genesis_data);
PendingVerification::<T>::put(pending_verification);

Ok(())
}

fn schedule_parachain_change(
updater: impl FnOnce(&mut BoundedVec<ParaId, T::MaxLengthParaIds>) -> DispatchResult,
) -> DispatchResult {
Expand Down
5 changes: 4 additions & 1 deletion pallets/registrar/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,10 @@ fn parathread_register_change_params_deregister() {
// Deregister parathread while parathread params are pending
assert_ok!(ParaRegistrar::deregister(RuntimeOrigin::root(), 42.into()));
assert!(ParaRegistrar::para_genesis_data(ParaId::from(42)).is_some());
assert!(ParaRegistrar::parathread_params(ParaId::from(42)).is_some());
assert_eq!(
ParaRegistrar::parathread_params(ParaId::from(42)),
Some(SlotFrequency { min: 1, max: 1 })
);

// Params removed after 2 sessions
run_to_session(2);
Expand Down

0 comments on commit 11af492

Please sign in to comment.