Rust区块链索引管理库pallet-indices的使用:高效账户索引与Substrate链上ID管理
Rust区块链索引管理库pallet-indices的使用:高效账户索引与Substrate链上ID管理
索引是地址的简短形式。该模块处理为新创建的账户分配索引。
许可证:Apache-2.0
安装
在项目目录中运行以下Cargo命令:
cargo add pallet-indices
或者在Cargo.toml中添加以下行:
pallet-indices = "42.0.0"
完整示例代码
以下是一个更完整的pallet-indices使用示例,展示了账户索引的生命周期管理:
// 导入必要的模块和库
use frame_support::{
decl_module, decl_storage, decl_event, decl_error,
dispatch, ensure, traits::Currency
};
use frame_system::{self as system, ensure_signed, ensure_root};
use sp_runtime::traits::{StaticLookup, LookupError, Zero};
use pallet_indices::{self as indices, Index};
/// 配置模块的trait
pub trait Trait: system::Trait + indices::Trait {
/// 事件类型
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
/// 货币类型
type Currency: Currency<Self::AccountId>;
}
// 存储定义
decl_storage! {
trait Store for Module<T: Trait> as IndexDemo {
/// 账户到值的映射
AccountData get(fn account_data):
map hasher(blake2_128_concat) T::AccountId => u128;
/// 系统保留的索引
ReservedIndices get(fn reserved_indices): Vec<Index>;
}
}
// 事件定义
decl_event!(
pub enum Event<T>
where
AccountId = <T as system::Trait>::AccountId,
Index = indices::Index,
{
/// 新索引已分配
NewIndexAssigned(AccountId, Index),
/// 索引已冻结
IndexFrozen(Index),
/// 索引已解冻
IndexThawed(Index),
/// 索引已转移
IndexTransferred(Index, AccountId),
/// 数据已更新
DataUpdated(AccountId, u128),
}
);
// 错误定义
decl_error! {
pub enum Error for Module<T: Trait> {
/// 账户已有索引
AlreadyIndexed,
/// 索引无效
InvalidIndex,
/// 余额不足
InsufficientBalance,
}
}
// 模块实现
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
type Error = Error<T>;
fn deposit_event() = default;
/// 为账户分配新索引
#[weight = 10_000]
pub fn assign_index(
origin,
who: <T::Lookup as StaticLookup>::Source
) -> dispatch::DispatchResult {
let sender = ensure_signed(origin)?;
// 解析目标账户
let who = T::Lookup::lookup(who)?;
// 检查账户是否已有索引
if indices::Module::<T>::lookup_index(&who).is_ok() {
return Err(Error::<T>::AlreadyIndexed.into());
}
// 分配新索引
let index = indices::Module::<T>::claim(sender.clone(), who.clone())?;
// 发出事件
Self::deposit_event(RawEvent::NewIndexAssigned(who, index));
Ok(())
}
/// 冻结指定索引
#[weight = 10_000]
pub fn freeze_index(origin, index: Index) -> dispatch::DispatchResult {
ensure_root(origin)?;
// 冻结索引
indices::Module::<T>::freeze(index)?;
// 发出事件
Self::deposit_event(RawEvent::IndexFrozen(index));
Ok(())
}
/// 更新账户数据并检查索引
#[weight = 10_000]
pub fn update_data(
origin,
value: u128
) -> dispatch::DispatchResult {
let who = ensure_signed(origin)?;
// 检查账户是否有索引
let index = indices::Module::<T>::lookup_index(&who)?;
// 检查索引是否被冻结
ensure!(
!indices::Module::<T>::is_frozen(&index),
Error::<T>::InvalidIndex
);
// 更新存储
<AccountData<T>>::insert(&who, value);
// 发出事件
Self::deposit_event(RawEvent::DataUpdated(who, value));
Ok(())
}
/// 保留系统索引
#[weight = 10_000]
pub fn reserve_system_index(origin, index: Index) -> dispatch::DispatchResult {
ensure_root(origin)?;
// 保留索引
<ReservedIndices>::mutate(|v| v.push(index));
Ok(())
}
}
}
// 实现一些辅助函数
impl<T: Trait> Module<T> {
/// 检查索引是否被保留
pub fn is_index_reserved(index: &Index) -> bool {
<ReservedIndices>::get().contains(index)
}
/// 获取账户数据
pub fn get_account_data(who: &T::AccountId) -> Option<u128> {
<AccountData<T>>::get(who)
}
}
功能说明
- 完整的索引生命周期管理:包含索引分配、冻结、解冻等操作
- 权限控制:部分功能限制为root账户使用
- 状态检查:包含索引有效性检查、保留状态检查等
- 存储管理:展示了如何存储和管理与索引关联的数据
- 事件系统:详细的事件记录机制
进阶用法扩展
// 获取账户的索引
let account_id = // 获取账户ID;
match indices::Module::<T>::lookup_index(&account_id) {
Ok(index) => {
log::info!("Account {} has index {}", account_id, index);
},
Err(_) => {
log::warn!("Account {} has no index assigned", account_id);
}
}
// 批量分配索引
for account in new_accounts.iter() {
let _ = indices::Module::<T>::claim(sender.clone(), account.clone());
}
// 检查并解冻索引
if indices::Module::<T>::is_frozen(&index) {
indices::Module::<T>::thaw(index)?;
}
// 管理员强制转移索引
indices::Module::<T>::force_assign(admin, index, new_account)?;
这个完整示例展示了pallet-indices在实际应用中的综合使用方式,包括索引管理、权限控制和数据存储等核心功能。
1 回复