substrate入门-常用宏和常用存储类型

substrate常用宏

substrate为了便于模块式的开发,定义了需要的宏;对于开发者来说,只需要按照相应的模板,编写具体的业务逻辑即可,加快了开发速度,下面罗列了常用的一些宏定义

// 定义具体的一个功能模块
#[frame_support::pallet]
pub mod pallet {}

// 定义相关存储类型 
#[pallet::storage]
#[pallet::getter(fn something)]
pub type Something<T> = StorageValue<_, u32>;

// 定义触发的时间类型
#[pallet::event]
#[pallet::metadata(T::AccountId = "AccountId")]
#[pallet::generate_deposit(pub (super) fn deposit_event)]
pub enum Event<T: Config> {}

// 定义错误类型
#[pallet::error]
pub enum Error<T> {}

// 出块前后的回调
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

// 定义具体逻辑处理方法
#[pallet::call]
impl<T: Config> Pallet<T> {}

具体的使用方法,我们可以查看相关的例子,刚开始的时候可能有点懵,没办法要使用这个框架,都必须适应它的规则,这个没啥难度的,花费时间去熟悉即可,具体的一个实例可以参考视频

substrate常用存储类型

  • 在代码 frame_support库中定义,为什么会有这些类型呢, 多数应用都需要存储数据,Substrate底层使用的是RocketDb key-value数据库,在整个基础上进行了封装,为了便于存储数据需要我们需要这些api,下面列出了常用具体的类型和常用的一些方法。
  • 在使用过程中我们需要注意的是,尽量避免无用,耗时的操作(查找,遍历耗时的操作),防止影响节点出块。
  • 尽量避免存储大数据在链上
  • 一般先验证数据,在写入
  • 创造限制边界

StorageValue

StorageValue: 单值的类型,主要存储单个值。

// 在模块中的定义一个存储,存储类型为u32 
#[pallet::storage]
#[pallet::getter(fn something)]                   // 使用宏生成一个获取该值的一个方法 something
pub type Something<T> = StorageValue<_, u32>;     // 定义一个存储类型


// 存储一个number值
Something::<T>::put(number);
// 读取该值 
Something::<T>::get();
// 修改该值
Something::<T>::mutate(|v|v+1);
// 清楚该值 
Something::<T>::kill(); 
// 获取值之后删除
Something::<T>::take();

给类型设置默认值:

// 定义了一个获取默认值的方法 
#[pallet::type_value]
pub fn my_default_value<T: Config>() -> u32 { 1337u32 }

// 作为一个默认值,把方法作为值传入
#[pallet::storage]
#[pallet::getter(fn something)]
pub type Something<T:Config> = StorageValue<_, u32,ValueQuery,my_default_value<T>>;

// 读取该值 
Something::<T>::get(); 

tips:

  • 除了使用以上格式调用之外呢,也还可以使用 <Something<T>>::get() 这样格式调用
  • 其它的类型的调用方法也都大概类似,详细的方法可以查看其api

url:

StorageMap

StorageMap: HashMap类型,存储键值对。

// 定义存储单元 ,存储凭证
#[pallet::storage]
#[pallet::getter(fn proofs)]                // 定义了一个 proofs 函数
pub type Proofs<T: Config> = StorageMap<
    _,
    Blake2_128Concat,                       // 采用的hash算法
    Vec<u8>,                                // Map的Key,存储的hash值
    (T::AccountId, T::BlockNumber)          // Map的value,定义的元组(账号id,区块高度)
>;


// 插入value
Proofs::<T>::insert(&user, entry);
// 获取value
let entry = Proofs::<T>::get(account);
// Take
let entry = Proofs::<T>::take(&user);
// 是否包含该值
Proofs::<T>::contains_key(&user)

Hash算法

  • Blake2 128 Concat
  • TwoX 64 Concat
  • Identity

url:

StorageDoubleMap

StorageDoubleMap : 双键值key Map类型

// 定义存储,使用了Blake2_128Concat 算法定义了双键(u32,AccountId)map,值为 u32
#[pallet::storage]
#[pallet::getter(fn SomeDoubleMap)]
pub type SomeDoubleMap<T: Config> = StorageDoubleMap<_, Blake2_128Concat, u32, Blake2_128Concat, T::AccountId, u32, ValueQuery>;

// 是否包含key
SomeDoubleMap::<T>::contains_key(key1, key2);
// 插入值 
SomeDoubleMap::<T>::insert(key1, key2, value);
// 获取值
SomeDoubleMap::<T>::get(key1, key2);
// 删除值
SomeDoubleMap::<T>::remove(key1,key2);

url:

StorageNMap

StorageNMap : 多键映射类型

// 定义多键值类型 ,key定义的是一个元组,value 是u32类型的 
#[pallet::storage]
#[pallet::getter(fn some_nmap)]
pub type SomeNMap<T: Config> = StorageNMap<
    _,
    (NMapKey<Blake2_128Concat, u32>, NMapKey<Blake2_128Concat, u32>, NMapKey<Blake2_128Concat, u32>),
    u32>;

// 是否存在
SomeNMap::<T>::contains_key(key1,key2,key3));
//插入
SomeNMap::<T>::insert((key1,key2,key3),100);
// 获取
SomeNMap::<T>::get((key1,key2,key3))
// 删除
SomeNMap::<T>::remove((key1,key2,key3))
posted @ 2021-08-09 11:06  NiRao  阅读(565)  评论(0编辑  收藏  举报