Rust客户端API库sc-client-api的使用,为Substrate区块链客户端提供核心接口与功能扩展
Rust客户端API库sc-client-api的使用,为Substrate区块链客户端提供核心接口与功能扩展
概述
sc-client-api 是 Substrate 区块链客户端的核心接口库,提供了与区块链客户端交互的基本API和功能扩展能力。该库遵循 GPL-3.0-or-later WITH Classpath-exception-2.0 许可证。
安装
在您的项目目录中运行以下 Cargo 命令:
cargo add sc-client-api
或者在 Cargo.toml 中添加:
sc-client-api = "41.0.0"
基本使用示例
下面是一个使用 sc-client-api 与 Substrate 区块链交互的完整示例:
use sc_client_api::{Backend, BlockBackend, BlockchainEvents};
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use std::sync::Arc;
// 定义我们的区块链类型
type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
// 客户端结构体
struct Client<B: Backend<Block>> {
backend: Arc<B>,
}
impl<B: Backend<Block>> Client<B> {
fn new(backend: Arc<B>) -> Self {
Client { backend }
}
// 获取最新区块头
fn latest_header(&self) -> Option<<Block as BlockT>::Header> {
self.backend.blockchain().header(BlockId::Latest).ok()?
}
// 订阅新区块
fn subscribe_blocks(&self) -> sc_client_api::blockchain::BlockchainEvents<Block> {
self.backend.blockchain().events()
}
}
// 示例使用
fn main() {
// 注意:实际使用中需要替换为具体的后端实现
// let backend = create_actual_backend();
// let client = Client::new(backend);
// println!("Latest block header: {:?}", client.latest_header());
// let mut subscription = client.subscribe_blocks();
// while let Some(notification) = subscription.next() {
// println!("New block notification: {:?}", notification);
// }
}
完整示例代码
下面是一个更完整的示例,展示如何使用sc-client-api与Substrate区块链交互:
use sc_client_api::{
Backend, BlockBackend, BlockchainEvents,
ExecutionExtensions, ExecutorProvider,
StorageProvider
};
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT},
};
use std::sync::Arc;
// 定义区块链类型
type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
// 自定义客户端结构体
struct SubstrateClient<B: Backend<Block>> {
backend: Arc<B>,
}
impl<B: Backend<Block>> SubstrateClient<B> {
pub fn new(backend: Arc<B>) -> Self {
SubstrateClient { backend }
}
// 获取指定高度的区块头
pub fn get_block_header(&self, number: u32) -> Option<<Block as BlockT>::Header> {
self.backend.blockchain().header(BlockId::Number(number)).ok()?
}
// 获取最新区块头
pub fn latest_header(&self) -> Option<<Block as BlockT>::Header> {
self.backend.blockchain().header(BlockId::Latest).ok()?
}
// 订阅新区块事件
pub fn subscribe_blocks(&self) -> sc_client_api::blockchain::BlockchainEvents<Block> {
self.backend.blockchain().events()
}
// 获取指定区块的存储数据
pub fn get_storage(&self, block: BlockId<Block>, key: &[u8]) -> Option<Vec<u8>> {
self.backend.blockchain().storage(block, key).ok()?
}
}
// 示例主函数
fn main() {
// 注意:实际应用中需要替换为真实的后端实现
// let backend = create_actual_backend();
// let client = SubstrateClient::new(backend);
// 示例用法
// if let Some(header) = client.latest_header() {
// println!("Latest block header: {:?}", header);
// }
// 订阅新区块通知
// let mut subscription = client.subscribe_blocks();
// while let Some(notification) = subscription.next() {
// println!("New block: {:?}", notification.header);
// }
}
核心功能
sc-client-api 提供了以下主要功能接口:
- 区块链数据访问:通过
BlockBackend
trait 提供区块、头、存储等数据的访问 - 事件订阅:通过
BlockchainEvents
trait 提供区块导入、最终化等事件的订阅 - 执行环境:提供区块构建和执行的接口
- 状态访问:提供区块链状态的访问方法
高级功能扩展
您可以通过实现 sc-client-api 中定义的各种 trait 来扩展客户端功能。例如,自定义存储后端:
use sc_client_api::{Backend, AuxStore};
use sp_runtime::traits::Block as BlockT;
// 自定义后端实现
#[derive(Clone)]
struct CustomBackend<Block: BlockT> {
// 这里添加自定义存储字段
}
impl<Block: BlockT> Backend<Block> for CustomBackend<Block> {
// 实现所需的Backend trait方法
}
impl<Block: BlockT> AuxStore for CustomBackend<Block> {
// 实现辅助存储方法
fn insert_aux<
'a,
'b: 'a,
'c: 'a,
I: IntoIterator<Item = &'a(&'c [u8], &'c [u8])>,
D: IntoIterator<Item = &'a &'b [u8]>,
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()> {
// 实现具体逻辑
Ok(())
}
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
// 实现具体逻辑
Ok(None)
}
}
注意事项
- 该库主要面向需要与 Substrate 区块链客户端深度交互的高级用户
- 使用时需要熟悉 Substrate 区块链的基本概念
- 实际使用时需要结合具体的后端实现
1 回复
Rust客户端API库sc-client-api的使用指南
概述
sc-client-api
是Substrate区块链框架中的一个核心库,为区块链客户端提供了一系列基础接口和功能扩展点。这个库定义了客户端与服务之间的关键交互协议,允许开发者构建自定义区块链客户端或扩展现有客户端功能。
主要功能
- 提供区块链客户端核心接口
- 定义客户端后端抽象
- 支持区块导入和验证
- 提供状态查询功能
- 支持执行运行时调用
- 提供证明生成和验证
基本使用方法
添加依赖
首先在Cargo.toml
中添加依赖:
[dependencies]
sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
基本客户端初始化
use sc_client_api::{Backend, BlockchainEvents, ExecutionStrategies};
use sp_runtime::traits::Block as BlockT;
struct MyBackend<Block: BlockT> {
// 实现你的后端
}
impl<Block: BlockT> Backend<Block> for MyBackend<Block> {
// 实现必要的trait方法
}
// 创建客户端配置
let client_config = sc_client_api::ClientConfig {
backend: Box::new(MyBackend::new()),
execution_strategies: ExecutionStrategies {
syncing: ExecutionStrategy::NativeElseWasm,
importing: ExecutionStrategy::NativeElseWasm,
block_construction: ExecutionStrategy::AlwaysWasm,
other: ExecutionStrategy::NativeElseWasm,
},
// 其他配置...
};
区块导入示例
use sc_client_api::BlockImport;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::Header;
async fn import_block<B, Block>(
client: &Arc<B>,
block: Block,
) -> Result<(), sp_blockchain::Error>
where
B: sc_client_api::BlockBackend<Block>,
Block: sp_runtime::traits::Block,
{
let import = sc_client_api::BlockImportParams {
origin: sp_consensus::BlockOrigin::NetworkBroadcast,
header: block.header().clone(),
body: Some(block.extrinsics().to_vec()),
// 其他导入参数...
};
client.import_block(import, Default::default()).await
}
状态查询示例
use sc_client_api::StorageProvider;
fn query_storage<B, Block>(
client: &Arc<B>,
block: BlockId<Block>,
key: &[u8],
) -> Result<Option<Vec<u8>>, sp_blockchain::Error>
where
B: sc_client_api::StorageProvider<Block>,
Block: sp_runtime::traits::Block,
{
client.storage(&block, key)
}
高级功能
自定义客户端扩展
use sc_client_api::{ClientInfo, ExecutionExtension};
struct MyExtension;
impl<Block, Client> ExecutionExtension<Block, Client> for MyExtension
where
Block: sp_runtime::traits::Block,
Client: sc_client_api::BlockBackend<Block> + Send + Sync + 'static,
{
// 实现你的扩展逻辑
}
// 注册扩展
let mut extensions = sc_client_api::Extensions::new();
extensions.register(MyExtension);
订阅区块链事件
use futures::StreamExt;
use sc_client_api::BlockchainEvents;
async fn subscribe_to_blocks<B, Block>(
client: Arc<B>,
) where
B: sc_client_api::BlockchainEvents<Block>,
Block: sp_runtime::traits::Block,
{
let mut import_notification_stream = client.import_notification_stream();
while let Some(notification) = import_notification_stream.next().await {
println!("New block imported: {:?}", notification.hash);
}
}
完整示例
下面是一个完整的Substrate客户端示例,演示了如何使用sc-client-api构建一个基本的区块链客户端:
use sc_client_api::{
Backend, BlockBackend, BlockchainEvents, ExecutionStrategies,
BlockImport, StorageProvider, ClientConfig
};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use sp_runtime::generic::BlockId;
use std::sync::Arc;
// 定义简单的内存后端
struct InMemoryBackend<Block: BlockT> {
blocks: std::collections::HashMap<Block::Hash, Block>,
}
impl<Block: BlockT> InMemoryBackend<Block> {
fn new() -> Self {
Self {
blocks: Default::default(),
}
}
}
// 实现Backend trait
impl<Block: BlockT> Backend<Block> for InMemoryBackend<Block> {
// 简化实现 - 实际使用时需要完整实现所有方法
}
// 主客户端结构
struct SubstrateClient<Block: BlockT, Backend> {
backend: Arc<Backend>,
// 其他客户端状态
}
impl<Block, Backend> SubstrateClient<Block, Backend>
where
Block: BlockT,
Backend: Backend<Block>,
{
fn new(backend: Backend) -> Self {
Self {
backend: Arc::new(backend),
}
}
}
// 实现BlockBackend trait
impl<Block, Backend> BlockBackend<Block> for SubstrateClient<Block, Backend>
where
Block: BlockT,
Backend: Backend<Block>,
{
fn block(&self, id: &BlockId<Block>) -> Result<Option<Block>, sp_blockchain::Error> {
match id {
BlockId::Hash(hash) => Ok(self.backend.blocks.get(hash).cloned()),
_ => Ok(None), // 简化实现
}
}
}
#[tokio::main]
async fn main() {
// 初始化内存后端
let backend = InMemoryBackend::<sp_runtime::generic::Block<_, _>>::new();
// 创建客户端配置
let config = ClientConfig {
backend: Box::new(backend),
execution_strategies: ExecutionStrategies {
syncing: ExecutionStrategy::NativeElseWasm,
importing: ExecutionStrategy::NativeElseWasm,
block_construction: ExecutionStrategy::AlwaysWasm,
other: ExecutionStrategy::NativeElseWasm,
},
};
// 创建客户端实例
let client = SubstrateClient::new(config.backend);
// 示例:查询不存在的块
let block = client.block(&BlockId::Number(0));
println!("Block query result: {:?}", block);
}
最佳实践
- 尽量使用提供的trait而不是具体实现,以提高代码的可移植性
- 对于资源密集型操作,考虑使用异步执行
- 合理处理错误和边缘情况
- 注意线程安全,特别是当客户端在多个线程间共享时
注意事项
- 该库通常与Substrate的其他组件一起使用,如
sc-service
和sp-api
- API可能会随着Substrate版本的更新而变化
- 生产环境使用时需要仔细考虑性能和安全因素
通过sc-client-api
,开发者可以构建高度定制化的区块链客户端,同时保持与Substrate生态系统的兼容性。