Rust区块链开发框架polkadot-sdk-frame的使用,构建高性能Substrate链和Polkadot平行链的核心工具库

FRAME

FRAME开发环境提供了模块(称为"pallets")和支持库,您可以使用、修改和扩展这些模块来构建适合您区块链需求的运行时逻辑。

Metadata

  • 版本: 0.11.0
  • 发布时间: 7天前
  • 版本年份: 2021 edition
  • 许可证: Apache-2.0
  • 大小: 35.3 KiB

安装

在项目目录中运行以下Cargo命令:

cargo add polkadot-sdk-frame

或添加以下内容到您的Cargo.toml:

polkadot-sdk-frame = "0.11.0"

完整示例代码

以下是一个使用polkadot-sdk-frame构建Substrate链的完整示例:

//! 使用FRAME构建Substrate链的示例

use frame::{prelude::*, runtime::prelude::*};

// 定义我们的运行时配置
#[derive(Default)]
pub struct Runtime;

// 实现Runtime的配置
impl Config for Runtime {
    type Index = u32;
    type BlockNumber = u32;
    type Hash = sp_core::H256;
    type Hashing = sp_runtime::traits::BlakeTwo256;
    type AccountId = u64;
    type Event = ();
}

// 定义我们的pallet
pub mod pallet_example {
    use super::*;
    
    // 定义pallet的配置trait
    pub trait Config: frame::Config {
        type Event: From<Event<Self>> + Into<<Self as frame::Config>::Event>;
    }
    
    // 定义pallet
    pub struct Pallet<T>(sp_std::marker::PhantomData<T>);
    
    // 定义pallet的事件
    #[derive(Debug, Clone, Eq, PartialEq, codec::Enencode, codec::Decode)]
    pub enum Event<T: Config> {
        SomethingHappened(u32),
    }
    
    // 实现pallet
    impl<T: Config> Pallet<T> {
        pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
            ensure_signed(origin)?;
            Self::deposit_event(Event::SomethingHappened(something));
            Ok(())
        }
    }
}

// 构建我们的运行时
construct_runtime!(
    pub struct Runtime where
        Block = Block,
        NodeBlock = Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        System: frame_system,
        ExamplePallet: pallet_example,
    }
);

fn main() {
    println!("Substrate链运行时构建示例");
}

这个示例展示了如何使用FRAME框架:

  1. 定义了一个基本的Runtime配置
  2. 创建了一个自定义pallet
  3. 使用construct_runtime!宏构建运行时

要构建平行链,您还需要实现平行链特定的逻辑,如跨链消息传递和共识机制。

扩展完整示例

以下是一个更完整的FRAME开发示例,包含存储、事件和调用:

//! 更完整的FRAME开发示例

use frame::{prelude::*, runtime::prelude::*};
use sp_std::prelude::*;

// 运行时配置
#[derive(Default)]
pub struct Runtime;

impl Config for Runtime {
    type Index = u32;
    type BlockNumber = u32;
    type Hash = sp_core::H256;
    type Hashing = sp_runtime::traits::BlakeTwo256;
    type AccountId = u64;
    type Event = Event;
}

// 自定义pallet
pub mod pallet_template {
    use super::*;
    
    // 配置trait
    pub trait Config: frame::Config {
        type Event: From<Event<Self>> + Into<<Self as frame::Config>::Event>;
    }
    
    // pallet存储定义
    #[pallet::storage]
    pub type Value<T: Config> = StorageValue<_, u32, ValueQuery>;
    
    // pallet事件
    #[pallet::event]
    #[pallet::generate_deposit(pub(super) fn deposit_event)]
    pub enum Event<T: Config> {
        ValueStored(u32, T::AccountId),
    }
    
    // pallet错误
    #[pallet::error]
    pub enum Error<T> {
        /// 值已经存在
        AlreadySet,
        /// 值溢出
        Overflow,
    }
    
    // pallet实现
    #[pallet::pallet]
    pub struct Pallet<T>(_);
    
    #[pallet::call]
    impl<T: Config> Pallet<T> {
        // 设置值的函数
        #[pallet::weight(10_000)]
        pub fn set_value(
            origin: OriginFor<T>,
            value: u32,
        ) -> DispatchResultWithPostInfo {
            let who = ensure_signed(origin)?;
            
            // 检查值是否已设置
            if <Value<T>>::exists() {
                return Err(Error::<T>::AlreadySet.into());
            }
            
            // 存储新值
            <Value<T>>::put(value);
            
            // 触发事件
            Self::deposit_event(Event::ValueStored(value, who));
            
            Ok(().into())
        }
    }
}

// 构建运行时
construct_runtime!(
    pub struct Runtime where
        Block = Block,
        NodeBlock = Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        System: frame_system,
        TemplateModule: pallet_template,
    }
);

fn main() {
    println!("完整的FRAME开发示例");
}

这个扩展示例包含:

  1. 存储定义(StorageValue)
  2. 事件定义和触发
  3. 错误处理
  4. 调用函数和权重
  5. 更完整的pallet结构

您可以根据实际需求扩展这个模板,添加更多功能和逻辑。


1 回复

Rust区块链开发框架polkadot-sdk-frame使用指南

简介

polkadot-sdk-frame是构建Substrate区块链和Polkadot平行链的核心框架,提供了一套模块化组件来简化区块链开发。它是Polkadot生态系统中最重要的发展工具之一,使开发者能够快速构建高性能、可定制的区块链。

主要特性

  • 模块化设计,可组合各种区块链组件
  • 支持Substrate和Polkadot生态系统
  • 高性能运行时执行环境
  • 内置共识机制、网络层和RPC接口
  • 支持Wasm智能合约
  • 丰富的预构建模块(pallets)

安装与设置

首先确保已安装Rust工具链:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup update nightly
rustup target add wasm32-unknown-unknown --toolchain nightly

然后创建一个新的Substrate项目:

cargo install --git https://github.com/paritytech/substrate.git --branch polkadot-v1.0.0 substrate-node-template
cargo install --git https://github.com/paritytech/substrate.git --branch polkadot-v1.0.0 substrate-front-end-template

基本使用

1. 创建自定义pallet

// 在pallets/template/src/lib.rs中

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

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
    use frame_support::pallet_prelude::*;
    use frame system::pallet_prelude::*;

    #[pallet::config]
    pub trait Config: frame_system::Config {
        type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
    }

    #[pallet::pallet]
    #[pallet::generate_store(pub(super) trait Store)]
    pub struct Pallet<T>(_);

    #[pallet::storage]
    #[pallet::getter(fn something)]
    pub type Something<T> = StorageValue<_, u32>;

    #[pallet::event]
    #[pallet::generate_deposit(pub(super) fn deposit_event)]
    pub enum Event<T: Config> {
        SomethingStored(u32, T::AccountId),
    }

    #[pallet::call]
    impl<T: Config] Pallet<T> {
        #[pallet::weight(10_000)]
        pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
            let who = ensure_signed(origin)?;
            <Something<T>>::put(something);
            Self::deposit_event(Event::SomethingStored(something, who));
            Ok(())
        }
    }
}

2. 将pallet集成到运行时

// 在runtime/src/lib.rs中

impl pallet_template::Config for Runtime {
    type Event = Event;
}

construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        // 其他pallet...
        TemplateModule: pallet_template::{Pallet, Call, Storage, Event<T>},
    }
);

3. 构建和运行链

# 以开发模式运行
cargo run --release -- --dev

# 生产模式构建
cargo build --release

构建平行链

1. 配置平行链

// 在runtime/src/lib.rs中

impl cumulus_pallet_parachain_system::Config for Runtime {
    type Event = Event;
    type OnSystemEvent = ();
    type SelfParaId = parachain_info::Pallet<Runtime>;
    type OutboundXcmpMessageSource = XcmpQueue;
    type DmpMessageHandler = DmpQueue;
    type ReservedDmpWeight = ReservedDmpWeight;
    type XcmpMessageHandler = XcmpQueue;
    type ReservedXcmpWeight = ReservedXcmpWeight;
}

2. 注册平行链

// 在node/src/chain_spec.rs中

pub fn local_testnet_config() -> ChainSpec {
    ChainSpec::from_genesis(
        // ...其他配置
        polkadot_runtime_parachains::configuration::HostConfiguration {
            max_code_size: MAX_CODE_SIZE,
            max_head_data_size: MAX_HEAD_DATA_SIZE,
            // ...其他平行链特定配置
        },
    )
}

高级功能

1. 自定义共识

impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
    fn slot_duration() -> sp_consensus_aura::SlotDuration {
        sp_consensus_aura::SlotDuration::from_millis(AURA.slot_duration)
    }

    fn authorities() -> Vec<AuraId> {
        Aura::authorities().into_inner()
    }
}

2. 跨链通信(XCM)

impl xcm_config::Config for Runtime {
    type Call = Call;
    type XcmSender = XcmRouter;
    type AssetTransactor = LocalAssetTransactor;
    type OriginConverter = xcm_config::OriginConverter;
    type IsReserve = NativeAsset;
    type IsTeleporter = ();
    type LocationInverter = xcm_config::LocationInverter<Ancestry>;
    type Barrier = xcm_config::Barrier;
    type Weigher = xcm_config::Weigher;
    type Trader = xcm_config::Trader;
    type ResponseHandler = ();
    type AssetTrap = ();
    type AssetClaims = ();
    type SubscriptionService = ();
}

最佳实践

  1. 模块化设计:将业务逻辑拆分为独立的pallets
  2. 最小化运行时:只包含必要的功能以减少Wasm二进制大小
  3. 安全审计:特别注意存储操作和权重计算
  4. 测试覆盖:编写全面的单元测试和集成测试
  5. 链上升级:设计支持无分叉升级的运行时

通过polkadot-sdk-frame,开发者可以充分利用Substrate和Polkadot生态系统的优势,构建高性能、可互操作的区块链解决方案。

完整示例

下面是一个完整的自定义pallet示例,实现了一个简单的存证功能:

// 在pallets/evidence/src/lib.rs中

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

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
    use frame_support::{pallet_prelude::*, Blake2_128Concat};
    use frame_system::pallet_prelude::*;
    use sp_std::vec::Vec;

    /// 存证数据结构
    #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
    #[scale_info(skip_type_params(T))]
    pub struct Evidence<T: Config> {
        /// 存证内容哈希
        pub hash: [u8; 32],
        /// 存证创建者
        pub creator: T::AccountId,
        /// 创建时间
        pub timestamp: u64,
    }

    #[pallet::config]
    pub trait Config: frame_system::Config {
        type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
    }

    #[pallet::pallet]
    #[pallet::generate_store(pub(super) trait Store)]
    pub struct Pallet<T>(_);

    /// 存储所有存证的哈希值
    #[pallet::storage]
    #[pallet::getter(fn evidence_hashes)]
    pub type EvidenceHashes<T: Config> = StorageValue<_, Vec<[u8; 32]>>;

    /// 存储具体的存证内容
    #[pallet::storage]
    #[pallet::getter(fn evidences)]
    pub type Evidences<T: Config> = StorageMap<
        _,
        Blake2_128Concat,
        [u8; 32],
        Evidence<T>,
    >;

    #[pallet::event]
    #[pallet::generate_deposit(pub(super) fn deposit_event)]
    pub enum Event<T: Config> {
        /// 存证已创建
        EvidenceCreated([u8; 32], T::AccountId),
    }

    #[pallet::error]
    pub enum Error<T> {
        /// 存证已存在
        EvidenceAlreadyExists,
    }

    #[pallet::call]
    impl<T: Config> Pallet<T> {
        /// 创建新存证
        #[pallet::weight(10_000)]
        pub fn create_evidence(
            origin: OriginFor<T>,
            hash: [u8; 32],
            timestamp: u64,
        ) -> DispatchResult {
            let creator = ensure_signed(origin)?;
            
            // 检查存证是否已存在
            ensure!(!<Evidences<T>>::contains_key(&hash), Error::<T>::EvidenceAlreadyExists);
            
            let evidence = Evidence {
                hash,
                creator: creator.clone(),
                timestamp,
            };
            
            // 更新存储
            <Evidences<T>>::insert(&hash, evidence);
            <EvidenceHashes<T>>::mutate(|hashes| hashes.push(hash));
            
            // 触发事件
            Self::deposit_event(Event::EvidenceCreated(hash, creator));
            
            Ok(())
        }
    }
}

将此pallet集成到运行时的完整示例:

// 在runtime/src/lib.rs中

// 引入自定义pallet
pub use pallet_evidence;

// 实现pallet配置
impl pallet_evidence::Config for Runtime {
    type Event = Event;
}

// 构造运行时
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        System: frame_system,
        // 其他pallet...
        EvidenceModule: pallet_evidence::{Pallet, Call, Storage, Event<T>},
    }
);

这个完整示例展示了一个简单的存证系统,包含了存储定义、事件处理、错误处理和基本业务逻辑。开发者可以基于此模板扩展更复杂的功能。

回到顶部