RLP

Trie树的序列化和反序列化

序列化主要是指把内存表示的数据存放到数据库里面, 反序列化是指把数据库里面的Trie数据加载成内存表示的数据。 序列化的目的主要是方便存储,减少存储大小等。 反序列化的目的是把存储的数据加载到内存,方便Trie树的插入,查询,修改等需求。

以太坊所相关有网络上 x 发送的数据均遵循 RLP 编码。 提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式。RLP的唯一目标就是解决结构体的编码问题;对原子数据类型(比如,字符串,整数型,浮点型)的编码则交给更高层的协议;以太坊中要求数字必须是一个大端字节序的、没有零占位的存储的格式(也就是说,一个整数0和一个空数组是等同的)。 rlp目的是可以将常用的数据结构序列化以及反序列化. 要注意的是rlp特别不支持有符号数的序列化。

Ethereum 中具体使用的哈希算法,就是对某个类型对象的RLP编码值做了SHA3哈希运算,可称为RLP Hash。 Ethereum 在底层存储中特意选择了专门存储和读取[k, v] 键值对的第三方数据库,[k, v] 中的v 就是某个结构体对象的RLP编码值([]byte),k大多数情况就是v的RLP编码后的SHA-3哈希值在Ethereum 代码里,所有用到的哈希值,都使用该Hash类型,长度为32bytes,即256 bits;Ethereum 中所有跟帐号(Account)相关的信息,比如交易转帐的转出帐号(地址)和转入帐号(地址),都会用该Address类型表示,长度20bytes。

RLP(递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式。RLP的唯一目标就是解决结构体的编码问题;对原子数据类型(比如,字符串,整数型,浮点型)的编码则交给更高层的协议;以太坊中要求数字必须是一个大端字节序的、没有零占位的存储的格式(也就是说,一个整数0和一个空数组是等同的)。

字符串dog的正确编码方式是[131,100,111,103]
RLP编码算法:
(1)单字节值在[0x00,0x7f]之间的,编码就是自身
(2)如果一个string长度在0-55之间,编码结果的第1个字节为0x80+string的长度,后面跟着string。因此第1个字节范围在[0x80,0xb7]。
(3)如果一个string长度超过了55个字节,编码结果的第1个字节为0xb7+string的长度值(字节表示)的长度,后跟着string的长度,后跟着string。
比如string长度为1024(0x0400),0x0400的长度为2,因此第1个字节为0xb9,后面跟着0x0400,再后面跟着string。第1个字节的范围是[0xb8,0xbf],因此string长度值最大是8,
string的长度最大是2**64-1,这是一个非常大的数字。
(4)如果一个数组中所有元素的长度之和在0-55之间,编码结果的第1个字节为0xc0+所有元素的长度,后面跟着list中元素的编码串,因此第1个字节的范围在[0xc0,0xf7]。
(5)如果数组中所有元素的长度超过55个字节,编码结果的第1个字节为0xf8+所有元素长度值(字节表示)的长度,后跟所有元素长度,后面跟着数组。第1个字节的范围是[0xf8,0xff]。
交易必须是正确格式化的RLP。”RLP”代表Recursive Length Prefix,它是一种数据格式,用来编码二进制数据嵌套数组。以太坊就是使用RLP格式序列化对象。
以太坊中的所有数据都以“递归长度前缀编码(recursive length prefix encoding,RLP)”形式存储, 这种编码格式将任意长度和维度的字符串构成的数组串接成字符串。
例如,['dog', 'cat']被串接 (以字节数组格式) 为 [ 130, 67, 100, 111, 103, 67, 99, 97, 116];
其基本的思想是把数据类型和长度编码成一个单独的字节放在实际数据的前面(例如‘dog’的字节数组编码为[ 100, 111, 103 ], 于是串接后就成了[ 67, 100, 111, 103 ].)

请问 67是怎么算的,还有130的得出方法,谢谢。

采用的是RLP编码,只能对字符串编码。编码规则是 
1. 如果是字符串,编码结果是”\x00” 加上字符串的长度,再加上原字符串。计算字符串的长度有一个规则,确保编码无二义性,能正确解码。 
2.如果是字符串数组,编码结果是”\x01”加上每一个字符串编码结果的长度和的编码,再加上每一个字符串的编码结果。有点绕口,这是个递归的过程。 
3.如果是其他类型需要转换成字符串或者字符串数组。 
RLP编码的规律是以数据类型开始,字符串是”\x00”, 字符串数组是”\x01, 然后是数据长度,最后是数据内容。 

RLP编码和解码是递归过程,实现比较简单,编码紧凑,传输效率较高,后续版本中,在网络传输和本地存储都有RLP编码的影子。

Ethereum 代码里哈希(hash)无处不在,许许多多的类型对象通过给定的哈希算法,可以得到一个哈希值。注意,算法中所使用的哈希函数是不可逆的,即对于h = hash(x), 仅仅通过哈希运算的结果h 无法作逆运算得到输入x。哈希值在数学上的唯一性使得它可以用作某个对象的全局唯一标识符。

Ethereum 中用到的哈希函数全部采用SHA-3(Secure Hash Algorithm 3,wikipedia)。SHA-3在2015年8月由美国标准技术协会(NIST)正式发布,作为Secure Hash Algorithm家族的最新一代标准,它相比于SHA-2和SHA-1,采用了完全不同的设计思路,性能也比较好。需要注意的是,SHA-2目前并没有出现被成功攻克的案例,SHA-3也没有要立即取代SHA-2的趋势,NIST只是考虑到SHA-1有过被攻克的案例,未雨绸缪的征选了采用全新结构和思路的SHA-3来作为一种最新的SHA方案。

RLP(Recursive Length Prefix)编码,其定义可见wiki,它可以将一个任意嵌套的字节数组([]byte),编码成一个“展平”无嵌套的[]byte。1 byte取值范围0x00 ~ 0xff,可以表示任意字符,所以[]byte可以线性的表示任意的数据。最简单比如一个字符串,如果每个字符用ASCII码的二进制表示,整个字符串就变成一个[]byte。 RLP 编码其实提供了一种序列化的编码方法,无论输入是何种嵌套形式的元素或数组,编码输出形式都是[]byte。RLP是可逆的,它提供了互逆的编码、解码方法。

Ethereum 中具体使用的哈希算法,就是对某个类型对象的RLP编码值做了SHA3哈希运算,可称为RLP Hash。 Ethereum 在底层存储中特意选择了专门存储和读取[k, v] 键值对的第三方数据库,[k, v] 中的v 就是某个结构体对象的RLP编码值([]byte),k大多数情况就是v的RLP编码后的SHA-3哈希值

在Ethereum 代码里,所有用到的哈希值,都使用该Hash类型,长度为32bytes,即256 bits;Ethereum 中所有跟帐号(Account)相关的信息,比如交易转帐的转出帐号(地址)和转入帐号(地址),都会用该Address类型表示,长度20bytes。

要想得到父区块(parentBlock)对象,直接解析这个ParentHash是不够的, 而是要将ParentHash同其他字符串([]byte)组合成合适的key([]byte), 去kv数据库里查询相应的value才能解析得到。


你可能感兴趣的:(以太坊)