其他分享
首页 > 其他分享> > Substrate区块链应用开发-存证模块的功能开发

Substrate区块链应用开发-存证模块的功能开发

作者:互联网

Substrate区块链应用开发-存证模块的功能开发

链上存证介绍

在这里插入图片描述

最小化substrate代码开发

来源substrate官方维护的最小框架

substrate-node-template 是substrate的最小化框架,最小实现,麻雀虽小,五脏俱全,适合新手入门和理解substrate
https://github.com/substrate-developer-hub/substrate-node-template

关注pallets和runtime

1. pallets template

存证模板

2.runtime

应用实现
在这里插入图片描述

pallets poe 模块编写

poe : proof of existence

建立poe模块
1.复制pallets/template 为 pallets/poe

在这里插入图片描述

2.修改poe的Cargo.toml配置文件

修改[package]的description和name
描述和名字可自定义
在这里插入图片描述

3.修改poe的lib.rs文件

认识lib.rs构成
lib.rs:模板引入依赖、主程序、存储单元(宏)、事件(宏)、异常处理(宏)、可调用函数(宏)
在这里插入图片描述

4. decl_storage 定义存储单元

目标:先定义一个存储单元,用于存储存在归属信息
代码实现:
(1) 定义一个存储项 Proofs,给它一个default get散户,称之为 proofs
(2) 给Proofs设置类型为map,map的key是Vec,即存证hash值,由于无法得知使用哪些hash函数,所以使用变长类型u8
(3)存证归属信息需要归属到一个人身上,以及它在哪个时间点被存储。这里定义一个tuple,给定两个参数,一个是用户信息(AccountId),一个是区块链时间(BlockNumber)
(4)由于Vec是由用户输入,属于非安全的,这里得使用blake2_128_concat
(5)一个简单存储单元编码完成,可以使用cargo check或者cargo build来检查语法是否有错误
(6)使用了Vec,需要引入依赖

use sp_std::prelude::*;  // 使用了Vec

在这里插入图片描述

5. decl_module 创建存证

注意:Proofs存储项是在decl_storage存储单元中定义的
(1)我们需要创建一个存证,创建存证需要有两个关键参数:交易发送方origin,和存证hash值claim,由于存证使用的hash函数是未知的,也需要和上面decl_storage定义对应,这里需要使用变长Vec来保存存证
(2)创建存证之前,我们需要“Verify First,Write Last”的原则,先对存证内容进行检查,检查两个方面:
:交易发送方是不是一个签名的用户;
:存证是否被别人创建过,创建过就得抛出异常(由decl_error处理)
(3)通过ensuer_signed来验证存证拥有人sender就是交易发送方origin
(4)通过Proofs::::contains_key传参claim的引用去获取存证,不存在就抛出异常Error::::ProofAlreadyExist,该异常ProofAlreadyExit需要由decl_error处理
(5)如果通过检查校验,开始插入操作:insert是一个map的key-value插入操作,这里的key-value是一个tuple,这个tuple的第一个元素是AccountId;第二个元素是当前交易所处的区块,使用系统模块提供的block_number工具方法获取;
(6)插入完毕,触发一个event时间来通知客户端,RawEvent由宏生成(为啥使用该宏?)

        // 创建存证,创建存证需要有两个关键参数:交易发送方origin,存证hash值claim,由于存证hash函数未知,也和decl_storage定义对应,这里使用变长Vec<u8>
        #[weight = 0]
		pub fn create_claim(origin,claim:Vec<u8>)->dispatch::DispatchResult{
			// 做必要检查,检查内容: 1,交易发送方是不是一个签名的用户 2,存证是否被别人创建过,创建过就抛出错误
			// 首先去创建签名交易,通过ensure_signed这样的system提供的版本方法来校验
			let sender = ensure_signed(origin)?;  // 存证拥有人是交易发送方,只有拥有人才可以调用存证,sender即当前交易发送方
  			// 如果存在存证,返回错误 ProofAlreadyExist
  			// ps:ensure!宏是确保表达式中的结果为true,这里取反操作
			ensure!(!Proofs::<T>::contains_key(&claim),Error::<T>::ProofAlreadyExist);  // 这里用到一个错误  ProofAlreadyExist,该错误需要在decl_error声明
			// 做insert操作,insert是key-value方式。这里的key-value是一个tuple
			// 这个tuple的第一个元素是AccountId;第二个是当前交易所处的区块,使用系统模块提供的block_number工具方法获取
			Proofs::<T>::insert(&claim,(sender.clone(),system::Module::<T>::block_number()));  // 插入操作
			// 触发一个event来通知客户端,RawEvent由宏生成;   sender:存在拥有人;claim:存在hash值 通过event通知客户端
			Self::deposit_event(RawEvent::ClaimCreated(sender,claim));   // ClaimCreated事件,需要decl_event处理
			// 返回ok
			Ok(())

		}
6.decl_error 异常处理

将decl_module中定义的存证异常ProofAlreadyExist,需要在decl_error中声明

// 异常处理
// The pallet's errors
decl_error! {
	pub enum Error for Module<T: Trait> {
		ProofAlreadyExist,    // 存在异常,即存证已经存在
	}
}
7. decl_event 事件处理

将decl_module中定义的ClaimCreated事件在decl_evnet中声明处理

// 事件
// The pallet's events
decl_event!(
	pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
		ClaimCreated(AccountId,Vec<u8>),  // 用户AccountId,存证内容 Vec<u8>
	}
);
8. 撤销存证
#[weight = 0]
		pub fn revoke_claim(origin,claim: Vec<u8>) -> dispatch::DispatchResult{
			let sender = ensure_signed(origin)?;  // 交易发送方式已签名的, 存证拥有人是交易发送方,只有拥有人才可以吊销存证

  			// 判断存储单元里面是存在这样一个存证;如果不存在,抛出错误,错误我们叫ClaimNotExist
			ensure!(Proofs::<T>::contains_key(&claim),Error::<T>::ClaimNotExist);

			// 获取这样的存证  owner: accountId   block_number
			let (owner,_block_number) = Proofs::<T>::get(&claim);  // 通过get api获取这样的一个存证

			ensure!(owner == sender,Error::<T>::NotClaimOwner);  // 确保交易发送方是我们的存证人,如果不是,返回Error,这个Error我们叫NotClaimOwner

			// 以上校验完成之后,我们就可以删除我们的存证
		    // 存储向上调用remove函数进行删除
		    Proofs::<T>::remove(&claim);

			// 触发一个事件,返回存证人和hash
		    Self::deposit_event(RawEvent::ClaimRevoked(sender,claim));

			// 返回
			Ok(())


		}
9. 将第8步中用到的异常处理和事件进行声明
// 事件
// The pallet's events
decl_event!(
	pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
		ClaimCreated(AccountId,Vec<u8>),  // 用户AccountId,存证内容 Vec<u8>
		ClaimRevoked(AccountId,Vec<u8>),
	}
);

// 异常处理
// The pallet's errors
decl_error! {
	pub enum Error for Module<T: Trait> {
		ProofAlreadyExist,    // 存证已经存在
		ClaimNotExist,
		NotClaimOwner,
	}
}

在runtime中引入poe模块

在runtime/Cargo.toml 中添加poe模块

# 引入poe依赖
[dependencies.poe]
default-features = false
package = 'pallet-poe'
path = '../pallets/poe'
version = '2.0.0-rc2'
[features]
default = ['std']
std = [
    'aura/std',
    'balances/std',
    'codec/std',
    'frame-executive/std',
    'frame-support/std',
    'grandpa/std',
    'randomness-collective-flip/std',
    'serde',
    'sp-api/std',
    'sp-block-builder/std',
    'sp-consensus-aura/std',
    'sp-core/std',
    'sp-inherents/std',
    'sp-io/std',
    'sp-offchain/std',
    'sp-runtime/std',
    'sp-session/std',
    'sp-std/std',
    'sp-transaction-pool/std',
    'sp-version/std',
    'sudo/std',
    'system/std',
    'timestamp/std',
    'transaction-payment/std',
    'template/std',
    'poe/std',  # 增加标签
]

在runtime/src/lib.rs中引入配置接口

实现配置接口
/// 对配置接口进行实现
impl poe::Trait for Runtime{
	type Event = Event;
}
引入poe接口对应的操作信息
construct_runtime!(
	pub enum Runtime where
		Block = Block,
		NodeBlock = opaque::Block,
		UncheckedExtrinsic = UncheckedExtrinsic
	{
		System: system::{Module, Call, Config, Storage, Event<T>},
		RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},
		Timestamp: timestamp::{Module, Call, Storage, Inherent},
		Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
		Grandpa: grandpa::{Module, Call, Storage, Config, Event},
		Balances: balances::{Module, Call, Storage, Config<T>, Event<T>},
		TransactionPayment: transaction_payment::{Module, Storage},
		Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},
		// Used for the module template in `./template.rs`
		TemplateModule: template::{Module, Call, Storage, Event<T>},
		// 引入poe对应模块的操作信息  Module: 模块  Call:调用函数  Storage:存储项  Event<T>:事件  Error不需要额外引入
		PoeModule: poe::{Module, Call, Storage, Event<T>},
	}
);

标签:std,decl,poe,Substrate,claim,存证,Module,区块
来源: https://blog.csdn.net/xkjscm/article/details/106536228