Skip to content

Commit

Permalink
Migrate parachain swaps to Coretime (#3714)
Browse files Browse the repository at this point in the history
This PR notifies broker pallet for any parachain slot swaps performed on
the relay chain. This is achieved by registering an `OnSwap` for the the
`coretime` pallet. The hook sends XCM message to the broker chain and
invokes a new extrinsic `swap_leases` which updates `Leases` storage
item (which keeps the legacy parachain leases).

I made two assumptions in this PR:
1.
[`Leases`](https://github.com/paritytech/polkadot-sdk/blob/4987d7982461e2e5ffe219cdf71ec697284cea7c/substrate/frame/broker/src/lib.rs#L120)
in `broker` pallet and
[`Leases`](https://github.com/paritytech/polkadot-sdk/blob/4987d7982461e2e5ffe219cdf71ec697284cea7c/polkadot/runtime/common/src/slots/mod.rs#L118)
in `slots` pallet are in sync.
2. `swap_leases` extrinsic from `broker` pallet can be triggered only by
root or by the XCM message from the relay chain. If not - the extrinsic
will generate an error and do nothing.

As a side effect from the changes `OnSwap` trait is moved from
runtime/common/traits.rs to runtime/parachains. Otherwise it is not
accessible from `broker` pallet.

Closes #3552

TODOs:

- [x] Weights
- [x] Tests

---------

Co-authored-by: command-bot <>
Co-authored-by: eskimor <eskimor@users.noreply.github.com>
Co-authored-by: Bastian Köcher <git@kchr.de>
  • Loading branch information
3 people committed Mar 26, 2024
1 parent fd79b3b commit 9023454
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 322 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions polkadot/runtime/parachains/src/coretime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ enum CoretimeCalls {
SetLease(pallet_broker::TaskId, pallet_broker::Timeslice),
#[codec(index = 19)]
NotifyCoreCount(u16),
#[codec(index = 99)]
SwapLeases(ParaId, ParaId),
}

#[frame_support::pallet]
Expand Down Expand Up @@ -233,6 +235,24 @@ impl<T: Config> Pallet<T> {
}
}
}

// Handle legacy swaps in coretime. Notifies broker parachain that a lease swap has occurred via
// XCM message. This function is meant to be used in an implementation of `OnSwap` trait.
pub fn on_legacy_lease_swap(one: ParaId, other: ParaId) {
let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
mk_coretime_call(crate::coretime::CoretimeCalls::SwapLeases(one, other)),
]);
if let Err(err) = send_xcm::<T::SendXcm>(
Location::new(0, [Junction::Parachain(T::BrokerId::get())]),
message,
) {
log::error!("Sending `SwapLeases` to coretime chain failed: {:?}", err);
}
}
}

impl<T: Config> OnNewSession<BlockNumberFor<T>> for Pallet<T> {
Expand Down
12 changes: 10 additions & 2 deletions polkadot/runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use runtime_common::{
LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter,
},
paras_registrar, paras_sudo_wrapper, prod_or_fast, slots,
traits::Leaser,
traits::{Leaser, OnSwap},
BlockHashCount, BlockLength, SlowAdjustingFeeUpdate,
};
use scale_info::TypeInfo;
Expand Down Expand Up @@ -1078,7 +1078,7 @@ impl paras_registrar::Config for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type OnSwap = (Crowdloan, Slots);
type OnSwap = (Crowdloan, Slots, SwapLeases);
type ParaDeposit = ParaDeposit;
type DataDepositPerByte = DataDepositPerByte;
type WeightInfo = weights::runtime_common_paras_registrar::WeightInfo<Runtime>;
Expand Down Expand Up @@ -1306,6 +1306,14 @@ impl pallet_asset_rate::Config for Runtime {
type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments;
}

// Notify `coretime` pallet when a lease swap occurs
pub struct SwapLeases;
impl OnSwap for SwapLeases {
fn on_swap(one: ParaId, other: ParaId) {
coretime::Pallet::<Runtime>::on_legacy_lease_swap(one, other);
}
}

construct_runtime! {
pub enum Runtime
{
Expand Down
12 changes: 10 additions & 2 deletions polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ use runtime_common::{
LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter,
},
paras_registrar, paras_sudo_wrapper, prod_or_fast, slots,
traits::Leaser,
traits::{Leaser, OnSwap},
BalanceToU256, BlockHashCount, BlockLength, CurrencyToVote, SlowAdjustingFeeUpdate,
U256ToBalance,
};
Expand Down Expand Up @@ -1302,7 +1302,7 @@ impl paras_registrar::Config for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type OnSwap = (Crowdloan, Slots);
type OnSwap = (Crowdloan, Slots, SwapLeases);
type ParaDeposit = ParaDeposit;
type DataDepositPerByte = RegistrarDataDepositPerByte;
type WeightInfo = weights::runtime_common_paras_registrar::WeightInfo<Runtime>;
Expand Down Expand Up @@ -1414,6 +1414,14 @@ impl pallet_asset_rate::Config for Runtime {
type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments;
}

// Notify `coretime` pallet when a lease swap occurs
pub struct SwapLeases;
impl OnSwap for SwapLeases {
fn on_swap(one: ParaId, other: ParaId) {
coretime::Pallet::<Runtime>::on_legacy_lease_swap(one, other);
}
}

#[frame_support::runtime(legacy_ordering)]
mod runtime {
#[runtime::runtime]
Expand Down
10 changes: 10 additions & 0 deletions prdoc/pr_3714.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
title: Handle legacy lease swaps on coretime

doc:
- audience: Runtime Dev
description: |
When a `registar::swap` extrinsic is executed it swaps two leases on the relay chain but the
broker chain never knows about this swap. This change notifies the broker chain via a XCM
message for a swap so that it can update its state.
crates:
- name: pallet-broker
17 changes: 17 additions & 0 deletions substrate/frame/broker/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,23 @@ mod benches {
Ok(())
}

#[benchmark]
fn swap_leases() -> Result<(), BenchmarkError> {
let admin_origin =
T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;

// Add two leases in `Leases`
let n = (T::MaxLeasedCores::get() / 2) as usize;
let mut leases = vec![LeaseRecordItem { task: 1, until: 10u32.into() }; n];
leases.extend(vec![LeaseRecordItem { task: 2, until: 20u32.into() }; n]);
Leases::<T>::put(BoundedVec::try_from(leases).unwrap());

#[extrinsic_call]
_(admin_origin as T::RuntimeOrigin, 1, 2);

Ok(())
}

// Implements a test for each benchmark. Execute with:
// `cargo test -p pallet-broker --features runtime-benchmarks`.
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
Expand Down
18 changes: 18 additions & 0 deletions substrate/frame/broker/src/dispatchable_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,4 +437,22 @@ impl<T: Config> Pallet<T> {
Self::deposit_event(Event::AllowedRenewalDropped { core, when });
Ok(())
}

pub(crate) fn do_swap_leases(id: TaskId, other: TaskId) -> DispatchResult {
let mut id_leases_count = 0;
let mut other_leases_count = 0;
Leases::<T>::mutate(|leases| {
leases.iter_mut().for_each(|lease| {
if lease.task == id {
lease.task = other;
id_leases_count += 1;
} else if lease.task == other {
lease.task = id;
other_leases_count += 1;
}
})
});

Ok(())
}
}
8 changes: 8 additions & 0 deletions substrate/frame/broker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -786,5 +786,13 @@ pub mod pallet {
Self::do_notify_core_count(core_count)?;
Ok(())
}

#[pallet::call_index(99)]
#[pallet::weight(T::WeightInfo::swap_leases())]
pub fn swap_leases(origin: OriginFor<T>, id: TaskId, other: TaskId) -> DispatchResult {
T::AdminOrigin::ensure_origin_or_root(origin)?;
Self::do_swap_leases(id, other)?;
Ok(())
}
}
}

0 comments on commit 9023454

Please sign in to comment.