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))