1use alloc::{borrow::Cow, boxed::Box, vec, vec::Vec};
88use core::{fmt::Debug, marker::PhantomData};
89use pallet_prelude::{BlockNumberFor, HeaderFor};
90#[cfg(feature = "std")]
91use serde::Serialize;
92use subsoil::io::hashing::blake2_256;
93#[cfg(feature = "runtime-benchmarks")]
94use subsoil::runtime::traits::TrailingZeroInput;
95use subsoil::runtime::{
96 generic,
97 traits::{
98 self, AsTransactionAuthorizedOrigin, AtLeast32Bit, BadOrigin, BlockNumberProvider, Bounded,
99 CheckEqual, Dispatchable, Hash, Header, Lookup, LookupError, MaybeDisplay,
100 MaybeSerializeDeserialize, Member, One, Saturating, SimpleBitOps, StaticLookup, Zero,
101 },
102 transaction_validity::{
103 InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidity,
104 ValidTransaction,
105 },
106 DispatchError,
107};
108use subsoil::version::RuntimeVersion;
109
110use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, FullCodec, MaxEncodedLen};
111use scale_info::TypeInfo;
112use subsoil::core::storage::well_known_keys;
113use subsoil::runtime::{
114 traits::{DispatchInfoOf, PostDispatchInfoOf},
115 transaction_validity::TransactionValidityError,
116};
117use subsoil::weights::{RuntimeDbWeight, Weight, WeightMeter};
118#[cfg(feature = "std")]
119use topsoil_core::traits::BuildGenesisConfig;
120use topsoil_core::{
121 dispatch::{
122 extract_actual_pays_fee, extract_actual_weight, DispatchClass, DispatchInfo,
123 DispatchResult, DispatchResultWithPostInfo, GetDispatchInfo, PerDispatchClass,
124 PostDispatchInfo,
125 },
126 ensure, impl_ensure_origin_with_arg_ignoring_arg,
127 migrations::MultiStepMigrator,
128 pallet_prelude::Pays,
129 storage::{self, StorageStreamIter},
130 traits::{
131 ConstU32, Contains, EnsureOrigin, EnsureOriginWithArg, Get, HandleLifetime,
132 OnKilledAccount, OnNewAccount, OnRuntimeUpgrade, OriginTrait, PalletInfo, SortedMembers,
133 StoredMap, TypedGet,
134 },
135 Parameter,
136};
137
138#[cfg(any(feature = "std", test))]
139use subsoil::io::TestExternalities;
140
141pub mod limits;
142#[cfg(test)]
143pub(crate) mod mock;
144
145pub mod offchain;
146
147mod extensions;
148#[cfg(feature = "std")]
149pub mod mocking;
150#[cfg(test)]
151mod tests;
152pub mod weights;
153
154pub mod migrations;
155
156pub use extensions::{
157 authorize_call::AuthorizeCall,
158 check_genesis::CheckGenesis,
159 check_mortality::CheckMortality,
160 check_non_zero_sender::CheckNonZeroSender,
161 check_nonce::{CheckNonce, ValidNonceInfo},
162 check_spec_version::CheckSpecVersion,
163 check_tx_version::CheckTxVersion,
164 check_weight::CheckWeight,
165 weight_reclaim::WeightReclaim,
166 weights::SubstrateWeight as SubstrateExtensionsWeight,
167 WeightInfo as ExtensionsWeightInfo,
168};
169pub use extensions::check_mortality::CheckMortality as CheckEra;
171use subsoil::core::storage::StateVersion;
172pub use topsoil_core::dispatch::RawOrigin;
173use topsoil_core::traits::{Authorize, PostInherents, PostTransactions, PreInherents};
174pub use weights::WeightInfo;
175
176const LOG_TARGET: &str = "runtime::system";
177
178pub fn extrinsics_root<H: Hash, E: codec::Encode>(
183 extrinsics: &[E],
184 state_version: StateVersion,
185) -> H::Output {
186 extrinsics_data_root::<H>(extrinsics.iter().map(codec::Encode::encode).collect(), state_version)
187}
188
189pub fn extrinsics_data_root<H: Hash>(xts: Vec<Vec<u8>>, state_version: StateVersion) -> H::Output {
194 H::ordered_trie_root(xts, state_version)
195}
196
197pub type ConsumedWeight = PerDispatchClass<Weight>;
199
200pub use pallet::*;
201
202pub trait SetCode<T: Config> {
204 fn set_code(code: Vec<u8>) -> DispatchResult;
206}
207
208impl<T: Config> SetCode<T> for () {
209 fn set_code(code: Vec<u8>) -> DispatchResult {
210 <Pallet<T>>::update_code_in_storage(&code);
211 Ok(())
212 }
213}
214
215pub trait ConsumerLimits {
217 fn max_consumers() -> RefCount;
219 fn max_overflow() -> RefCount;
225}
226
227impl<const Z: u32> ConsumerLimits for ConstU32<Z> {
228 fn max_consumers() -> RefCount {
229 Z
230 }
231 fn max_overflow() -> RefCount {
232 Z
233 }
234}
235
236impl<MaxNormal: Get<u32>, MaxOverflow: Get<u32>> ConsumerLimits for (MaxNormal, MaxOverflow) {
237 fn max_consumers() -> RefCount {
238 MaxNormal::get()
239 }
240 fn max_overflow() -> RefCount {
241 MaxOverflow::get()
242 }
243}
244
245#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)]
248#[scale_info(skip_type_params(T))]
249pub struct CodeUpgradeAuthorization<T>
250where
251 T: Config,
252{
253 code_hash: T::Hash,
255 check_version: bool,
257}
258
259#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
260impl<T> CodeUpgradeAuthorization<T>
261where
262 T: Config,
263{
264 pub fn code_hash(&self) -> &T::Hash {
265 &self.code_hash
266 }
267}
268
269#[derive(
273 Clone, Copy, Eq, PartialEq, Default, Debug, Encode, Decode, DecodeWithMemTracking, TypeInfo,
274)]
275pub struct DispatchEventInfo {
276 pub weight: Weight,
278 pub class: DispatchClass,
280 pub pays_fee: Pays,
282}
283
284#[topsoil_core::pallet]
285pub mod pallet {
286 use crate::system::{self as topsoil_system, pallet_prelude::*, *};
287 use codec::HasCompact;
288 use topsoil_core::pallet_prelude::*;
289
290 pub mod config_preludes {
292 use super::{inject_runtime_type, DefaultConfig};
293 use topsoil_core::{derive_impl, traits::Get};
294
295 pub struct TestBlockHashCount<C: Get<u32>>(core::marker::PhantomData<C>);
301 impl<I: From<u32>, C: Get<u32>> Get<I> for TestBlockHashCount<C> {
302 fn get() -> I {
303 C::get().into()
304 }
305 }
306
307 pub struct TestDefaultConfig;
314
315 #[topsoil_core::register_default_impl(TestDefaultConfig)]
316 impl DefaultConfig for TestDefaultConfig {
317 type Nonce = u32;
318 type Hash = subsoil::core::hash::H256;
319 type Hashing = subsoil::runtime::traits::BlakeTwo256;
320 type AccountId = u64;
321 type Lookup = subsoil::runtime::traits::IdentityLookup<Self::AccountId>;
322 type MaxConsumers = topsoil_core::traits::ConstU32<16>;
323 type AccountData = ();
324 type OnNewAccount = ();
325 type OnKilledAccount = ();
326 type SystemWeightInfo = ();
327 type ExtensionsWeightInfo = ();
328 type SS58Prefix = ();
329 type Version = ();
330 type BlockWeights = ();
331 type BlockLength = ();
332 type DbWeight = ();
333 #[inject_runtime_type]
334 type RuntimeEvent = ();
335 #[inject_runtime_type]
336 type RuntimeOrigin = ();
337 #[inject_runtime_type]
338 type RuntimeCall = ();
339 #[inject_runtime_type]
340 type PalletInfo = ();
341 #[inject_runtime_type]
342 type RuntimeTask = ();
343 type BaseCallFilter = topsoil_core::traits::Everything;
344 type BlockHashCount = TestBlockHashCount<topsoil_core::traits::ConstU32<10>>;
345 type OnSetCode = ();
346 type SingleBlockMigrations = ();
347 type MultiBlockMigrator = ();
348 type PreInherents = ();
349 type PostInherents = ();
350 type PostTransactions = ();
351 }
352
353 pub struct SolochainDefaultConfig;
367
368 #[topsoil_core::register_default_impl(SolochainDefaultConfig)]
369 impl DefaultConfig for SolochainDefaultConfig {
370 type Nonce = u32;
372
373 type Hash = subsoil::core::hash::H256;
375
376 type Hashing = subsoil::runtime::traits::BlakeTwo256;
378
379 type AccountId = subsoil::runtime::AccountId32;
381
382 type Lookup = subsoil::runtime::traits::AccountIdLookup<Self::AccountId, ()>;
384
385 type MaxConsumers = topsoil_core::traits::ConstU32<128>;
387
388 type AccountData = ();
390
391 type OnNewAccount = ();
393
394 type OnKilledAccount = ();
396
397 type SystemWeightInfo = ();
399
400 type ExtensionsWeightInfo = ();
402
403 type SS58Prefix = ();
405
406 type Version = ();
408
409 type BlockWeights = ();
411
412 type BlockLength = ();
414
415 type DbWeight = ();
417
418 #[inject_runtime_type]
420 type RuntimeEvent = ();
421
422 #[inject_runtime_type]
424 type RuntimeOrigin = ();
425
426 #[inject_runtime_type]
429 type RuntimeCall = ();
430
431 #[inject_runtime_type]
433 type RuntimeTask = ();
434
435 #[inject_runtime_type]
437 type PalletInfo = ();
438
439 type BaseCallFilter = topsoil_core::traits::Everything;
441
442 type BlockHashCount = TestBlockHashCount<topsoil_core::traits::ConstU32<256>>;
445
446 type OnSetCode = ();
448 type SingleBlockMigrations = ();
449 type MultiBlockMigrator = ();
450 type PreInherents = ();
451 type PostInherents = ();
452 type PostTransactions = ();
453 }
454
455 pub struct RelayChainDefaultConfig;
457
458 #[derive_impl(SolochainDefaultConfig as DefaultConfig, no_aggregated_types)]
460 #[topsoil_core::register_default_impl(RelayChainDefaultConfig)]
461 impl DefaultConfig for RelayChainDefaultConfig {}
462
463 pub struct ParaChainDefaultConfig;
465
466 #[derive_impl(SolochainDefaultConfig as DefaultConfig, no_aggregated_types)]
468 #[topsoil_core::register_default_impl(ParaChainDefaultConfig)]
469 impl DefaultConfig for ParaChainDefaultConfig {}
470 }
471
472 #[pallet::config(with_default, frame_system_config)]
474 #[pallet::disable_frame_system_supertrait_check]
475 pub trait Config: 'static + Eq + Clone {
476 #[pallet::no_default_bounds]
478 type RuntimeEvent: Parameter
479 + Member
480 + From<Event<Self>>
481 + Debug
482 + IsType<<Self as topsoil_system::Config>::RuntimeEvent>;
483
484 #[pallet::no_default_bounds]
495 type BaseCallFilter: Contains<Self::RuntimeCall>;
496
497 #[pallet::constant]
499 type BlockWeights: Get<limits::BlockWeights>;
500
501 #[pallet::constant]
503 type BlockLength: Get<limits::BlockLength>;
504
505 #[pallet::no_default_bounds]
507 type RuntimeOrigin: Into<Result<RawOrigin<Self::AccountId>, Self::RuntimeOrigin>>
508 + From<RawOrigin<Self::AccountId>>
509 + Clone
510 + OriginTrait<Call = Self::RuntimeCall, AccountId = Self::AccountId>
511 + AsTransactionAuthorizedOrigin;
512
513 #[docify::export(system_runtime_call)]
514 #[pallet::no_default_bounds]
516 type RuntimeCall: Parameter
517 + Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
518 + Debug
519 + GetDispatchInfo
520 + From<Call<Self>>
521 + Authorize;
522
523 #[pallet::no_default_bounds]
525 type RuntimeTask: Task;
526
527 type Nonce: Parameter
529 + HasCompact<Type: DecodeWithMemTracking>
530 + Member
531 + MaybeSerializeDeserialize
532 + Debug
533 + Default
534 + MaybeDisplay
535 + AtLeast32Bit
536 + Copy
537 + MaxEncodedLen;
538
539 type Hash: Parameter
541 + Member
542 + MaybeSerializeDeserialize
543 + Debug
544 + MaybeDisplay
545 + SimpleBitOps
546 + Ord
547 + Default
548 + Copy
549 + CheckEqual
550 + core::hash::Hash
551 + AsRef<[u8]>
552 + AsMut<[u8]>
553 + MaxEncodedLen;
554
555 type Hashing: Hash<Output = Self::Hash> + TypeInfo;
557
558 type AccountId: Parameter
560 + Member
561 + MaybeSerializeDeserialize
562 + Debug
563 + MaybeDisplay
564 + Ord
565 + MaxEncodedLen;
566
567 type Lookup: StaticLookup<Target = Self::AccountId>;
574
575 #[pallet::no_default]
578 type Block: Parameter + Member + traits::Block<Hash = Self::Hash>;
579
580 #[pallet::constant]
582 #[pallet::no_default_bounds]
583 type BlockHashCount: Get<BlockNumberFor<Self>>;
584
585 #[pallet::constant]
587 type DbWeight: Get<RuntimeDbWeight>;
588
589 #[pallet::constant]
591 type Version: Get<RuntimeVersion>;
592
593 #[pallet::no_default_bounds]
600 type PalletInfo: PalletInfo;
601
602 type AccountData: Member + FullCodec + Clone + Default + TypeInfo + MaxEncodedLen;
605
606 type OnNewAccount: OnNewAccount<Self::AccountId>;
608
609 type OnKilledAccount: OnKilledAccount<Self::AccountId>;
613
614 type SystemWeightInfo: WeightInfo;
616
617 type ExtensionsWeightInfo: extensions::WeightInfo;
619
620 #[pallet::constant]
626 type SS58Prefix: Get<u16>;
627
628 #[pallet::no_default_bounds]
636 type OnSetCode: SetCode<Self>;
637
638 type MaxConsumers: ConsumerLimits;
640
641 type SingleBlockMigrations: OnRuntimeUpgrade;
648
649 type MultiBlockMigrator: MultiStepMigrator;
654
655 type PreInherents: PreInherents;
659
660 type PostInherents: PostInherents;
664
665 type PostTransactions: PostTransactions;
669 }
670
671 #[pallet::pallet]
672 pub struct Pallet<T>(_);
673
674 #[pallet::hooks]
675 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
676 #[cfg(feature = "std")]
677 fn integrity_test() {
678 T::BlockWeights::get().validate().expect("The weights are invalid.");
679 }
680 }
681
682 #[pallet::call(weight = <T as Config>::SystemWeightInfo)]
683 impl<T: Config> Pallet<T> {
684 #[pallet::call_index(0)]
688 #[pallet::weight(T::SystemWeightInfo::remark(remark.len() as u32))]
689 pub fn remark(_origin: OriginFor<T>, remark: Vec<u8>) -> DispatchResultWithPostInfo {
690 let _ = remark; Ok(().into())
692 }
693
694 #[pallet::call_index(1)]
696 #[pallet::weight((T::SystemWeightInfo::set_heap_pages(), DispatchClass::Operational))]
697 pub fn set_heap_pages(origin: OriginFor<T>, pages: u64) -> DispatchResultWithPostInfo {
698 ensure_root(origin)?;
699 storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode());
700 Self::deposit_log(generic::DigestItem::RuntimeEnvironmentUpdated);
701 Ok(().into())
702 }
703
704 #[pallet::call_index(2)]
706 #[pallet::weight((T::SystemWeightInfo::set_code(), DispatchClass::Operational))]
707 pub fn set_code(origin: OriginFor<T>, code: Vec<u8>) -> DispatchResultWithPostInfo {
708 ensure_root(origin)?;
709 Self::can_set_code(&code, true).into_result()?;
710 T::OnSetCode::set_code(code)?;
711 Ok(Some(T::BlockWeights::get().max_block).into())
713 }
714
715 #[pallet::call_index(3)]
720 #[pallet::weight((T::SystemWeightInfo::set_code(), DispatchClass::Operational))]
721 pub fn set_code_without_checks(
722 origin: OriginFor<T>,
723 code: Vec<u8>,
724 ) -> DispatchResultWithPostInfo {
725 ensure_root(origin)?;
726 Self::can_set_code(&code, false).into_result()?;
727 T::OnSetCode::set_code(code)?;
728 Ok(Some(T::BlockWeights::get().max_block).into())
729 }
730
731 #[pallet::call_index(4)]
733 #[pallet::weight((
734 T::SystemWeightInfo::set_storage(items.len() as u32),
735 DispatchClass::Operational,
736 ))]
737 pub fn set_storage(
738 origin: OriginFor<T>,
739 items: Vec<KeyValue>,
740 ) -> DispatchResultWithPostInfo {
741 ensure_root(origin)?;
742 for i in &items {
743 storage::unhashed::put_raw(&i.0, &i.1);
744 }
745 Ok(().into())
746 }
747
748 #[pallet::call_index(5)]
750 #[pallet::weight((
751 T::SystemWeightInfo::kill_storage(keys.len() as u32),
752 DispatchClass::Operational,
753 ))]
754 pub fn kill_storage(origin: OriginFor<T>, keys: Vec<Key>) -> DispatchResultWithPostInfo {
755 ensure_root(origin)?;
756 for key in &keys {
757 storage::unhashed::kill(key);
758 }
759 Ok(().into())
760 }
761
762 #[pallet::call_index(6)]
767 #[pallet::weight((
768 T::SystemWeightInfo::kill_prefix(subkeys.saturating_add(1)),
769 DispatchClass::Operational,
770 ))]
771 pub fn kill_prefix(
772 origin: OriginFor<T>,
773 prefix: Key,
774 subkeys: u32,
775 ) -> DispatchResultWithPostInfo {
776 ensure_root(origin)?;
777 let _ = storage::unhashed::clear_prefix(&prefix, Some(subkeys), None);
778 Ok(().into())
779 }
780
781 #[pallet::call_index(7)]
783 #[pallet::weight(T::SystemWeightInfo::remark_with_event(remark.len() as u32))]
784 pub fn remark_with_event(
785 origin: OriginFor<T>,
786 remark: Vec<u8>,
787 ) -> DispatchResultWithPostInfo {
788 let who = ensure_signed(origin)?;
789 let hash = T::Hashing::hash(&remark[..]);
790 Self::deposit_event(Event::Remarked { sender: who, hash });
791 Ok(().into())
792 }
793
794 #[cfg(feature = "experimental")]
795 #[pallet::call_index(8)]
796 #[pallet::weight(task.weight())]
797 pub fn do_task(_origin: OriginFor<T>, task: T::RuntimeTask) -> DispatchResultWithPostInfo {
798 if !task.is_valid() {
799 return Err(Error::<T>::InvalidTask.into());
800 }
801
802 Self::deposit_event(Event::TaskStarted { task: task.clone() });
803 if let Err(err) = task.run() {
804 Self::deposit_event(Event::TaskFailed { task, err });
805 return Err(Error::<T>::FailedTask.into());
806 }
807
808 Self::deposit_event(Event::TaskCompleted { task });
810
811 Ok(().into())
813 }
814
815 #[pallet::call_index(9)]
820 #[pallet::weight((T::SystemWeightInfo::authorize_upgrade(), DispatchClass::Operational))]
821 pub fn authorize_upgrade(origin: OriginFor<T>, code_hash: T::Hash) -> DispatchResult {
822 ensure_root(origin)?;
823 Self::do_authorize_upgrade(code_hash, true);
824 Ok(())
825 }
826
827 #[pallet::call_index(10)]
836 #[pallet::weight((T::SystemWeightInfo::authorize_upgrade(), DispatchClass::Operational))]
837 pub fn authorize_upgrade_without_checks(
838 origin: OriginFor<T>,
839 code_hash: T::Hash,
840 ) -> DispatchResult {
841 ensure_root(origin)?;
842 Self::do_authorize_upgrade(code_hash, false);
843 Ok(())
844 }
845
846 #[pallet::call_index(11)]
856 #[pallet::weight((T::SystemWeightInfo::apply_authorized_upgrade(), DispatchClass::Operational))]
857 pub fn apply_authorized_upgrade(
858 _: OriginFor<T>,
859 code: Vec<u8>,
860 ) -> DispatchResultWithPostInfo {
861 let res = Self::validate_code_is_authorized(&code)?;
862 AuthorizedUpgrade::<T>::kill();
863
864 match Self::can_set_code(&code, res.check_version) {
865 CanSetCodeResult::Ok => {},
866 CanSetCodeResult::MultiBlockMigrationsOngoing => {
867 return Err(Error::<T>::MultiBlockMigrationsOngoing.into())
868 },
869 CanSetCodeResult::InvalidVersion(error) => {
870 Self::deposit_event(Event::RejectedInvalidAuthorizedUpgrade {
872 code_hash: res.code_hash,
873 error: error.into(),
874 });
875
876 return Ok(Pays::No.into());
878 },
879 };
880 T::OnSetCode::set_code(code)?;
881
882 Ok(PostDispatchInfo {
883 actual_weight: Some(T::BlockWeights::get().max_block),
885 pays_fee: Pays::No,
887 })
888 }
889 }
890
891 #[pallet::event]
893 pub enum Event<T: Config> {
894 ExtrinsicSuccess { dispatch_info: DispatchEventInfo },
896 ExtrinsicFailed { dispatch_error: DispatchError, dispatch_info: DispatchEventInfo },
898 CodeUpdated,
900 NewAccount { account: T::AccountId },
902 KilledAccount { account: T::AccountId },
904 Remarked { sender: T::AccountId, hash: T::Hash },
906 #[cfg(feature = "experimental")]
907 TaskStarted { task: T::RuntimeTask },
909 #[cfg(feature = "experimental")]
910 TaskCompleted { task: T::RuntimeTask },
912 #[cfg(feature = "experimental")]
913 TaskFailed { task: T::RuntimeTask, err: DispatchError },
915 UpgradeAuthorized { code_hash: T::Hash, check_version: bool },
917 RejectedInvalidAuthorizedUpgrade { code_hash: T::Hash, error: DispatchError },
919 }
920
921 #[pallet::error]
923 pub enum Error<T> {
924 InvalidSpecName,
927 SpecVersionNeedsToIncrease,
930 FailedToExtractRuntimeVersion,
934 NonDefaultComposite,
936 NonZeroRefCount,
938 CallFiltered,
940 MultiBlockMigrationsOngoing,
942 #[cfg(feature = "experimental")]
943 InvalidTask,
945 #[cfg(feature = "experimental")]
946 FailedTask,
948 NothingAuthorized,
950 Unauthorized,
952 }
953
954 #[pallet::origin]
956 pub type Origin<T> = RawOrigin<<T as Config>::AccountId>;
957
958 #[pallet::storage]
960 #[pallet::getter(fn account)]
961 pub type Account<T: Config> = StorageMap<
962 _,
963 Blake2_128Concat,
964 T::AccountId,
965 AccountInfo<T::Nonce, T::AccountData>,
966 ValueQuery,
967 >;
968
969 #[pallet::storage]
971 #[pallet::whitelist_storage]
972 pub(super) type ExtrinsicCount<T: Config> = StorageValue<_, u32>;
973
974 #[pallet::storage]
976 #[pallet::whitelist_storage]
977 pub type InherentsApplied<T: Config> = StorageValue<_, bool, ValueQuery>;
978
979 #[pallet::storage]
981 #[pallet::whitelist_storage]
982 #[pallet::getter(fn block_weight)]
983 pub type BlockWeight<T: Config> = StorageValue<_, ConsumedWeight, ValueQuery>;
984
985 #[pallet::storage]
989 #[pallet::whitelist_storage]
990 pub type BlockSize<T: Config> = StorageValue<_, u32>;
991
992 #[pallet::storage]
994 #[pallet::getter(fn block_hash)]
995 pub type BlockHash<T: Config> =
996 StorageMap<_, Twox64Concat, BlockNumberFor<T>, T::Hash, ValueQuery>;
997
998 #[pallet::storage]
1000 #[pallet::getter(fn extrinsic_data)]
1001 #[pallet::unbounded]
1002 pub(super) type ExtrinsicData<T: Config> =
1003 StorageMap<_, Twox64Concat, u32, Vec<u8>, ValueQuery>;
1004
1005 #[pallet::storage]
1007 #[pallet::whitelist_storage]
1008 #[pallet::getter(fn block_number)]
1009 pub(super) type Number<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
1010
1011 #[pallet::storage]
1013 #[pallet::getter(fn parent_hash)]
1014 pub(super) type ParentHash<T: Config> = StorageValue<_, T::Hash, ValueQuery>;
1015
1016 #[pallet::storage]
1018 #[pallet::whitelist_storage]
1019 #[pallet::unbounded]
1020 #[pallet::getter(fn digest)]
1021 pub(super) type Digest<T: Config> = StorageValue<_, generic::Digest, ValueQuery>;
1022
1023 #[pallet::storage]
1031 #[pallet::whitelist_storage]
1032 #[pallet::disable_try_decode_storage]
1033 #[pallet::unbounded]
1034 pub(super) type Events<T: Config> =
1035 StorageValue<_, Vec<Box<EventRecord<T::RuntimeEvent, T::Hash>>>, ValueQuery>;
1036
1037 #[pallet::storage]
1039 #[pallet::whitelist_storage]
1040 #[pallet::getter(fn event_count)]
1041 pub(super) type EventCount<T: Config> = StorageValue<_, EventIndex, ValueQuery>;
1042
1043 #[pallet::storage]
1054 #[pallet::unbounded]
1055 #[pallet::getter(fn event_topics)]
1056 pub(super) type EventTopics<T: Config> =
1057 StorageMap<_, Blake2_128Concat, T::Hash, Vec<(BlockNumberFor<T>, EventIndex)>, ValueQuery>;
1058
1059 #[pallet::storage]
1061 #[pallet::unbounded]
1062 pub type LastRuntimeUpgrade<T: Config> = StorageValue<_, LastRuntimeUpgradeInfo>;
1063
1064 #[pallet::storage]
1066 pub(super) type UpgradedToU32RefCount<T: Config> = StorageValue<_, bool, ValueQuery>;
1067
1068 #[pallet::storage]
1071 pub(super) type UpgradedToTripleRefCount<T: Config> = StorageValue<_, bool, ValueQuery>;
1072
1073 #[pallet::storage]
1075 #[pallet::whitelist_storage]
1076 pub(super) type ExecutionPhase<T: Config> = StorageValue<_, Phase>;
1077
1078 #[pallet::storage]
1080 #[pallet::getter(fn authorized_upgrade)]
1081 pub(super) type AuthorizedUpgrade<T: Config> =
1082 StorageValue<_, CodeUpgradeAuthorization<T>, OptionQuery>;
1083
1084 #[pallet::storage]
1092 #[pallet::whitelist_storage]
1093 pub type ExtrinsicWeightReclaimed<T: Config> = StorageValue<_, Weight, ValueQuery>;
1094
1095 #[derive(topsoil_core::DefaultNoBound)]
1096 #[pallet::genesis_config]
1097 pub struct GenesisConfig<T: Config> {
1098 #[serde(skip)]
1099 pub _config: core::marker::PhantomData<T>,
1100 }
1101
1102 #[pallet::genesis_build]
1103 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
1104 fn build(&self) {
1105 <BlockHash<T>>::insert::<_, T::Hash>(BlockNumberFor::<T>::zero(), hash69());
1106 <ParentHash<T>>::put::<T::Hash>(hash69());
1107 <LastRuntimeUpgrade<T>>::put(LastRuntimeUpgradeInfo::from(T::Version::get()));
1108 <UpgradedToU32RefCount<T>>::put(true);
1109 <UpgradedToTripleRefCount<T>>::put(true);
1110
1111 subsoil::io::storage::set(well_known_keys::EXTRINSIC_INDEX, &0u32.encode());
1112 }
1113 }
1114
1115 #[pallet::validate_unsigned]
1116 impl<T: Config> subsoil::runtime::traits::ValidateUnsigned for Pallet<T> {
1117 type Call = Call<T>;
1118 fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity {
1119 if let Call::apply_authorized_upgrade { ref code } = call {
1120 if let Ok(res) = Self::validate_code_is_authorized(&code[..]) {
1121 if Self::can_set_code(&code, false).is_ok() {
1122 return Ok(ValidTransaction {
1123 priority: u64::max_value(),
1124 requires: Vec::new(),
1125 provides: vec![res.code_hash.encode()],
1126 longevity: TransactionLongevity::max_value(),
1127 propagate: true,
1128 });
1129 }
1130 }
1131 }
1132
1133 #[cfg(feature = "experimental")]
1134 if let Call::do_task { ref task } = call {
1135 if source == TransactionSource::InBlock || source == TransactionSource::Local {
1143 if task.is_valid() {
1144 return Ok(ValidTransaction {
1145 priority: u64::max_value(),
1146 requires: Vec::new(),
1147 provides: vec![T::Hashing::hash_of(&task.encode()).as_ref().to_vec()],
1148 longevity: TransactionLongevity::max_value(),
1149 propagate: false,
1150 });
1151 }
1152 }
1153 }
1154
1155 #[cfg(not(feature = "experimental"))]
1156 let _ = source;
1157
1158 Err(InvalidTransaction::Call.into())
1159 }
1160 }
1161}
1162
1163pub type Key = Vec<u8>;
1164pub type KeyValue = (Vec<u8>, Vec<u8>);
1165
1166#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
1168#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))]
1169pub enum Phase {
1170 ApplyExtrinsic(u32),
1172 Finalization,
1174 Initialization,
1176}
1177
1178impl Default for Phase {
1179 fn default() -> Self {
1180 Self::Initialization
1181 }
1182}
1183
1184#[derive(Encode, Decode, Debug, TypeInfo)]
1186#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))]
1187pub struct EventRecord<E: Parameter + Member, T> {
1188 pub phase: Phase,
1190 pub event: E,
1192 pub topics: Vec<T>,
1194}
1195
1196fn hash69<T: AsMut<[u8]> + Default>() -> T {
1199 let mut h = T::default();
1200 h.as_mut().iter_mut().for_each(|byte| *byte = 69);
1201 h
1202}
1203
1204type EventIndex = u32;
1209
1210pub type RefCount = u32;
1212
1213#[derive(Clone, Eq, PartialEq, Default, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)]
1215pub struct AccountInfo<Nonce, AccountData> {
1216 pub nonce: Nonce,
1218 pub consumers: RefCount,
1221 pub providers: RefCount,
1224 pub sufficients: RefCount,
1227 pub data: AccountData,
1230}
1231
1232#[derive(Debug, Encode, Decode, TypeInfo)]
1235#[cfg_attr(feature = "std", derive(PartialEq))]
1236pub struct LastRuntimeUpgradeInfo {
1237 pub spec_version: codec::Compact<u32>,
1238 pub spec_name: Cow<'static, str>,
1239}
1240
1241impl LastRuntimeUpgradeInfo {
1242 pub fn was_upgraded(&self, current: &RuntimeVersion) -> bool {
1246 current.spec_version > self.spec_version.0 || current.spec_name != self.spec_name
1247 }
1248}
1249
1250impl From<RuntimeVersion> for LastRuntimeUpgradeInfo {
1251 fn from(version: RuntimeVersion) -> Self {
1252 Self { spec_version: version.spec_version.into(), spec_name: version.spec_name }
1253 }
1254}
1255
1256pub struct EnsureRoot<AccountId>(core::marker::PhantomData<AccountId>);
1258impl<O: OriginTrait, AccountId> EnsureOrigin<O> for EnsureRoot<AccountId> {
1259 type Success = ();
1260 fn try_origin(o: O) -> Result<Self::Success, O> {
1261 match o.as_system_ref() {
1262 Some(RawOrigin::Root) => Ok(()),
1263 _ => Err(o),
1264 }
1265 }
1266
1267 #[cfg(feature = "runtime-benchmarks")]
1268 fn try_successful_origin() -> Result<O, ()> {
1269 Ok(O::root())
1270 }
1271}
1272
1273impl_ensure_origin_with_arg_ignoring_arg! {
1274 impl< { O: .., AccountId: Decode, T } >
1275 EnsureOriginWithArg<O, T> for EnsureRoot<AccountId>
1276 {}
1277}
1278
1279pub struct EnsureRootWithSuccess<AccountId, Success>(
1281 core::marker::PhantomData<(AccountId, Success)>,
1282);
1283impl<O: OriginTrait, AccountId, Success: TypedGet> EnsureOrigin<O>
1284 for EnsureRootWithSuccess<AccountId, Success>
1285{
1286 type Success = Success::Type;
1287 fn try_origin(o: O) -> Result<Self::Success, O> {
1288 match o.as_system_ref() {
1289 Some(RawOrigin::Root) => Ok(Success::get()),
1290 _ => Err(o),
1291 }
1292 }
1293
1294 #[cfg(feature = "runtime-benchmarks")]
1295 fn try_successful_origin() -> Result<O, ()> {
1296 Ok(O::root())
1297 }
1298}
1299
1300impl_ensure_origin_with_arg_ignoring_arg! {
1301 impl< { O: .., AccountId: Decode, Success: TypedGet, T } >
1302 EnsureOriginWithArg<O, T> for EnsureRootWithSuccess<AccountId, Success>
1303 {}
1304}
1305
1306pub struct EnsureWithSuccess<Ensure, AccountId, Success>(
1308 core::marker::PhantomData<(Ensure, AccountId, Success)>,
1309);
1310
1311impl<O: OriginTrait, Ensure: EnsureOrigin<O>, AccountId, Success: TypedGet> EnsureOrigin<O>
1312 for EnsureWithSuccess<Ensure, AccountId, Success>
1313{
1314 type Success = Success::Type;
1315
1316 fn try_origin(o: O) -> Result<Self::Success, O> {
1317 Ensure::try_origin(o).map(|_| Success::get())
1318 }
1319
1320 #[cfg(feature = "runtime-benchmarks")]
1321 fn try_successful_origin() -> Result<O, ()> {
1322 Ensure::try_successful_origin()
1323 }
1324}
1325
1326pub struct EnsureSigned<AccountId>(core::marker::PhantomData<AccountId>);
1328impl<O: OriginTrait<AccountId = AccountId>, AccountId: Decode + Clone> EnsureOrigin<O>
1329 for EnsureSigned<AccountId>
1330{
1331 type Success = AccountId;
1332 fn try_origin(o: O) -> Result<Self::Success, O> {
1333 match o.as_system_ref() {
1334 Some(RawOrigin::Signed(who)) => Ok(who.clone()),
1335 _ => Err(o),
1336 }
1337 }
1338
1339 #[cfg(feature = "runtime-benchmarks")]
1340 fn try_successful_origin() -> Result<O, ()> {
1341 let zero_account_id =
1342 AccountId::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?;
1343 Ok(O::signed(zero_account_id))
1344 }
1345}
1346
1347impl_ensure_origin_with_arg_ignoring_arg! {
1348 impl< { O: OriginTrait<AccountId = AccountId>, AccountId: Decode + Clone, T } >
1349 EnsureOriginWithArg<O, T> for EnsureSigned<AccountId>
1350 {}
1351}
1352
1353pub struct EnsureSignedBy<Who, AccountId>(core::marker::PhantomData<(Who, AccountId)>);
1355impl<
1356 O: OriginTrait<AccountId = AccountId>,
1357 Who: SortedMembers<AccountId>,
1358 AccountId: PartialEq + Clone + Ord + Decode,
1359 > EnsureOrigin<O> for EnsureSignedBy<Who, AccountId>
1360{
1361 type Success = AccountId;
1362 fn try_origin(o: O) -> Result<Self::Success, O> {
1363 match o.as_system_ref() {
1364 Some(RawOrigin::Signed(ref who)) if Who::contains(who) => Ok(who.clone()),
1365 _ => Err(o),
1366 }
1367 }
1368
1369 #[cfg(feature = "runtime-benchmarks")]
1370 fn try_successful_origin() -> Result<O, ()> {
1371 let first_member = match Who::sorted_members().first() {
1372 Some(account) => account.clone(),
1373 None => AccountId::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?,
1374 };
1375 Ok(O::signed(first_member))
1376 }
1377}
1378
1379impl_ensure_origin_with_arg_ignoring_arg! {
1380 impl< { O: OriginTrait<AccountId = AccountId>, Who: SortedMembers<AccountId>, AccountId: PartialEq + Clone + Ord + Decode, T } >
1381 EnsureOriginWithArg<O, T> for EnsureSignedBy<Who, AccountId>
1382 {}
1383}
1384
1385pub struct EnsureNone<AccountId>(core::marker::PhantomData<AccountId>);
1387impl<O: OriginTrait<AccountId = AccountId>, AccountId> EnsureOrigin<O> for EnsureNone<AccountId> {
1388 type Success = ();
1389 fn try_origin(o: O) -> Result<Self::Success, O> {
1390 match o.as_system_ref() {
1391 Some(RawOrigin::None) => Ok(()),
1392 _ => Err(o),
1393 }
1394 }
1395
1396 #[cfg(feature = "runtime-benchmarks")]
1397 fn try_successful_origin() -> Result<O, ()> {
1398 Ok(O::none())
1399 }
1400}
1401
1402impl_ensure_origin_with_arg_ignoring_arg! {
1403 impl< { O: OriginTrait<AccountId = AccountId>, AccountId, T } >
1404 EnsureOriginWithArg<O, T> for EnsureNone<AccountId>
1405 {}
1406}
1407
1408pub struct EnsureNever<Success>(core::marker::PhantomData<Success>);
1410impl<O, Success> EnsureOrigin<O> for EnsureNever<Success> {
1411 type Success = Success;
1412 fn try_origin(o: O) -> Result<Self::Success, O> {
1413 Err(o)
1414 }
1415
1416 #[cfg(feature = "runtime-benchmarks")]
1417 fn try_successful_origin() -> Result<O, ()> {
1418 Err(())
1419 }
1420}
1421
1422impl_ensure_origin_with_arg_ignoring_arg! {
1423 impl< { O, Success, T } >
1424 EnsureOriginWithArg<O, T> for EnsureNever<Success>
1425 {}
1426}
1427
1428#[docify::export]
1429pub fn ensure_signed<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<AccountId, BadOrigin>
1432where
1433 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1434{
1435 match o.into() {
1436 Ok(RawOrigin::Signed(t)) => Ok(t),
1437 _ => Err(BadOrigin),
1438 }
1439}
1440
1441pub fn ensure_signed_or_root<OuterOrigin, AccountId>(
1445 o: OuterOrigin,
1446) -> Result<Option<AccountId>, BadOrigin>
1447where
1448 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1449{
1450 match o.into() {
1451 Ok(RawOrigin::Root) => Ok(None),
1452 Ok(RawOrigin::Signed(t)) => Ok(Some(t)),
1453 _ => Err(BadOrigin),
1454 }
1455}
1456
1457pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), BadOrigin>
1459where
1460 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1461{
1462 match o.into() {
1463 Ok(RawOrigin::Root) => Ok(()),
1464 _ => Err(BadOrigin),
1465 }
1466}
1467
1468pub fn ensure_none<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), BadOrigin>
1470where
1471 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1472{
1473 match o.into() {
1474 Ok(RawOrigin::None) => Ok(()),
1475 _ => Err(BadOrigin),
1476 }
1477}
1478
1479pub fn ensure_authorized<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), BadOrigin>
1482where
1483 OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>,
1484{
1485 match o.into() {
1486 Ok(RawOrigin::Authorized) => Ok(()),
1487 _ => Err(BadOrigin),
1488 }
1489}
1490
1491#[derive(Debug)]
1493pub enum RefStatus {
1494 Referenced,
1495 Unreferenced,
1496}
1497
1498#[derive(Eq, PartialEq, Debug)]
1500pub enum IncRefStatus {
1501 Created,
1503 Existed,
1505}
1506
1507#[derive(Eq, PartialEq, Debug)]
1509pub enum DecRefStatus {
1510 Reaped,
1512 Exists,
1514}
1515
1516pub enum CanSetCodeResult<T: Config> {
1518 Ok,
1520 MultiBlockMigrationsOngoing,
1522 InvalidVersion(Error<T>),
1524}
1525
1526impl<T: Config> CanSetCodeResult<T> {
1527 pub fn into_result(self) -> Result<(), DispatchError> {
1529 match self {
1530 Self::Ok => Ok(()),
1531 Self::MultiBlockMigrationsOngoing => {
1532 Err(Error::<T>::MultiBlockMigrationsOngoing.into())
1533 },
1534 Self::InvalidVersion(err) => Err(err.into()),
1535 }
1536 }
1537
1538 pub fn is_ok(&self) -> bool {
1540 matches!(self, Self::Ok)
1541 }
1542}
1543
1544impl<T: Config> Pallet<T> {
1545 #[doc = docify::embed!("src/system/tests.rs", last_runtime_upgrade_spec_version_usage)]
1559 pub fn last_runtime_upgrade_spec_version() -> u32 {
1560 LastRuntimeUpgrade::<T>::get().map_or(0, |l| l.spec_version.0)
1561 }
1562
1563 pub fn account_exists(who: &T::AccountId) -> bool {
1565 Account::<T>::contains_key(who)
1566 }
1567
1568 pub fn update_code_in_storage(code: &[u8]) {
1574 storage::unhashed::put_raw(well_known_keys::CODE, code);
1575 Self::deposit_log(generic::DigestItem::RuntimeEnvironmentUpdated);
1576 Self::deposit_event(Event::CodeUpdated);
1577 }
1578
1579 pub fn inherents_applied() -> bool {
1581 InherentsApplied::<T>::get()
1582 }
1583
1584 pub fn note_inherents_applied() {
1589 InherentsApplied::<T>::put(true);
1590 }
1591
1592 #[deprecated = "Use `inc_consumers` instead"]
1594 pub fn inc_ref(who: &T::AccountId) {
1595 let _ = Self::inc_consumers(who);
1596 }
1597
1598 #[deprecated = "Use `dec_consumers` instead"]
1601 pub fn dec_ref(who: &T::AccountId) {
1602 let _ = Self::dec_consumers(who);
1603 }
1604
1605 #[deprecated = "Use `consumers` instead"]
1607 pub fn refs(who: &T::AccountId) -> RefCount {
1608 Self::consumers(who)
1609 }
1610
1611 #[deprecated = "Use `!is_provider_required` instead"]
1613 pub fn allow_death(who: &T::AccountId) -> bool {
1614 !Self::is_provider_required(who)
1615 }
1616
1617 pub fn inc_providers(who: &T::AccountId) -> IncRefStatus {
1619 Account::<T>::mutate(who, |a| {
1620 if a.providers == 0 && a.sufficients == 0 {
1621 a.providers = 1;
1623 Self::on_created_account(who.clone(), a);
1624 IncRefStatus::Created
1625 } else {
1626 a.providers = a.providers.saturating_add(1);
1627 IncRefStatus::Existed
1628 }
1629 })
1630 }
1631
1632 pub fn dec_providers(who: &T::AccountId) -> Result<DecRefStatus, DispatchError> {
1636 Account::<T>::try_mutate_exists(who, |maybe_account| {
1637 if let Some(mut account) = maybe_account.take() {
1638 if account.providers == 0 {
1639 log::error!(
1641 target: LOG_TARGET,
1642 "Logic error: Unexpected underflow in reducing provider",
1643 );
1644 account.providers = 1;
1645 }
1646 match (account.providers, account.consumers, account.sufficients) {
1647 (1, 0, 0) => {
1648 Pallet::<T>::on_killed_account(who.clone());
1651 Ok(DecRefStatus::Reaped)
1652 },
1653 (1, c, _) if c > 0 => {
1654 Err(DispatchError::ConsumerRemaining)
1656 },
1657 (x, _, _) => {
1658 account.providers = x - 1;
1661 *maybe_account = Some(account);
1662 Ok(DecRefStatus::Exists)
1663 },
1664 }
1665 } else {
1666 log::error!(
1667 target: LOG_TARGET,
1668 "Logic error: Account already dead when reducing provider",
1669 );
1670 Ok(DecRefStatus::Reaped)
1671 }
1672 })
1673 }
1674
1675 pub fn inc_sufficients(who: &T::AccountId) -> IncRefStatus {
1677 Account::<T>::mutate(who, |a| {
1678 if a.providers + a.sufficients == 0 {
1679 a.sufficients = 1;
1681 Self::on_created_account(who.clone(), a);
1682 IncRefStatus::Created
1683 } else {
1684 a.sufficients = a.sufficients.saturating_add(1);
1685 IncRefStatus::Existed
1686 }
1687 })
1688 }
1689
1690 pub fn dec_sufficients(who: &T::AccountId) -> DecRefStatus {
1694 Account::<T>::mutate_exists(who, |maybe_account| {
1695 if let Some(mut account) = maybe_account.take() {
1696 if account.sufficients == 0 {
1697 log::error!(
1699 target: LOG_TARGET,
1700 "Logic error: Unexpected underflow in reducing sufficients",
1701 );
1702 }
1703 match (account.sufficients, account.providers) {
1704 (0, 0) | (1, 0) => {
1705 Pallet::<T>::on_killed_account(who.clone());
1706 DecRefStatus::Reaped
1707 },
1708 (x, _) => {
1709 account.sufficients = x.saturating_sub(1);
1710 *maybe_account = Some(account);
1711 DecRefStatus::Exists
1712 },
1713 }
1714 } else {
1715 log::error!(
1716 target: LOG_TARGET,
1717 "Logic error: Account already dead when reducing provider",
1718 );
1719 DecRefStatus::Reaped
1720 }
1721 })
1722 }
1723
1724 pub fn providers(who: &T::AccountId) -> RefCount {
1726 Account::<T>::get(who).providers
1727 }
1728
1729 pub fn sufficients(who: &T::AccountId) -> RefCount {
1731 Account::<T>::get(who).sufficients
1732 }
1733
1734 pub fn reference_count(who: &T::AccountId) -> RefCount {
1736 let a = Account::<T>::get(who);
1737 a.providers + a.sufficients
1738 }
1739
1740 pub fn inc_consumers(who: &T::AccountId) -> Result<(), DispatchError> {
1745 Account::<T>::try_mutate(who, |a| {
1746 if a.providers > 0 {
1747 if a.consumers < T::MaxConsumers::max_consumers() {
1748 a.consumers = a.consumers.saturating_add(1);
1749 Ok(())
1750 } else {
1751 Err(DispatchError::TooManyConsumers)
1752 }
1753 } else {
1754 Err(DispatchError::NoProviders)
1755 }
1756 })
1757 }
1758
1759 pub fn inc_consumers_without_limit(who: &T::AccountId) -> Result<(), DispatchError> {
1763 Account::<T>::try_mutate(who, |a| {
1764 if a.providers > 0 {
1765 a.consumers = a.consumers.saturating_add(1);
1766 Ok(())
1767 } else {
1768 Err(DispatchError::NoProviders)
1769 }
1770 })
1771 }
1772
1773 pub fn dec_consumers(who: &T::AccountId) {
1776 Account::<T>::mutate(who, |a| {
1777 if a.consumers > 0 {
1778 a.consumers -= 1;
1779 } else {
1780 log::error!(
1781 target: LOG_TARGET,
1782 "Logic error: Unexpected underflow in reducing consumer",
1783 );
1784 }
1785 })
1786 }
1787
1788 pub fn consumers(who: &T::AccountId) -> RefCount {
1790 Account::<T>::get(who).consumers
1791 }
1792
1793 pub fn is_provider_required(who: &T::AccountId) -> bool {
1795 Account::<T>::get(who).consumers != 0
1796 }
1797
1798 pub fn can_dec_provider(who: &T::AccountId) -> bool {
1800 let a = Account::<T>::get(who);
1801 a.consumers == 0 || a.providers > 1
1802 }
1803
1804 pub fn can_accrue_consumers(who: &T::AccountId, amount: u32) -> bool {
1807 let a = Account::<T>::get(who);
1808 match a.consumers.checked_add(amount) {
1809 Some(c) => a.providers > 0 && c <= T::MaxConsumers::max_consumers(),
1810 None => false,
1811 }
1812 }
1813
1814 pub fn can_inc_consumer(who: &T::AccountId) -> bool {
1817 Self::can_accrue_consumers(who, 1)
1818 }
1819
1820 pub fn deposit_event(event: impl Into<T::RuntimeEvent>) {
1824 Self::deposit_event_indexed(&[], event.into());
1825 }
1826
1827 pub fn deposit_event_indexed(topics: &[T::Hash], event: T::RuntimeEvent) {
1835 let block_number = Self::block_number();
1836
1837 if block_number.is_zero() {
1839 return;
1840 }
1841
1842 let phase = ExecutionPhase::<T>::get().unwrap_or_default();
1843 let event = EventRecord { phase, event, topics: topics.to_vec() };
1844
1845 let event_idx = {
1847 let old_event_count = EventCount::<T>::get();
1848 let new_event_count = match old_event_count.checked_add(1) {
1849 None => return,
1852 Some(nc) => nc,
1853 };
1854 EventCount::<T>::put(new_event_count);
1855 old_event_count
1856 };
1857
1858 Events::<T>::append(event);
1859
1860 for topic in topics {
1861 <EventTopics<T>>::append(topic, &(block_number, event_idx));
1862 }
1863 }
1864
1865 pub fn extrinsic_index() -> Option<u32> {
1867 storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX)
1868 }
1869
1870 pub fn extrinsic_count() -> u32 {
1872 ExtrinsicCount::<T>::get().unwrap_or_default()
1873 }
1874
1875 pub fn block_size() -> u32 {
1877 BlockSize::<T>::get().unwrap_or_default()
1878 }
1879
1880 pub fn register_extra_weight_unchecked(weight: Weight, class: DispatchClass) {
1896 BlockWeight::<T>::mutate(|current_weight| {
1897 current_weight.accrue(weight, class);
1898 });
1899 }
1900
1901 pub fn initialize(number: &BlockNumberFor<T>, parent_hash: &T::Hash, digest: &generic::Digest) {
1908 let expected_block_number = Self::block_number() + One::one();
1909 assert_eq!(expected_block_number, *number, "Block number must be strictly increasing.");
1910
1911 ExecutionPhase::<T>::put(Phase::Initialization);
1913 storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
1914 Self::initialize_intra_block_entropy(parent_hash);
1915 <Number<T>>::put(number);
1916 <Digest<T>>::put(digest);
1917 <ParentHash<T>>::put(parent_hash);
1918 <BlockHash<T>>::insert(*number - One::one(), parent_hash);
1919
1920 BlockWeight::<T>::kill();
1922
1923 let digest_size = digest.encoded_size();
1926 let empty_header = <<T as Config>::Block as traits::Block>::Header::new(
1927 *number,
1928 Default::default(),
1929 Default::default(),
1930 *parent_hash,
1931 Default::default(),
1932 );
1933 let empty_header_size = empty_header.encoded_size();
1934 let overhead = digest_size.saturating_add(empty_header_size) as u32;
1935 BlockSize::<T>::put(overhead);
1936
1937 let max_total_header = T::BlockLength::get().max_header_size();
1939 assert!(
1940 overhead <= max_total_header as u32,
1941 "Header size ({overhead}) exceeds max header size limit ({max_total_header})"
1942 );
1943 }
1944
1945 pub fn initialize_intra_block_entropy(parent_hash: &T::Hash) {
1949 let entropy = (b"topsoil_system::initialize", parent_hash).using_encoded(blake2_256);
1950 storage::unhashed::put_raw(well_known_keys::INTRABLOCK_ENTROPY, &entropy[..]);
1951 }
1952
1953 pub fn resource_usage_report() {
1957 log::debug!(
1958 target: LOG_TARGET,
1959 "[{:?}] {} extrinsics, block size: {} (normal {}%, op: {}%, mandatory {}%) / normal weight:\
1960 {} (ref_time: {}%, proof_size: {}%) op weight {} (ref_time {}%, proof_size {}%) / \
1961 mandatory weight {} (ref_time: {}%, proof_size: {}%)",
1962 Self::block_number(),
1963 Self::extrinsic_count(),
1964 Self::block_size(),
1965 subsoil::runtime::Percent::from_rational(
1966 Self::block_size(),
1967 *T::BlockLength::get().max.get(DispatchClass::Normal)
1968 ).deconstruct(),
1969 subsoil::runtime::Percent::from_rational(
1970 Self::block_size(),
1971 *T::BlockLength::get().max.get(DispatchClass::Operational)
1972 ).deconstruct(),
1973 subsoil::runtime::Percent::from_rational(
1974 Self::block_size(),
1975 *T::BlockLength::get().max.get(DispatchClass::Mandatory)
1976 ).deconstruct(),
1977 Self::block_weight().get(DispatchClass::Normal),
1978 subsoil::runtime::Percent::from_rational(
1979 Self::block_weight().get(DispatchClass::Normal).ref_time(),
1980 T::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap_or(Bounded::max_value()).ref_time()
1981 ).deconstruct(),
1982 subsoil::runtime::Percent::from_rational(
1983 Self::block_weight().get(DispatchClass::Normal).proof_size(),
1984 T::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap_or(Bounded::max_value()).proof_size()
1985 ).deconstruct(),
1986 Self::block_weight().get(DispatchClass::Operational),
1987 subsoil::runtime::Percent::from_rational(
1988 Self::block_weight().get(DispatchClass::Operational).ref_time(),
1989 T::BlockWeights::get().get(DispatchClass::Operational).max_total.unwrap_or(Bounded::max_value()).ref_time()
1990 ).deconstruct(),
1991 subsoil::runtime::Percent::from_rational(
1992 Self::block_weight().get(DispatchClass::Operational).proof_size(),
1993 T::BlockWeights::get().get(DispatchClass::Operational).max_total.unwrap_or(Bounded::max_value()).proof_size()
1994 ).deconstruct(),
1995 Self::block_weight().get(DispatchClass::Mandatory),
1996 subsoil::runtime::Percent::from_rational(
1997 Self::block_weight().get(DispatchClass::Mandatory).ref_time(),
1998 T::BlockWeights::get().get(DispatchClass::Mandatory).max_total.unwrap_or(Bounded::max_value()).ref_time()
1999 ).deconstruct(),
2000 subsoil::runtime::Percent::from_rational(
2001 Self::block_weight().get(DispatchClass::Mandatory).proof_size(),
2002 T::BlockWeights::get().get(DispatchClass::Mandatory).max_total.unwrap_or(Bounded::max_value()).proof_size()
2003 ).deconstruct(),
2004 );
2005 }
2006
2007 pub fn finalize() -> HeaderFor<T> {
2010 Self::resource_usage_report();
2011 ExecutionPhase::<T>::kill();
2012 BlockSize::<T>::kill();
2013 storage::unhashed::kill(well_known_keys::INTRABLOCK_ENTROPY);
2014 InherentsApplied::<T>::kill();
2015
2016 let number = <Number<T>>::get();
2027 let parent_hash = <ParentHash<T>>::get();
2028 let digest = <Digest<T>>::get();
2029
2030 let extrinsics = (0..ExtrinsicCount::<T>::take().unwrap_or_default())
2031 .map(ExtrinsicData::<T>::take)
2032 .collect();
2033 let extrinsics_root_state_version = T::Version::get().extrinsics_root_state_version();
2034 let extrinsics_root =
2035 extrinsics_data_root::<T::Hashing>(extrinsics, extrinsics_root_state_version);
2036
2037 let block_hash_count = T::BlockHashCount::get();
2039 let to_remove = number.saturating_sub(block_hash_count).saturating_sub(One::one());
2040
2041 if !to_remove.is_zero() {
2043 <BlockHash<T>>::remove(to_remove);
2044 }
2045
2046 let version = T::Version::get().state_version();
2047 let storage_root = T::Hash::decode(&mut &subsoil::io::storage::root(version)[..])
2048 .expect("Node is configured to use the same hash; qed");
2049
2050 HeaderFor::<T>::new(number, extrinsics_root, storage_root, parent_hash, digest)
2051 }
2052
2053 pub fn deposit_log(item: generic::DigestItem) {
2058 BlockSize::<T>::mutate(|len| {
2059 *len = Some(len.unwrap_or(0).saturating_add(item.encoded_size() as u32));
2060 });
2061 <Digest<T>>::append(item);
2062 }
2063
2064 #[cfg(any(feature = "std", test))]
2066 pub fn externalities() -> TestExternalities {
2067 TestExternalities::new(subsoil::core::storage::Storage {
2068 top: [
2069 (<BlockHash<T>>::hashed_key_for(BlockNumberFor::<T>::zero()), [69u8; 32].encode()),
2070 (<Number<T>>::hashed_key().to_vec(), BlockNumberFor::<T>::one().encode()),
2071 (<ParentHash<T>>::hashed_key().to_vec(), [69u8; 32].encode()),
2072 ]
2073 .into_iter()
2074 .collect(),
2075 children_default: Default::default(),
2076 })
2077 }
2078
2079 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2087 pub fn events() -> Vec<EventRecord<T::RuntimeEvent, T::Hash>> {
2088 Self::read_events_no_consensus().map(|e| *e).collect()
2090 }
2091
2092 pub fn event_no_consensus(index: usize) -> Option<T::RuntimeEvent> {
2097 Self::read_events_no_consensus().nth(index).map(|e| e.event.clone())
2098 }
2099
2100 pub fn read_events_no_consensus(
2105 ) -> impl Iterator<Item = Box<EventRecord<T::RuntimeEvent, T::Hash>>> {
2106 Events::<T>::stream_iter()
2107 }
2108
2109 pub fn read_events_for_pallet<E>() -> Vec<E>
2114 where
2115 T::RuntimeEvent: TryInto<E>,
2116 {
2117 Events::<T>::get()
2118 .into_iter()
2119 .map(|er| er.event)
2120 .filter_map(|e| e.try_into().ok())
2121 .collect::<_>()
2122 }
2123
2124 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2133 pub fn run_to_block_with<AllPalletsWithSystem>(
2134 n: BlockNumberFor<T>,
2135 mut hooks: RunToBlockHooks<T>,
2136 ) where
2137 AllPalletsWithSystem: topsoil_core::traits::OnInitialize<BlockNumberFor<T>>
2138 + topsoil_core::traits::OnFinalize<BlockNumberFor<T>>,
2139 {
2140 let mut bn = Self::block_number();
2141
2142 while bn < n {
2143 if !bn.is_zero() {
2145 (hooks.before_finalize)(bn);
2146 AllPalletsWithSystem::on_finalize(bn);
2147 (hooks.after_finalize)(bn);
2148 }
2149
2150 bn += One::one();
2151
2152 Self::set_block_number(bn);
2153 (hooks.before_initialize)(bn);
2154 AllPalletsWithSystem::on_initialize(bn);
2155 (hooks.after_initialize)(bn);
2156 }
2157 }
2158
2159 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2161 pub fn run_to_block<AllPalletsWithSystem>(n: BlockNumberFor<T>)
2162 where
2163 AllPalletsWithSystem: topsoil_core::traits::OnInitialize<BlockNumberFor<T>>
2164 + topsoil_core::traits::OnFinalize<BlockNumberFor<T>>,
2165 {
2166 Self::run_to_block_with::<AllPalletsWithSystem>(n, Default::default());
2167 }
2168
2169 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2172 pub fn set_block_number(n: BlockNumberFor<T>) {
2173 <Number<T>>::put(n);
2174 }
2175
2176 #[cfg(any(feature = "std", test))]
2178 pub fn set_extrinsic_index(extrinsic_index: u32) {
2179 storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &extrinsic_index)
2180 }
2181
2182 #[cfg(any(feature = "std", test))]
2185 pub fn set_parent_hash(n: T::Hash) {
2186 <ParentHash<T>>::put(n);
2187 }
2188
2189 #[cfg(any(feature = "std", test))]
2191 pub fn set_block_consumed_resources(weight: Weight, len: usize) {
2192 BlockWeight::<T>::mutate(|current_weight| {
2193 current_weight.set(weight, DispatchClass::Normal)
2194 });
2195 BlockSize::<T>::put(len as u32);
2196 }
2197
2198 pub fn reset_events() {
2203 <Events<T>>::kill();
2204 EventCount::<T>::kill();
2205 let _ = <EventTopics<T>>::clear(u32::max_value(), None);
2206 }
2207
2208 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2212 #[track_caller]
2213 pub fn assert_has_event(event: T::RuntimeEvent) {
2214 let warn = if Self::block_number().is_zero() {
2215 "WARNING: block number is zero, and events are not registered at block number zero.\n"
2216 } else {
2217 ""
2218 };
2219
2220 let events = Self::events();
2221 assert!(
2222 events.iter().any(|record| record.event == event),
2223 "{warn}expected event {event:?} not found in events {events:?}",
2224 );
2225 }
2226
2227 #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2231 #[track_caller]
2232 pub fn assert_last_event(event: T::RuntimeEvent) {
2233 let warn = if Self::block_number().is_zero() {
2234 "WARNING: block number is zero, and events are not registered at block number zero.\n"
2235 } else {
2236 ""
2237 };
2238
2239 let last_event = Self::events()
2240 .last()
2241 .expect(&alloc::format!("{warn}events expected"))
2242 .event
2243 .clone();
2244 assert_eq!(
2245 last_event, event,
2246 "{warn}expected event {event:?} is not equal to the last event {last_event:?}",
2247 );
2248 }
2249
2250 pub fn runtime_version() -> RuntimeVersion {
2252 T::Version::get()
2253 }
2254
2255 pub fn account_nonce(who: impl EncodeLike<T::AccountId>) -> T::Nonce {
2257 Account::<T>::get(who).nonce
2258 }
2259
2260 pub fn inc_account_nonce(who: impl EncodeLike<T::AccountId>) {
2262 Account::<T>::mutate(who, |a| a.nonce += T::Nonce::one());
2263 }
2264
2265 pub fn note_extrinsic(encoded_xt: Vec<u8>) {
2270 ExtrinsicData::<T>::insert(Self::extrinsic_index().unwrap_or_default(), encoded_xt);
2271 }
2272
2273 pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, info: DispatchInfo) {
2279 let weight = extract_actual_weight(r, &info)
2280 .saturating_add(T::BlockWeights::get().get(info.class).base_extrinsic);
2281 let class = info.class;
2282 let pays_fee = extract_actual_pays_fee(r, &info);
2283 let dispatch_event_info = DispatchEventInfo { weight, class, pays_fee };
2284
2285 Self::deposit_event(match r {
2286 Ok(_) => Event::ExtrinsicSuccess { dispatch_info: dispatch_event_info },
2287 Err(err) => {
2288 log::trace!(
2289 target: LOG_TARGET,
2290 "Extrinsic failed at block({:?}): {:?}",
2291 Self::block_number(),
2292 err,
2293 );
2294 Event::ExtrinsicFailed {
2295 dispatch_error: err.error,
2296 dispatch_info: dispatch_event_info,
2297 }
2298 },
2299 });
2300
2301 log::trace!(
2302 target: LOG_TARGET,
2303 "Used block weight: {:?}",
2304 BlockWeight::<T>::get(),
2305 );
2306
2307 log::trace!(
2308 target: LOG_TARGET,
2309 "Used block length: {:?}",
2310 Pallet::<T>::block_size(),
2311 );
2312
2313 let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32;
2314
2315 storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index);
2316 ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(next_extrinsic_index));
2317 ExtrinsicWeightReclaimed::<T>::kill();
2318 }
2319
2320 pub fn note_finished_extrinsics() {
2323 let extrinsic_index: u32 =
2324 storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap_or_default();
2325 ExtrinsicCount::<T>::put(extrinsic_index);
2326 ExecutionPhase::<T>::put(Phase::Finalization);
2327 }
2328
2329 pub fn note_finished_initialize() {
2332 ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(0))
2333 }
2334
2335 pub fn on_created_account(who: T::AccountId, _a: &mut AccountInfo<T::Nonce, T::AccountData>) {
2337 T::OnNewAccount::on_new_account(&who);
2338 Self::deposit_event(Event::NewAccount { account: who });
2339 }
2340
2341 fn on_killed_account(who: T::AccountId) {
2343 T::OnKilledAccount::on_killed_account(&who);
2344 Self::deposit_event(Event::KilledAccount { account: who });
2345 }
2346
2347 pub fn can_set_code(code: &[u8], check_version: bool) -> CanSetCodeResult<T> {
2351 if T::MultiBlockMigrator::ongoing() {
2352 return CanSetCodeResult::MultiBlockMigrationsOngoing;
2353 }
2354
2355 if check_version {
2356 let current_version = T::Version::get();
2357 let Some(new_version) = subsoil::io::misc::runtime_version(code)
2358 .and_then(|v| RuntimeVersion::decode(&mut &v[..]).ok())
2359 else {
2360 return CanSetCodeResult::InvalidVersion(Error::<T>::FailedToExtractRuntimeVersion);
2361 };
2362
2363 cfg_if::cfg_if! {
2364 if #[cfg(all(feature = "runtime-benchmarks", not(test)))] {
2365 core::hint::black_box((new_version, current_version));
2367 } else {
2368 if new_version.spec_name != current_version.spec_name {
2369 return CanSetCodeResult::InvalidVersion(Error::<T>::InvalidSpecName)
2370 }
2371
2372 if new_version.spec_version <= current_version.spec_version {
2373 return CanSetCodeResult::InvalidVersion(Error::<T>::SpecVersionNeedsToIncrease)
2374 }
2375 }
2376 }
2377 }
2378
2379 CanSetCodeResult::Ok
2380 }
2381
2382 pub fn do_authorize_upgrade(code_hash: T::Hash, check_version: bool) {
2384 AuthorizedUpgrade::<T>::put(CodeUpgradeAuthorization { code_hash, check_version });
2385 Self::deposit_event(Event::UpgradeAuthorized { code_hash, check_version });
2386 }
2387
2388 fn validate_code_is_authorized(
2392 code: &[u8],
2393 ) -> Result<CodeUpgradeAuthorization<T>, DispatchError> {
2394 let authorization = AuthorizedUpgrade::<T>::get().ok_or(Error::<T>::NothingAuthorized)?;
2395 let actual_hash = T::Hashing::hash(code);
2396 ensure!(actual_hash == authorization.code_hash, Error::<T>::Unauthorized);
2397 Ok(authorization)
2398 }
2399
2400 pub fn reclaim_weight(
2405 info: &DispatchInfoOf<T::RuntimeCall>,
2406 post_info: &PostDispatchInfoOf<T::RuntimeCall>,
2407 ) -> Result<(), TransactionValidityError>
2408 where
2409 T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
2410 {
2411 let already_reclaimed = crate::system::ExtrinsicWeightReclaimed::<T>::get();
2412 let unspent = post_info.calc_unspent(info);
2413 let accurate_reclaim = already_reclaimed.max(unspent);
2414 let to_reclaim_more = accurate_reclaim.saturating_sub(already_reclaimed);
2416 if to_reclaim_more != Weight::zero() {
2417 crate::system::BlockWeight::<T>::mutate(|current_weight| {
2418 current_weight.reduce(to_reclaim_more, info.class);
2419 });
2420 crate::system::ExtrinsicWeightReclaimed::<T>::put(accurate_reclaim);
2421 }
2422
2423 Ok(())
2424 }
2425
2426 pub fn remaining_block_weight() -> WeightMeter {
2428 let limit = T::BlockWeights::get().max_block;
2429 let consumed = BlockWeight::<T>::get().total();
2430
2431 WeightMeter::with_consumed_and_limit(consumed, limit)
2432 }
2433}
2434
2435pub fn unique(entropy: impl Encode) -> [u8; 32] {
2438 let mut last = [0u8; 32];
2439 subsoil::io::storage::read(well_known_keys::INTRABLOCK_ENTROPY, &mut last[..], 0);
2440 let next = (b"topsoil_system::unique", entropy, last).using_encoded(blake2_256);
2441 subsoil::io::storage::set(well_known_keys::INTRABLOCK_ENTROPY, &next);
2442 next
2443}
2444
2445pub struct Provider<T>(PhantomData<T>);
2447impl<T: Config> HandleLifetime<T::AccountId> for Provider<T> {
2448 fn created(t: &T::AccountId) -> Result<(), DispatchError> {
2449 Pallet::<T>::inc_providers(t);
2450 Ok(())
2451 }
2452 fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
2453 Pallet::<T>::dec_providers(t).map(|_| ())
2454 }
2455}
2456
2457pub struct SelfSufficient<T>(PhantomData<T>);
2459impl<T: Config> HandleLifetime<T::AccountId> for SelfSufficient<T> {
2460 fn created(t: &T::AccountId) -> Result<(), DispatchError> {
2461 Pallet::<T>::inc_sufficients(t);
2462 Ok(())
2463 }
2464 fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
2465 Pallet::<T>::dec_sufficients(t);
2466 Ok(())
2467 }
2468}
2469
2470pub struct Consumer<T>(PhantomData<T>);
2472impl<T: Config> HandleLifetime<T::AccountId> for Consumer<T> {
2473 fn created(t: &T::AccountId) -> Result<(), DispatchError> {
2474 Pallet::<T>::inc_consumers(t)
2475 }
2476 fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
2477 Pallet::<T>::dec_consumers(t);
2478 Ok(())
2479 }
2480}
2481
2482impl<T: Config> BlockNumberProvider for Pallet<T> {
2483 type BlockNumber = BlockNumberFor<T>;
2484
2485 fn current_block_number() -> Self::BlockNumber {
2486 Pallet::<T>::block_number()
2487 }
2488
2489 #[cfg(feature = "runtime-benchmarks")]
2490 fn set_block_number(n: BlockNumberFor<T>) {
2491 Self::set_block_number(n)
2492 }
2493}
2494
2495impl<T: Config> StoredMap<T::AccountId, T::AccountData> for Pallet<T> {
2501 fn get(k: &T::AccountId) -> T::AccountData {
2502 Account::<T>::get(k).data
2503 }
2504
2505 fn try_mutate_exists<R, E: From<DispatchError>>(
2506 k: &T::AccountId,
2507 f: impl FnOnce(&mut Option<T::AccountData>) -> Result<R, E>,
2508 ) -> Result<R, E> {
2509 let account = Account::<T>::get(k);
2510 let is_default = account.data == T::AccountData::default();
2511 let mut some_data = if is_default { None } else { Some(account.data) };
2512 let result = f(&mut some_data)?;
2513 if Self::providers(k) > 0 || Self::sufficients(k) > 0 {
2514 Account::<T>::mutate(k, |a| a.data = some_data.unwrap_or_default());
2515 } else {
2516 Account::<T>::remove(k)
2517 }
2518 Ok(result)
2519 }
2520}
2521
2522pub fn split_inner<T, R, S>(
2524 option: Option<T>,
2525 splitter: impl FnOnce(T) -> (R, S),
2526) -> (Option<R>, Option<S>) {
2527 match option {
2528 Some(inner) => {
2529 let (r, s) = splitter(inner);
2530 (Some(r), Some(s))
2531 },
2532 None => (None, None),
2533 }
2534}
2535
2536pub struct ChainContext<T>(PhantomData<T>);
2537impl<T> Default for ChainContext<T> {
2538 fn default() -> Self {
2539 ChainContext(PhantomData)
2540 }
2541}
2542
2543impl<T: Config> Lookup for ChainContext<T> {
2544 type Source = <T::Lookup as StaticLookup>::Source;
2545 type Target = <T::Lookup as StaticLookup>::Target;
2546
2547 fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError> {
2548 <T::Lookup as StaticLookup>::lookup(s)
2549 }
2550}
2551
2552#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2554pub struct RunToBlockHooks<'a, T>
2555where
2556 T: 'a + Config,
2557{
2558 before_initialize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2559 after_initialize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2560 before_finalize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2561 after_finalize: Box<dyn 'a + FnMut(BlockNumberFor<T>)>,
2562}
2563
2564#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2565impl<'a, T> RunToBlockHooks<'a, T>
2566where
2567 T: 'a + Config,
2568{
2569 pub fn before_initialize<F>(mut self, f: F) -> Self
2571 where
2572 F: 'a + FnMut(BlockNumberFor<T>),
2573 {
2574 self.before_initialize = Box::new(f);
2575 self
2576 }
2577 pub fn after_initialize<F>(mut self, f: F) -> Self
2579 where
2580 F: 'a + FnMut(BlockNumberFor<T>),
2581 {
2582 self.after_initialize = Box::new(f);
2583 self
2584 }
2585 pub fn before_finalize<F>(mut self, f: F) -> Self
2587 where
2588 F: 'a + FnMut(BlockNumberFor<T>),
2589 {
2590 self.before_finalize = Box::new(f);
2591 self
2592 }
2593 pub fn after_finalize<F>(mut self, f: F) -> Self
2595 where
2596 F: 'a + FnMut(BlockNumberFor<T>),
2597 {
2598 self.after_finalize = Box::new(f);
2599 self
2600 }
2601}
2602
2603#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2604impl<'a, T> Default for RunToBlockHooks<'a, T>
2605where
2606 T: Config,
2607{
2608 fn default() -> Self {
2609 Self {
2610 before_initialize: Box::new(|_| {}),
2611 after_initialize: Box::new(|_| {}),
2612 before_finalize: Box::new(|_| {}),
2613 after_finalize: Box::new(|_| {}),
2614 }
2615 }
2616}
2617
2618pub mod pallet_prelude {
2620 pub use crate::system::{
2621 ensure_authorized, ensure_none, ensure_root, ensure_signed, ensure_signed_or_root,
2622 };
2623
2624 pub type OriginFor<T> = <T as crate::system::Config>::RuntimeOrigin;
2626
2627 pub type HeaderFor<T> =
2629 <<T as crate::system::Config>::Block as subsoil::runtime::traits::HeaderProvider>::HeaderT;
2630
2631 pub type BlockNumberFor<T> = <HeaderFor<T> as subsoil::runtime::traits::Header>::Number;
2633
2634 pub type ExtrinsicFor<T> =
2636 <<T as crate::system::Config>::Block as subsoil::runtime::traits::Block>::Extrinsic;
2637
2638 pub type RuntimeCallFor<T> = <T as crate::system::Config>::RuntimeCall;
2640
2641 pub type AccountIdFor<T> = <T as crate::system::Config>::AccountId;
2643}