cosmos-store
Cosmos state
在使用时有用到查询存储的值的api,这个api不仅返回了key对应的value,还返回了proof。使用proof可证明这个value的确存储在链上。这是怎么证明的呢?
翻了下源码,大概了解到是怎么证明的了。随手也记录一下。
首先,在cosms-sdk中的设计是插件式,可以据情况使用x/
包下的插件。
在存储上的话,使用的是store/rootmulti/store.go
.. ,根据包名猜测下是会有多颗树,然后每颗一个root,多个root又组成一颗树。根据上面的插件,所以就是据情况多个插件,多颗树吧。
源码分析
store/rootmulti/store.go
1 | type Store struct { |
主要看到1、2、3处为map结构。3的话比较明显是key是string类型,value是封装的某Key类型,这个某Key类型刚好是1和2的 key,注意到1的value类型是storeParams,好像只是参数,不是我想要的树结构。但是2的类型types.CommitKVStore
,看起来有点像。types.CommitKVStore
是接口类型,实现有store/transient/store.go
和store/iavl/store.go
,这里iavl好像很熟悉…gaia中对store实例化默认选择的是iavl。那么ival
就是我想找的答案啦。
ival
store/iavl/store.go
里有我想找的tree结构,但…时间限制..我没看实现🤦♀️
简单而言,我选择从测试入手… 首先是这里面的tree的存储是带有版本的..相当于会根据版本存储
1 | //store/iavl/store_test.go |
rootmulti
然后再回来看rootmulti/store
同样,还是看测试store/rootmulti/store_test.go
1 | func TestHashStableWithEmptyCommit(t *testing.T) { |
更多测试可在``store/rootmulti/store_test.go`中。
结论是,首先会添加多个key值,每个key一个树,然后这些树的roothash作为rootmulti树的叶子节点,组成树,计算出来的root-hash会作为apphash存储在区块头中。那些小树的叶子节点的值就是存储的具体的内容啦。
证明key-value确实在区块头的方式是,首先证明key-value在某颗小树上(store-key下),其次计算出小树的roothash,再使用roothash计算出apphash,与区块头的apphash对比即可证明。
在使用的时候,选择的区块高度,证明为到这个区块为止,这个数据是存在的。
最后结论草草结尾,有时间再细化。