Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate parachain swaps to Coretime #3714

Merged
merged 24 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
36a6368
Move trait `OnSwap` from `runtime_common` to `parachains`
tdimitrov Mar 14, 2024
37962d0
Benchmark and weights
tdimitrov Mar 15, 2024
d60b31e
`swap_leases` implementation
tdimitrov Mar 15, 2024
03aaad2
Fix compilation errors
tdimitrov Mar 15, 2024
bd32142
Fix benchmark
tdimitrov Mar 18, 2024
4bd69ab
Undo trait move and fix `OnSwap` registration
tdimitrov Mar 18, 2024
518a072
Change call id of `swap_leases` to 99
tdimitrov Mar 18, 2024
296521a
Fix a compilation error
tdimitrov Mar 18, 2024
e0a1424
clippy
tdimitrov Mar 18, 2024
ff0d3d7
Merge branch 'master' of https://github.com/paritytech/polkadot-sdk i…
Mar 20, 2024
2f72d26
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Mar 20, 2024
b2c5ddd
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Mar 20, 2024
1953bc2
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Mar 20, 2024
e419bb7
Merge branch 'master' into tsv-ct-parachain-swaps
tdimitrov Mar 21, 2024
8986843
Merge branch 'master' into tsv-ct-parachain-swaps
eskimor Mar 21, 2024
7f630c8
Add a prdoc
tdimitrov Mar 21, 2024
cc2efb7
Implement `OnSwap` for a struct instead of for `Runtime` directly :sw…
tdimitrov Mar 21, 2024
a8f17f7
Merge branch 'master' into tsv-ct-parachain-swaps
tdimitrov Mar 21, 2024
f5f6dce
Swap no more than two leases
tdimitrov Mar 21, 2024
113bbcf
Merge branch 'master' into tsv-ct-parachain-swaps
tdimitrov Mar 21, 2024
89ef634
Apply suggestions from code review
tdimitrov Mar 22, 2024
fce11f9
Fix compilation errors and apply more code review suggestions
tdimitrov Mar 22, 2024
7351ea6
Merge branch 'master' into tsv-ct-parachain-swaps
tdimitrov Mar 26, 2024
0bbcfd1
Fix taplo errors
tdimitrov Mar 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion polkadot/runtime/common/src/crowdloan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ impl<T: Config> Pallet<T> {
}
}

impl<T: Config> crate::traits::OnSwap for Pallet<T> {
impl<T: Config> runtime_parachains::OnSwap for Pallet<T> {
fn on_swap(one: ParaId, other: ParaId) {
Funds::<T>::mutate(one, |x| Funds::<T>::mutate(other, |y| sp_std::mem::swap(x, y)))
}
Expand Down
9 changes: 6 additions & 3 deletions polkadot/runtime/common/src/paras_registrar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ use runtime_parachains::{
};
use sp_std::{prelude::*, result};

use crate::traits::{OnSwap, Registrar};
use crate::traits::Registrar;
pub use pallet::*;
use parity_scale_codec::{Decode, Encode};
use runtime_parachains::paras::{OnNewHead, ParaKind};
use runtime_parachains::{
paras::{OnNewHead, ParaKind},
OnSwap,
};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{CheckedSub, Saturating},
Expand Down Expand Up @@ -131,7 +134,7 @@ pub mod pallet {
type Currency: ReservableCurrency<Self::AccountId>;

/// Runtime hook for when a lease holding parachain and on-demand parachain swap.
type OnSwap: crate::traits::OnSwap;
type OnSwap: runtime_parachains::OnSwap;

/// The deposit to be paid to run a on-demand parachain.
/// This should include the cost for storing the genesis head and validation code.
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/common/src/slots/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ impl<T: Config> Pallet<T> {
}
}

impl<T: Config> crate::traits::OnSwap for Pallet<T> {
impl<T: Config> runtime_parachains::OnSwap for Pallet<T> {
fn on_swap(one: ParaId, other: ParaId) {
Leases::<T>::mutate(one, |x| Leases::<T>::mutate(other, |y| sp_std::mem::swap(x, y)))
}
Expand Down
9 changes: 0 additions & 9 deletions polkadot/runtime/common/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,3 @@ pub trait Auctioneer<BlockNumber> {
/// Check if the para and user combination has won an auction in the past.
fn has_won_an_auction(para: ParaId, bidder: &Self::AccountId) -> bool;
}

/// Runtime hook for when we swap a lease holding parachain and an on-demand parachain.
#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait OnSwap {
tdimitrov marked this conversation as resolved.
Show resolved Hide resolved
/// Updates any needed state/references to enact a logical swap of two parachains. Identity,
/// code and `head_data` remain equivalent for all parachains/threads, however other properties
/// such as leases, deposits held and thread/chain nature are swapped.
fn on_swap(one: ParaId, other: ParaId);
}
21 changes: 21 additions & 0 deletions polkadot/runtime/parachains/src/coretime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use crate::{
assigner_coretime::{self, PartsOf57600},
initializer::{OnNewSession, SessionChangeNotification},
origin::{ensure_parachain, Origin},
OnSwap,
};

mod benchmarking;
Expand Down Expand Up @@ -83,6 +84,8 @@ enum CoretimeCalls {
SetLease(pallet_broker::TaskId, pallet_broker::Timeslice),
#[codec(index = 19)]
NotifyCoreCount(u16),
#[codec(index = 20)]
SwapLeases(ParaId, ParaId),
tdimitrov marked this conversation as resolved.
Show resolved Hide resolved
}

#[frame_support::pallet]
Expand Down Expand Up @@ -241,6 +244,24 @@ impl<T: Config> OnNewSession<BlockNumberFor<T>> for Pallet<T> {
}
}

impl<T: Config> OnSwap for Pallet<T> {
fn on_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);
}
}
}

fn mk_coretime_call(call: crate::coretime::CoretimeCalls) -> Instruction<()> {
Instruction::Transact {
origin_kind: OriginKind::Superuser,
Expand Down
9 changes: 9 additions & 0 deletions polkadot/runtime/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,12 @@ pub fn schedule_code_upgrade<T: paras::Config>(
pub fn set_current_head<T: paras::Config>(id: ParaId, new_head: HeadData) {
paras::Pallet::<T>::set_current_head(id, new_head)
}

/// Runtime hook for when we swap a lease holding parachain and an on-demand parachain.
#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait OnSwap {
/// Updates any needed state/references to enact a logical swap of two parachains. Identity,
/// code and `head_data` remain equivalent for all parachains/threads, however other properties
/// such as leases, deposits held and thread/chain nature are swapped.
fn on_swap(one: ParaId, other: ParaId);
}
14 changes: 14 additions & 0 deletions substrate/frame/broker/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,20 @@ mod benches {
Ok(())
}

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

setup_leases::<T>(T::MaxLeasedCores::get(), 1, 10);
setup_leases::<T>(T::MaxLeasedCores::get(), 2, 10);

#[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
32 changes: 32 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,36 @@ 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_exists = false;
let mut other_exists = false;
let leases = Leases::<T>::get()
.into_inner()
.into_iter()
.map(|mut lease| {
if lease.task == id {
lease.task = other;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I don't think TaskId uniqueness is enforced anywhere in Leases, so this effectively swaps all leases sharing a TaskId. This shouldn't really matter as there should only be one task for both id and other.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point though!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought there could be multiple leases and we do want to swap all of them.

If this is the case, we'd better add another ensure! for it?

Copy link
Contributor Author

@tdimitrov tdimitrov Mar 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this -> f5f6dce

The error code I use is not entirely correct but I don't see a point adding a new one just for a temp call.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No Basti has a point. The "correctness" of the swap has already been verified on the relay chain, we should be very lenient on the Coretime chain. In particular, there could be a race and the lease of one para expired by the time the message arrives at the coretime chain (admittedly super unlikely edge case, but still), we should still do the swap, although one of the leases does not exist.

I mean that race in particular is really super niche, if a user updates that close he could miss the deadline himself already.

Nevertheless, I would err on as little ensures as possible: The swap is confirmed, it actually has to be good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I came to the same conclusion and removed everything. Even if someone decides to use the extrinsic directly it can be called again and 'undo' the result.

id_exists = true;
} else if lease.task == other {
lease.task = id;
other_exists = true;
}
lease
})
.collect::<Vec<_>>();

ensure!(id_exists && other_exists, Error::<T>::UnknownReservation);

let leases = if let Ok(leases) = BoundedVec::try_from(leases) {
leases
} else {
defensive!("leases is extracted from a `BoundedVec` without adding new elements so the conversation should always succeed");
return Err(DispatchError::Other("Failed to convert leases to BoundedVec"));
};

Leases::<T>::set(leases);

tdimitrov marked this conversation as resolved.
Show resolved Hide resolved
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(20)]
#[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(())
}
}
}
9 changes: 9 additions & 0 deletions substrate/frame/broker/src/weights.rs

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

Loading