Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
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
35 changes: 26 additions & 9 deletions frame/support/src/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ pub use sp_inherents::{
CheckInherentsResult, InherentData, InherentIdentifier, IsFatalError, MakeFatalError,
};

/// A pallet that provides or verifies an inherent extrinsic.
/// A pallet that provides or verifies an inherent extrinsic will implement this trait.
///
/// The pallet may provide the inherent, verify an inherent, or both provide and verify.
/// The pallet may provide an inherent, verify an inherent, or both provide and verify.
///
/// Briefly, inherent extrinsics ("inherents") are extrinsics that are added to a block by the block
/// producer. See [`sp_inherents`] for more documentation on inherents.
pub trait ProvideInherent {
/// The call type of the pallet.
type Call;
Expand All @@ -36,6 +39,12 @@ pub trait ProvideInherent {
const INHERENT_IDENTIFIER: self::InherentIdentifier;

/// Create an inherent out of the given `InherentData`.
///
/// NOTE: All checks necessary to ensure that the inherent is correct and that can be done in
/// the runtime should happen in the returned `Call`.
/// E.g. if this provides the timestamp, the call will check that the given timestamp is
/// increasing the old timestamp by more than a minimum and it will also check that the
/// timestamp hasn't already been set in the current block.
fn create_inherent(data: &InherentData) -> Option<Self::Call>;

/// Determines whether this inherent is required in this block.
Expand All @@ -44,15 +53,17 @@ pub trait ProvideInherent {
/// implementation returns this.
///
/// - `Ok(Some(e))` indicates that this inherent is required in this block. `construct_runtime!`
/// will call this function from in its implementation of `fn check_extrinsics`.
/// will call this function in its implementation of `fn check_extrinsics`.
/// If the inherent is not present, it will return `e`.
///
/// - `Err(_)` indicates that this function failed and further operations should be aborted.
///
/// NOTE: If inherent is required then the runtime asserts that the block contains at least
/// NOTE: If the inherent is required then the runtime asserts that the block contains at least
/// one inherent for which:
/// * type is [`Self::Call`],
/// * [`Self::is_inherent`] returns true.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how to write it but this is_inherent_required is currently only checked by other block producer same as check_inherent, maybe we can change it to make it part of the execute_block. But it is not the case currently.

///
/// NOTE: This is currently only checked by block producers, not all full nodes.
fn is_inherent_required(_: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
Ok(None)
}
Expand All @@ -64,21 +75,27 @@ pub trait ProvideInherent {
/// included in the block by its author. Whereas the second parameter represents the inherent
/// data that the verifying node calculates.
///
/// NOTE: A block can contains multiple inherent.
/// This is intended to allow for checks that cannot be done within the runtime such as, e.g.,
/// the timestamp.
///
/// # Warning
///
/// This check is not guaranteed to be run by all full nodes and cannot be relied upon for
/// ensuring that the block is correct.
fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> {
Ok(())
}

/// Return whether the call is an inherent call.
///
/// NOTE: Signed extrinsics are not inherent, but signed extrinsic with the given call variant
/// can be dispatched.
/// NOTE: Signed extrinsics are not inherents, but a signed extrinsic with the given call
/// variant can be dispatched.
///
/// # Warning
///
/// In FRAME, inherent are enforced to be before other extrinsics, for this reason,
/// In FRAME, inherents are enforced to be executed before other extrinsics. For this reason,
/// pallets with unsigned transactions **must ensure** that no unsigned transaction call
/// is an inherent call, when implementing `ValidateUnsigned::validate_unsigned`.
/// Otherwise block producer can produce invalid blocks by including them after non inherent.
/// Otherwise block producers can produce invalid blocks by including them after non inherents.
fn is_inherent(call: &Self::Call) -> bool;
}
12 changes: 6 additions & 6 deletions primitives/inherents/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Substrate inherent extrinsics
//! Substrate Inherent Extrinsics
//!
//! Inherent extrinsics are extrinsics that are inherently added to each block. However, it is up to
//! runtime implementation to require an inherent for each block or to make it optional. Inherents
//! are mainly used to pass data from the block producer to the runtime. So, inherents require some
//! part that is running on the client side and some part that is running on the runtime side. Any
//! data that is required by an inherent is passed as [`InherentData`] from the client to the
//! runtime when the inherents are constructed.
//! the runtime implementation to require an inherent for each block or to make it optional.
//! Inherents are mainly used to pass data from the block producer to the runtime. So, inherents
//! require some part that is running on the client side and some part that is running on the
//! runtime side. Any data that is required by an inherent is passed as [`InherentData`] from the
//! client to the runtime when the inherents are constructed.
//!
//! The process of constructing and applying inherents is the following:
//!
Expand Down