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