RLP 有很多问题, 但适合区块链
又一个序列化编码
RLP(“递归前缀编码”)编码是在以太坊中使用的主要序列化格式,并在所有地方都使用-用于区块,交易,账户状态数据和有线协议消息。
比特币的经验
比特币协议中存在一个设计缺陷,即第三方可能会进行您的有效交易并对其进行变异,从而使其保持有效且功能相同,但具有不同的交易ID。 这极大地增加了编写正确的钱包软件的复杂性,并且可以滥用它来使依赖于非突变交易的未确认交易的长链无效(因为交易通过txid相互引用)。
此问题来自多个来源,其中之一是OpenSSL愿意接受并理解具有无效编码的签名。 正常的ECDSA签名会编码两个大整数,但编码长度不是固定的-如果有前导零,则应该丢弃它们。
关键是适用性
假设签名是固定长度,然后在其中保留多余的前导零,则编写软件很容易。
这是一个非常有趣的警示故事,并且尤其重要,因为此类情况是我们在开发理念中做出某些设计决策的原因之一。具体来说,问题是这样的:许多人继续指出,我们在许多地方不必要地重新发明了轮子,创建了自己的序列化格式RLP,而不是使用现有的protobuf,我们正在构建特定于应用程序的脚本语言,而不是“仅使用Lua”。这是一个非常有效的担忧;非此处发明综合症是一种常用的贬义词,因此进行这种内部开发确实需要证明。
上面引用的警示故事恰好提供了上述的辩护的完美示例。外部技术,无论是protobuf,Lua还是OpenSSL,都非常好,并且拥有多年的开发经验,但是在很多情况下,它们从来没有考虑到加密货币所需的完美共识,确定性和加密完整性。上面的OpenSSL情况就是一个很好的例子。除了加密货币之外,实际上没有其他情况可以使用有效签名并将其转换为具有不同哈希值的另一个有效签名这一事实,这是一个重大问题,但这是致命的。以太坊的核心原则之一就是简单。该协议应尽可能简单,并且该协议不应包含任何黑框。每个子协议的每个功能都应该准确地100%记录在白皮书或Wiki中,并以该功能作为规范来实现(即测试驱动的开发)。可以说,对现有的软件包执行此操作几乎与从头开始构建全新的软件包一样困难。实际上,这可能甚至更难,因为现有软件包通常具有比其完整的功能更复杂的功能,而我们的替代品则不需要-阅读protobuf规范并将其与RLP规范进行比较以了解我的知识。意思。
请注意,上述原则有其局限性。例如,我们当然不会愚蠢地开始发明自己的哈希算法,而是使用广受赞誉和经过严格审查的SHA3,并且对于签名,我们使用与比特币相同的旧secp256k1,尽管我们使用RLP进行存储v,r,s三元组(v是用于公共密钥恢复的额外两位),而不是OpenSSL缓冲区协议。在这种情况下,“仅使用X”就是正确的选择,因为X具有清晰易懂的界面,并且不同的实现之间没有细微的差异。空字符串的SHA3在C ++,Python和Javascript中为c5d2460186…a470;没有关于它的辩论。在这两个极端之间,基本上是要找到适当的平衡。
RLP做出的简化
RLP的替代品将使用现有的算法,例如protobuf或BSON; 但是,我们更喜欢RLP,因为
- 实现简单
- 确保绝对的字节完美一致性。
许多语言中的键/值映射没有明确的顺序,浮点格式有很多特殊情况,有可能导致同一数据导致不同的编码,从而导致不同的哈希。 通过内部开发协议,可以确保在设计这些协议时便牢记这些目标(这是一条通用原则,也适用于代码的其他部分,例如VM)。 请注意,虽然BitTorrent使用的bencode与长度的十进制编码相比,它与二进制RLP相比稍差一些,但它可能为RLP提供了一种可替代的选择。
参考
RLP规范描述