use crate::{xcm_config::LocationToAccountId, *};
use codec::{Decode, Encode};
use cumulus_pallet_parachain_system::RelaychainDataProvider;
use cumulus_primitives_core::relay_chain;
use frame_support::parameter_types;
use pallet_broker::{
CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600, RCBlockNumberOf, TaskId,
};
use parachains_common::{AccountId, Balance};
use sp_runtime::traits::MaybeConvert;
use westend_runtime_constants::system_parachain::coretime;
use xcm::latest::prelude::*;
use xcm_executor::traits::ConvertLocation;
#[derive(Encode, Decode)]
enum RelayRuntimePallets {
#[codec(index = 66)]
Coretime(CoretimeProviderCalls),
}
#[derive(Encode, Decode)]
enum CoretimeProviderCalls {
#[codec(index = 1)]
RequestCoreCount(CoreIndex),
#[codec(index = 2)]
RequestRevenueInfoAt(relay_chain::BlockNumber),
#[codec(index = 3)]
CreditAccount(AccountId, Balance),
#[codec(index = 4)]
AssignCore(
CoreIndex,
relay_chain::BlockNumber,
Vec<(CoreAssignment, PartsOf57600)>,
Option<relay_chain::BlockNumber>,
),
}
parameter_types! {
pub const BrokerPalletId: PalletId = PalletId(*b"py/broke");
pub const MinimumCreditPurchase: Balance = UNITS / 10;
pub const MinimumEndPrice: Balance = UNITS;
}
pub struct CoretimeAllocator;
impl CoretimeInterface for CoretimeAllocator {
type AccountId = AccountId;
type Balance = Balance;
type RelayChainBlockNumberProvider = RelaychainDataProvider<Runtime>;
fn request_core_count(count: CoreIndex) {
use crate::coretime::CoretimeProviderCalls::RequestCoreCount;
let request_core_count_call = RelayRuntimePallets::Coretime(RequestCoreCount(count));
let call_weight = Weight::from_parts(190_000_000, 1700);
let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Native,
call: request_core_count_call.encode().into(),
fallback_max_weight: Some(call_weight),
},
]);
match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
Ok(_) => tracing::debug!(
target: "runtime::coretime",
"Request to update schedulable cores sent successfully."
),
Err(e) => tracing::error!(
target: "runtime::coretime", error=?e,
"Failed to send request to update schedulable cores"
),
}
}
fn request_revenue_info_at(when: RCBlockNumberOf<Self>) {
use crate::coretime::CoretimeProviderCalls::RequestRevenueInfoAt;
let request_revenue_info_at_call =
RelayRuntimePallets::Coretime(RequestRevenueInfoAt(when));
let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Native,
call: request_revenue_info_at_call.encode().into(),
fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)),
},
]);
match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
Ok(_) => tracing::debug!(
target: "runtime::coretime",
"Request for revenue information sent successfully."
),
Err(e) => tracing::error!(
target: "runtime::coretime", error=?e,
"Request for revenue information failed to send"
),
}
}
fn credit_account(who: Self::AccountId, amount: Self::Balance) {
use crate::coretime::CoretimeProviderCalls::CreditAccount;
let credit_account_call = RelayRuntimePallets::Coretime(CreditAccount(who, amount));
let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Native,
call: credit_account_call.encode().into(),
fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)),
},
]);
match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
Ok(_) => tracing::debug!(
target: "runtime::coretime",
"Instruction to credit account sent successfully."
),
Err(e) => tracing::error!(
target: "runtime::coretime", error=?e,
"Instruction to credit account failed to send"
),
}
}
fn assign_core(
core: CoreIndex,
begin: RCBlockNumberOf<Self>,
assignment: Vec<(CoreAssignment, PartsOf57600)>,
end_hint: Option<RCBlockNumberOf<Self>>,
) {
use crate::coretime::CoretimeProviderCalls::AssignCore;
let call_weight = Weight::from_parts(980_000_000, 3800);
let assignment = if assignment.len() > 28 {
let mut total_parts = 0u16;
let mut assignment_truncated = vec![(CoreAssignment::Idle, 0)];
assignment_truncated.extend(
assignment
.into_iter()
.filter(|(a, _)| *a != CoreAssignment::Idle)
.take(27)
.inspect(|(_, parts)| total_parts += *parts)
.collect::<Vec<_>>(),
);
assignment_truncated[0].1 = 57_600u16.saturating_sub(total_parts);
assignment_truncated
} else {
assignment
};
let assign_core_call =
RelayRuntimePallets::Coretime(AssignCore(core, begin, assignment, end_hint));
let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Native,
call: assign_core_call.encode().into(),
fallback_max_weight: Some(call_weight),
},
]);
match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
Ok(_) => tracing::debug!(
target: "runtime::coretime",
"Core assignment sent successfully."
),
Err(e) => tracing::error!(
target: "runtime::coretime", error=?e,
"Core assignment failed to send"
),
}
}
}
pub struct SovereignAccountOf;
impl MaybeConvert<TaskId, AccountId> for SovereignAccountOf {
fn maybe_convert(id: TaskId) -> Option<AccountId> {
let location = Location::new(1, [Parachain(id)]);
LocationToAccountId::convert_location(&location)
}
}
impl pallet_broker::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type OnRevenue = DapSatellite;
type TimeslicePeriod = ConstU32<{ coretime::TIMESLICE_PERIOD }>;
type MaxLeasedCores = ConstU32<50>;
type MaxReservedCores = ConstU32<50>;
type Coretime = CoretimeAllocator;
type ConvertBalance = sp_runtime::traits::Identity;
type WeightInfo = weights::pallet_broker::WeightInfo<Runtime>;
type PalletId = BrokerPalletId;
type AdminOrigin = EnsureRoot<AccountId>;
type SovereignAccountOf = SovereignAccountOf;
type MaxAutoRenewals = ConstU32<50>;
type PriceAdapter = pallet_broker::MinimumPrice<Balance, MinimumEndPrice>;
type MinimumCreditPurchase = MinimumCreditPurchase;
}