以太坊之rlp

一般理解rlp你会找到这两篇。
https://github.com/ethereum/wiki/wiki/%5B%E4%B8%AD%E6%96%87%5D-RLP
https://github.com/ethereum/wiki/wiki/RLP

RLP编码算法:
(1)单字节值在[0x00,0x7f]之间的,编码就是自身即0-127
(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]。

一般要想学明白一个东西就是打开命令行或者IDE,把他跑起来run一下。

#!/usr/bin/env python
# encoding=utf-8


def rlp_encode(input_):
    if isinstance(input_, str):
        if len(input_) == 1 and ord(input_) < 0x80: return input_
        else : return encode_length(len(input_),0x80) + input_
    elif isinstance(input_, list):
        output = ''
        for item in input_: output += rlp_encode(item)
        return encode_length(len(output),0xc0) + output

def encode_length(L,offset):
    if L < 56:
        return chr(L + offset)
    elif L < 256**8: #(2**8)**8
        BL = to_binary(L)
        return chr(len(BL) + offset + 55) + BL
    else:
        raise Exception("input to long!")

def to_binary(x):
    if x == 0:
        return ''
    else:
        return to_binary(int(x/256))+chr(x%256)

def my_print(string):
    for i in string:
        if ord(i) > 32 and ord(i) < 127:
            print i,
        else:
            print hex(ord(i)),

if __name__ == "__main__":
    #string = "dog"
    #string =  ["cat", "dog"] 
    string = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
    my_print(rlp_encode(string))

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