mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-18 15:15:42 +00:00
Coretime Feature branch (relay chain) (#1694)
Also fixes: https://github.com/paritytech/polkadot-sdk/issues/1417 - [x] CoreIndex -> AssignmentProvider mapping will be able to change any time. - [x] Implement - [x] Provide Migrations - [x] Add and fix tests - [x] Implement bulk assigner logic - [x] bulk assigner tests - [x] Port over current assigner to use bulk designer (+ share on-demand with bulk): top-level assigner has core ranges: legacy, bulk - [x] Adjust migrations to reflect new assigner structure - [x] Move migration code to Assignment code directly and make it recursive (make it possible to skip releases) -> follow up ticket. - [x] Test migrations - [x] Add migration PR to runtimes repo -> follow up ticket. - [x] Wire up with actual UMP messages - [x] Write PR docs --------- Co-authored-by: eskimor <eskimor@no-such-url.com> Co-authored-by: Bradley Olson <34992650+BradleyOlson64@users.noreply.github.com> Co-authored-by: BradleyOlson64 <lotrftw9@gmail.com> Co-authored-by: Anton Vilhelm Ásgeirsson <antonva@users.noreply.github.com> Co-authored-by: antonva <anton.asgeirsson@parity.io> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Marcin S. <marcin@realemail.net> Co-authored-by: Bastian Köcher <info@kchr.de> Co-authored-by: command-bot <>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! On demand assigner pallet benchmarking.
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use super::*;
|
||||
use frame_benchmarking::v2::*;
|
||||
use frame_support::traits::OriginTrait;
|
||||
use pallet_broker::CoreIndex as BrokerCoreIndex;
|
||||
|
||||
#[benchmarks]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
use assigner_coretime::PartsOf57600;
|
||||
|
||||
#[benchmark]
|
||||
fn request_core_count() {
|
||||
// Setup
|
||||
let root_origin = <T as frame_system::Config>::RuntimeOrigin::root();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(
|
||||
root_origin as <T as frame_system::Config>::RuntimeOrigin,
|
||||
// random core count
|
||||
100,
|
||||
)
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn assign_core(s: Linear<1, 100>) {
|
||||
// Setup
|
||||
let root_origin = <T as frame_system::Config>::RuntimeOrigin::root();
|
||||
|
||||
// Use parameterized assignment count
|
||||
let mut assignments: Vec<(CoreAssignment, PartsOf57600)> = vec![0u16; s as usize - 1]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, parts)| {
|
||||
(CoreAssignment::Task(index as u32), PartsOf57600::new_saturating(parts))
|
||||
})
|
||||
.collect();
|
||||
// Parts must add up to exactly 57600. Here we add all the parts in one assignment, as
|
||||
// it won't effect the weight and splitting up the parts into even groupings may not
|
||||
// work for every value `s`.
|
||||
assignments.push((CoreAssignment::Task(s as u32), PartsOf57600::FULL));
|
||||
|
||||
let core_index: BrokerCoreIndex = 0;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(
|
||||
root_origin as <T as frame_system::Config>::RuntimeOrigin,
|
||||
core_index,
|
||||
BlockNumberFor::<T>::from(5u32),
|
||||
assignments,
|
||||
Some(BlockNumberFor::<T>::from(20u32)),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Migrations for the Coretime pallet.
|
||||
|
||||
pub use v_coretime::{GetLegacyLease, MigrateToCoretime};
|
||||
|
||||
mod v_coretime {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use crate::scheduler::common::AssignmentProvider;
|
||||
use crate::{
|
||||
assigner_coretime, configuration,
|
||||
coretime::{mk_coretime_call, Config, PartsOf57600, WeightInfo},
|
||||
paras,
|
||||
};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
use frame_support::{
|
||||
traits::{OnRuntimeUpgrade, PalletInfoAccess, StorageVersion},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use pallet_broker::{CoreAssignment, CoreMask, ScheduleItem};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use parity_scale_codec::Decode;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use parity_scale_codec::Encode;
|
||||
use polkadot_parachain_primitives::primitives::IsSystem;
|
||||
use primitives::{CoreIndex, Id as ParaId};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_core::Get;
|
||||
use sp_runtime::BoundedVec;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_std::vec::Vec;
|
||||
use sp_std::{iter, prelude::*, result};
|
||||
use xcm::v3::{
|
||||
send_xcm, Instruction, Junction, Junctions, MultiLocation, SendError, WeightLimit, Xcm,
|
||||
};
|
||||
|
||||
/// Return information about a legacy lease of a parachain.
|
||||
pub trait GetLegacyLease<N> {
|
||||
/// If parachain is a lease holding parachain, return the block at which the lease expires.
|
||||
fn get_parachain_lease_in_blocks(para: ParaId) -> Option<N>;
|
||||
}
|
||||
|
||||
/// Migrate a chain to use coretime.
|
||||
///
|
||||
/// This assumes that the `Coretime` and the `AssignerCoretime` pallets are added at the same
|
||||
/// time to a runtime.
|
||||
pub struct MigrateToCoretime<T, SendXcm, LegacyLease>(
|
||||
sp_std::marker::PhantomData<(T, SendXcm, LegacyLease)>,
|
||||
);
|
||||
|
||||
impl<T: Config, SendXcm: xcm::v3::SendXcm, LegacyLease: GetLegacyLease<BlockNumberFor<T>>>
|
||||
MigrateToCoretime<T, SendXcm, LegacyLease>
|
||||
{
|
||||
fn already_migrated() -> bool {
|
||||
// We are using the assigner coretime because the coretime pallet doesn't has any
|
||||
// storage data. But both pallets are introduced at the same time, so this is fine.
|
||||
let name_hash = assigner_coretime::Pallet::<T>::name_hash();
|
||||
let mut next_key = name_hash.to_vec();
|
||||
let storage_version_key = StorageVersion::storage_key::<assigner_coretime::Pallet<T>>();
|
||||
|
||||
loop {
|
||||
match sp_io::storage::next_key(&next_key) {
|
||||
// StorageVersion is initialized before, so we need to ingore it.
|
||||
Some(key) if &key == &storage_version_key => {
|
||||
next_key = key;
|
||||
},
|
||||
// If there is any other key with the prefix of the pallet,
|
||||
// we already have executed the migration.
|
||||
Some(key) if key.starts_with(&name_hash) => {
|
||||
log::info!("`MigrateToCoretime` already executed!");
|
||||
return true
|
||||
},
|
||||
// Any other key/no key means that we did not yet have migrated.
|
||||
None | Some(_) => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
T: Config + crate::dmp::Config,
|
||||
SendXcm: xcm::v3::SendXcm,
|
||||
LegacyLease: GetLegacyLease<BlockNumberFor<T>>,
|
||||
> OnRuntimeUpgrade for MigrateToCoretime<T, SendXcm, LegacyLease>
|
||||
{
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if Self::already_migrated() {
|
||||
return Weight::zero()
|
||||
}
|
||||
|
||||
log::info!("Migrating existing parachains to coretime.");
|
||||
migrate_to_coretime::<T, SendXcm, LegacyLease>()
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::DispatchError> {
|
||||
if Self::already_migrated() {
|
||||
return Ok(Vec::new())
|
||||
}
|
||||
|
||||
let legacy_paras = paras::Parachains::<T>::get();
|
||||
let config = <configuration::Pallet<T>>::config();
|
||||
let total_core_count = config.coretime_cores + legacy_paras.len() as u32;
|
||||
|
||||
let dmp_queue_size =
|
||||
crate::dmp::Pallet::<T>::dmq_contents(T::BrokerId::get().into()).len() as u32;
|
||||
|
||||
let total_core_count = total_core_count as u32;
|
||||
|
||||
Ok((total_core_count, dmp_queue_size).encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
|
||||
if state.is_empty() {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
log::trace!("Running post_upgrade()");
|
||||
|
||||
let (prev_core_count, prev_dmp_queue_size) =
|
||||
<(u32, u32)>::decode(&mut &state[..]).unwrap();
|
||||
|
||||
let dmp_queue_size =
|
||||
crate::dmp::Pallet::<T>::dmq_contents(T::BrokerId::get().into()).len() as u32;
|
||||
let new_core_count = assigner_coretime::Pallet::<T>::session_core_count();
|
||||
ensure!(new_core_count == prev_core_count, "Total number of cores need to not change.");
|
||||
ensure!(
|
||||
dmp_queue_size == prev_dmp_queue_size + 1,
|
||||
"There should have been enqueued one DMP message."
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate to Coretime.
|
||||
//
|
||||
// NOTE: Also migrates coretime_cores config value in configuration::ActiveConfig.
|
||||
fn migrate_to_coretime<
|
||||
T: Config,
|
||||
SendXcm: xcm::v3::SendXcm,
|
||||
LegacyLease: GetLegacyLease<BlockNumberFor<T>>,
|
||||
>() -> Weight {
|
||||
let legacy_paras = paras::Pallet::<T>::parachains();
|
||||
let legacy_count = legacy_paras.len() as u32;
|
||||
let now = <frame_system::Pallet<T>>::block_number();
|
||||
for (core, para_id) in legacy_paras.into_iter().enumerate() {
|
||||
let r = assigner_coretime::Pallet::<T>::assign_core(
|
||||
CoreIndex(core as u32),
|
||||
now,
|
||||
vec![(CoreAssignment::Task(para_id.into()), PartsOf57600::FULL)],
|
||||
None,
|
||||
);
|
||||
if let Err(err) = r {
|
||||
log::error!(
|
||||
"Creating assignment for existing para failed: {:?}, error: {:?}",
|
||||
para_id,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let config = <configuration::Pallet<T>>::config();
|
||||
// coretime_cores was on_demand_cores until now:
|
||||
for on_demand in 0..config.coretime_cores {
|
||||
let core = CoreIndex(legacy_count.saturating_add(on_demand as _));
|
||||
let r = assigner_coretime::Pallet::<T>::assign_core(
|
||||
core,
|
||||
now,
|
||||
vec![(CoreAssignment::Pool, PartsOf57600::FULL)],
|
||||
None,
|
||||
);
|
||||
if let Err(err) = r {
|
||||
log::error!("Creating assignment for existing on-demand core, failed: {:?}", err);
|
||||
}
|
||||
}
|
||||
let total_cores = config.coretime_cores + legacy_count;
|
||||
configuration::ActiveConfig::<T>::mutate(|c| {
|
||||
c.coretime_cores = total_cores;
|
||||
});
|
||||
|
||||
if let Err(err) = migrate_send_assignments_to_coretime_chain::<T, SendXcm, LegacyLease>() {
|
||||
log::error!("Sending legacy chain data to coretime chain failed: {:?}", err);
|
||||
}
|
||||
|
||||
let single_weight = <T as Config>::WeightInfo::assign_core(1);
|
||||
single_weight
|
||||
.saturating_mul(u64::from(legacy_count.saturating_add(config.coretime_cores)))
|
||||
// Second read from sending assignments to the coretime chain.
|
||||
.saturating_add(T::DbWeight::get().reads_writes(2, 1))
|
||||
}
|
||||
|
||||
fn migrate_send_assignments_to_coretime_chain<
|
||||
T: Config,
|
||||
SendXcm: xcm::v3::SendXcm,
|
||||
LegacyLease: GetLegacyLease<BlockNumberFor<T>>,
|
||||
>() -> result::Result<(), SendError> {
|
||||
let legacy_paras = paras::Pallet::<T>::parachains();
|
||||
let legacy_paras_count = legacy_paras.len();
|
||||
let (system_chains, lease_holding): (Vec<_>, Vec<_>) =
|
||||
legacy_paras.into_iter().partition(IsSystem::is_system);
|
||||
|
||||
let reservations = system_chains.into_iter().map(|p| {
|
||||
let schedule = BoundedVec::truncate_from(vec![ScheduleItem {
|
||||
mask: CoreMask::complete(),
|
||||
assignment: CoreAssignment::Task(p.into()),
|
||||
}]);
|
||||
mk_coretime_call(crate::coretime::CoretimeCalls::Reserve(schedule))
|
||||
});
|
||||
|
||||
let leases = lease_holding.into_iter().filter_map(|p| {
|
||||
log::trace!(target: "coretime-migration", "Preparing sending of lease holding para {:?}", p);
|
||||
let Some(valid_until) = LegacyLease::get_parachain_lease_in_blocks(p) else {
|
||||
log::error!("Lease holding chain with no lease information?!");
|
||||
return None
|
||||
};
|
||||
let valid_until: u32 = match valid_until.try_into() {
|
||||
Ok(val) => val,
|
||||
Err(_) => {
|
||||
log::error!("Converting block number to u32 failed!");
|
||||
return None
|
||||
},
|
||||
};
|
||||
// We assume the coretime chain set this parameter to the recommened value in RFC-1:
|
||||
const TIME_SLICE_PERIOD: u32 = 80;
|
||||
let round_up = if valid_until % TIME_SLICE_PERIOD > 0 { 1 } else { 0 };
|
||||
let time_slice = valid_until / TIME_SLICE_PERIOD + TIME_SLICE_PERIOD * round_up;
|
||||
log::trace!(target: "coretime-migration", "Sending of lease holding para {:?}, valid_until: {:?}, time_slice: {:?}", p, valid_until, time_slice);
|
||||
Some(mk_coretime_call(crate::coretime::CoretimeCalls::SetLease(p.into(), time_slice)))
|
||||
});
|
||||
|
||||
let core_count: u16 = configuration::Pallet::<T>::config().coretime_cores.saturated_into();
|
||||
let set_core_count = iter::once(mk_coretime_call(
|
||||
crate::coretime::CoretimeCalls::NotifyCoreCount(core_count),
|
||||
));
|
||||
|
||||
let pool = (legacy_paras_count..core_count.into()).map(|_| {
|
||||
let schedule = BoundedVec::truncate_from(vec![ScheduleItem {
|
||||
mask: CoreMask::complete(),
|
||||
assignment: CoreAssignment::Pool,
|
||||
}]);
|
||||
// Reserved cores will come before lease cores, so cores will change their assignments
|
||||
// when coretime chain sends us their assign_core calls -> Good test.
|
||||
mk_coretime_call(crate::coretime::CoretimeCalls::Reserve(schedule))
|
||||
});
|
||||
|
||||
let message_content = iter::once(Instruction::UnpaidExecution {
|
||||
weight_limit: WeightLimit::Unlimited,
|
||||
check_origin: None,
|
||||
})
|
||||
.chain(reservations)
|
||||
.chain(pool)
|
||||
.chain(leases)
|
||||
.chain(set_core_count)
|
||||
.collect();
|
||||
|
||||
let message = Xcm(message_content);
|
||||
|
||||
send_xcm::<SendXcm>(
|
||||
MultiLocation {
|
||||
parents: 0,
|
||||
interior: Junctions::X1(Junction::Parachain(T::BrokerId::get())),
|
||||
},
|
||||
message,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Extrinsics implementing the relay chain side of the Coretime interface.
|
||||
//!
|
||||
//! <https://github.com/polkadot-fellows/RFCs/blob/main/text/0005-coretime-interface.md>
|
||||
|
||||
use sp_std::{prelude::*, result};
|
||||
|
||||
use frame_support::{pallet_prelude::*, traits::Currency};
|
||||
use frame_system::pallet_prelude::*;
|
||||
pub use pallet::*;
|
||||
use pallet_broker::{CoreAssignment, CoreIndex as BrokerCoreIndex};
|
||||
use primitives::{CoreIndex, Id as ParaId};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use xcm::v3::{
|
||||
send_xcm, Instruction, Junction, Junctions, MultiLocation, OriginKind, SendXcm, Xcm,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
assigner_coretime::{self, PartsOf57600},
|
||||
initializer::{OnNewSession, SessionChangeNotification},
|
||||
origin::{ensure_parachain, Origin},
|
||||
};
|
||||
|
||||
mod benchmarking;
|
||||
pub mod migration;
|
||||
|
||||
pub trait WeightInfo {
|
||||
fn request_core_count() -> Weight;
|
||||
//fn request_revenue_info_at() -> Weight;
|
||||
//fn credit_account() -> Weight;
|
||||
fn assign_core(s: u32) -> Weight;
|
||||
}
|
||||
|
||||
/// A weight info that is only suitable for testing.
|
||||
pub struct TestWeightInfo;
|
||||
|
||||
impl WeightInfo for TestWeightInfo {
|
||||
fn request_core_count() -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
// TODO: Add real benchmarking functionality for each of these to
|
||||
// benchmarking.rs, then uncomment here and in trait definition.
|
||||
/*fn request_revenue_info_at() -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
fn credit_account() -> Weight {
|
||||
Weight::MAX
|
||||
}*/
|
||||
fn assign_core(_s: u32) -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
}
|
||||
|
||||
/// Broker pallet index on the coretime chain. Used to
|
||||
///
|
||||
/// construct remote calls. The codec index must correspond to the index of `Broker` in the
|
||||
/// `construct_runtime` of the coretime chain.
|
||||
#[derive(Encode, Decode)]
|
||||
enum BrokerRuntimePallets {
|
||||
#[codec(index = 50)]
|
||||
Broker(CoretimeCalls),
|
||||
}
|
||||
|
||||
/// Call encoding for the calls needed from the Broker pallet.
|
||||
#[derive(Encode, Decode)]
|
||||
enum CoretimeCalls {
|
||||
#[codec(index = 1)]
|
||||
Reserve(pallet_broker::Schedule),
|
||||
#[codec(index = 3)]
|
||||
SetLease(pallet_broker::TaskId, pallet_broker::Timeslice),
|
||||
#[codec(index = 19)]
|
||||
NotifyCoreCount(u16),
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use crate::configuration;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::without_storage_info]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config + assigner_coretime::Config {
|
||||
type RuntimeOrigin: From<<Self as frame_system::Config>::RuntimeOrigin>
|
||||
+ Into<result::Result<Origin, <Self as Config>::RuntimeOrigin>>;
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
/// The runtime's definition of a Currency.
|
||||
type Currency: Currency<Self::AccountId>;
|
||||
/// The ParaId of the broker system parachain.
|
||||
#[pallet::constant]
|
||||
type BrokerId: Get<u32>;
|
||||
/// Something that provides the weight of this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
type SendXcm: SendXcm;
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
/// The broker chain has asked for revenue information for a specific block.
|
||||
RevenueInfoRequested { when: BlockNumberFor<T> },
|
||||
/// A core has received a new assignment from the broker chain.
|
||||
CoreAssigned { core: CoreIndex },
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// The paraid making the call is not the coretime brokerage system parachain.
|
||||
NotBroker,
|
||||
}
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
#[pallet::weight(<T as Config>::WeightInfo::request_core_count())]
|
||||
#[pallet::call_index(1)]
|
||||
pub fn request_core_count(origin: OriginFor<T>, count: u16) -> DispatchResult {
|
||||
// Ignore requests not coming from the broker parachain or root.
|
||||
Self::ensure_root_or_para(origin, <T as Config>::BrokerId::get().into())?;
|
||||
|
||||
configuration::Pallet::<T>::set_coretime_cores_unchecked(u32::from(count))
|
||||
}
|
||||
|
||||
//// TODO Impl me!
|
||||
////#[pallet::weight(<T as Config>::WeightInfo::request_revenue_info_at())]
|
||||
//#[pallet::call_index(2)]
|
||||
//pub fn request_revenue_info_at(
|
||||
// origin: OriginFor<T>,
|
||||
// _when: BlockNumberFor<T>,
|
||||
//) -> DispatchResult {
|
||||
// // Ignore requests not coming from the broker parachain or root.
|
||||
// Self::ensure_root_or_para(origin, <T as Config>::BrokerId::get().into())?;
|
||||
// Ok(())
|
||||
//}
|
||||
|
||||
//// TODO Impl me!
|
||||
////#[pallet::weight(<T as Config>::WeightInfo::credit_account())]
|
||||
//#[pallet::call_index(3)]
|
||||
//pub fn credit_account(
|
||||
// origin: OriginFor<T>,
|
||||
// _who: T::AccountId,
|
||||
// _amount: BalanceOf<T>,
|
||||
//) -> DispatchResult {
|
||||
// // Ignore requests not coming from the broker parachain or root.
|
||||
// Self::ensure_root_or_para(origin, <T as Config>::BrokerId::get().into())?;
|
||||
// Ok(())
|
||||
//}
|
||||
|
||||
/// Receive instructions from the `ExternalBrokerOrigin`, detailing how a specific core is
|
||||
/// to be used.
|
||||
///
|
||||
/// Parameters:
|
||||
/// -`origin`: The `ExternalBrokerOrigin`, assumed to be the Broker system parachain.
|
||||
/// -`core`: The core that should be scheduled.
|
||||
/// -`begin`: The starting blockheight of the instruction.
|
||||
/// -`assignment`: How the blockspace should be utilised.
|
||||
/// -`end_hint`: An optional hint as to when this particular set of instructions will end.
|
||||
// The broker pallet's `CoreIndex` definition is `u16` but on the relay chain it's `struct
|
||||
// CoreIndex(u32)`
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(<T as Config>::WeightInfo::assign_core(assignment.len() as u32))]
|
||||
pub fn assign_core(
|
||||
origin: OriginFor<T>,
|
||||
core: BrokerCoreIndex,
|
||||
begin: BlockNumberFor<T>,
|
||||
assignment: Vec<(CoreAssignment, PartsOf57600)>,
|
||||
end_hint: Option<BlockNumberFor<T>>,
|
||||
) -> DispatchResult {
|
||||
// Ignore requests not coming from the broker parachain or root.
|
||||
Self::ensure_root_or_para(origin, T::BrokerId::get().into())?;
|
||||
|
||||
let core = u32::from(core).into();
|
||||
|
||||
<assigner_coretime::Pallet<T>>::assign_core(core, begin, assignment, end_hint)?;
|
||||
Self::deposit_event(Event::<T>::CoreAssigned { core });
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Ensure the origin is one of Root or the `para` itself.
|
||||
fn ensure_root_or_para(
|
||||
origin: <T as frame_system::Config>::RuntimeOrigin,
|
||||
id: ParaId,
|
||||
) -> DispatchResult {
|
||||
if let Ok(caller_id) = ensure_parachain(<T as Config>::RuntimeOrigin::from(origin.clone()))
|
||||
{
|
||||
// Check if matching para id...
|
||||
ensure!(caller_id == id, Error::<T>::NotBroker);
|
||||
} else {
|
||||
// Check if root...
|
||||
ensure_root(origin.clone())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn initializer_on_new_session(notification: &SessionChangeNotification<BlockNumberFor<T>>) {
|
||||
let old_core_count = notification.prev_config.coretime_cores;
|
||||
let new_core_count = notification.new_config.coretime_cores;
|
||||
if new_core_count != old_core_count {
|
||||
let core_count: u16 = new_core_count.saturated_into();
|
||||
let message = Xcm(vec![mk_coretime_call(
|
||||
crate::coretime::CoretimeCalls::NotifyCoreCount(core_count),
|
||||
)]);
|
||||
if let Err(err) = send_xcm::<T::SendXcm>(
|
||||
MultiLocation {
|
||||
parents: 0,
|
||||
interior: Junctions::X1(Junction::Parachain(T::BrokerId::get())),
|
||||
},
|
||||
message,
|
||||
) {
|
||||
log::error!("Sending `NotifyCoreCount` to coretime chain failed: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> OnNewSession<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn on_new_session(notification: &SessionChangeNotification<BlockNumberFor<T>>) {
|
||||
Self::initializer_on_new_session(notification);
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_coretime_call(call: crate::coretime::CoretimeCalls) -> Instruction<()> {
|
||||
Instruction::Transact {
|
||||
origin_kind: OriginKind::Native,
|
||||
require_weight_at_most: Weight::from_parts(1000000000, 200000),
|
||||
call: BrokerRuntimePallets::Broker(call).encode().into(),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user