coretime_westend_runtime/
coretime.rs1use crate::{xcm_config::LocationToAccountId, *};
18use codec::{Decode, Encode};
19use cumulus_pallet_parachain_system::RelaychainDataProvider;
20use cumulus_primitives_core::relay_chain;
21use frame_support::parameter_types;
22use pallet_broker::{
23 CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600, RCBlockNumberOf, TaskId,
24};
25use parachains_common::{AccountId, Balance};
26use sp_runtime::traits::MaybeConvert;
27use westend_runtime_constants::system_parachain::coretime;
28use xcm::latest::prelude::*;
29use xcm_executor::traits::ConvertLocation;
30
31#[derive(Encode, Decode)]
35enum RelayRuntimePallets {
36 #[codec(index = 66)]
37 Coretime(CoretimeProviderCalls),
38}
39
40#[derive(Encode, Decode)]
42enum CoretimeProviderCalls {
43 #[codec(index = 1)]
44 RequestCoreCount(CoreIndex),
45 #[codec(index = 2)]
46 RequestRevenueInfoAt(relay_chain::BlockNumber),
47 #[codec(index = 3)]
48 CreditAccount(AccountId, Balance),
49 #[codec(index = 4)]
50 AssignCore(
51 CoreIndex,
52 relay_chain::BlockNumber,
53 Vec<(CoreAssignment, PartsOf57600)>,
54 Option<relay_chain::BlockNumber>,
55 ),
56}
57
58parameter_types! {
59 pub const BrokerPalletId: PalletId = PalletId(*b"py/broke");
60 pub const MinimumCreditPurchase: Balance = UNITS / 10;
61 pub const MinimumEndPrice: Balance = UNITS;
62}
63
64pub struct CoretimeAllocator;
68impl CoretimeInterface for CoretimeAllocator {
69 type AccountId = AccountId;
70 type Balance = Balance;
71 type RelayChainBlockNumberProvider = RelaychainDataProvider<Runtime>;
72
73 fn request_core_count(count: CoreIndex) {
74 use crate::coretime::CoretimeProviderCalls::RequestCoreCount;
75 let request_core_count_call = RelayRuntimePallets::Coretime(RequestCoreCount(count));
76
77 let call_weight = Weight::from_parts(190_000_000, 1700);
82
83 let message = Xcm(vec![
84 Instruction::UnpaidExecution {
85 weight_limit: WeightLimit::Unlimited,
86 check_origin: None,
87 },
88 Instruction::Transact {
89 origin_kind: OriginKind::Native,
90 call: request_core_count_call.encode().into(),
91 fallback_max_weight: Some(call_weight),
92 },
93 ]);
94
95 match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
96 Ok(_) => tracing::debug!(
97 target: "runtime::coretime",
98 "Request to update schedulable cores sent successfully."
99 ),
100 Err(e) => tracing::error!(
101 target: "runtime::coretime", error=?e,
102 "Failed to send request to update schedulable cores"
103 ),
104 }
105 }
106
107 fn request_revenue_info_at(when: RCBlockNumberOf<Self>) {
108 use crate::coretime::CoretimeProviderCalls::RequestRevenueInfoAt;
109 let request_revenue_info_at_call =
110 RelayRuntimePallets::Coretime(RequestRevenueInfoAt(when));
111
112 let message = Xcm(vec![
113 Instruction::UnpaidExecution {
114 weight_limit: WeightLimit::Unlimited,
115 check_origin: None,
116 },
117 Instruction::Transact {
118 origin_kind: OriginKind::Native,
119 call: request_revenue_info_at_call.encode().into(),
120 fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)),
121 },
122 ]);
123
124 match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
125 Ok(_) => tracing::debug!(
126 target: "runtime::coretime",
127 "Request for revenue information sent successfully."
128 ),
129 Err(e) => tracing::error!(
130 target: "runtime::coretime", error=?e,
131 "Request for revenue information failed to send"
132 ),
133 }
134 }
135
136 fn credit_account(who: Self::AccountId, amount: Self::Balance) {
137 use crate::coretime::CoretimeProviderCalls::CreditAccount;
138 let credit_account_call = RelayRuntimePallets::Coretime(CreditAccount(who, amount));
139
140 let message = Xcm(vec![
141 Instruction::UnpaidExecution {
142 weight_limit: WeightLimit::Unlimited,
143 check_origin: None,
144 },
145 Instruction::Transact {
146 origin_kind: OriginKind::Native,
147 call: credit_account_call.encode().into(),
148 fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)),
149 },
150 ]);
151
152 match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
153 Ok(_) => tracing::debug!(
154 target: "runtime::coretime",
155 "Instruction to credit account sent successfully."
156 ),
157 Err(e) => tracing::error!(
158 target: "runtime::coretime", error=?e,
159 "Instruction to credit account failed to send"
160 ),
161 }
162 }
163
164 fn assign_core(
165 core: CoreIndex,
166 begin: RCBlockNumberOf<Self>,
167 assignment: Vec<(CoreAssignment, PartsOf57600)>,
168 end_hint: Option<RCBlockNumberOf<Self>>,
169 ) {
170 use crate::coretime::CoretimeProviderCalls::AssignCore;
171
172 let call_weight = Weight::from_parts(980_000_000, 3800);
177
178 let assignment = if assignment.len() > 28 {
185 let mut total_parts = 0u16;
186 let mut assignment_truncated = vec![(CoreAssignment::Idle, 0)];
190 assignment_truncated.extend(
192 assignment
193 .into_iter()
194 .filter(|(a, _)| *a != CoreAssignment::Idle)
195 .take(27)
196 .inspect(|(_, parts)| total_parts += *parts)
197 .collect::<Vec<_>>(),
198 );
199
200 assignment_truncated[0].1 = 57_600u16.saturating_sub(total_parts);
202 assignment_truncated
203 } else {
204 assignment
205 };
206
207 let assign_core_call =
208 RelayRuntimePallets::Coretime(AssignCore(core, begin, assignment, end_hint));
209
210 let message = Xcm(vec![
211 Instruction::UnpaidExecution {
212 weight_limit: WeightLimit::Unlimited,
213 check_origin: None,
214 },
215 Instruction::Transact {
216 origin_kind: OriginKind::Native,
217 call: assign_core_call.encode().into(),
218 fallback_max_weight: Some(call_weight),
219 },
220 ]);
221
222 match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
223 Ok(_) => tracing::debug!(
224 target: "runtime::coretime",
225 "Core assignment sent successfully."
226 ),
227 Err(e) => tracing::error!(
228 target: "runtime::coretime", error=?e,
229 "Core assignment failed to send"
230 ),
231 }
232 }
233}
234
235pub struct SovereignAccountOf;
236impl MaybeConvert<TaskId, AccountId> for SovereignAccountOf {
237 fn maybe_convert(id: TaskId) -> Option<AccountId> {
238 let location = Location::new(1, [Parachain(id)]);
240 LocationToAccountId::convert_location(&location)
241 }
242}
243
244impl pallet_broker::Config for Runtime {
245 type RuntimeEvent = RuntimeEvent;
246 type Currency = Balances;
247 type OnRevenue = AccumulateForward;
248 type TimeslicePeriod = ConstU32<{ coretime::TIMESLICE_PERIOD }>;
249 type MaxLeasedCores = ConstU32<50>;
250 type MaxReservedCores = ConstU32<50>;
251 type Coretime = CoretimeAllocator;
252 type ConvertBalance = sp_runtime::traits::Identity;
253 type WeightInfo = weights::pallet_broker::WeightInfo<Runtime>;
254 type PalletId = BrokerPalletId;
255 type AdminOrigin = EnsureRoot<AccountId>;
256 type SovereignAccountOf = SovereignAccountOf;
257 type MaxAutoRenewals = ConstU32<50>;
258 type PriceAdapter = pallet_broker::MinimumPrice<Balance, MinimumEndPrice>;
259 type MinimumCreditPurchase = MinimumCreditPurchase;
260}