Rust NIS模块pallet-nis的使用:Substrate区块链框架中的非交互式质押与治理功能库

Rust NIS模块pallet-nis的使用:Substrate区块链框架中的非交互式质押与治理功能库

NIS模块

提供了一种非交互式的质押变体。

许可证: Apache-2.0

元数据

  • 版本: 42.0.0
  • 发布时间: 约17小时前
  • 2021版本
  • 大小: 45 KiB

安装

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

cargo add pallet-nis

或者在你的Cargo.toml中添加以下行:

pallet-nis = "42.0.0"

完整示例代码

// 引入必要的依赖
use frame_support::{decl_module, decl_event, decl_storage, dispatch::DispatchResult};
use frame_system::ensure_signed;

// 定义NIS模块
pub trait Trait: frame_system::Trait {
    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
}

// 定义存储项
decl_storage! {
    trait Store for Module<T: Trait> as Nis {
        // 存储质押总额
        pub TotalStake get(fn total_stake): u64;
        // 存储账户质押余额
        pub AccountStake get(fn account_stake): map hasher(blake2_128_concat) T::AccountId => u64;
    }
}

// 定义事件
decl_event!(
    pub enum Event<T> where AccountId = <T as frame_system::Trait>::AccountId {
        // 质押事件
        Staked(AccountId, u64),
        // 解除质押事件
        Unstaked(AccountId, u64),
    }
);

// 定义模块
decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        // 初始化事件
        fn deposit_event() = default;

        // 质押函数
        #[weight = 10_000]
        pub fn stake(origin, amount: u64) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            
            // 更新存储
            <AccountStake<T>>::mutate(&sender, |balance| *balance += amount);
            <TotalStake<T>>::mutate(|total| *total += amount);
            
            // 发出事件
            Self::deposit_event(RawEvent::Staked(sender, amount));
            
            Ok(())
        }

        // 解除质押函数
        #[weight = 10_000]
        pub fn unstake(origin, amount: u64) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            
            // 检查余额是否足够
            let current = <AccountStake<T>>::get(&sender);
            if current < amount {
                return Err("Insufficient stake balance".into());
            }
            
            // 更新存储
            <AccountStake<T>>::mutate(&sender, |balance| *balance -= amount);
            <TotalStake<T>>::mutate(|total| *total -= amount);
            
            // 发出事件
            Self::deposit_event(RawEvent::Unstaked(sender, amount));
            
            Ok(())
        }
    }
}

// 测试模块
#[cfg(test)]
mod tests {
    use super::*;
    use frame_support::{assert_ok, assert_err, impl_outer_origin, parameter_types};
    use sp_core::H256;
    use sp_runtime::{testing::Header, traits::{BlakeTwo256, IdentityLookup}, Perbill};
    
    impl_outer_origin! {
        pub enum Origin for Test {}
    }
    
    #[derive(Clone, Eq, PartialEq)]
    pub struct Test;
    parameter_types! {
        pub const BlockHashCount: u64 = 250;
        pub const MaximumBlockWeight: u32 = 1024;
        pub const MaximumBlockLength: u32 = 2 * 1024;
        pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
    }
    
    impl frame_system::Trait for Test {
        type Origin = Origin;
        type Call = ();
        type Index = u64;
        type BlockNumber = u64;
        type Hash = H256;
        type Hashing = BlakeTwo256;
        type AccountId = u64;
        type Lookup = IdentityLookup<Self::AccountId>;
        type Header = Header;
        type Event = ();
        type BlockHashCount = BlockHashCount;
        type MaximumBlockWeight = MaximumBlockWeight;
        type MaximumBlockLength = MaximumBlockLength;
        type AvailableBlockRatio = AvailableBlockRatio;
        type Version = ();
        type ModuleToIndex = ();
        type AccountData = ();
        type OnNewAccount = ();
        type OnKilledAccount = ();
    }
    
    impl Trait for Test {
        type Event = ();
    }
    
    type Nis = Module<Test>;
    
    #[test]
    fn test_stake() {
        new_test_ext().execute_with(|| {
            // 初始状态检查
            assert_eq!(Nis::total_stake(), 0);
            assert_eq!(Nis::account_stake(1), 0);
            
            // 质押成功
            assert_ok!(Nis::stake(Origin::signed极简,仅包含核心功能,适合快速上手和理解NIS模块的基本概念。

1 回复

以下是基于提供内容的完整示例demo,首先展示内容中提供的示例,然后补充完整实现:

内容中提供的示例

参与质押

use frame_support::weights::DispatchClass;

let call = pallet_nis::Call::<Runtime>::place_bid {
    amount: 100u32.into(),
    duration: 28u32.into(),
};
let origin = Origin::signed(1);
let info = call.get_dispatch_info();
let result = Nis::place_bid(origin, call, info.weight, info.class);

查询质押信息

use pallet_nis::Queues;

// 获取当前队列中的质押信息
let queues = Queues::<Runtime>::get();
println!("Current queues: {:?}", queues);

治理投票

let call = pallet_nis::Call::<Runtime>::vote {
    poll_index: 1,
    aye: true,
};
let origin = Origin::signed(1);
let _ = Nis::vote(origin, call);

完整示例demo

//! 完整的pallet-nis使用示例

use frame_support::{dispatch::DispatchResult, weights::DispatchClass};
use frame_system::RawOrigin;
use pallet_nis::{self as nis, Queues};

/// 自定义运行时配置
pub struct Runtime;

impl nis::Config for Runtime {
    type RuntimeEvent = ();
    type WeightInfo = ();
    type Currency = Balances;
    type Counterpart = ();
    type Deficit = ();
    type Surplus = ();
    type MinBid = frame_support::traits::ConstU32<10>;
    type QueueCount = frame_support::traits::ConstU32<8>;
    type MaxDuration = frame_support::traits::ConstU32<365>;
}

/// 模拟Balances模块
pub struct Balances;

/// NIS模块完整示例
pub struct NisDemo;

impl NisDemo {
    /// 参与质押的完整示例
    pub fn place_bid_example() -> DispatchResult {
        // 创建质押调用
        let call = nis::Call::<Runtime>::place_bid {
            amount: 100u32.into(),
            duration: 28u32.into(),
        };
        
        // 获取调度信息
        let info = call.get_dispatch_info();
        
        // 执行质押操作
        nis::Pallet::<Runtime>::place_bid(
            RawOrigin::Signed(1).into(),
            call,
            info.weight,
            info.class
        )
    }

    /// 查询质押信息的完整示例
    pub fn query_queues_example() {
        // 获取质押队列
        let queues = Queues::<Runtime>::get();
        
        // 打印队列信息
        println!("质押队列详情:");
        for (duration, queue) in queues.iter() {
            println!("持续时间: {} 天, 队列长度: {}", duration, queue.len());
        }
    }

    /// 治理投票的完整示例
    pub fn vote_example() -> DispatchResult {
        // 创建投票调用
        let call = nis::Call::<Runtime>::vote {
            poll_index: 1,
            aye: true,  // 赞成票
        };
        
        // 执行投票操作
        nis::Pallet::<Runtime>::vote(
            RawOrigin::Signed(1).into(),
            call
        )
    }

    /// 综合示例:质押、查询、投票
    pub fn full_demo() {
        println!("开始NIS模块演示...");
        
        // 1. 参与质押
        match Self::place_bid_example() {
            Ok(_) => println!("质押成功"),
            Err(e) => println!("质押失败: {:?}", e),
        }
        
        // 2. 查询质押信息
        Self::query_queues_example();
        
        // 3. 参与治理投票
        match Self::vote_example() {
            Ok(_) => println!("投票成功"),
            Err(e) => println!("投票失败: {:?}", e),
        }
        
        println!("NIS模块演示完成");
    }
}

// 运行示例
fn main() {
    NisDemo::full_demo();
}

代码说明

  1. 运行时配置:实现了nis::Config trait,包含最小出价、队列数量和最大持续时间等配置项
  2. Balances模拟:简化了Balances模块的实现
  3. 核心功能
    • place_bid_example: 展示如何参与质押
    • query_queues_example: 展示如何查询质押队列
    • vote_example: 展示如何进行治理投票
  4. 完整流程full_demo方法展示了从质押到投票的完整流程

注意事项

  1. 实际使用时需要根据具体区块链项目调整参数
  2. 需要确保运行时已正确配置所有依赖项
  3. 生产环境应考虑添加错误处理和日志记录
  4. 投票功能需要链上已有对应的提案才能成功执行
回到顶部