1#[cfg(feature = "runtime-benchmarks")]
18use crate::benchmarks::*;
19use crate::{
21 configs::{xcm_config, RuntimeBlockWeights},
22 constants::relay::fee::WeightToFee,
23 BlockNumber, Contracts, EventRecord, Hash, OriginCaller, PolkadotXcm, RuntimeEvent,
24 CONTRACTS_DEBUG_OUTPUT, CONTRACTS_EVENTS,
25};
26use bp_idn::types::SERIALIZED_SIG_SIZE;
27use frame_support::{
28 genesis_builder_helper::{build_state, get_preset},
29 weights::{Weight, WeightToFee as _},
30};
31use pallet_aura::Authorities;
32use pallet_idn_manager::{BalanceOf, SubscriptionOf};
33use sp_api::impl_runtime_apis;
34use sp_consensus_aura::sr25519::AuthorityId as AuraId;
35use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
36use sp_runtime::{
37 traits::Block as BlockT,
38 transaction_validity::{TransactionSource, TransactionValidity},
39 AccountId32, ApplyExtrinsicResult,
40};
41use sp_std::prelude::Vec;
42use sp_version::RuntimeVersion;
43use xcm::{
44 prelude::AssetId, Version as XcmVersion, VersionedAsset, VersionedAssetId, VersionedAssets,
45 VersionedLocation, VersionedXcm,
46};
47use xcm_runtime_apis::{
48 dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
49 fees::Error as XcmPaymentApiError,
50 trusted_query::XcmTrustedQueryResult,
51};
52
53use super::{
55 AccountId, Balance, Block, ConsensusHook, Executive, InherentDataExt, Nonce, ParachainSystem,
56 Runtime, RuntimeCall, RuntimeGenesisConfig, SessionKeys, System, TransactionPayment,
57 SLOT_DURATION, VERSION,
58};
59
60impl_runtime_apis! {
61
62 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
63 fn slot_duration() -> sp_consensus_aura::SlotDuration {
64 sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
65 }
66
67 fn authorities() -> Vec<AuraId> {
68 Authorities::<Runtime>::get().into_inner()
69 }
70 }
71
72 impl cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> for Runtime {
73 fn can_build_upon(
74 included_hash: <Block as BlockT>::Hash,
75 slot: cumulus_primitives_aura::Slot
76 ) -> bool {
77 ConsensusHook::can_build_upon(included_hash, slot)
78 }
79 }
80
81 impl sp_api::Core<Block> for Runtime {
82 fn version() -> RuntimeVersion {
83 VERSION
84 }
85
86 fn execute_block(block: Block) {
87 Executive::execute_block(block)
88 }
89
90 fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
91 Executive::initialize_block(header)
92 }
93 }
94
95 impl sp_api::Metadata<Block> for Runtime {
96 fn metadata() -> OpaqueMetadata {
97 OpaqueMetadata::new(Runtime::metadata().into())
98 }
99
100 fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
101 Runtime::metadata_at_version(version)
102 }
103
104 fn metadata_versions() -> Vec<u32> {
105 Runtime::metadata_versions()
106 }
107 }
108
109 impl sp_block_builder::BlockBuilder<Block> for Runtime {
110 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
111 Executive::apply_extrinsic(extrinsic)
112 }
113
114 fn finalize_block() -> <Block as BlockT>::Header {
115 Executive::finalize_block()
116 }
117
118 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
119 data.create_extrinsics()
120 }
121
122 fn check_inherents(
123 block: Block,
124 data: sp_inherents::InherentData,
125 ) -> sp_inherents::CheckInherentsResult {
126 data.check_extrinsics(&block)
127 }
128 }
129
130 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
131 fn validate_transaction(
132 source: TransactionSource,
133 tx: <Block as BlockT>::Extrinsic,
134 block_hash: <Block as BlockT>::Hash,
135 ) -> TransactionValidity {
136 Executive::validate_transaction(source, tx, block_hash)
137 }
138 }
139
140 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
141 fn offchain_worker(header: &<Block as BlockT>::Header) {
142 Executive::offchain_worker(header)
143 }
144 }
145
146 impl sp_session::SessionKeys<Block> for Runtime {
147 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
148 SessionKeys::generate(seed)
149 }
150
151 fn decode_session_keys(
152 encoded: Vec<u8>,
153 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
154 SessionKeys::decode_into_raw_public_keys(&encoded)
155 }
156 }
157
158 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
159 fn account_nonce(account: AccountId) -> Nonce {
160 System::account_nonce(account)
161 }
162 }
163
164 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
165 fn query_info(
166 uxt: <Block as BlockT>::Extrinsic,
167 len: u32,
168 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
169 TransactionPayment::query_info(uxt, len)
170 }
171 fn query_fee_details(
172 uxt: <Block as BlockT>::Extrinsic,
173 len: u32,
174 ) -> pallet_transaction_payment::FeeDetails<Balance> {
175 TransactionPayment::query_fee_details(uxt, len)
176 }
177 fn query_weight_to_fee(weight: Weight) -> Balance {
178 TransactionPayment::weight_to_fee(weight)
179 }
180 fn query_length_to_fee(length: u32) -> Balance {
181 TransactionPayment::length_to_fee(length)
182 }
183 }
184
185 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
186 for Runtime
187 {
188 fn query_call_info(
189 call: RuntimeCall,
190 len: u32,
191 ) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
192 TransactionPayment::query_call_info(call, len)
193 }
194 fn query_call_fee_details(
195 call: RuntimeCall,
196 len: u32,
197 ) -> pallet_transaction_payment::FeeDetails<Balance> {
198 TransactionPayment::query_call_fee_details(call, len)
199 }
200 fn query_weight_to_fee(weight: Weight) -> Balance {
201 TransactionPayment::weight_to_fee(weight)
202 }
203 fn query_length_to_fee(length: u32) -> Balance {
204 TransactionPayment::length_to_fee(length)
205 }
206 }
207
208 impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
209 fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
210 ParachainSystem::collect_collation_info(header)
211 }
212 }
213
214 #[cfg(feature = "try-runtime")]
215 impl frame_try_runtime::TryRuntime<Block> for Runtime {
216 fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
217 use super::configs::RuntimeBlockWeights;
218
219 let weight = Executive::try_runtime_upgrade(checks).unwrap();
220 (weight, RuntimeBlockWeights::get().max_block)
221 }
222
223 fn execute_block(
224 block: Block,
225 state_root_check: bool,
226 signature_check: bool,
227 select: frame_try_runtime::TryStateSelect,
228 ) -> Weight {
229 Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
232 }
233 }
234
235 #[cfg(feature = "runtime-benchmarks")]
236 impl frame_benchmarking::Benchmark<Block> for Runtime {
237 fn benchmark_metadata(extra: bool) -> (
238 Vec<frame_benchmarking::BenchmarkList>,
239 Vec<frame_support::traits::StorageInfo>,
240 ) {
241 let mut list = Vec::<BenchmarkList>::new();
242 list_benchmarks!(list, extra);
243
244 let storage_info = AllPalletsWithSystem::storage_info();
245 (list, storage_info)
246 }
247
248 fn dispatch_benchmark(
249 config: frame_benchmarking::BenchmarkConfig
250 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
251 let whitelist = AllPalletsWithSystem::whitelisted_storage_keys();
252 let mut batches = Vec::<BenchmarkBatch>::new();
253 let params = (&config, &whitelist);
254 add_benchmarks!(params, batches);
255
256 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
257 Ok(batches)
258 }
259 }
260
261 impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
262 fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
263 build_state::<RuntimeGenesisConfig>(config)
264 }
265
266 fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
267 get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
268 }
269
270 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
271 crate::genesis_config_presets::preset_names()
272 }
273 }
274
275 impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
276 fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
277 let native_token = xcm_config::RelayLocation::get();
278 let acceptable_assets = Vec::from([AssetId(native_token)]);
279 PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
280 }
281
282 fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
283 let native_asset = xcm_config::RelayLocation::get();
284 let fee_in_native = WeightToFee::weight_to_fee(&weight);
285 let latest_asset_id: Result<AssetId, ()> = asset.clone().try_into();
286 match latest_asset_id {
287 Ok(asset_id) if asset_id.0 == native_asset => {
288 Ok(fee_in_native)
290 },
291 Ok(asset_id) => {
292 log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!");
293 Err(XcmPaymentApiError::AssetNotFound)
294 },
295 Err(_) => {
296 log::trace!(target: "xcm::xcm_runtime_apis", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!");
297 Err(XcmPaymentApiError::VersionedConversionFailed)
298 }
299 }
300 }
301
302 fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
303 PolkadotXcm::query_xcm_weight(message)
304 }
305
306 fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
307 PolkadotXcm::query_delivery_fees(destination, message)
308 }
309 }
310
311 impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
312 fn dry_run_call(origin: OriginCaller, call: RuntimeCall, result_xcms_version: XcmVersion) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
313 PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call, result_xcms_version)
314 }
315
316 fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
317 PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
318 }
319 }
320
321 impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
322 fn convert_location(location: VersionedLocation) -> Result<
323 AccountId,
324 xcm_runtime_apis::conversions::Error
325 > {
326 xcm_runtime_apis::conversions::LocationToAccountHelper::<
327 AccountId,
328 xcm_config::LocationToAccountId,
329 >::convert_location(location)
330 }
331 }
332
333 impl xcm_runtime_apis::trusted_query::TrustedQueryApi<Block> for Runtime {
334 fn is_trusted_reserve(asset: VersionedAsset, location: VersionedLocation) -> XcmTrustedQueryResult {
335 PolkadotXcm::is_trusted_reserve(asset, location)
336 }
337
338 fn is_trusted_teleporter(asset: VersionedAsset, location: VersionedLocation) -> XcmTrustedQueryResult {
339 PolkadotXcm::is_trusted_teleporter(asset, location)
340 }
341 }
342
343 impl xcm_runtime_apis::authorized_aliases::AuthorizedAliasersApi<Block> for Runtime {
344 fn authorized_aliasers(target: VersionedLocation) -> Result<
345 Vec<xcm_runtime_apis::authorized_aliases::OriginAliaser>,
346 xcm_runtime_apis::authorized_aliases::Error
347 > {
348 PolkadotXcm::authorized_aliasers(target)
349 }
350 fn is_authorized_alias(origin: VersionedLocation, target: VersionedLocation) -> Result<
351 bool,
352 xcm_runtime_apis::authorized_aliases::Error
353 > {
354 PolkadotXcm::is_authorized_alias(origin, target)
355 }
356 }
357
358 impl pallet_randomness_beacon::RandomnessBeaconApi<Block> for Runtime {
359 fn build_extrinsic(
360 asig: Vec<u8>,
361 start: u64,
362 end: u64,
363 signature: Vec<u8>,
364 ) -> crate::UncheckedExtrinsic {
365 let formatted: [u8; sp_consensus_randomness_beacon::types::SERIALIZED_SIG_SIZE] =
367 asig.try_into().unwrap_or([0u8; SERIALIZED_SIG_SIZE]);
368
369 let mut sig_array = [0u8; 64];
370 sig_array.copy_from_slice(&signature);
371 let sig = sp_runtime::MultiSignature::Sr25519(
372 sp_core::sr25519::Signature::from_raw(sig_array)
373 );
374
375 let call = crate::RuntimeCall::RandBeacon(
376 pallet_randomness_beacon::Call::try_submit_asig {
377 asig: formatted,
378 start,
379 end,
380 signature: sig,
381 }
382 );
383 crate::UncheckedExtrinsic::new_bare(call)
384 }
385
386 fn next_round() -> sp_consensus_randomness_beacon::types::RoundNumber {
387 pallet_randomness_beacon::Pallet::<Runtime>::next_round()
388 }
389
390 fn max_rounds() -> u8 {
391 pallet_randomness_beacon::Pallet::<Runtime>::max_rounds()
392 }
393 }
394
395 impl pallet_idn_manager::IdnManagerApi<
396 Block,
397 BalanceOf<Runtime>,
398 u64,
399 AccountId32,
400 SubscriptionOf<Runtime>,
401 <Runtime as pallet_idn_manager::Config>::SubscriptionId,
402 > for Runtime {
403 fn calculate_subscription_fees(
404 credits: <Runtime as pallet_idn_manager::Config>::Credits
405 ) -> BalanceOf<Runtime> {
406 pallet_idn_manager::Pallet::<Runtime>::calculate_subscription_fees(&credits)
407 }
408 fn get_subscription(
409 sub_id: <Runtime as pallet_idn_manager::Config>::SubscriptionId
410 ) -> Option<SubscriptionOf<Runtime>> {
411 pallet_idn_manager::Pallet::<Runtime>::get_subscription(&sub_id)
412 }
413 fn get_subscriptions_for_subscriber(
414 subscriber: AccountId32
415 ) -> Vec<SubscriptionOf<Runtime>> {
416 pallet_idn_manager::Pallet::<Runtime>::get_subscriptions_for_subscriber(&subscriber)
417 }
418 }
419
420 impl pallet_contracts::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash, EventRecord>
421 for Runtime
422 {
423 fn call(
424 origin: AccountId,
425 dest: AccountId,
426 value: Balance,
427 gas_limit: Option<Weight>,
428 storage_deposit_limit: Option<Balance>,
429 input_data: Vec<u8>,
430 ) -> pallet_contracts::ContractExecResult<Balance, EventRecord> {
431 let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
432 Contracts::bare_call(
433 origin,
434 dest,
435 value,
436 gas_limit,
437 storage_deposit_limit,
438 input_data,
439 CONTRACTS_DEBUG_OUTPUT,
440 CONTRACTS_EVENTS,
441 pallet_contracts::Determinism::Enforced,
442 )
443 }
444
445 fn instantiate(
446 origin: AccountId,
447 value: Balance,
448 gas_limit: Option<Weight>,
449 storage_deposit_limit: Option<Balance>,
450 code: pallet_contracts::Code<Hash>,
451 data: Vec<u8>,
452 salt: Vec<u8>,
453 ) -> pallet_contracts::ContractInstantiateResult<AccountId, Balance, EventRecord>
454 {
455 let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
456 Contracts::bare_instantiate(
457 origin,
458 value,
459 gas_limit,
460 storage_deposit_limit,
461 code,
462 data,
463 salt,
464 CONTRACTS_DEBUG_OUTPUT,
465 CONTRACTS_EVENTS,
466 )
467 }
468
469 fn upload_code(
470 origin: AccountId,
471 code: Vec<u8>,
472 storage_deposit_limit: Option<Balance>,
473 determinism: pallet_contracts::Determinism,
474 ) -> pallet_contracts::CodeUploadResult<Hash, Balance>
475 {
476 Contracts::bare_upload_code(origin, code, storage_deposit_limit, determinism)
477 }
478
479 fn get_storage(
480 address: AccountId,
481 key: Vec<u8>,
482 ) -> pallet_contracts::GetStorageResult {
483 Contracts::get_storage(address, key)
484 }
485 }
486}