• RLP


    ** 原创勿转 **

    这是在看devp2p时看到的,英文原文地址:https://github.com/ethereum/wiki/wiki/RLP

    RLP:  Recursive Length Prefix,中文直译“递归长度前缀”(很别扭有没有,不管叫什么,它就在那里)。 实际上就是一种数据编码方式,类似Base64之类的。

    一.    推荐的两种编码形式
       . 使用[[k1,v1],[k2,v2]...],  其中k1,k2,... 是字典顺序
       . 使用Patricia Tree, 以太坊中使用这种方式

    二. 编码函数需要一个数据项(item)

         对于item的定义:
         . 串(比如字节数组,  golang: []byte{}, java: byte[])是一个item
         . item列表也是一个item

         例:空string, 空列表[], "cat",  列表["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"]
        
         在原文中, string并不是一个字符串,是"a certain number of bytes of binary data"的同义词, 即某个特定长度的二进制数据, 对于具体的数据,长度是固定的。

         可以理解为字节数组, 而不仅仅是字符串。

    三. 具体的编码过程 

      其中第一个字节是特殊的,以byte0表示, byte0 按其值将[0x00,0xff]划分为5个部分:   [0x00,0x7f],   [0x80,0xb7],   [0xb8, 0xbf],   [0xc0, 0xf7],   [0xf8, 0xff]
     
      *** 这里的方括号表示区间, 同时编码结果也用方括号表示,比如[0x83, 'c','a','t'], 注意区分。
     
      1.  单字节
           单字节值的取值范围在[0x00, 0x7f]之间的数据,编码等于这个字节
           生成数据的格式:[byte0], 所以 byte0的取值范围是[0x00, 0x7f]
           比如: "A", 0x41, 编码就是[0x41]
           
           对于[0x80, 0xff]的单字节,适用下一条规则
          
      2.  0-55个字节的数据

           这包括1里排除的[0x80, 0xff]单字节, 它的编码数据是这样产生的:
           编码格式:[byte0, 原始数据]
           byte 0 = 0x80 + 原始数据的长度, 所以byte0的取值范围就是0x80 + (0-55) = [0x80, 0x80+55] = [0x80, 0xb7]   (0x80= 128,0xb7=183)  
          

           比如:
              0x95,  长度为1, 那么byte0 = 0x80 + 1 = 0x81,  编码为[0x81, 0x95], 这个是1里排除的数据
              "cat",  长度为3,    那么byte0 = 0x80 + 3 = 0x83,  编码为[0x83, 'c', 'a', 't']
              string('null')  = 0x00 = [0x80 + 0(长度为0, 空格按1规则编码)] = [0x80]         
           
      3.  对于长度大于55的数据
           编码格式: [byte0, 长度(不一定几个字节), 原始数据]
           byte0 = 0xb7 + 长度占用的字节。 长度是整数, 比如15,那么它占用1个字节,说得绕一点,就是长度的长度
           长度:就是其二进制表示
           
           比如:长度为1024的数据, byte0 = 0xb7 + 2 (1024的十六进制表示为0x0400, 所以占用两个字节)  = 0xb9
           整个数据的编码就是[0xb9, 0x04, 0x00, 原始数据]
           
           长度既然是整数, 其在内存里最多占用8个字节, 所以byte0的取值范围:[0xb7 + (1-8)] = [0xb8, 0xbf]
           
     4.  对于列表来说

          (对于列表,我的理解应该算是串的数组吧。)

          如果它的每个数据都被编码过了,而整个列表的数据长度是0-55, 那么
          编码格式:[byte0,列表各项编码后的数据]
          byte0 = 0xc0 + 列表所有数据的长度,  那么byte0 = 0xc0 + (0-55) = [0xc0, 0xc0 + 55] = [0xc0, 0xf7]   (0xc0=192, 0xf7=247)
          
          比如:"cat" = [0x83,'c','a','t'],  "dog" = [0x83, 'd','o','g'],  这两个适用规则2
                    byte0 = 0xc0 + 8("cat"和"dog"编码后的总长度)  = 0xc8
                    ["cat", "dog"] = [0xc8,  0x83, 'c','a','t',  0x83, 'd','o','g']
                    
    5.  相对于规则4, 如果列表编码后数据总长度大于55
         编码格式: [byte0, 长度,列表各项编码后数据]
         byte0 = 0xf7 + 长度的长度, 所以byte0的取值范围:[0xf7 + (1-8)] = [0xf8, 0xff], 长度的长度取值是1个字节到8个字节

    总的来说,对于超过55的长度, 要使用长度的长度。

    解码是相反的过程,有时间再写吧。
       

  • 相关阅读:
    让源码包apache服务被服务管理命令识别
    zabbix客户端监控脚本shell
    zabbix指定版本自动化安装脚本shell
    haproxy配置详解
    HAproxy 让后端RS记录真实IP
    Centos 7.x系统下忘记用户登录密码,重置root密码的方法
    Win2008 server R2重置登录密码Administrator
    序列自动机总结与例题
    整体二分总结
    容易推错的式子
  • 原文地址:https://www.cnblogs.com/bear129/p/8134715.html
Copyright © 2020-2023  润新知