在Cashbox动态库功能的开发中,我们对基于Substate开发的链转账功能进行了支持。这篇文章的目的是借助介绍构造账户信息查询key的过程,顺便说明substrate中的存储key设计原理。 查询方式 Substrate提供了一整套RPC方法,涉及链信息、存储查询、交易提交等功能,由于不同的链启用的模块有所区别,针对具体使用链节点,可以通过默认的UI界面发送rpc_methods来查询当前节点所支持的所有的rpc方法; 针对本文接下来介绍存储查询,我们主要使用state_getStorage这个RPC方法来实现;该方法需要一个十六进制类型参数来构造rpc请求,请求格式如下:{"id":1,"jsonrpc":"2.0","method":"state_getStorage","params":["xxx"]}本文接下来重点主要用来介绍该参数的构造过程。了解存储key构造过程的朋友,可以忽略以下内容。 Substrate存储方式 Substrate使用??RocksDB来实现数据的持久化,为链平台提供快速高效的键值对存储服务,满足各客户端组件所需要的数据服务。这里不再对RocksDB进行详细的介绍。为了能够将链上所有数据存储到数据库中,同时还能实现对数据高效查询,隐私保护等要求,需要对存储数据的进行编码。这里涉及到键的构造,值的序列化过程。关于值的序列化与反序列化,打算后期再整理一篇文章来说明,在本文中先暂时忽略。 与链业务相关的功能是在Frame模块中实现,与存储相关的数据类型定义类似以下过程: decl_storage!?{ ?????????trait?Store?for?Module<T:?Trait>?as?Example?{ ???????????????????Foo?get(fn?foo)?config():?u32=12; ???????????????????Bar?get(fn?bar):?map?hasher(blake2_128_concat)?T::AccountId?=>?T::Balance; ???????????????????pub?Zed?double_map?hasher(blake2_128_concat)?T::BlockNumber,?hasher(twox_64_concat)?T::BlockNumber?=>?Option<T::BlockNumber>; ?????????} ?} 我们称模块名字为module_prefix,存储项名称为storage_prefix。如上代码所示,Example是module_prefix,Foo、Bar、Zed是storage_prefix。其中针对存储项的类型主要有以下三种情况,键构造方式有所区别: lStorage Value:这种类型的定义Foo: type,键的构造直接使用Twox128(module_prefix) ++ Twox128(storage_prefix)这种方式即可,整个构造过程比较简单; lStorage Maps:这种类型的定义Foo: map hasher($hash) type => type,最终的键是由twox128(module_prefix) ++ twox128(storage_prefix) ++ hasher(encode(key))这三部分组合构成的,这里需要注意的是,由于Map是通过KV这种方式来存储数据的,所以针对Map来说,还需要对Map中的键进行hash计算,计算使用的算法即为hasher所表示的。当前具体支持的hash算法在稍后来进行说明; lStorage DoublMap:这种类型的定义Foo: double_map hasher($hash1) u32, hasher($hash2) u32 => u32,用于支持更复杂的数据类型,最终的键是由Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2))这四部分组合构成; 支持的hash算法 当前在存储类型定义时,使用的hasher有三种类型,他们对应的使用场景如下: lblake2_128_concat:针对任一存储项是默认的选择,前缀blake2b表明该算法为加密安全的hash算法,最后将原始的数据附加在hash结果的后面; ltwox_64_concat:该算法为不安全的hash算法,只能用于你确定该键不能由用户任意构造的场景,该算法拥有相当好的性能,内存利用率高,并且支持键和值的迭代;参数的构造过程同blake2_128_concat类似; lidentity:这不是hash算法,它会直接使用键。由于它不进行hash计算或者追加值,因此速度是最快的,但是也是最不安全的。仅当该key是通过类似blake2算法计算出来的值时,才可以安全的使用它; 以Alice的Account ID?5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY为例,针对使用hasher算法为blake2_128_concat的存储项定义如下: Bar?get(fn?bar):?map?hasher(blake2_128_concat)?T::AccountId?=>?T::Balance; hasher计算的过程如下: 将对应Account ID转换为十六进制表示:0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d,通过blake2_128计算出来的结果为0xde1e86a9a8c739864cf3cc5ec2bea59f,最终的表示结果为 0xde1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d--------------?hash?--------------++++++++++++++++++++++++++?raw?key?+++++++++++++++++++++++++++++ 关于这方面内容的介绍,可以查看源码frame/support/procedural/src/lib.rs中相关注释; 如何使用 通过前面的各种铺垫,将查询存储key值编码所需的准备工作已经完成。针对在cashbox中使用比较多的场景,是查询用户的余额,通过源码我们可以知道账户信息存放的位置: trait?Store?for?Module<T:?Trait>?as?System?{ ????///?The?full?account?information?for?a?particular?account?ID. ??????????pub?Account?get(fn?account): ???????????????????map?hasher(blake2_128_concat)?T::AccountId?=>?AccountInfo<T::Index,?T::AccountData>; ????} 还是继续使用Alice这个账户为例,动态库根据cashbox flutter模块传递进来的相关参数,通过存储方式部分的内容知道该使用哪种方式来拼接最终结果,其中:twox128("System")得到的结果为0x26aa394eea5630e07c48ae0c9558cef7,twox128("Account")得到的结果为0xb99d880ec681799c0cf30e8886371da9,最终得到的查询key值为:0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d; Flutter根据动态库返回的结果,构造JsonRpc请求{"id":1,"jsonrpc":"2.0","method":"state_getStorage","params":["0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"]},链服务端将返回该Account ID对应的账户信息,类似如下结果0x24000000000000000000ecfaea666eb30a13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; 总结 本文针对常规模块中的存储项查询key的编码方案进行了详细的说明,在了解了存储键的编码规则后,借助JsonRpc方法,能够很方便的查询到各个frame中定义的存储类型。针对查询出来的结果值解码方案,计划在下一篇文章中来进行说明. —- 编译者/作者:scry 玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。 |
SCRY技术分享Substrate链存储查询介绍
2021-06-18 scry 来源:区块链网络
LOADING...
相关阅读:
- Swarm机制中的流量激励是什么?2021-06-18
- 寻找币市中没有中间商瞎折腾的DEX!2021-06-18
- 加密原生保险的春天:Helmet2021-06-17
- POS:科技时代又一个伟大的算法发明2021-06-17
- 区块链技术助力中小微企业融资2021-06-17