1#![cfg_attr(not(feature = "std"), no_std)]
19
20#[cfg(doc)]
122#[cfg_attr(doc, aquamarine::aquamarine)]
123pub mod block_flowchart {}
150
151#[cfg(test)]
152mod tests;
153
154extern crate alloc;
155
156use codec::{Codec, Encode};
157use core::marker::PhantomData;
158use frame_support::{
159 defensive_assert,
160 dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo},
161 migrations::MultiStepMigrator,
162 pallet_prelude::InvalidTransaction,
163 traits::{
164 BeforeAllRuntimeMigrations, ExecuteBlock, IsInherent, OffchainWorker, OnFinalize, OnIdle,
165 OnInitialize, OnPoll, OnRuntimeUpgrade, PostInherents, PostTransactions, PreInherents,
166 },
167 weights::{Weight, WeightMeter},
168 MAX_EXTRINSIC_DEPTH,
169};
170use frame_system::pallet_prelude::BlockNumberFor;
171use sp_runtime::{
172 generic::Digest,
173 traits::{
174 self, Applyable, CheckEqual, Checkable, Dispatchable, Header, NumberFor, One,
175 ValidateUnsigned, Zero,
176 },
177 transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
178 ApplyExtrinsicResult, ExtrinsicInclusionMode,
179};
180
181#[cfg(feature = "try-runtime")]
182use ::{
183 frame_support::{
184 traits::{TryDecodeEntireStorage, TryDecodeEntireStorageError, TryState},
185 StorageNoopGuard,
186 },
187 frame_try_runtime::{TryStateSelect, UpgradeCheckSelect},
188 log,
189 sp_runtime::TryRuntimeError,
190};
191
192#[allow(dead_code)]
193const LOG_TARGET: &str = "runtime::executive";
194
195pub type CheckedOf<E, C> = <E as Checkable<C>>::Checked;
196pub type CallOf<E, C> = <CheckedOf<E, C> as Applyable>::Call;
197pub type OriginOf<E, C> = <CallOf<E, C> as Dispatchable>::RuntimeOrigin;
198
199#[derive(PartialEq)]
200pub enum ExecutiveError {
201 InvalidInherentPosition(usize),
202 OnlyInherentsAllowed,
203 ApplyExtrinsic(TransactionValidityError),
204 Custom(&'static str),
205}
206
207impl core::fmt::Debug for ExecutiveError {
208 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
209 match self {
210 ExecutiveError::InvalidInherentPosition(i) =>
211 write!(fmt, "Invalid inherent position for extrinsic at index {}", i),
212 ExecutiveError::OnlyInherentsAllowed =>
213 write!(fmt, "Only inherents are allowed in this block"),
214 ExecutiveError::ApplyExtrinsic(e) => write!(
215 fmt,
216 "ExecuteBlockError applying extrinsic: {}",
217 Into::<&'static str>::into(*e)
218 ),
219 ExecutiveError::Custom(err) => write!(fmt, "{err}"),
220 }
221 }
222}
223
224pub struct Executive<
236 System,
237 Block,
238 Context,
239 UnsignedValidator,
240 AllPalletsWithSystem,
241 OnRuntimeUpgrade = (),
242>(
243 PhantomData<(
244 System,
245 Block,
246 Context,
247 UnsignedValidator,
248 AllPalletsWithSystem,
249 OnRuntimeUpgrade,
250 )>,
251);
252
253impl<
254 System: frame_system::Config + IsInherent<Block::Extrinsic>,
255 Block: traits::Block<
256 Header = frame_system::pallet_prelude::HeaderFor<System>,
257 Hash = System::Hash,
258 >,
259 Context: Default,
260 UnsignedValidator,
261 AllPalletsWithSystem: OnRuntimeUpgrade
262 + BeforeAllRuntimeMigrations
263 + OnInitialize<BlockNumberFor<System>>
264 + OnIdle<BlockNumberFor<System>>
265 + OnFinalize<BlockNumberFor<System>>
266 + OffchainWorker<BlockNumberFor<System>>
267 + OnPoll<BlockNumberFor<System>>,
268 COnRuntimeUpgrade: OnRuntimeUpgrade,
269 > ExecuteBlock<Block>
270 for Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
271where
272 Block::Extrinsic: Checkable<Context> + Codec,
273 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
274 CallOf<Block::Extrinsic, Context>:
275 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
276 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
277 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
278{
279 fn execute_block(block: Block) {
280 Executive::<
281 System,
282 Block,
283 Context,
284 UnsignedValidator,
285 AllPalletsWithSystem,
286 COnRuntimeUpgrade,
287 >::execute_block(block);
288 }
289}
290
291#[cfg(feature = "try-runtime")]
292impl<
293 System: frame_system::Config + IsInherent<Block::Extrinsic>,
294 Block: traits::Block<
295 Header = frame_system::pallet_prelude::HeaderFor<System>,
296 Hash = System::Hash,
297 >,
298 Context: Default,
299 UnsignedValidator,
300 AllPalletsWithSystem: OnRuntimeUpgrade
301 + BeforeAllRuntimeMigrations
302 + OnInitialize<BlockNumberFor<System>>
303 + OnIdle<BlockNumberFor<System>>
304 + OnFinalize<BlockNumberFor<System>>
305 + OffchainWorker<BlockNumberFor<System>>
306 + OnPoll<BlockNumberFor<System>>
307 + TryState<BlockNumberFor<System>>
308 + TryDecodeEntireStorage,
309 COnRuntimeUpgrade: OnRuntimeUpgrade,
310 > Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
311where
312 Block::Extrinsic: Checkable<Context> + Codec,
313 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
314 CallOf<Block::Extrinsic, Context>:
315 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
316 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
317 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
318{
319 pub fn try_execute_block(
328 block: Block,
329 state_root_check: bool,
330 signature_check: bool,
331 select: frame_try_runtime::TryStateSelect,
332 ) -> Result<Weight, ExecutiveError> {
333 log::info!(
334 target: LOG_TARGET,
335 "try-runtime: executing block #{:?} / state root check: {:?} / signature check: {:?} / try-state-select: {:?}",
336 block.header().number(),
337 state_root_check,
338 signature_check,
339 select,
340 );
341
342 let mode = Self::initialize_block(block.header());
343 Self::initial_checks(&block);
344 let (header, extrinsics) = block.deconstruct();
345
346 let signature_check = if signature_check {
348 Block::Extrinsic::check
349 } else {
350 Block::Extrinsic::unchecked_into_checked_i_know_what_i_am_doing
351 };
352 Self::apply_extrinsics(mode, extrinsics.into_iter(), |uxt, is_inherent| {
353 Self::do_apply_extrinsic(uxt, is_inherent, signature_check)
354 })?;
355
356 if !<frame_system::Pallet<System>>::inherents_applied() {
358 Self::inherents_applied();
359 }
360
361 <frame_system::Pallet<System>>::note_finished_extrinsics();
363 <System as frame_system::Config>::PostTransactions::post_transactions();
364
365 Self::on_idle_hook(*header.number());
366 Self::on_finalize_hook(*header.number());
367
368 let _guard = frame_support::StorageNoopGuard::default();
370 <AllPalletsWithSystem as frame_support::traits::TryState<
371 BlockNumberFor<System>,
372 >>::try_state(*header.number(), select.clone())
373 .map_err(|e| {
374 log::error!(target: LOG_TARGET, "failure: {:?}", e);
375 ExecutiveError::Custom(e.into())
376 })?;
377 if select.any() {
378 let res = AllPalletsWithSystem::try_decode_entire_state();
379 Self::log_decode_result(res).map_err(|e| ExecutiveError::Custom(e.into()))?;
380 }
381 drop(_guard);
382
383 {
386 let new_header = <frame_system::Pallet<System>>::finalize();
387 let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
388 for (header_item, computed_item) in items_zip {
389 header_item.check_equal(computed_item);
390 assert!(header_item == computed_item, "Digest item must match that calculated.");
391 }
392
393 if state_root_check {
394 let storage_root = new_header.state_root();
395 header.state_root().check_equal(storage_root);
396 assert!(
397 header.state_root() == storage_root,
398 "Storage root must match that calculated."
399 );
400 }
401
402 assert!(
403 header.extrinsics_root() == new_header.extrinsics_root(),
404 "Transaction trie root must be valid.",
405 );
406 }
407
408 log::info!(
409 target: LOG_TARGET,
410 "try-runtime: Block #{:?} successfully executed",
411 header.number(),
412 );
413
414 Ok(frame_system::Pallet::<System>::block_weight().total())
415 }
416
417 pub fn try_runtime_upgrade(checks: UpgradeCheckSelect) -> Result<Weight, TryRuntimeError> {
425 let before_all_weight =
426 <AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
427
428 let try_on_runtime_upgrade_weight =
429 <(
430 COnRuntimeUpgrade,
431 <System as frame_system::Config>::SingleBlockMigrations,
432 AllPalletsWithSystem,
435 ) as OnRuntimeUpgrade>::try_on_runtime_upgrade(checks.pre_and_post())?;
436
437 frame_system::LastRuntimeUpgrade::<System>::put(
438 frame_system::LastRuntimeUpgradeInfo::from(
439 <System::Version as frame_support::traits::Get<_>>::get(),
440 ),
441 );
442
443 let _guard = StorageNoopGuard::default();
445
446 if checks.any() {
448 let res = AllPalletsWithSystem::try_decode_entire_state();
449 Self::log_decode_result(res)?;
450 }
451
452 if checks.try_state() {
454 AllPalletsWithSystem::try_state(
455 frame_system::Pallet::<System>::block_number(),
456 TryStateSelect::All,
457 )?;
458 }
459
460 Ok(before_all_weight.saturating_add(try_on_runtime_upgrade_weight))
461 }
462
463 fn log_decode_result(
465 res: Result<usize, alloc::vec::Vec<TryDecodeEntireStorageError>>,
466 ) -> Result<(), TryRuntimeError> {
467 match res {
468 Ok(bytes) => {
469 log::info!(
470 target: LOG_TARGET,
471 "✅ Entire runtime state decodes without error. {} bytes total.",
472 bytes
473 );
474
475 Ok(())
476 },
477 Err(errors) => {
478 log::error!(
479 target: LOG_TARGET,
480 "`try_decode_entire_state` failed with {} errors",
481 errors.len(),
482 );
483
484 for (i, err) in errors.iter().enumerate() {
485 log::error!(target: LOG_TARGET, "- {i}. error: {err}");
487 log::debug!(target: LOG_TARGET, "- {i}. error: {err:?}");
488 }
489
490 Err("`try_decode_entire_state` failed".into())
491 },
492 }
493 }
494}
495
496impl<
497 System: frame_system::Config + IsInherent<Block::Extrinsic>,
498 Block: traits::Block<
499 Header = frame_system::pallet_prelude::HeaderFor<System>,
500 Hash = System::Hash,
501 >,
502 Context: Default,
503 UnsignedValidator,
504 AllPalletsWithSystem: OnRuntimeUpgrade
505 + BeforeAllRuntimeMigrations
506 + OnInitialize<BlockNumberFor<System>>
507 + OnIdle<BlockNumberFor<System>>
508 + OnFinalize<BlockNumberFor<System>>
509 + OffchainWorker<BlockNumberFor<System>>
510 + OnPoll<BlockNumberFor<System>>,
511 COnRuntimeUpgrade: OnRuntimeUpgrade,
512 > Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
513where
514 Block::Extrinsic: Checkable<Context> + Codec,
515 CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
516 CallOf<Block::Extrinsic, Context>:
517 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
518 OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
519 UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
520{
521 pub fn execute_on_runtime_upgrade() -> Weight {
523 let before_all_weight =
524 <AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
525
526 let runtime_upgrade_weight = <(
527 COnRuntimeUpgrade,
528 <System as frame_system::Config>::SingleBlockMigrations,
529 AllPalletsWithSystem,
532 ) as OnRuntimeUpgrade>::on_runtime_upgrade();
533
534 before_all_weight.saturating_add(runtime_upgrade_weight)
535 }
536
537 pub fn initialize_block(
539 header: &frame_system::pallet_prelude::HeaderFor<System>,
540 ) -> ExtrinsicInclusionMode {
541 sp_io::init_tracing();
542 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block");
543 let digests = Self::extract_pre_digest(header);
544 Self::initialize_block_impl(header.number(), header.parent_hash(), &digests);
545
546 Self::extrinsic_mode()
547 }
548
549 fn extrinsic_mode() -> ExtrinsicInclusionMode {
550 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
551 ExtrinsicInclusionMode::OnlyInherents
552 } else {
553 ExtrinsicInclusionMode::AllExtrinsics
554 }
555 }
556
557 fn extract_pre_digest(header: &frame_system::pallet_prelude::HeaderFor<System>) -> Digest {
558 let mut digest = <Digest>::default();
559 header.digest().logs().iter().for_each(|d| {
560 if d.as_pre_runtime().is_some() {
561 digest.push(d.clone())
562 }
563 });
564 digest
565 }
566
567 fn initialize_block_impl(
568 block_number: &BlockNumberFor<System>,
569 parent_hash: &System::Hash,
570 digest: &Digest,
571 ) {
572 <frame_system::Pallet<System>>::reset_events();
576
577 let mut weight = Weight::zero();
578 if Self::runtime_upgraded() {
579 weight = weight.saturating_add(Self::execute_on_runtime_upgrade());
580
581 frame_system::LastRuntimeUpgrade::<System>::put(
582 frame_system::LastRuntimeUpgradeInfo::from(
583 <System::Version as frame_support::traits::Get<_>>::get(),
584 ),
585 );
586 }
587 <frame_system::Pallet<System>>::initialize(block_number, parent_hash, digest);
588 weight = weight.saturating_add(<AllPalletsWithSystem as OnInitialize<
589 BlockNumberFor<System>,
590 >>::on_initialize(*block_number));
591 weight = weight.saturating_add(
592 <System::BlockWeights as frame_support::traits::Get<_>>::get().base_block,
593 );
594 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
595 weight,
596 DispatchClass::Mandatory,
597 );
598
599 frame_system::Pallet::<System>::note_finished_initialize();
600 <System as frame_system::Config>::PreInherents::pre_inherents();
601 }
602
603 fn runtime_upgraded() -> bool {
605 let last = frame_system::LastRuntimeUpgrade::<System>::get();
606 let current = <System::Version as frame_support::traits::Get<_>>::get();
607
608 last.map(|v| v.was_upgraded(¤t)).unwrap_or(true)
609 }
610
611 fn initial_checks(block: &Block) {
612 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks");
613 let header = block.header();
614
615 let n = *header.number();
617 assert!(
618 n > BlockNumberFor::<System>::zero() &&
619 <frame_system::Pallet<System>>::block_hash(n - BlockNumberFor::<System>::one()) ==
620 *header.parent_hash(),
621 "Parent hash should be valid.",
622 );
623 }
624
625 pub fn execute_block(block: Block) {
627 sp_io::init_tracing();
628 sp_tracing::within_span! {
629 sp_tracing::info_span!("execute_block", ?block);
630 let mode = Self::initialize_block(block.header());
632 Self::initial_checks(&block);
633
634 let (header, extrinsics) = block.deconstruct();
635 if let Err(e) = Self::apply_extrinsics(
636 mode,
637 extrinsics.into_iter(),
638 |uxt, is_inherent| {
639 Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
640 }
641 ) {
642 panic!("{:?}", e)
643 }
644
645 if !<frame_system::Pallet<System>>::inherents_applied() {
647 Self::inherents_applied();
648 }
649
650 <frame_system::Pallet<System>>::note_finished_extrinsics();
651 <System as frame_system::Config>::PostTransactions::post_transactions();
652
653 Self::on_idle_hook(*header.number());
654 Self::on_finalize_hook(*header.number());
655 Self::final_checks(&header);
656 }
657 }
658
659 pub fn inherents_applied() {
663 <frame_system::Pallet<System>>::note_inherents_applied();
664 <System as frame_system::Config>::PostInherents::post_inherents();
665
666 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
667 let used_weight = <System as frame_system::Config>::MultiBlockMigrator::step();
668 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
669 used_weight,
670 DispatchClass::Mandatory,
671 );
672 } else {
673 let block_number = <frame_system::Pallet<System>>::block_number();
674 Self::on_poll_hook(block_number);
675 }
676 }
677
678 fn apply_extrinsics(
680 mode: ExtrinsicInclusionMode,
681 extrinsics: impl Iterator<Item = Block::Extrinsic>,
682 mut apply_extrinsic: impl FnMut(Block::Extrinsic, bool) -> ApplyExtrinsicResult,
683 ) -> Result<(), ExecutiveError> {
684 let mut first_non_inherent_idx = 0;
685 for (idx, uxt) in extrinsics.into_iter().enumerate() {
686 let is_inherent = System::is_inherent(&uxt);
687 if is_inherent {
688 if first_non_inherent_idx != idx {
690 return Err(ExecutiveError::InvalidInherentPosition(idx));
691 }
692 first_non_inherent_idx += 1;
693 } else {
694 if mode == ExtrinsicInclusionMode::OnlyInherents {
696 return Err(ExecutiveError::OnlyInherentsAllowed)
697 }
698 }
699
700 log::debug!(target: LOG_TARGET, "Executing transaction: {:?}", uxt);
701 if let Err(e) = apply_extrinsic(uxt, is_inherent) {
702 log::error!(
703 target: LOG_TARGET,
704 "Transaction({idx}) failed due to {e:?}. \
705 Aborting the rest of the block execution.",
706 );
707 return Err(ExecutiveError::ApplyExtrinsic(e.into()));
708 }
709 }
710
711 Ok(())
712 }
713
714 pub fn finalize_block() -> frame_system::pallet_prelude::HeaderFor<System> {
718 sp_io::init_tracing();
719 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "finalize_block");
720
721 if !<frame_system::Pallet<System>>::inherents_applied() {
723 Self::inherents_applied();
724 }
725
726 <frame_system::Pallet<System>>::note_finished_extrinsics();
727 <System as frame_system::Config>::PostTransactions::post_transactions();
728 let block_number = <frame_system::Pallet<System>>::block_number();
729 Self::on_idle_hook(block_number);
730 Self::on_finalize_hook(block_number);
731 <frame_system::Pallet<System>>::finalize()
732 }
733
734 fn on_idle_hook(block_number: NumberFor<Block>) {
737 if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
738 return
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_weight = max_weight.saturating_sub(weight.total());
744
745 if remaining_weight.all_gt(Weight::zero()) {
746 let used_weight = <AllPalletsWithSystem as OnIdle<BlockNumberFor<System>>>::on_idle(
747 block_number,
748 remaining_weight,
749 );
750 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
751 used_weight,
752 DispatchClass::Mandatory,
753 );
754 }
755 }
756
757 fn on_poll_hook(block_number: NumberFor<Block>) {
758 defensive_assert!(
759 !<System as frame_system::Config>::MultiBlockMigrator::ongoing(),
760 "on_poll should not be called during migrations"
761 );
762
763 let weight = <frame_system::Pallet<System>>::block_weight();
764 let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
765 let remaining = max_weight.saturating_sub(weight.total());
766
767 if remaining.all_gt(Weight::zero()) {
768 let mut meter = WeightMeter::with_limit(remaining);
769 <AllPalletsWithSystem as OnPoll<BlockNumberFor<System>>>::on_poll(
770 block_number,
771 &mut meter,
772 );
773 <frame_system::Pallet<System>>::register_extra_weight_unchecked(
774 meter.consumed(),
775 DispatchClass::Mandatory,
776 );
777 }
778 }
779
780 fn on_finalize_hook(block_number: NumberFor<Block>) {
782 <AllPalletsWithSystem as OnFinalize<BlockNumberFor<System>>>::on_finalize(block_number);
783 }
784
785 fn do_apply_extrinsic(
790 uxt: Block::Extrinsic,
791 is_inherent: bool,
792 check: impl FnOnce(
793 Block::Extrinsic,
794 &Context,
795 ) -> Result<CheckedOf<Block::Extrinsic, Context>, TransactionValidityError>,
796 ) -> ApplyExtrinsicResult {
797 sp_io::init_tracing();
798 let encoded = uxt.encode();
799 let encoded_len = encoded.len();
800 sp_tracing::enter_span!(sp_tracing::info_span!("apply_extrinsic",
801 ext=?sp_core::hexdisplay::HexDisplay::from(&encoded)));
802
803 let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
804 MAX_EXTRINSIC_DEPTH,
805 &mut &encoded[..],
806 )
807 .map_err(|_| InvalidTransaction::Call)?;
808
809 let xt = check(uxt, &Context::default())?;
811
812 let dispatch_info = xt.get_dispatch_info();
813
814 if !is_inherent && !<frame_system::Pallet<System>>::inherents_applied() {
815 Self::inherents_applied();
816 }
817
818 <frame_system::Pallet<System>>::note_extrinsic(encoded);
822
823 let r = Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?;
826
827 if r.is_err() && dispatch_info.class == DispatchClass::Mandatory {
832 return Err(InvalidTransaction::BadMandatory.into())
833 }
834
835 <frame_system::Pallet<System>>::note_applied_extrinsic(&r, dispatch_info);
836
837 Ok(r.map(|_| ()).map_err(|e| e.error))
838 }
839
840 pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult {
845 let is_inherent = System::is_inherent(&uxt);
846 Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
847 }
848
849 fn final_checks(header: &frame_system::pallet_prelude::HeaderFor<System>) {
850 sp_tracing::enter_span!(sp_tracing::Level::TRACE, "final_checks");
851 let new_header = <frame_system::Pallet<System>>::finalize();
853
854 assert_eq!(
856 header.digest().logs().len(),
857 new_header.digest().logs().len(),
858 "Number of digest items must match that calculated."
859 );
860 let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
861 for (header_item, computed_item) in items_zip {
862 header_item.check_equal(computed_item);
863 assert!(header_item == computed_item, "Digest item must match that calculated.");
864 }
865
866 let storage_root = new_header.state_root();
868 header.state_root().check_equal(storage_root);
869 assert!(header.state_root() == storage_root, "Storage root must match that calculated.");
870
871 assert!(
872 header.extrinsics_root() == new_header.extrinsics_root(),
873 "Transaction trie root must be valid.",
874 );
875 }
876
877 pub fn validate_transaction(
883 source: TransactionSource,
884 uxt: Block::Extrinsic,
885 block_hash: Block::Hash,
886 ) -> TransactionValidity {
887 sp_io::init_tracing();
888 use sp_tracing::{enter_span, within_span};
889
890 <frame_system::Pallet<System>>::initialize(
891 &(frame_system::Pallet::<System>::block_number() + One::one()),
892 &block_hash,
893 &Default::default(),
894 );
895
896 enter_span! { sp_tracing::Level::TRACE, "validate_transaction" };
897
898 let encoded = within_span! { sp_tracing::Level::TRACE, "using_encoded";
899 uxt.encode()
900 };
901
902 let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
903 MAX_EXTRINSIC_DEPTH,
904 &mut &encoded[..],
905 )
906 .map_err(|_| InvalidTransaction::Call)?;
907
908 let xt = within_span! { sp_tracing::Level::TRACE, "check";
909 uxt.check(&Default::default())
910 }?;
911
912 let dispatch_info = within_span! { sp_tracing::Level::TRACE, "dispatch_info";
913 xt.get_dispatch_info()
914 };
915
916 if dispatch_info.class == DispatchClass::Mandatory {
917 return Err(InvalidTransaction::MandatoryValidation.into())
918 }
919
920 within_span! {
921 sp_tracing::Level::TRACE, "validate";
922 xt.validate::<UnsignedValidator>(source, &dispatch_info, encoded.len())
923 }
924 }
925
926 pub fn offchain_worker(header: &frame_system::pallet_prelude::HeaderFor<System>) {
928 sp_io::init_tracing();
929 let digests = header.digest().clone();
933
934 <frame_system::Pallet<System>>::initialize(header.number(), header.parent_hash(), &digests);
935
936 frame_system::BlockHash::<System>::insert(header.number(), header.hash());
940
941 <AllPalletsWithSystem as OffchainWorker<BlockNumberFor<System>>>::offchain_worker(
942 *header.number(),
943 )
944 }
945}