#data-provider #inherent #traits #block #checking #data-block #create

无 std sp-inherents

提供创建和检查内在类型的类型和特质的工具。(polkadot v1.15.0)

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.52020 年 3 月 24 日

#2 in #inherent

Download history 5435/week @ 2024-04-28 4715/week @ 2024-05-05 4318/week @ 2024-05-12 5714/week @ 2024-05-19 5065/week @ 2024-05-26 5232/week @ 2024-06-02 3479/week @ 2024-06-09 4084/week @ 2024-06-16 6142/week @ 2024-06-23 2352/week @ 2024-06-30 3555/week @ 2024-07-07 6747/week @ 2024-07-14 3995/week @ 2024-07-21 4421/week @ 2024-07-28 4062/week @ 2024-08-04 5201/week @ 2024-08-11

每月 18,106 次下载
用于 580 个存储库 (76 个直接使用)

Apache-2.0

125KB
2K SLoC

提供创建和检查内在类型的类型和特质的工具。

每个内在类型都会添加到一个生成的块中。每个运行时都会决定它希望将其块附加到哪些内在类型上。所有运行时创建内在类型所需的数据都存储在 InherentData 中。此 InherentData 由节点构建并传递给运行时。

为内在类型提供数据的类型应实现 InherentDataProvider 并需要在 InherentDataProviders 中进行注册。

在运行时,当模块可以创建和/或检查内在类型时,需要实现 ProvideInherent。通过实现 ProvideInherent,模块不必强制创建内在类型。模块也可以仅检查给定的内在类型。要使用模块作为内在类型提供者,需要通过 construct_runtime! 宏进行注册。宏文档提供了更多关于如何执行此操作的信息。

许可证:Apache-2.0


lib.rs:

Substrate 内在外设

固有外部特性是指内在地添加到每个块的特性。然而,是否要求每个块都必须有固有特性,或者将其作为可选特性,则由运行时实现来决定。固有特性主要用于将数据从块生产者传递到运行时。因此,固有特性需要一部分在客户端运行,另一部分在运行时端运行。任何固有特性所需的数据都将在构建固有特性时,以 InherentData 的形式从客户端传递到运行时。

构建和应用固有特性的过程如下:

  1. 块生产者首先使用由 CreateInherentDataProviders 创建的固有数据提供者创建 InherentData

  2. InherentData 传递给运行时 BlockBuilder api 的 inherent_extrinsics 函数。这将调用运行时,创建应应用于块的固有特性。

  3. 像任何正常的外部特性一样,将每个固有特性应用于块。

在块导入时,通过调用运行时的 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