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, IsInherent, OffchainWorker, OnFinalize, OnIdle,
127 OnInitialize, OnPoll, OnRuntimeUpgrade, PostInherents, PostTransactions, PreInherents,
128 },
129 weights::{Weight, WeightMeter},
130 MAX_EXTRINSIC_DEPTH,
131};
132use frame_system::pallet_prelude::BlockNumberFor;
133use sp_runtime::{
134 generic::Digest,
135 traits::{
136 self, Applyable, CheckEqual, Checkable, Dispatchable, Header, NumberFor, One,
137 ValidateUnsigned, Zero,
138 },
139 transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
140 ApplyExtrinsicResult, ExtrinsicInclusionMode,
141};
142
143#[cfg(feature = "try-runtime")]
144use ::{
145 frame_support::{
146 traits::{TryDecodeEntireStorage, TryDecodeEntireStorageError, TryState},
147 StorageNoopGuard,
148 },
149 frame_try_runtime::{TryStateSelect, UpgradeCheckSelect},
150 log,
151 sp_runtime::TryRuntimeError,
152};
153
154#[allow(dead_code)]
155const LOG_TARGET: &str = "runtime::executive";
156
157pub type CheckedOf<E, C> = <E as Checkable<C>>::Checked;
158pub type CallOf<E, C> = <CheckedOf<E, C> as Applyable>::Call;
159pub type OriginOf<E, C> = <CallOf<E, C> as Dispatchable>::RuntimeOrigin;
160
161#[derive(PartialEq)]
162pub enum ExecutiveError {
163 InvalidInherentPosition(usize),
164 OnlyInherentsAllowed,
165 ApplyExtrinsic(TransactionValidityError),
166 Custom(&'static str),
167}
168
169impl core::fmt::Debug for ExecutiveError {
170 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
171 match self {
172 ExecutiveError::InvalidInherentPosition(i) =>
173 write!(fmt, "Invalid inherent position for extrinsic at index {}", i),
174 ExecutiveError::OnlyInherentsAllowed =>
175 write!(fmt, "Only inherents are allowed in this block"),
176 ExecutiveError::ApplyExtrinsic(e) => write!(
177 fmt,
178 "ExecuteBlockError applying extrinsic: {}",
179 Into::<&'static str>::into(*e)
180 ),
181 ExecutiveError::Custom(err) => write!(fmt, "{err}"),
182 }
183 }
184}
185
186#[allow(deprecated)]
198pub struct Executive<
199 System,
200 Block,
201 Context,
202 UnsignedValidator,
203 AllPalletsWithSystem,
204 #[deprecated(
205 note = "`OnRuntimeUpgrade` parameter in Executive is deprecated, will be removed after September 2026. \
206 Use type `SingleBlockMigrations` in frame_system::Config instead."
207 )] OnRuntimeUpgrade = (),
208>(
209 PhantomData<(
210 System,
211 Block,
212 Context,
213 UnsignedValidator,
214 AllPalletsWithSystem,
215 OnRuntimeUpgrade,
216 )>,
217);
218
219#[allow(deprecated)]
223impl<
224 System: frame_system::Config + IsInherent<Block::Extrinsic>,
225 Block: traits::Block<
226 Header = frame_system::pallet_prelude::HeaderFor<System>,
227 Hash = System::Hash,
228 >,
229 Context: Default,
230 UnsignedValidator,
231 AllPalletsWithSystem: OnRuntimeUpgrade
232 + BeforeAllRuntimeMigrations
233 + OnInitialize<BlockNumberFor<System>>
234 + OnIdle<BlockNumberFor<System>>
235 + OnFinalize<BlockNumberFor<System>>
236 + OffchainWorker<BlockNumberFor<System>>
237 + OnPoll<BlockNumberFor<System>>,
238 COnRuntimeUpgrade: OnRuntimeUpgrade,
239 > ExecuteBlock<Block>
240 for Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
241where
242 Block::Extrinsic: Checkable<Context> + Codec,
243 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
244 CallOf<Block::Extrinsic, Context>:
245 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
246 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
247 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
248{
249 fn execute_block(block: Block) {
250 Executive::<
251 System,
252 Block,
253 Context,
254 UnsignedValidator,
255 AllPalletsWithSystem,
256 COnRuntimeUpgrade,
257 >::execute_block(block);
258 }
259}
260
261#[allow(deprecated)]
265#[cfg(feature = "try-runtime")]
266impl<
267 System: frame_system::Config + IsInherent<Block::Extrinsic>,
268 Block: traits::Block<
269 Header = frame_system::pallet_prelude::HeaderFor<System>,
270 Hash = System::Hash,
271 >,
272 Context: Default,
273 UnsignedValidator,
274 AllPalletsWithSystem: OnRuntimeUpgrade
275 + BeforeAllRuntimeMigrations
276 + OnInitialize<BlockNumberFor<System>>
277 + OnIdle<BlockNumberFor<System>>
278 + OnFinalize<BlockNumberFor<System>>
279 + OffchainWorker<BlockNumberFor<System>>
280 + OnPoll<BlockNumberFor<System>>
281 + TryState<BlockNumberFor<System>>
282 + TryDecodeEntireStorage,
283 COnRuntimeUpgrade: OnRuntimeUpgrade,
284 > Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
285where
286 Block::Extrinsic: Checkable<Context> + Codec,
287 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
288 CallOf<Block::Extrinsic, Context>:
289 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
290 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
291 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
292{
293 pub fn try_execute_block(
302 block: Block,
303 state_root_check: bool,
304 signature_check: bool,
305 select: frame_try_runtime::TryStateSelect,
306 ) -> Result<Weight, ExecutiveError> {
307 log::info!(
308 target: LOG_TARGET,
309 "try-runtime: executing block #{:?} / state root check: {:?} / signature check: {:?} / try-state-select: {:?}",
310 block.header().number(),
311 state_root_check,
312 signature_check,
313 select,
314 );
315
316 let mode = Self::initialize_block(block.header());
317 Self::initial_checks(&block);
318 let (header, extrinsics) = block.deconstruct();
319
320 let signature_check = if signature_check {
322 Block::Extrinsic::check
323 } else {
324 Block::Extrinsic::unchecked_into_checked_i_know_what_i_am_doing
325 };
326 Self::apply_extrinsics(mode, extrinsics.into_iter(), |uxt, is_inherent| {
327 Self::do_apply_extrinsic(uxt, is_inherent, signature_check)
328 })?;
329
330 if !<frame_system::Pallet<System>>::inherents_applied() {
332 Self::inherents_applied();
333 }
334
335 <frame_system::Pallet<System>>::note_finished_extrinsics();
337 <System as frame_system::Config>::PostTransactions::post_transactions();
338
339 Self::on_idle_hook(*header.number());
340 Self::on_finalize_hook(*header.number());
341
342 let _guard = frame_support::StorageNoopGuard::default();
344 <AllPalletsWithSystem as frame_support::traits::TryState<
345 BlockNumberFor<System>,
346 >>::try_state(*header.number(), select.clone())
347 .map_err(|e| {
348 log::error!(target: LOG_TARGET, "failure: {:?}", e);
349 ExecutiveError::Custom(e.into())
350 })?;
351 if select.any() {
352 let res = AllPalletsWithSystem::try_decode_entire_state();
353 Self::log_decode_result(res).map_err(|e| ExecutiveError::Custom(e.into()))?;
354 }
355 drop(_guard);
356
357 {
360 let new_header = <frame_system::Pallet<System>>::finalize();
361 let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
362 for (header_item, computed_item) in items_zip {
363 header_item.check_equal(computed_item);
364 assert!(header_item == computed_item, "Digest item must match that calculated.");
365 }
366
367 if state_root_check {
368 let storage_root = new_header.state_root();
369 header.state_root().check_equal(storage_root);
370 assert!(
371 header.state_root() == storage_root,
372 "Storage root must match that calculated."
373 );
374 }
375
376 assert!(
377 header.extrinsics_root() == new_header.extrinsics_root(),
378 "Transaction trie root must be valid.",
379 );
380 }
381
382 log::info!(
383 target: LOG_TARGET,
384 "try-runtime: Block #{:?} successfully executed",
385 header.number(),
386 );
387
388 Ok(frame_system::Pallet::<System>::block_weight().total())
389 }
390
391 pub fn try_runtime_upgrade(checks: UpgradeCheckSelect) -> Result<Weight, TryRuntimeError> {
399 let before_all_weight =
400 <AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
401
402 let try_on_runtime_upgrade_weight =
403 <(
404 COnRuntimeUpgrade,
405 <System as frame_system::Config>::SingleBlockMigrations,
406 AllPalletsWithSystem,
409 ) as OnRuntimeUpgrade>::try_on_runtime_upgrade(checks.pre_and_post())?;
410
411 frame_system::LastRuntimeUpgrade::<System>::put(
412 frame_system::LastRuntimeUpgradeInfo::from(
413 <System::Version as frame_support::traits::Get<_>>::get(),
414 ),
415 );
416
417 let _guard = StorageNoopGuard::default();
419
420 if checks.any() {
422 let res = AllPalletsWithSystem::try_decode_entire_state();
423 Self::log_decode_result(res)?;
424 }
425
426 if checks.try_state() {
428 AllPalletsWithSystem::try_state(
429 frame_system::Pallet::<System>::block_number(),
430 TryStateSelect::All,
431 )?;
432 }
433
434 Ok(before_all_weight.saturating_add(try_on_runtime_upgrade_weight))
435 }
436
437 fn log_decode_result(
439 res: Result<usize, alloc::vec::Vec<TryDecodeEntireStorageError>>,
440 ) -> Result<(), TryRuntimeError> {
441 match res {
442 Ok(bytes) => {
443 log::info!(
444 target: LOG_TARGET,
445 "✅ Entire runtime state decodes without error. {} bytes total.",
446 bytes
447 );
448
449 Ok(())
450 },
451 Err(errors) => {
452 log::error!(
453 target: LOG_TARGET,
454 "`try_decode_entire_state` failed with {} errors",
455 errors.len(),
456 );
457
458 for (i, err) in errors.iter().enumerate() {
459 log::error!(target: LOG_TARGET, "- {i}. error: {err}");
461 log::debug!(target: LOG_TARGET, "- {i}. error: {err:?}");
462 }
463
464 Err("`try_decode_entire_state` failed".into())
465 },
466 }
467 }
468}
469
470#[allow(deprecated)]
474impl<
475 System: frame_system::Config + IsInherent<Block::Extrinsic>,
476 Block: traits::Block<
477 Header = frame_system::pallet_prelude::HeaderFor<System>,
478 Hash = System::Hash,
479 >,
480 Context: Default,
481 UnsignedValidator,
482 AllPalletsWithSystem: OnRuntimeUpgrade
483 + BeforeAllRuntimeMigrations
484 + OnInitialize<BlockNumberFor<System>>
485 + OnIdle<BlockNumberFor<System>>
486 + OnFinalize<BlockNumberFor<System>>
487 + OffchainWorker<BlockNumberFor<System>>
488 + OnPoll<BlockNumberFor<System>>,
489 COnRuntimeUpgrade: OnRuntimeUpgrade,
490 > Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
491where
492 Block::Extrinsic: Checkable<Context> + Codec,
493 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
494 CallOf<Block::Extrinsic, Context>:
495 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
496 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
497 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
498{
499 pub fn execute_on_runtime_upgrade() -> Weight {
501 let before_all_weight =
502 <AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
503
504 let runtime_upgrade_weight = <(
505 COnRuntimeUpgrade,
506 <System as frame_system::Config>::SingleBlockMigrations,
507 AllPalletsWithSystem,
510 ) as OnRuntimeUpgrade>::on_runtime_upgrade();
511
512 before_all_weight.saturating_add(runtime_upgrade_weight)
513 }
514
515 pub fn initialize_block(
517 header: &frame_system::pallet_prelude::HeaderFor<System>,
518 ) -> ExtrinsicInclusionMode {
519 sp_io::init_tracing();
520 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block");
521 let digests = Self::extract_pre_digest(header);
522 Self::initialize_block_impl(header.number(), header.parent_hash(), &digests);
523
524 Self::extrinsic_mode()
525 }
526
527 fn extrinsic_mode() -> ExtrinsicInclusionMode {
528 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
529 ExtrinsicInclusionMode::OnlyInherents
530 } else {
531 ExtrinsicInclusionMode::AllExtrinsics
532 }
533 }
534
535 fn extract_pre_digest(header: &frame_system::pallet_prelude::HeaderFor<System>) -> Digest {
536 let mut digest = <Digest>::default();
537 header.digest().logs().iter().for_each(|d| {
538 if d.as_pre_runtime().is_some() {
539 digest.push(d.clone())
540 }
541 });
542 digest
543 }
544
545 fn initialize_block_impl(
546 block_number: &BlockNumberFor<System>,
547 parent_hash: &System::Hash,
548 digest: &Digest,
549 ) {
550 <frame_system::Pallet<System>>::reset_events();
554
555 let mut weight = Weight::zero();
556 if Self::runtime_upgraded() {
557 weight = weight.saturating_add(Self::execute_on_runtime_upgrade());
558
559 frame_system::LastRuntimeUpgrade::<System>::put(
560 frame_system::LastRuntimeUpgradeInfo::from(
561 <System::Version as frame_support::traits::Get<_>>::get(),
562 ),
563 );
564 }
565 <frame_system::Pallet<System>>::initialize(block_number, parent_hash, digest);
566 weight = weight.saturating_add(<AllPalletsWithSystem as OnInitialize<
567 BlockNumberFor<System>,
568 >>::on_initialize(*block_number));
569 weight = weight.saturating_add(
570 <System::BlockWeights as frame_support::traits::Get<_>>::get().base_block,
571 );
572 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
573 weight,
574 DispatchClass::Mandatory,
575 );
576
577 frame_system::Pallet::<System>::note_finished_initialize();
578 <System as frame_system::Config>::PreInherents::pre_inherents();
579 }
580
581 fn runtime_upgraded() -> bool {
583 let last = frame_system::LastRuntimeUpgrade::<System>::get();
584 let current = <System::Version as frame_support::traits::Get<_>>::get();
585
586 last.map(|v| v.was_upgraded(¤t)).unwrap_or(true)
587 }
588
589 fn initial_checks(block: &Block) {
590 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks");
591 let header = block.header();
592
593 let n = *header.number();
595 assert!(
596 n > BlockNumberFor::<System>::zero() &&
597 <frame_system::Pallet<System>>::block_hash(n - BlockNumberFor::<System>::one()) ==
598 *header.parent_hash(),
599 "Parent hash should be valid.",
600 );
601 }
602
603 pub fn execute_block(block: Block) {
605 sp_io::init_tracing();
606 sp_tracing::within_span! {
607 sp_tracing::info_span!("execute_block", ?block);
608 let mode = Self::initialize_block(block.header());
610 Self::initial_checks(&block);
611
612 let (header, extrinsics) = block.deconstruct();
613 if let Err(e) = Self::apply_extrinsics(
614 mode,
615 extrinsics.into_iter(),
616 |uxt, is_inherent| {
617 Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
618 }
619 ) {
620 panic!("{:?}", e)
621 }
622
623 if !<frame_system::Pallet<System>>::inherents_applied() {
625 Self::inherents_applied();
626 }
627
628 <frame_system::Pallet<System>>::note_finished_extrinsics();
629 <System as frame_system::Config>::PostTransactions::post_transactions();
630
631 Self::on_idle_hook(*header.number());
632 Self::on_finalize_hook(*header.number());
633 Self::final_checks(&header);
634 }
635 }
636
637 pub fn inherents_applied() {
641 <frame_system::Pallet<System>>::note_inherents_applied();
642 <System as frame_system::Config>::PostInherents::post_inherents();
643
644 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
645 let used_weight = <System as frame_system::Config>::MultiBlockMigrator::step();
646 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
647 used_weight,
648 DispatchClass::Mandatory,
649 );
650 } else {
651 let block_number = <frame_system::Pallet<System>>::block_number();
652 Self::on_poll_hook(block_number);
653 }
654 }
655
656 fn apply_extrinsics(
658 mode: ExtrinsicInclusionMode,
659 extrinsics: impl Iterator<Item = Block::Extrinsic>,
660 mut apply_extrinsic: impl FnMut(Block::Extrinsic, bool) -> ApplyExtrinsicResult,
661 ) -> Result<(), ExecutiveError> {
662 let mut first_non_inherent_idx = 0;
663 for (idx, uxt) in extrinsics.into_iter().enumerate() {
664 let is_inherent = System::is_inherent(&uxt);
665 if is_inherent {
666 if first_non_inherent_idx != idx {
668 return Err(ExecutiveError::InvalidInherentPosition(idx));
669 }
670 first_non_inherent_idx += 1;
671 } else {
672 if mode == ExtrinsicInclusionMode::OnlyInherents {
674 return Err(ExecutiveError::OnlyInherentsAllowed)
675 }
676 }
677
678 log::debug!(target: LOG_TARGET, "Executing transaction: {:?}", uxt);
679 if let Err(e) = apply_extrinsic(uxt, is_inherent) {
680 log::error!(
681 target: LOG_TARGET,
682 "Transaction({idx}) failed due to {e:?}. \
683 Aborting the rest of the block execution.",
684 );
685 return Err(ExecutiveError::ApplyExtrinsic(e.into()));
686 }
687 }
688
689 Ok(())
690 }
691
692 pub fn finalize_block() -> frame_system::pallet_prelude::HeaderFor<System> {
696 sp_io::init_tracing();
697 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "finalize_block");
698
699 if !<frame_system::Pallet<System>>::inherents_applied() {
701 Self::inherents_applied();
702 }
703
704 <frame_system::Pallet<System>>::note_finished_extrinsics();
705 <System as frame_system::Config>::PostTransactions::post_transactions();
706 let block_number = <frame_system::Pallet<System>>::block_number();
707 Self::on_idle_hook(block_number);
708 Self::on_finalize_hook(block_number);
709 <frame_system::Pallet<System>>::finalize()
710 }
711
712 fn on_idle_hook(block_number: NumberFor<Block>) {
715 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
716 return
717 }
718
719 let weight = <frame_system::Pallet<System>>::block_weight();
720 let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
721 let remaining_weight = max_weight.saturating_sub(weight.total());
722
723 if remaining_weight.all_gt(Weight::zero()) {
724 let used_weight = <AllPalletsWithSystem as OnIdle<BlockNumberFor<System>>>::on_idle(
725 block_number,
726 remaining_weight,
727 );
728 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
729 used_weight,
730 DispatchClass::Mandatory,
731 );
732 }
733 }
734
735 fn on_poll_hook(block_number: NumberFor<Block>) {
736 defensive_assert!(
737 !<System as frame_system::Config>::MultiBlockMigrator::ongoing(),
738 "on_poll should not be called during migrations"
739 );
740
741 let weight = <frame_system::Pallet<System>>::block_weight();
742 let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
743 let remaining = max_weight.saturating_sub(weight.total());
744
745 if remaining.all_gt(Weight::zero()) {
746 let mut meter = WeightMeter::with_limit(remaining);
747 <AllPalletsWithSystem as OnPoll<BlockNumberFor<System>>>::on_poll(
748 block_number,
749 &mut meter,
750 );
751 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
752 meter.consumed(),
753 DispatchClass::Mandatory,
754 );
755 }
756 }
757
758 fn on_finalize_hook(block_number: NumberFor<Block>) {
760 <AllPalletsWithSystem as OnFinalize<BlockNumberFor<System>>>::on_finalize(block_number);
761 }
762
763 fn do_apply_extrinsic(
768 uxt: Block::Extrinsic,
769 is_inherent: bool,
770 check: impl FnOnce(
771 Block::Extrinsic,
772 &Context,
773 ) -> Result<CheckedOf<Block::Extrinsic, Context>, TransactionValidityError>,
774 ) -> ApplyExtrinsicResult {
775 sp_io::init_tracing();
776 let encoded = uxt.encode();
777 let encoded_len = encoded.len();
778 sp_tracing::enter_span!(sp_tracing::info_span!("apply_extrinsic",
779 ext=?sp_core::hexdisplay::HexDisplay::from(&encoded)));
780
781 let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
782 MAX_EXTRINSIC_DEPTH,
783 &mut &encoded[..],
784 )
785 .map_err(|_| InvalidTransaction::Call)?;
786
787 let xt = check(uxt, &Context::default())?;
789
790 let dispatch_info = xt.get_dispatch_info();
791
792 if !is_inherent && !<frame_system::Pallet<System>>::inherents_applied() {
793 Self::inherents_applied();
794 }
795
796 <frame_system::Pallet<System>>::note_extrinsic(encoded);
800
801 let r = Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?;
804
805 if r.is_err() && dispatch_info.class == DispatchClass::Mandatory {
810 return Err(InvalidTransaction::BadMandatory.into())
811 }
812
813 <frame_system::Pallet<System>>::note_applied_extrinsic(&r, dispatch_info);
814
815 Ok(r.map(|_| ()).map_err(|e| e.error))
816 }
817
818 pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult {
823 let is_inherent = System::is_inherent(&uxt);
824 Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
825 }
826
827 fn final_checks(header: &frame_system::pallet_prelude::HeaderFor<System>) {
828 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "final_checks");
829 let new_header = <frame_system::Pallet<System>>::finalize();
831
832 assert_eq!(
834 header.digest().logs().len(),
835 new_header.digest().logs().len(),
836 "Number of digest items must match that calculated."
837 );
838 let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
839 for (header_item, computed_item) in items_zip {
840 header_item.check_equal(computed_item);
841 assert!(header_item == computed_item, "Digest item must match that calculated.");
842 }
843
844 let storage_root = new_header.state_root();
846 header.state_root().check_equal(storage_root);
847 assert!(header.state_root() == storage_root, "Storage root must match that calculated.");
848
849 assert!(
850 header.extrinsics_root() == new_header.extrinsics_root(),
851 "Transaction trie root must be valid.",
852 );
853 }
854
855 pub fn validate_transaction(
861 source: TransactionSource,
862 uxt: Block::Extrinsic,
863 block_hash: Block::Hash,
864 ) -> TransactionValidity {
865 sp_io::init_tracing();
866 use sp_tracing::{enter_span, within_span};
867
868 <frame_system::Pallet<System>>::initialize(
869 &(frame_system::Pallet::<System>::block_number() + One::one()),
870 &block_hash,
871 &Default::default(),
872 );
873
874 enter_span! { sp_tracing::Level::TRACE, "validate_transaction" };
875
876 let encoded = within_span! { sp_tracing::Level::TRACE, "using_encoded";
877 uxt.encode()
878 };
879
880 let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
881 MAX_EXTRINSIC_DEPTH,
882 &mut &encoded[..],
883 )
884 .map_err(|_| InvalidTransaction::Call)?;
885
886 let xt = within_span! { sp_tracing::Level::TRACE, "check";
887 uxt.check(&Default::default())
888 }?;
889
890 let dispatch_info = within_span! { sp_tracing::Level::TRACE, "dispatch_info";
891 xt.get_dispatch_info()
892 };
893
894 if dispatch_info.class == DispatchClass::Mandatory {
895 return Err(InvalidTransaction::MandatoryValidation.into())
896 }
897
898 within_span! {
899 sp_tracing::Level::TRACE, "validate";
900 xt.validate::<UnsignedValidator>(source, &dispatch_info, encoded.len())
901 }
902 }
903
904 pub fn offchain_worker(header: &frame_system::pallet_prelude::HeaderFor<System>) {
906 sp_io::init_tracing();
907 let digests = header.digest().clone();
911
912 <frame_system::Pallet<System>>::initialize(header.number(), header.parent_hash(), &digests);
913
914 frame_system::BlockHash::<System>::insert(header.number(), header.hash());
918
919 <AllPalletsWithSystem as OffchainWorker<BlockNumberFor<System>>>::offchain_worker(
920 *header.number(),
921 )
922 }
923}