上一篇文章编写了存证 pallet 模块,存证单元设置的是 BoundedVec<u8,u32> ,为了使 pallet 更加通用,将 poe 模块修改通过 runtime 设置存证长度限制。(类似于 java 的泛型接口)
修改 config
在 pallet 模板代码3 的位置上通过注释可以看到通过指定 Config 的参数和类型来配置pallet。
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
type MaxBytesInHash: Get<u32>;
type PoeLen: AtLeast32Bit + Copy + Parameter + Default + Bounded + MaxEncodedLen;
}
使用 Config 的参数
// Pallets use events to inform users when important changes are made.
// https://docs.substrate.io/v3/runtime/events-and-errors
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Event emitted when a proof has been claimed. [who, claim]
//(1)
ClaimCreated(T::AccountId, BoundedVec<T::PoeLen, T::MaxBytesInHash>),
/// Event emitted when a claim is revoked by the owner. [who, claim]
ClaimRevoked(T::AccountId, BoundedVec<T::PoeLen, T::MaxBytesInHash>),
ClaimTransaction(T::AccountId, T::AccountId, BoundedVec<T::PoeLen, T::MaxBytesInHash>),
}
// Errors inform users that something went wrong.
#[pallet::error]
pub enum Error<T> {
/// The proof has already been claimed.
ProofAlreadyClaimed,
/// The proof does not exist, so it cannot be revoked.
NoSuchProof,
/// The proof is claimed by another account, so caller can't revoke it.
NotProofOwner,
}
//可调用函数
// Dispatchable functions allows users to interact with the pallet and invoke state changes.
// These functions materialize as "extrinsics", which are often compared to transactions.
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000)]
pub fn create_claim(
origin:OriginFor<T>,
//(2)
proof:BoundedVec<T::PoeLen,T::MaxBytesInHash>,
) -> DispatchResult {
// 检查是否签名
let sender = ensure_signed(origin)?;
//检查 proof 是否已经被 claimed, 是的话 报错 ProofAlreadyClaimed
ensure!(!Proofs::<T>::contains_key(&proof),Error::<T>::ProofAlreadyClaimed);
// 获得当前的块号
let current_block = <frame_system::Pallet<T>>::block_number();
// 向 StorageMap 中插入
Proofs::<T>::insert(&proof, (&sender, current_block));
// 发送 ClaimCreated 通知
Self::deposit_event(Event::ClaimCreated(sender, proof));
Ok(())
}
#[pallet::weight(1_000)]
pub fn revole_claim(
origin:OriginFor<T>,
//(2)
proof:BoundedVec<T::PoeLen,T::MaxBytesInHash>
)->DispatchResult{
let sender = ensure_signed(origin)?;
ensure!(Proofs::<T>::contains_key(&proof), Error::<T>::NoSuchProof);
// StorageMap 获得 value
let (owner, _) = Proofs::<T>::get(&proof).expect("All proofs must have an owner!");
ensure!(sender == owner, Error::<T>::NotProofOwner);
Proofs::<T>::remove(&proof);
Self::deposit_event(Event::ClaimRevoked(sender, proof));
Ok(())
}
#[pallet::weight(1_000)]
pub fn transaction_claim(
origin:OriginFor<T>,
//(2)
proof:BoundedVec<T::PoeLen,T::MaxBytesInHash>,
to_address:T::AccountId
)->DispatchResult{
let sender = ensure_signed(origin)?;
ensure!(Proofs::<T>::contains_key(&proof), Error::<T>::NoSuchProof);
// StorageMap 获得 value
let (owner, _) = Proofs::<T>::get(&proof).expect("All proofs must have an owner!");
ensure!(sender == owner, Error::<T>::NotProofOwner);
// 获得当前的块号
let current_block = <frame_system::Pallet<T>>::block_number();
Proofs::<T>::remove(&proof);
// 向 StorageMap 中插入
Proofs::<T>::insert(&proof, (&to_address, current_block));
Self::deposit_event(Event::ClaimTransaction(sender, to_address,proof));
Ok(())
}
}
////定义存证单元 可选择get函数
#[pallet::storage]
#[pallet::getter(fn proofs)]
pub(super) type Proofs<T:Config> = StorageMap<
_,
Blake2_128Concat,//key加密方式
//(3)
BoundedVec<T::PoeLen,T::MaxBytesInHash>,//key
(T::AccountId,T::BlockNumber),//value
OptionQuery,//查询方式
>;
代码中分别展示了在不同位置使用 config 的实例 (1) ClaimCreated(T::AccountId, BoundedVec<u8, u32>), 改成了 ClaimCreated(T::AccountId, BoundedVec<T::PoeLen, T::MaxBytesInHash>) (2) 展示了如何在 pallet:call 中使用 (3) 展示在 storage 中使用
都是相同的 因为定义声明使用了 <T: Config> 所以可以通过 T 来使用到 Config 里的参数。
在 runtime 指定 config 的参数具体类类型
把之前
impl pallet_poe::Config for Runtime { type Event = Event; }
修改成
impl pallet_poe::Config for Runtime {
type Event = Event;
type MaxBytesInHash = frame_support::traits::ConstU32<64>;
type PoeLen = u8;
}