52 个版本 (32 个主要版本)
34.0.0 | 2024 年 7 月 18 日 |
---|---|
33.0.0 | 2024 年 6 月 21 日 |
32.0.0 | 2024 年 5 月 23 日 |
31.0.0 | 2024 年 4 月 30 日 |
2.0.0-alpha.5 | 2020 年 3 月 24 日 |
#2 in #inherent
每月 18,106 次下载
用于 580 个存储库 (76 个直接使用)
125KB
2K SLoC
提供创建和检查内在类型的类型和特质的工具。
每个内在类型都会添加到一个生成的块中。每个运行时都会决定它希望将其块附加到哪些内在类型上。所有运行时创建内在类型所需的数据都存储在 InherentData
中。此 InherentData
由节点构建并传递给运行时。
为内在类型提供数据的类型应实现 InherentDataProvider
并需要在 InherentDataProviders
中进行注册。
在运行时,当模块可以创建和/或检查内在类型时,需要实现 ProvideInherent
。通过实现 ProvideInherent
,模块不必强制创建内在类型。模块也可以仅检查给定的内在类型。要使用模块作为内在类型提供者,需要通过 construct_runtime!
宏进行注册。宏文档提供了更多关于如何执行此操作的信息。
许可证:Apache-2.0
lib.rs
:
Substrate 内在外设
固有外部特性是指内在地添加到每个块的特性。然而,是否要求每个块都必须有固有特性,或者将其作为可选特性,则由运行时实现来决定。固有特性主要用于将数据从块生产者传递到运行时。因此,固有特性需要一部分在客户端运行,另一部分在运行时端运行。任何固有特性所需的数据都将在构建固有特性时,以 InherentData
的形式从客户端传递到运行时。
构建和应用固有特性的过程如下:
-
块生产者首先使用由
CreateInherentDataProviders
创建的固有数据提供者创建InherentData
。 -
将
InherentData
传递给运行时BlockBuilder
api 的inherent_extrinsics
函数。这将调用运行时,创建应应用于块的固有特性。 -
像任何正常的外部特性一样,将每个固有特性应用于块。
在块导入时,通过调用运行时的 check_inherents
api 检查块中的固有特性。这也会传递一个 InherentData
的实例,运行时可以使用它来验证所有固有特性。如果某些固有数据对于验证固有特性不是必需的,在提供块导入的固有数据提供者时可以省略。
提供固有数据
要从客户端提供固有数据,应实现 InherentDataProvider
。
use codec::Decode;
use sp_inherents::{InherentIdentifier, InherentData};
// This needs to be unique for the runtime.
const INHERENT_IDENTIFIER: InherentIdentifier = *b"testinh0";
/// Some custom inherent data provider
struct InherentDataProvider;
#[async_trait::async_trait]
impl sp_inherents::InherentDataProvider for InherentDataProvider {
async fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
) -> Result<(), sp_inherents::Error> {
// We can insert any data that implements [`codec::Encode`].
inherent_data.put_data(INHERENT_IDENTIFIER, &"hello")
}
/// When validating the inherents, the runtime implementation can throw errors. We support
/// two error modes, fatal and non-fatal errors. A fatal error means that the block is invalid
/// and this function here should return `Err(_)` to not import the block. Non-fatal errors
/// are allowed to be handled here in this function and the function should return `Ok(())`
/// if it could be handled. A non-fatal error is for example that a block is in the future
/// from the point of view of the local node. In such a case the block import for example
/// should be delayed until the block is valid.
///
/// If this functions returns `None`, it means that it is not responsible for this error or
/// that the error could not be interpreted.
async fn try_handle_error(
&self,
identifier: &InherentIdentifier,
mut error: &[u8],
) -> Option<Result<(), sp_inherents::Error>> {
// Check if this error belongs to us.
if *identifier != INHERENT_IDENTIFIER {
return None;
}
// For demonstration purposes we are using a `String` as error type. In real
// implementations it is advised to not use `String`.
Some(Err(
sp_inherents::Error::Application(Box::from(String::decode(&mut error).ok()?))
))
}
}
在服务中,需要将相关的固有数据提供者传递给块生产和块导入。如上所述,提供者可以在导入和生成之间不同。
async fn cool_consensus_block_production(
// The second parameter to the trait are parameters that depend on what the caller
// can provide on extra data.
_: impl sp_inherents::CreateInherentDataProviders<Block, ()>,
) {
// do cool stuff
}
async fn cool_consensus_block_import(
_: impl sp_inherents::CreateInherentDataProviders<Block, ()>,
) {
// do cool stuff
}
async fn build_service(is_validator: bool) {
// For block import we don't pass any inherent data provider, because our runtime
// does not need any inherent data to validate the inherents.
let block_import = cool_consensus_block_import(|_parent, ()| async { Ok(()) });
let block_production = if is_validator {
// For block production we want to provide our inherent data provider
cool_consensus_block_production(|_parent, ()| async {
Ok(InherentDataProvider)
}).boxed()
} else {
futures::future::pending().boxed()
};
futures::pin_mut!(block_import);
futures::future::select(block_import, block_production).await;
}
创建固有特性
由于固有特性是由运行时创建的,因此创建固有特性的方式取决于运行时实现。如上所述,客户端传递 InherentData
,并期望运行时从其中构建固有特性。在验证固有特性时,使用 CheckInherentsResult
与客户端通信结果。
依赖关系
~3–16MB
~212K SLoC