上一篇文章使用decl_module!宏创建了Substrate版本的Hello World,decl_module!宏用于定义处理业务逻辑的外部调用函数,并没有涉及到数据存储。 Substrate模块通过decl_storage!宏来声明数据存储,下面介绍decl_storage!宏的相关用法。 声明一个StorageMap StorageMap是Substrate中的HashMap(哈希表),是一种使用键值对(key-value)存储数据的数据结构,使用如下代码声明一个StorageMap: decl_storage! { trait Store for Module<T: Trait> as SimpleMap { SimpleMap get(fn simple_map): map hasher(blake2_128_concat) T::AccountId => u32; } } 这段代码包含的要点有: SimpleMap:存储数据的HashMap名称;get(fn simple_map):一个getter函数,返回从哈希表中获取的值;map hasher(blake2_128_concat):声明使用的哈希表类型,这里使用的是blake2_128_concat hasher;T::AccountId => u32:哈希表的键和值的数据类型,这里是键的类型是AccountId,值的类型是u32;Substrate提供三种哈希表类型:blake2_128_concat、twox_64_concat、identity,一般使用blake2_128_concat即可。 StorageMap API 下面是一些StorageMap常用的API。 添加数据<SimpleMap<T>>::insert(&user, entry); 获取数据let entry = <SimpleMap<T>>::get(account); let entry = <SimpleMap<T>>::take(&user); 检查数据<SimpleMap<T>>::contains_key(&user) 更多API可参考StorageMap文档,StorageMap不需要显式使用,decl_storage!已经完成了这部分工作。 编写模块代码 修改pallets/template/src/lib.rs代码如下: #![cfg_attr(not(feature = "std"), no_std)] use frame_support::{decl_module, decl_storage, dispatch::DispatchResult}; use frame_system::ensure_signed; pub trait Trait: frame_system::Trait {} decl_storage! { trait Store for Module<T: Trait> as SimpleMap { SimpleMap get(fn simple_map): map hasher(blake2_128_concat) T::AccountId => u32; } } decl_module! { pub struct Module<T: Trait> for enum Call where origin: T::Origin { #[weight = 10_000] fn set_single_entry(origin, entry: u32) -> DispatchResult { let user = ensure_signed(origin)?; <SimpleMap<T>>::insert(&user, entry); Ok(()) } } } 这段模块代码在decl_storage!中定义了一个StorageMap,在decl_module!中定义了一个模块函数set_single_entry用于存储一个u32类型的数据。 No std #![cfg_attr(not(feature = "std"), no_std)] 这句代码放在模块代码的最开头,表示除非明确告知,否则此模块不使用Rust标准库,因为Substrate runtime会把代码编译为Rust标准库不可用的Wasm二进制文件。 Weight注解 #[weight = 10_000] 配置默认调用权重,权重会影响用户调用该函数将要支付的费用。 修改runtime配置 runtime/src/lib.rs文件包含有关构成runtime的所有模块细节,对于每个模块都有如下处理流程: 1、导入包含该模块的Rust文件 2、实现其Trait 3、将该模块包含在construct_runtime!宏中 此处在construct_runtime!宏中添加了三种类型(Module、Call、Storage): TemplateModule: pallet_template::{Module, Call, Storage}, 所有这些类型都是由模板中定义的宏生成的。 编译 编译命令如下: cd substrate-node-template cargo +nightly-2020-08-23 build --release 使用了nightly-2020-08-23这个较稳定的cargo nightly版本以避免编译过程中出现bug。 测试 启动node-template ./target/release/node-template --dev 打开https://polkadot.js.org/apps,切换网络为DEVELOPMENT-Local Node: 选项卡选择开发者-交易,“提交下面的外部信息”选择templateModule,会自动获取到定义的函数saySingleEntry(entry): 可以设置函数参数entry的值,这里我设置了123。 点击右下角“提交交易”按钮,点击“签名并提交”: 就会调用decl_module!中定义的set_single_entry函数,存储123这个值到decl_storage!中定义的SimpleMap中。 选项卡选择开发者-链状态-存储,“查询所选状态”选择templateModule,会自动获取到定义的哈希表SimpleMap,AccountId选择ALICE,点击右侧加号可以获取刚刚存储的值: 下一篇文章介绍如何定义和触发事件(Event)。 —- 编译者/作者:松果 玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。 |
【Substrate开发教程】16 - Substrate声明存储宏decl_storage!的使用
2020-10-30 松果 来源:区块链网络
- 上一篇:浅谈DeFi中的税收风险
- 下一篇:尽管安全令牌增长强劲,tZERO仍在亏损
LOADING...
相关阅读:
- 重新定义财务:10月21日至28日,Harvest Finance充满好奇的案例2020-10-29
- 史诗浏览器:5个特征将其定义为浏览的安全选项2020-10-29
- 【Substrate开发教程】13 - 模块(Pallets)2020-10-27
- 马云:数字货币一定会重新定义货币2020-10-24
- 长假=去嗨皮?年轻人别活在他人的定义里,更别被暴富心理毁掉你的投2020-10-05