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 for chunk in assignment.chunks(28) {
183 let partial_assignment = chunk.to_vec();
184
185 let assign_core_call = RelayRuntimePallets::Coretime(AssignCore(
186 core,
187 begin,
188 partial_assignment,
189 end_hint,
190 ));
191
192 let message = Xcm(vec![
193 Instruction::UnpaidExecution {
194 weight_limit: WeightLimit::Unlimited,
195 check_origin: None,
196 },
197 Instruction::Transact {
198 origin_kind: OriginKind::Native,
199 call: assign_core_call.encode().into(),
200 fallback_max_weight: Some(call_weight),
201 },
202 ]);
203
204 match PolkadotXcm::send_xcm(Here, Location::parent(), message) {
205 Ok(_) => tracing::debug!(
206 target: "runtime::coretime",
207 "Core assignment sent successfully."
208 ),
209 Err(e) => tracing::error!(
210 target: "runtime::coretime", error=?e,
211 "Core assignment failed to send"
212 ),
213 }
214 }
215 }
216}
217
218pub struct SovereignAccountOf;
219impl MaybeConvert<TaskId, AccountId> for SovereignAccountOf {
220 fn maybe_convert(id: TaskId) -> Option<AccountId> {
221 let location = Location::new(1, [Parachain(id)]);
223 LocationToAccountId::convert_location(&location)
224 }
225}
226
227impl pallet_broker::Config for Runtime {
228 type RuntimeEvent = RuntimeEvent;
229 type Currency = Balances;
230 type OnRevenue = AccumulateForward;
231 type TimeslicePeriod = ConstU32<{ coretime::TIMESLICE_PERIOD }>;
232 type MaxLeasedCores = ConstU32<50>;
233 type MaxReservedCores = ConstU32<50>;
234 type Coretime = CoretimeAllocator;
235 type ConvertBalance = sp_runtime::traits::Identity;
236 type WeightInfo = weights::pallet_broker::WeightInfo<Runtime>;
237 type PalletId = BrokerPalletId;
238 type AdminOrigin = EnsureRoot<AccountId>;
239 type SovereignAccountOf = SovereignAccountOf;
240 type MaxAutoRenewals = ConstU32<50>;
241 type PriceAdapter = pallet_broker::MinimumPrice<Balance, MinimumEndPrice>;
242 type MinimumCreditPurchase = MinimumCreditPurchase;
243}