Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 55 additions & 17 deletions srml/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,45 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

//! Executive: Handles all of the top-level stuff; essentially just executing blocks/extrinsics.
//! # Executive Module
//!
//! The Executive module acts as the orchestration layer for the runtime. It dispatches incoming
//! extrinsic calls to the respective modules in the runtime.
//!
//! ## Overview
//!
//! The executive module is not a typical SRML module providing functionality around a specific feature.
//! It is a cross-cutting framework component for the SRML. It works in conjunction with the
//! [SRML System module](../srml_system/index.html) to perform these cross-cutting functions.
//!
//! The Executive module provides functions to:
//!
//! - Check transaction validity.
//! - Initialize a block.
//! - Apply extrinsics.
//! - Execute a block.
//! - Finalize a block.
//! - Start an off-chain worker.
//!
//! ### Implementations
//!
//! The Executive module provides the following implementations:
//!
//! - `ExecuteBlock`: Trait that can be used to execute a block.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this section? I think we decided not to mention implementation details in this section of the docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really describing the logic. I see it as, "avoid coupling with this module if these traits have what you need." Since executive in particular doesn't have a decl_module! or impl Module, then maybe it's not necessary at all.

//! - `Executive`: Type that can be used to make the SRML available from the runtime.
//!
//! ## Usage
//!
//! The default Substrate node template declares the [`Executive`](./struct.Executive.html) type in its library.
//!
//! ### Example
//!
//! `Executive` type declaration from the node template.
//!
//! ```ignore
//! /// Executive: handles dispatch to the various modules.
//! pub type Executive = executive::Executive<Runtime, Block, Context, Balances, AllModules>;
//! ```

#![cfg_attr(not(feature = "std"), no_std)]

Expand Down Expand Up @@ -48,9 +86,9 @@ mod internal {
}
}

/// Something that can be used to execute a block.
/// Trait that can be used to execute a block.
pub trait ExecuteBlock<Block: BlockT> {
/// Actually execute all transitioning for `block`.
/// Actually execute all transitions for `block`.
fn execute_block(block: Block);
}

Expand Down Expand Up @@ -100,20 +138,20 @@ impl<
fn initial_checks(block: &Block) {
let header = block.header();

// check parent_hash is correct.
// Check that `parent_hash` is correct.
let n = header.number().clone();
assert!(
n > System::BlockNumber::zero() && <system::Module<System>>::block_hash(n - System::BlockNumber::one()) == *header.parent_hash(),
"Parent hash should be valid."
);

// check transaction trie root represents the transactions.
// Check that transaction trie root represents the transactions.
let xts_root = extrinsics_root::<System::Hashing, _>(&block.extrinsics());
header.extrinsics_root().check_equal(&xts_root);
assert!(header.extrinsics_root() == &xts_root, "Transaction trie root must be valid.");
}

/// Actually execute all transitioning for `block`.
/// Actually execute all transitions for `block`.
pub fn execute_block(block: Block) {
Self::initialize_block(block.header());

Expand All @@ -128,11 +166,11 @@ impl<
Self::final_checks(&header);
}

/// Execute given extrinsics and take care of post-extrinsics book-keeping
/// Execute given extrinsics and take care of post-extrinsics book-keeping.
fn execute_extrinsics_with_book_keeping(extrinsics: Vec<Block::Extrinsic>, block_number: NumberFor<Block>) {
extrinsics.into_iter().for_each(Self::apply_extrinsic_no_note);

// post-extrinsics book-keeping.
// post-extrinsics book-keeping
<system::Module<System>>::note_finished_extrinsics();
<AllModules as OnFinalize<System::BlockNumber>>::on_finalize(block_number);
}
Expand All @@ -143,7 +181,7 @@ impl<
<system::Module<System>>::note_finished_extrinsics();
<AllModules as OnFinalize<System::BlockNumber>>::on_finalize(<system::Module<System>>::block_number());

// setup extrinsics
// set up extrinsics
<system::Module<System>>::derive_extrinsics();
<system::Module<System>>::finalize()
}
Expand Down Expand Up @@ -180,7 +218,7 @@ impl<

/// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash.
fn apply_extrinsic_with_len(uxt: Block::Extrinsic, encoded_len: usize, to_note: Option<Vec<u8>>) -> result::Result<internal::ApplyOutcome, internal::ApplyError> {
// Verify the signature is good.
// Verify that the signature is good.
let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?;

// Check the size of the block if that extrinsic is applied.
Expand All @@ -195,7 +233,7 @@ impl<
if index < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future }
) }

// pay any fees.
// pay any fees
Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?;

// AUDIT: Under no circumstances may this function panic from here onwards.
Expand All @@ -204,13 +242,13 @@ impl<
<system::Module<System>>::inc_account_nonce(sender);
}

// make sure to `note_extrinsic` only after we know it's going to be executed
// Make sure to `note_extrinsic` only after we know it's going to be executed
// to prevent it from leaking in storage.
if let Some(encoded) = to_note {
<system::Module<System>>::note_extrinsic(encoded);
}

// decode parameters and dispatch
// Decode parameters and dispatch
let (f, s) = xt.deconstruct();
let r = f.dispatch(s.into());
<system::Module<System>>::note_applied_extrinsic(&r, encoded_len as u32);
Expand All @@ -222,10 +260,10 @@ impl<
}

fn final_checks(header: &System::Header) {
// remove temporaries.
// remove temporaries
let new_header = <system::Module<System>>::finalize();

// check digest.
// check digest
assert_eq!(
header.digest().logs().len(),
new_header.digest().logs().len(),
Expand All @@ -246,7 +284,7 @@ impl<
/// Check a given transaction for validity. This doesn't execute any
/// side-effects; it merely checks whether the transaction would panic if it were included or not.
///
/// Changes made to the storage should be discarded.
/// Changes made to storage should be discarded.
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
// Note errors > 0 are from ApplyError
const UNKNOWN_ERROR: i8 = -127;
Expand All @@ -267,7 +305,7 @@ impl<
};

if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) {
// pay any fees.
// pay any fees
if Payment::make_payment(sender, encoded_len).is_err() {
return TransactionValidity::Invalid(ApplyError::CantPay as i8)
}
Expand Down