KV-Witness会不会是另一种高效区块见证方法?
2020-07-31 11:57 栏目:经验之谈 来源:网络整理 查看()
目前,无状态以太网中提出了一种块见证格式,它在GitHub repo中有一个规范。它是基于操作码的,你可以想象只有一个命令可以生成Merkle mupolitize的小型编程语言。
本文研究了块见证构造的另一种方法。它是基于键和值的列表,语义更简单。
在本文中,我将尝试回答以下问题:
1.什么是千伏-见证格式?它与当前提议的(基于操作码的)见证格式有什么不同?
2.比较千伏的优点和缺点是什么?
3.就网络带宽而言,这种格式的效率如何?
要求
任何集体证人必须符合以下要求:
正确性:我们可以使用这种格式正常运行以太网主网络的任何块。
效率:我们可以用最小的网络带宽来传送这个证人。
默克尔化见证格式必须支持默克尔代码。
独立性不可知:见证格式必须支持六进制和二进制Merkle尝试。
语义学
我在文章的这一部分描述的见证格式是语义的。我在这里不是在说确切的字节布局。
稍后,我将详细介绍用于测试的见证的确切二进制格式。
见证:=标题、正文、校样
报头:=版本:字节,trie_arity :字节
正文:=数组[ { type: byte key : []byte,value : []byte } ]
校样:=映射{ type: [ { prefix : []byte,hash : []byte } ] }
见证机构
见证机构由两个要素组成:
1、数据。
密钥可以是帐户地址、存储密钥或代码密钥,值分别是帐户、存储项目或代码块。证人身体的这一部分与用来验证其正确性的默克特里无关。此外,如果我们使用其他方法来检查正确性,这一部分将不会改变。
2、证据。
关键是Merkle路径和哈希值。根据不同的原则,十六进制和二进制的尝试会有所不同。这个语义允许不同类型的多个证明被包含在同一个见证中。因此,在理论上,我们可以成为支持十六进制和二进制的证人。
正文在字典中按字母顺序排序,请确保:
较短的键在列表的前面(因此我们重建了trie);从上到下);
当密钥相同时(这可能发生在帐户和代码之间),帐户总是第一位的。
解析算法
1.验证见证版本和证书Arity(确保见证证书Arity与此块所需的Trie Arity相匹配)。
2.验证见证哈希(如果有规范的见证)。
3.创建一个正确的空trie。
4.遍历数据,只需将数据按顺序插入这个trie(见证应该按照字典顺序排序)。
5.将证据插入trie。
6.验证根哈希(它应该与前一个块的根哈希匹配)。
优点和缺点
下面列出了基于操作码比较千伏见证和当前见证格式的优缺点。
优势
它与平面数据库结构相匹配,如果规范的见证哈希有效,可以立即插入(无需验证Merkle根)。
它可用于快照同步。
见证数据独立于我们选择的有效性证明方法:默克尝试或多项式承诺或其他。
不足之处
由于字节对齐(例如,校验码0b01,即2位将占用一个字节的存储空间),二进制尝试可能会占用更多的网络空间。
证人分析可能很慢。
带宽效率研究
kv见证实例的实现
我们需要能够证明格式的正确性。它应该能够在以太网主网络的所有模块上运行。
因此,我在turbo-geth存储库的一个分支中实现了这种见证格式:kv-见证-研究。
该实现已经在谷歌云5 . 000 . 000–8 . 000 . 000以太网主网络上进行了测试。
如何重复实验?
您需要至少200GB的可用空间和至少32gbs的内存(代码是PoC,优化程度不高)。
1)复制turbo-geth的kv-witness-research分支(提交a6 B4 DC 609 B3 d 871 c 78597 a 71 AC 08601 f 17 de 53
2)(在我的示例中,同步主网络的报头和主体花费了1天时间:run。/cmd/geth-同步模式分段-data dir ~/无状态链数据/
3)(在我的示例中花了17天)在这些数据上运行无状态原型。
快跑。/cmd/state无状态-block source ~/无状态-chaindata/geth
/chain data-state file ~/kv _ witness _ state file-证人间隔
5000000-stats file ~/stats _ kv _ witness . CSV 21 | tee debug . log
这样,您应该在stats_kv_witness.csv中获得与此文档相同的统计信息.
见证二进制格式
见证以包含版本:标头的单字节标头开始。
然后,有一个见证体,它由大小(1-4字节,取决于见证元素的数量)和元素本身组成。
每个元素都以单字节类型开始,后跟一个关键字字段,它是一个任意大小的字节数组,前缀是大字节和小字节(就像body一样),后面是实际数据。
数据取决于元素的类型:
对于存储叶,它是由字节大小决定的任意大小的字节数组;
对于代码叶,它也是一个任意大小的字节数组,以大小字节为前缀;
为了证明这一点,它是一个固定大小的32字节哈希值,没有任何大小的前缀。
对于会计来说,它更复杂,但基本上是:
标记字节(掩码,用于说明帐户元素是否没有默认值)
随机数,8字节(如果是随机数!=0)
平衡(如果平衡!=0),任何大小的字节数组,以其大小为前缀;
存储根哈希(如果不是空的),32字节,固定大小的字节数组;
代码哈希(如果代码不是空的),32字节,固定大小的字节数组。
最后,我们得到如下结果:this :[header witness _ elements _ count element 1 _ type element 1 _ key _ size element 1 _ key _ byte 1.element1 _ value _ size.element2 _ type.]
优化:删除关键前缀的重复数据
密钥是由半字节组成的Merkle路径,而不是全字节。十六进制trie的单个半字节大小为4位,而二进制trie的单个半字节大小为1位。这样,我们可以看到有时密钥可以是非整数字节:(例如,12位是8,5字节)。
键码是[]字节,它是字节对齐的(因此,len在4到5字节之间的键总是5字节)。类似地,一个额外的“屏蔽”字节被添加到开头,以显示最后一个字节中的哪些位是“活动的”。
Akey0xff (1字节):[00001000 11111111]==8个有效位
密钥0b11 (2位):[00000010 11000000]==2个有效位
Akey 0b10 (2位):[00000010 1000000]==2个有效位
密钥0b_10101010_01010101_1101(2字节4位):[11110000 10101010 01010101 11010000]
然后,我们可以添加一个简单的优化,这样我们就可以减少数据和证据中的重复前缀。
为了提高压缩效率,我们将数据和证明混合在同一个有序映射中。
报头字节的最高四位代表前一个密钥的字节偏移量。
因为关键字是根据我们的语义排序的,所以我们可以用前4个字节来描述以下情况:
该键与前一个键相同,然后整个键可以减少到1字节:[10000000]
密钥不与前一个密钥共享任何字节([0000xxxxx
售前客服二维码
文章均源于网络收集编辑侵删
提示:仅接受技术开发咨询!
郑重申明:资讯文章为网络收集整理,官方公告以外的资讯内容与本站无关!