原文地址:https://github.com/ethereum/wiki/wiki/RLP
内容
定义
例子
RLP ***
实现
RLP 是 Recursive Length Prefix 首字母的简写,翻译成什么合适呢?递归长度前缀?慢慢体会吧。
RLP目的是什么呢?程序员可能都听过序列化,为了便于数据在网络间的传输,往往会对数据进行序列化,其实就是一种编码,那么RLP的目的也是序列化,是对任意二进制数据嵌套数组(nested arrays of binary data)进行编码。以太坊中,对数据对象的序列化主要采用的就是这个RLP。RLP的唯一的目的就是对数据结构进行编码;对特定数据类型(比如字符串、浮点数)的编码留给了高阶协议(注:不懂,什么高阶协议?high-order protocols);但是正的RLP整型数据用大端的二进制形式表示,并去除高位多余的0。(这样使得整型0和空的字节数组是一样的了,思考一下)反序列化一个高位有0的正整型数据会以无效来对待。字符串长度和数据中的整型也都是按照这个方法进行编码的。附件的信息请查看以太坊黄皮书附录B。
如果你想用RLP对一个字典进行编码,推荐使用两种经典的方法,一种是 [[k1,v1],[k2,v2]…],其中Key是按字典序排列。或者使用另外一种,像以太坊一样,使用更高层次的帕特里夏树编码。
简言之,RLP就像一个 *** ON的二进制编码,前提是假设 *** ON被仅限于存储字符串和数组类型的数据。
定义
RLP编码函数接收一个item(item怎么翻译?),这个item定义如下:
一个字符串(包括:字节数组)是一个item
items的列表是一个item
例如,一个空字符串是一个item,如同一个字符串包含单词“cat”一样,一个列表包含任意数量的字符串,或者是更为复杂的数据结构,如[“cat”,[“puppy”,”cow”],”horse”,[[]],”pig”,[“”],”sheep”]。注意哈,这篇文章的后面部分,字符串就是一定数量的二进制数据字节;没有使用特别的编码程序,也不了解字符串里面的内容。
RLP编码定义如下:
对于一个单字节数据来说,它的值在[0x00, 0x7f]之间,那么RLP编码的结果是它本身。
否则,如果一个字符串长度在0~55之间,RLP编码包含一个单字节,它的值等于0x80加上字符串的长度,字符串本身紧随其后。第一个字节的取值范围是 [0x80, 0xb7] (0xb7 = 0x80 + 55)
如果一个字符串长度大于55,RLP编码包含一个单字节,这个字节的值等于0xb7加上字符串长度在二进制形式下的长度,然后是字符串长度,最后是字符串本身。例如,一个长度为1024的字符串,编码形式为 \xb9\x04\x00\字符串本身,(0xb9 = 0xb7 + 2 (2是1024的长度),0x0400是1024)。第一个字节的取值范围是 [0xb8, 0xbf]。
如果一个列表整个的字节长度(即是每一个item进行RLP编码之后的长度总和)为0~55字节,RLP编码包含一个单字节,它的值是0xc0加上列表的长度,所有item的RLP编码级联起来紧随其后。第一个字节的取值范围是 [0xc0, 0xf7] ,(0xf7 = 0xc0 + 55)
如果一个列表的字节长度超过55,RLP编码包含一个单字节,它的值是0xf7加上列表自己长度在二进制形式下的长度,然后是列表的长度,最后是所有item的RLP编码级联起来。第一个字节的取值范围是 [0xf8, 0xff]
代码实现是这样的,Python为例:
例子
字符串 “dog” = [ 0x83, ‘d’, ‘o’, ‘g’ ]
列表 [ “cat”, “dog” ] = [ 0xc8, 0x83, ‘c’, ‘a’, ‘t’, 0x83, ‘d’, ‘o’, ‘g’ ]
空字符串 (‘null’) = [ 0x80 ]
空列表 = [ 0xc0 ]
整型 0 = [ 0x80 ]
编码的整型 0 (‘\x00’) = [ 0x00 ]
编码的整型 15 (‘\x0f’) = [ 0x0f ]
编码的整型 1024 (‘\x04\x00’) = [ 0x82, 0x04, 0x00 ]
集合(The set theoretical representation of three,怎么翻译?), [ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]
字符串 “Lorem ipsum dolor sit amet, consectetur adipisicing elit” = [ 0xb8, 0x38, ‘L’, ‘o’, ‘r’, ‘e’, ‘m’, ‘ ‘, … , ‘e’, ‘l’, ‘i’, ‘t’ ]
RLP ***
根据RLP的编码处理过程,RLP *** 的输入应该是二进制数据的数组形式,处理过程如下:
根据输入数据第一个字节(也就是前缀),解出来数据类型、实际数据的长度和偏移;
根据数据类型和偏移量, *** 相应的数据;
继续 *** 输入剩下的数据;
其中, *** 数据类型和偏移量的规则如下:
如果第一个字节的范围是[0x00, 0x7f],数据就是一个字符串,而且这个字符串就是这个字节本身;
如果第一个字节的范围是[0x80, 0xb7],数据也是一个字符串,字符串的长度为第一个字节减去0x80;
如果第一个字节的范围是[0xb8, 0xbf],数据也是一个字符串,字符串长度的长度是第一个字节减去0xb7,随后是字符串长度,最后是字符串本身;
如果第一个字节的范围是[0xc0, 0xf7],所有item的RLP编码级联起来的长度等于第一个字节减去0xc0;
如果第一个字节的范围是[0xf8, 0xff],所有item的RLP编码级联起来的长度的长度等于第一个字节减去0xf7,(这里长度的长度解释一下,比如一个列表的字节长度是1024,这个长度的长度就是1024的长度,为2)然后是所有item的RLP编码级联起来的长度,最后是所有item的RLP编码的级联;
代码实现是这样的,还是Python为例:
实现
Go: go-ethereum
J *** a: web3j, ethereumj, headlong
J *** ascript: rlp
Kotlin: KEthereum/rlp
Objective-C: RLP-ObjC
Python: pyrlp
Swift: RLPSwift, RLP
PHP: rlp
….
未经允许不得转载:答案星辰 » rlp路由协议 (Rlp路由协议的应用场景有哪些)