1#![cfg_attr(not(feature = "std"), no_std)]
19
20#[cfg(doc)]
84#[cfg_attr(doc, aquamarine::aquamarine)]
85pub mod block_flowchart {}
112
113#[cfg(test)]
114mod tests;
115
116extern crate alloc;
117
118use codec::{Codec, Encode};
119use core::marker::PhantomData;
120use frame_support::{
121 defensive_assert,
122 dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo},
123 migrations::MultiStepMigrator,
124 pallet_prelude::InvalidTransaction,
125 traits::{
126 BeforeAllRuntimeMigrations, ExecuteBlock, Get, IsInherent, OffchainWorker, OnFinalize,
127 OnIdle, OnInitialize, OnPoll, OnRuntimeUpgrade, PostInherents, PostTransactions,
128 PreInherents,
129 },
130 weights::{Weight, WeightMeter},
131 MAX_EXTRINSIC_DEPTH,
132};
133use frame_system::pallet_prelude::BlockNumberFor;
134use sp_runtime::{
135 generic::Digest,
136 traits::{
137 self, Applyable, CheckEqual, Checkable, Dispatchable, Header, LazyBlock, NumberFor, One,
138 ValidateUnsigned, Zero,
139 },
140 transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
141 ApplyExtrinsicResult, ExtrinsicInclusionMode,
142};
143
144#[cfg(feature = "try-runtime")]
145use ::{
146 frame_support::{
147 traits::{TryDecodeEntireStorage, TryDecodeEntireStorageError, TryState},
148 StorageNoopGuard,
149 },
150 frame_try_runtime::{TryStateSelect, UpgradeCheckSelect},
151 log,
152 sp_runtime::TryRuntimeError,
153};
154
155#[allow(dead_code)]
156const LOG_TARGET: &str = "runtime::executive";
157
158pub type CheckedOf<E, C> = <E as Checkable<C>>::Checked;
159pub type CallOf<E, C> = <CheckedOf<E, C> as Applyable>::Call;
160pub type OriginOf<E, C> = <CallOf<E, C> as Dispatchable>::RuntimeOrigin;
161
162#[cfg(feature = "try-runtime")]
164#[derive(Debug, Clone)]
165pub struct TryRuntimeUpgradeConfig {
166 pub checks: UpgradeCheckSelect,
168 pub try_state_select: TryStateSelect,
170}
171
172#[cfg(feature = "try-runtime")]
173impl TryRuntimeUpgradeConfig {
174 pub fn new(checks: UpgradeCheckSelect) -> Self {
176 Self { checks, try_state_select: TryStateSelect::All }
177 }
178
179 pub fn with_try_state_select(mut self, try_state_select: TryStateSelect) -> Self {
181 self.try_state_select = try_state_select;
182 self
183 }
184}
185
186#[derive(PartialEq)]
187pub enum ExecutiveError {
188 UnableToDecodeExtrinsic,
189 InvalidInherentPosition(usize),
190 OnlyInherentsAllowed,
191 ApplyExtrinsic(TransactionValidityError),
192 Custom(&'static str),
193}
194
195impl core::fmt::Debug for ExecutiveError {
196 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
197 match self {
198 ExecutiveError::UnableToDecodeExtrinsic =>
199 write!(fmt, "The extrinsic could not be decoded correctly"),
200 ExecutiveError::InvalidInherentPosition(i) =>
201 write!(fmt, "Invalid inherent position for extrinsic at index {}", i),
202 ExecutiveError::OnlyInherentsAllowed =>
203 write!(fmt, "Only inherents are allowed in this block"),
204 ExecutiveError::ApplyExtrinsic(e) => write!(
205 fmt,
206 "ExecuteBlockError applying extrinsic: {}",
207 Into::<&'static str>::into(*e)
208 ),
209 ExecutiveError::Custom(err) => write!(fmt, "{err}"),
210 }
211 }
212}
213
214#[allow(deprecated)]
226pub struct Executive<
227 System,
228 Block,
229 Context,
230 UnsignedValidator,
231 AllPalletsWithSystem,
232 OnRuntimeUpgrade = (),
233>(
234 PhantomData<(
235 System,
236 Block,
237 Context,
238 UnsignedValidator,
239 AllPalletsWithSystem,
240 OnRuntimeUpgrade,
241 )>,
242);
243
244#[allow(deprecated)]
248impl<
249 System: frame_system::Config + IsInherent<Block::Extrinsic>,
250 Block: traits::Block<
251 Header = frame_system::pallet_prelude::HeaderFor<System>,
252 Hash = System::Hash,
253 >,
254 Context: Default,
255 UnsignedValidator,
256 AllPalletsWithSystem: OnRuntimeUpgrade
257 + BeforeAllRuntimeMigrations
258 + OnInitializeWithWeightRegistration<System>
259 + OnIdle<BlockNumberFor<System>>
260 + OnFinalize<BlockNumberFor<System>>
261 + OffchainWorker<BlockNumberFor<System>>
262 + OnPoll<BlockNumberFor<System>>,
263 COnRuntimeUpgrade: OnRuntimeUpgrade,
264 > ExecuteBlock<Block>
265 for Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
266where
267 Block::Extrinsic: Checkable<Context> + Codec,
268 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
269 CallOf<Block::Extrinsic, Context>:
270 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
271 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
272 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
273{
274 fn verify_and_remove_seal(_: &mut <Block as traits::Block>::LazyBlock) {
275 }
277
278 fn execute_verified_block(block: Block::LazyBlock) {
279 Executive::<
280 System,
281 Block,
282 Context,
283 UnsignedValidator,
284 AllPalletsWithSystem,
285 COnRuntimeUpgrade,
286 >::execute_block(block);
287 }
288}
289
290#[allow(deprecated)]
294#[cfg(feature = "try-runtime")]
295impl<
296 System: frame_system::Config + IsInherent<Block::Extrinsic>,
297 Block: traits::Block<
298 Header = frame_system::pallet_prelude::HeaderFor<System>,
299 Hash = System::Hash,
300 >,
301 Context: Default,
302 UnsignedValidator,
303 AllPalletsWithSystem: OnRuntimeUpgrade
304 + BeforeAllRuntimeMigrations
305 + OnInitializeWithWeightRegistration<System>
306 + OnIdle<BlockNumberFor<System>>
307 + OnFinalize<BlockNumberFor<System>>
308 + OffchainWorker<BlockNumberFor<System>>
309 + OnPoll<BlockNumberFor<System>>
310 + TryState<BlockNumberFor<System>>
311 + TryDecodeEntireStorage,
312 COnRuntimeUpgrade: OnRuntimeUpgrade,
313 > Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
314where
315 Block::Extrinsic: Checkable<Context> + Codec,
316 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
317 CallOf<Block::Extrinsic, Context>:
318 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
319 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
320 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
321{
322 pub fn try_execute_block(
331 block: Block::LazyBlock,
332 state_root_check: bool,
333 signature_check: bool,
334 select: frame_try_runtime::TryStateSelect,
335 ) -> Result<Weight, ExecutiveError> {
336 log::info!(
337 target: LOG_TARGET,
338 "try-runtime: executing block #{:?} / state root check: {:?} / signature check: {:?} / try-state-select: {:?}",
339 block.header().number(),
340 state_root_check,
341 signature_check,
342 select,
343 );
344
345 let mode = Self::initialize_block(block.header());
346 Self::initial_checks(block.header());
347
348 let signature_check = if signature_check {
350 Block::Extrinsic::check
351 } else {
352 Block::Extrinsic::unchecked_into_checked_i_know_what_i_am_doing
353 };
354 Self::apply_extrinsics(mode, block.extrinsics(), |uxt, is_inherent| {
355 Self::do_apply_extrinsic(uxt, is_inherent, signature_check)
356 })?;
357
358 if !<frame_system::Pallet<System>>::inherents_applied() {
360 Self::inherents_applied();
361 }
362
363 <frame_system::Pallet<System>>::note_finished_extrinsics();
365 <System as frame_system::Config>::PostTransactions::post_transactions();
366
367 let header = block.header();
368 Self::on_idle_hook(*header.number());
369 Self::on_finalize_hook(*header.number());
370
371 let _guard = frame_support::StorageNoopGuard::default();
373 <AllPalletsWithSystem as frame_support::traits::TryState<
374 BlockNumberFor<System>,
375 >>::try_state(*header.number(), select.clone())
376 .map_err(|e| {
377 log::error!(target: LOG_TARGET, "failure: {:?}", e);
378 ExecutiveError::Custom(e.into())
379 })?;
380 if select.any() {
381 let res = AllPalletsWithSystem::try_decode_entire_state();
382 Self::log_decode_result(res).map_err(|e| ExecutiveError::Custom(e.into()))?;
383 }
384 drop(_guard);
385
386 {
389 let new_header = <frame_system::Pallet<System>>::finalize();
390 let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
391 for (header_item, computed_item) in items_zip {
392 header_item.check_equal(computed_item);
393 assert!(header_item == computed_item, "Digest item must match that calculated.");
394 }
395
396 if state_root_check {
397 let storage_root = new_header.state_root();
398 header.state_root().check_equal(storage_root);
399 assert!(
400 header.state_root() == storage_root,
401 "Storage root must match that calculated."
402 );
403 }
404
405 assert!(
406 header.extrinsics_root() == new_header.extrinsics_root(),
407 "Transaction trie root must be valid.",
408 );
409 }
410
411 log::info!(
412 target: LOG_TARGET,
413 "try-runtime: Block #{:?} successfully executed",
414 header.number(),
415 );
416
417 Ok(frame_system::Pallet::<System>::block_weight().total())
418 }
419
420 pub fn try_runtime_upgrade(checks: UpgradeCheckSelect) -> Result<Weight, TryRuntimeError> {
432 Self::try_runtime_upgrade_with_config(TryRuntimeUpgradeConfig::new(checks))
433 }
434
435 pub fn try_runtime_upgrade_with_config(
445 config: TryRuntimeUpgradeConfig,
446 ) -> Result<Weight, TryRuntimeError> {
447 let checks = config.checks;
448 let try_state_select = config.try_state_select;
449 let before_all_weight =
450 <AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
451
452 let try_on_runtime_upgrade_weight =
453 <(
454 COnRuntimeUpgrade,
455 <System as frame_system::Config>::SingleBlockMigrations,
456 AllPalletsWithSystem,
459 ) as OnRuntimeUpgrade>::try_on_runtime_upgrade(checks.pre_and_post())?;
460
461 frame_system::LastRuntimeUpgrade::<System>::put(
462 frame_system::LastRuntimeUpgradeInfo::from(
463 <System::Version as frame_support::traits::Get<_>>::get(),
464 ),
465 );
466
467 let _guard = StorageNoopGuard::default();
469
470 if checks.any() {
472 let res = AllPalletsWithSystem::try_decode_entire_state();
473 Self::log_decode_result(res)?;
474 }
475
476 if checks.try_state() {
478 AllPalletsWithSystem::try_state(
479 frame_system::Pallet::<System>::block_number(),
480 try_state_select,
481 )?;
482 }
483
484 Ok(before_all_weight.saturating_add(try_on_runtime_upgrade_weight))
485 }
486
487 fn log_decode_result(
489 res: Result<usize, alloc::vec::Vec<TryDecodeEntireStorageError>>,
490 ) -> Result<(), TryRuntimeError> {
491 match res {
492 Ok(bytes) => {
493 log::info!(
494 target: LOG_TARGET,
495 "✅ Entire runtime state decodes without error. {} bytes total.",
496 bytes
497 );
498
499 Ok(())
500 },
501 Err(errors) => {
502 log::error!(
503 target: LOG_TARGET,
504 "`try_decode_entire_state` failed with {} errors",
505 errors.len(),
506 );
507
508 for (i, err) in errors.iter().enumerate() {
509 log::error!(target: LOG_TARGET, "- {i}. error: {err}");
511 log::debug!(target: LOG_TARGET, "- {i}. error: {err:?}");
512 }
513
514 Err("`try_decode_entire_state` failed".into())
515 },
516 }
517 }
518}
519
520pub trait OnInitializeWithWeightRegistration<T: frame_system::Config> {
527 fn on_initialize_with_weight_registration(_n: BlockNumberFor<T>) -> Weight;
529}
530
531frame_support::impl_for_tuples_attr! {
532 #[tuple_types_custom_trait_bound(OnInitialize<frame_system::pallet_prelude::BlockNumberFor<T>>)]
533 impl<T: frame_system::Config> OnInitializeWithWeightRegistration<T> for Tuple {
534 fn on_initialize_with_weight_registration(n: BlockNumberFor<T>) -> Weight {
535 let mut weight = Weight::zero();
536 for_tuples!( #(
537 let individual_weight = Tuple::on_initialize(n);
538
539 <frame_system::Pallet<T>>::register_extra_weight_unchecked(
540 individual_weight,
541 DispatchClass::Mandatory,
542 );
543
544 weight = weight.saturating_add(individual_weight);
545 )* );
546
547 weight
548 }
549 }
550}
551
552#[allow(deprecated)]
556impl<
557 System: frame_system::Config + IsInherent<Block::Extrinsic>,
558 Block: traits::Block<
559 Header = frame_system::pallet_prelude::HeaderFor<System>,
560 Hash = System::Hash,
561 >,
562 Context: Default,
563 UnsignedValidator,
564 AllPalletsWithSystem: OnRuntimeUpgrade
565 + BeforeAllRuntimeMigrations
566 + OnInitializeWithWeightRegistration<System>
567 + OnIdle<BlockNumberFor<System>>
568 + OnFinalize<BlockNumberFor<System>>
569 + OffchainWorker<BlockNumberFor<System>>
570 + OnPoll<BlockNumberFor<System>>,
571 COnRuntimeUpgrade: OnRuntimeUpgrade,
572 > Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
573where
574 Block::Extrinsic: Checkable<Context> + Codec,
575 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
576 CallOf<Block::Extrinsic, Context>:
577 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
578 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
579 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
580{
581 pub fn execute_on_runtime_upgrade() -> Weight {
583 let before_all_weight =
584 <AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
585
586 let runtime_upgrade_weight = <(
587 COnRuntimeUpgrade,
588 <System as frame_system::Config>::SingleBlockMigrations,
589 AllPalletsWithSystem,
592 ) as OnRuntimeUpgrade>::on_runtime_upgrade();
593
594 before_all_weight.saturating_add(runtime_upgrade_weight)
595 }
596
597 pub fn initialize_block(
599 header: &frame_system::pallet_prelude::HeaderFor<System>,
600 ) -> ExtrinsicInclusionMode {
601 sp_io::init_tracing();
602 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block");
603 let digests = Self::extract_pre_digest(header);
604 Self::initialize_block_impl(header.number(), header.parent_hash(), &digests);
605
606 Self::extrinsic_mode()
607 }
608
609 fn extrinsic_mode() -> ExtrinsicInclusionMode {
610 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
611 ExtrinsicInclusionMode::OnlyInherents
612 } else {
613 ExtrinsicInclusionMode::AllExtrinsics
614 }
615 }
616
617 fn extract_pre_digest(header: &frame_system::pallet_prelude::HeaderFor<System>) -> Digest {
618 let mut digest = <Digest>::default();
619 header.digest().logs().iter().for_each(|d| {
620 if d.as_pre_runtime().is_some() {
621 digest.push(d.clone())
622 }
623 });
624 digest
625 }
626
627 fn initialize_block_impl(
628 block_number: &BlockNumberFor<System>,
629 parent_hash: &System::Hash,
630 digest: &Digest,
631 ) {
632 <frame_system::Pallet<System>>::reset_events();
636
637 let mut weight = Weight::zero();
638 if Self::runtime_upgraded() {
639 weight = weight.saturating_add(Self::execute_on_runtime_upgrade());
640
641 frame_system::LastRuntimeUpgrade::<System>::put(
642 frame_system::LastRuntimeUpgradeInfo::from(
643 <System::Version as frame_support::traits::Get<_>>::get(),
644 ),
645 );
646 }
647 <frame_system::Pallet<System>>::initialize(block_number, parent_hash, digest);
648
649 weight = System::BlockWeights::get().base_block.saturating_add(weight);
650 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
652 weight,
653 DispatchClass::Mandatory,
654 );
655
656 weight = weight
657 .saturating_add(<AllPalletsWithSystem as OnInitializeWithWeightRegistration<
658 System,
659 >>::on_initialize_with_weight_registration(*block_number));
660
661 log::debug!(
662 target: LOG_TARGET,
663 "[{block_number:?}]: Block initialization weight consumption: {weight:?}",
664 );
665
666 frame_system::Pallet::<System>::note_finished_initialize();
667 <System as frame_system::Config>::PreInherents::pre_inherents();
668 }
669
670 fn runtime_upgraded() -> bool {
672 let last = frame_system::LastRuntimeUpgrade::<System>::get();
673 let current = <System::Version as frame_support::traits::Get<_>>::get();
674
675 last.map(|v| v.was_upgraded(¤t)).unwrap_or(true)
676 }
677
678 fn initial_checks(header: &Block::Header) {
679 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks");
680
681 let n = *header.number();
683 assert!(
684 n > BlockNumberFor::<System>::zero() &&
685 <frame_system::Pallet<System>>::block_hash(n - BlockNumberFor::<System>::one()) ==
686 *header.parent_hash(),
687 "Parent hash should be valid.",
688 );
689 }
690
691 pub fn execute_block(block: Block::LazyBlock) {
693 sp_io::init_tracing();
694 sp_tracing::within_span! {
695 sp_tracing::info_span!("execute_block", ?block);
696 let mode = Self::initialize_block(block.header());
698 Self::initial_checks(block.header());
699
700 let extrinsics = block.extrinsics();
701 if let Err(e) = Self::apply_extrinsics(
702 mode,
703 extrinsics,
704 |uxt, is_inherent| {
705 Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
706 }
707 ) {
708 panic!("{:?}", e)
709 }
710
711 if !<frame_system::Pallet<System>>::inherents_applied() {
713 Self::inherents_applied();
714 }
715
716 <frame_system::Pallet<System>>::note_finished_extrinsics();
717 <System as frame_system::Config>::PostTransactions::post_transactions();
718
719 let header = block.header();
720 Self::on_idle_hook(*header.number());
721 Self::on_finalize_hook(*header.number());
722 Self::final_checks(&header);
723 }
724 }
725
726 pub fn inherents_applied() {
730 <frame_system::Pallet<System>>::note_inherents_applied();
731 <System as frame_system::Config>::PostInherents::post_inherents();
732
733 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
734 let used_weight = <System as frame_system::Config>::MultiBlockMigrator::step();
735 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
736 used_weight,
737 DispatchClass::Mandatory,
738 );
739 } else {
740 let block_number = <frame_system::Pallet<System>>::block_number();
741 Self::on_poll_hook(block_number);
742 }
743 }
744
745 fn apply_extrinsics(
747 mode: ExtrinsicInclusionMode,
748 extrinsics: impl Iterator<Item = Result<Block::Extrinsic, codec::Error>>,
749 mut apply_extrinsic: impl FnMut(Block::Extrinsic, bool) -> ApplyExtrinsicResult,
750 ) -> Result<(), ExecutiveError> {
751 let mut first_non_inherent_idx = 0;
752 for (idx, maybe_uxt) in extrinsics.into_iter().enumerate() {
753 let uxt = maybe_uxt.map_err(|_| ExecutiveError::UnableToDecodeExtrinsic)?;
754 let is_inherent = System::is_inherent(&uxt);
755 if is_inherent {
756 if first_non_inherent_idx != idx {
758 return Err(ExecutiveError::InvalidInherentPosition(idx));
759 }
760 first_non_inherent_idx += 1;
761 } else {
762 if mode == ExtrinsicInclusionMode::OnlyInherents {
764 return Err(ExecutiveError::OnlyInherentsAllowed)
765 }
766 }
767
768 log::debug!(target: LOG_TARGET, "Executing transaction: {:?}", uxt);
769 if let Err(e) = apply_extrinsic(uxt, is_inherent) {
770 log::error!(
771 target: LOG_TARGET,
772 "Transaction({idx}) failed due to {e:?}. \
773 Aborting the rest of the block execution.",
774 );
775 return Err(ExecutiveError::ApplyExtrinsic(e.into()));
776 }
777 }
778
779 Ok(())
780 }
781
782 pub fn finalize_block() -> frame_system::pallet_prelude::HeaderFor<System> {
786 sp_io::init_tracing();
787 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "finalize_block");
788
789 if !<frame_system::Pallet<System>>::inherents_applied() {
791 Self::inherents_applied();
792 }
793
794 <frame_system::Pallet<System>>::note_finished_extrinsics();
795 <System as frame_system::Config>::PostTransactions::post_transactions();
796 let block_number = <frame_system::Pallet<System>>::block_number();
797 Self::on_idle_hook(block_number);
798 Self::on_finalize_hook(block_number);
799 <frame_system::Pallet<System>>::finalize()
800 }
801
802 fn on_idle_hook(block_number: NumberFor<Block>) {
805 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
806 return
807 }
808
809 let weight = <frame_system::Pallet<System>>::block_weight();
810 let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
811 let remaining_weight = max_weight.saturating_sub(weight.total());
812
813 if remaining_weight.all_gt(Weight::zero()) {
814 let used_weight = <AllPalletsWithSystem as OnIdle<BlockNumberFor<System>>>::on_idle(
815 block_number,
816 remaining_weight,
817 );
818 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
819 used_weight,
820 DispatchClass::Mandatory,
821 );
822 }
823 }
824
825 fn on_poll_hook(block_number: NumberFor<Block>) {
826 defensive_assert!(
827 !<System as frame_system::Config>::MultiBlockMigrator::ongoing(),
828 "on_poll should not be called during migrations"
829 );
830
831 let weight = <frame_system::Pallet<System>>::block_weight();
832 let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
833 let remaining = max_weight.saturating_sub(weight.total());
834
835 if remaining.all_gt(Weight::zero()) {
836 let mut meter = WeightMeter::with_limit(remaining);
837 <AllPalletsWithSystem as OnPoll<BlockNumberFor<System>>>::on_poll(
838 block_number,
839 &mut meter,
840 );
841 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
842 meter.consumed(),
843 DispatchClass::Mandatory,
844 );
845 }
846 }
847
848 fn on_finalize_hook(block_number: NumberFor<Block>) {
850 <AllPalletsWithSystem as OnFinalize<BlockNumberFor<System>>>::on_finalize(block_number);
851 }
852
853 fn do_apply_extrinsic(
858 uxt: Block::Extrinsic,
859 is_inherent: bool,
860 check: impl FnOnce(
861 Block::Extrinsic,
862 &Context,
863 ) -> Result<CheckedOf<Block::Extrinsic, Context>, TransactionValidityError>,
864 ) -> ApplyExtrinsicResult {
865 sp_io::init_tracing();
866 let encoded = uxt.encode();
867 let encoded_len = encoded.len();
868 sp_tracing::enter_span!(sp_tracing::info_span!("apply_extrinsic",
869 ext=?sp_core::hexdisplay::HexDisplay::from(&encoded)));
870
871 let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
872 MAX_EXTRINSIC_DEPTH,
873 &mut &encoded[..],
874 )
875 .map_err(|_| InvalidTransaction::Call)?;
876
877 let xt = check(uxt, &Context::default())?;
879
880 let dispatch_info = xt.get_dispatch_info();
881
882 if !is_inherent && !<frame_system::Pallet<System>>::inherents_applied() {
883 Self::inherents_applied();
884 }
885
886 <frame_system::Pallet<System>>::note_extrinsic(encoded);
890
891 let r = Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?;
894
895 if r.is_err() && dispatch_info.class == DispatchClass::Mandatory {
900 return Err(InvalidTransaction::BadMandatory.into())
901 }
902
903 <frame_system::Pallet<System>>::note_applied_extrinsic(&r, dispatch_info);
904
905 Ok(r.map(|_| ()).map_err(|e| e.error))
906 }
907
908 pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult {
913 let is_inherent = System::is_inherent(&uxt);
914 Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
915 }
916
917 fn final_checks(header: &frame_system::pallet_prelude::HeaderFor<System>) {
918 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "final_checks");
919 let new_header = <frame_system::Pallet<System>>::finalize();
921
922 assert_eq!(
924 header.digest().logs().len(),
925 new_header.digest().logs().len(),
926 "Number of digest items must match that calculated."
927 );
928 let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
929 for (header_item, computed_item) in items_zip {
930 header_item.check_equal(computed_item);
931 assert!(header_item == computed_item, "Digest item must match that calculated.");
932 }
933
934 let storage_root = new_header.state_root();
936 header.state_root().check_equal(storage_root);
937 assert!(header.state_root() == storage_root, "Storage root must match that calculated.");
938
939 assert!(
940 header.extrinsics_root() == new_header.extrinsics_root(),
941 "Transaction trie root must be valid.",
942 );
943 }
944
945 pub fn validate_transaction(
951 source: TransactionSource,
952 uxt: Block::Extrinsic,
953 block_hash: Block::Hash,
954 ) -> TransactionValidity {
955 sp_io::init_tracing();
956 use sp_tracing::{enter_span, within_span};
957
958 <frame_system::Pallet<System>>::initialize(
959 &(frame_system::Pallet::<System>::block_number() + One::one()),
960 &block_hash,
961 &Default::default(),
962 );
963
964 enter_span! { sp_tracing::Level::TRACE, "validate_transaction" };
965
966 let encoded = within_span! { sp_tracing::Level::TRACE, "using_encoded";
967 uxt.encode()
968 };
969
970 let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
971 MAX_EXTRINSIC_DEPTH,
972 &mut &encoded[..],
973 )
974 .map_err(|_| InvalidTransaction::Call)?;
975
976 let xt = within_span! { sp_tracing::Level::TRACE, "check";
977 uxt.check(&Default::default())
978 }?;
979
980 let dispatch_info = within_span! { sp_tracing::Level::TRACE, "dispatch_info";
981 xt.get_dispatch_info()
982 };
983
984 if dispatch_info.class == DispatchClass::Mandatory {
985 return Err(InvalidTransaction::MandatoryValidation.into())
986 }
987
988 within_span! {
989 sp_tracing::Level::TRACE, "validate";
990 xt.validate::<UnsignedValidator>(source, &dispatch_info, encoded.len())
991 }
992 }
993
994 pub fn offchain_worker(header: &frame_system::pallet_prelude::HeaderFor<System>) {
996 sp_io::init_tracing();
997 let digests = header.digest().clone();
1001
1002 let existing_digest = frame_system::Pallet::<System>::digest();
1004 for digest in digests.logs().iter().filter(|d| !existing_digest.logs.contains(d)) {
1005 frame_system::Pallet::<System>::deposit_log(digest.clone());
1006 }
1007
1008 frame_system::Pallet::<System>::initialize_intra_block_entropy(header.parent_hash());
1010
1011 frame_system::BlockHash::<System>::insert(header.number(), header.hash());
1015
1016 <AllPalletsWithSystem as OffchainWorker<BlockNumberFor<System>>>::offchain_worker(
1017 *header.number(),
1018 )
1019 }
1020}