Documentation ¶
Index ¶
- Variables
- func AppendUint64(b []byte, i uint64) []byte
- func CountValues(bz []byte) (int, error)
- func Decode(r io.Reader, val interface{}) error
- func DecodeBytes(bz []byte, val interface{}) error
- func Encode(w io.Writer, x interface{}) error
- func EncodeToBytes(x interface{}) ([]byte, error)
- func EncodeToReader(x interface{}) (size int, r io.Reader, err error)
- func IntSize(x uint64) int
- func ListSize(contentSize uint64) uint64
- func SplitList(bz []byte) (content, rest []byte, err error)
- func SplitString(bz []byte) (content, rest []byte, err error)
- func SplitUint64(bz []byte) (x uint64, rest []byte, err error)
- type ByteReader
- type Decoder
- type EncodeBuffer
- func (encBuf *EncodeBuffer) AppendToBytes(dst []byte) []byte
- func (encBuf *EncodeBuffer) Flush() error
- func (encBuf EncodeBuffer) ListEnd(index int)
- func (encBuf EncodeBuffer) ListStart() int
- func (encBuf *EncodeBuffer) Reset(dst io.Writer)
- func (encBuf *EncodeBuffer) ToBytes() []byte
- func (encBuf EncodeBuffer) Write(bz []byte) (int, error)
- func (encBuf EncodeBuffer) WriteBigInt(i *big.Int)
- func (encBuf EncodeBuffer) WriteBool(b bool)
- func (encBuf EncodeBuffer) WriteBytes(bz []byte)
- func (encBuf EncodeBuffer) WriteString(s string)
- func (encBuf EncodeBuffer) WriteUint64(i uint64)
- type Encoder
- type Kind
- type RawValue
- type Stream
- func (s *Stream) Bytes() ([]byte, error)
- func (s *Stream) Decode(val interface{}) error
- func (s *Stream) Kind() (kind Kind, size uint64, err error)
- func (s *Stream) ListEnd() error
- func (s *Stream) ListStart() (size uint64, err error)
- func (s *Stream) Raw() ([]byte, error)
- func (s *Stream) ReadBytes(bz []byte) error
- func (s *Stream) Reset(r io.Reader, inputLimit uint64)
- func (s *Stream) Uint64() (uint64, error)
Constants ¶
This section is empty.
Variables ¶
var ( ErrCanonSize = errors.New("rlp: non-canonical size information") ErrExpectedString = errors.New("rlp: expected String or Byte") ErrExpectedList = errors.New("rlp: expected List") ErrCanonInt = errors.New("rlp: non-canonical integer format") ErrElemTooLarge = errors.New("rlp: element is larger than containing list") ErrValueTooLarge = errors.New("rlp: value size exceeds available input length") ErrMoreThanOneValue = errors.New("rlp: input contains more than one value") )
var EOL = errors.New("rlp: end of list")
EOL ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
EOL "end of list"
var EmptyList = []byte{0xC0}
var EmptyString = []byte{0x80}
var ErrNegativeBigInt = errors.New("rlp: cannot encode negative big.Int")
ErrNegativeBigInt ♏ |作者:吴翔宇| 🍁 |日期:2022/11/8|
ErrNegativeBigInt 被编码的大整数是一个负数时,会报该错误。
Functions ¶
func AppendUint64 ¶
AppendUint64 ♏ |作者:吴翔宇| 🍁 |日期:2022/11/8|
AppendUint64 接受两个参数,第一个参数是一个字节切片bz,第二个参数是一个64位无符号整数i,该方法的目的就是将整数i的rlp编码 追加到切片bz之后。例如给定切片bz=[129 137],给定整数i=45678,执行该方法得到的切片result=[129 137 130 178 110]。
func CountValues ¶
CountValues ♏ |作者:吴翔宇| 🍁 |日期:2022/11/8|
CountValues 接受一个rlp编码结果bz,该方法的功能就是计算有多少个值被编码进bz里面,例如:
给定bz=[129 130 12 132 97 97 97 97],经过计算我们发现有三个值被编码进去了,分别是数字130、数字12 以及字符串"aaaa"。
func Decode ¶
Decode ♏ |作者:吴翔宇| 🍁 |日期:2022/11/11|
Decode 方法接受两个参数,第一个参数是一个 io.Reader,RLP编码数据被存储在里面,第二个参数是一个指针, 将被编码的数据解码到该指针里面。
func DecodeBytes ¶
DecodeBytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/11|
DecodeBytes 方法接受两个参数,第一个参数是一个字节切片,里面存储了原始的RLP编码数据,第二个参数是一个指针, 将被编码的数据解码到该指针里面。
func Encode ¶
Encode ♏ |作者:吴翔宇| 🍁 |日期:2022/11/9|
Encode 方法接受两个参数:第一个参数是一个 io.Writer,编码结果会被写入到writer里,第二个参数是任意类型的数据, 这个给定的数据就是要被编码的数据。该方法的返回值表明在编码过程中是否出现错误。
func EncodeToBytes ¶
EncodeToBytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/9|
EncodeToBytes 方法接受一个入参:任意类型的数据x,x是要被编码的数据,返回值有两个,第一个返回值表示 编码结果,第二个返回值表示编码过程中可能出现的错误。
func EncodeToReader ¶
EncodeToReader ♏ |作者:吴翔宇| 🍁 |日期:2022/11/9|
EncodeToReader 方法接受一个入参:任意类型的数据x,x是要被编码的数据,返回值有三个,第一个返回值表示 编码结果的长度(字节个数),第二个参数返回的是一个 *encReader 实例,该实例实现了 Read 方法,Read 方 法接受一个字节切片作为入参,然后将编码结果读取到给定的字节切片中,该方法用于网络传输数据,第三个参数表示 编码过程中可能遇到的错误。
func IntSize ¶
IntSize ♏ |作者:吴翔宇| 🍁 |日期:2022/11/7|
IntSize 方法接受一个64位无符号整型参数x,该方法的作用是计算对x进行rlp编码后得到的结果的字节长度。对于值 小于128的整数,可以将其看成是一个单独的ASCII码,根据rlp编码规则,所以仅需1个字节就可以存储编码结果;如果 值大于128,例如1025,1025需要两个字节来存储表示:00000100,00000001,那么编码1025这个数字就需要3个字 节:[128+2, 4, 1]->[10000010, 00000100, 00000001]。
func ListSize ¶
ListSize ♏ |作者:吴翔宇| 🍁 |日期:2022/11/7|
ListSize 方法接受一个64位无符号整型参数contentSize,contentSize表示的是对一个列表进行编码后,除去 头剩下的编码内容的长度。这个方法在 Block 和 Transaction 两个结构体实现 DecodeRLP 方法时被调用。
func SplitList ¶
SplitList ♏ |作者:吴翔宇| 🍁 |日期:2022/11/8|
SplitList 与 SplitString 方法作用类似,该方法明确知道bz里面含有rlp编码列表部分的内容,如果解析出来 的类型显式不是 List,则返回 ErrExpectedList 错误。
func SplitString ¶
SplitString ♏ |作者:吴翔宇| 🍁 |日期:2022/11/7|
SplitString 与 Split 方法类似,不同的地方在于,SplitString 方法知道自己要解析的对象bz是一个对象字符串进 行rlp编码的结果,所以,如果解析得到编码类型不是 String,则会报错。然后该方法的返回值与 Split 的后三个返回值 具有相同的含义。
func SplitUint64 ¶
SplitUint64 ♏ |作者:吴翔宇| 🍁 |日期:2022/11/7|
SplitUint64 方法接受一个字节切片bz作为入参,该方法的作用就是解析bz里面被rlp编码的整数,需要主义的是:
- 整数0的编码结果是0x80,它表示的是编码头后面有0个字节的内容是为整数0编码的,那么我们在解码的时候,会 得到0个字节,也就是len(content)=0,整数1的编码结果就是1,直到整数127的编码结果也是127,也就是说,编 码任何非0数字,都至少需要1个字节,那么当编码结果的长度等于1时,编码结果是不可能等于0的。
- 64位无符号整数最多由8个字节组成,超过8个字节的都是不合法的。
该方法第2个返回值很有意思,它表示的是整数编码内容后面紧跟着的数据,很像协议号的意思,例如我们给定一段数据 bz=[129 130 97 98 99],解析结果为:0x82, [97 98 99], nil
Types ¶
type ByteReader ¶
type ByteReader interface { Read(p []byte) (n int, err error) // 从源中读取至多len(p)个字节到p中 ReadByte() (byte, error) // 每次读取一个字节 }
ByteReader ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
ByteReader 接口被例如 bufio.Reader 和 bytes.Reader 实现。这里定义接口的方式与官方源码略有不同,官方源码地址:
https://github.com/ethereum/go-ethereum/blob/972007a517c49ee9e2a359950d81c74467492ed2/rlp/decode.go#L544
type EncodeBuffer ¶
type EncodeBuffer struct {
// contains filtered or unexported fields
}
EncodeBuffer ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
EncodeBuffer
func NewEncodeBuffer ¶
func NewEncodeBuffer(dst io.Writer) EncodeBuffer
NewEncodeBuffer ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
NewEncodeBuffer 方法根据给定的 io.Writer 生成一个新的 EncodeBuffer。需要注意的是,如果给定的 io.Writer 满足不同的条件,生成的 EncodeBuffer 会有区别:
- 如果给定的 io.Writer 的底层实现是 EncodeBuffer或者是*EncodeBuffer,再或者是*encBuffer,则生成的 EncodeBuffer 实例如下: EncodeBuffer{buf: encBufferFromWriter(dst), dst: nil, ownBuffer: false} 其中dst就是 NewEncodeBuffer 方法的入参
- 如果给定的 io.Writer 就是普通的writer,则生成的 EncodeBuffer 实例如下: EncodeBuffer{buf: encBufferPool.Get().(*encBuffer), dst: dst, ownBuffer: true}
func (*EncodeBuffer) AppendToBytes ¶
func (encBuf *EncodeBuffer) AppendToBytes(dst []byte) []byte
AppendToBytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
AppendToBytes 方法接受一个字节切片dst作为入参,该方法就是将 EncodeBuffer.buf 内存储的rlp编码结果追加到dst后面。
func (*EncodeBuffer) Flush ¶
func (encBuf *EncodeBuffer) Flush() error
Flush ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
Flush 方法将 EncodeBuffer.buf 里面缓存的rlp编码数据全部写入到 EncodeBuffer.dst 中,写完之后,EncodeBuffer.buf 如果是 EncodeBuffer 从 encBufferPool 里面拿的,那就要再把它放回去,并且 EncodeBuffer 会被重置为空,也就是说, Flush 方法只能被调用一次,下次还想调用,就必须在调用前先执行 Reset 方法。
func (EncodeBuffer) ListEnd ¶
func (encBuf EncodeBuffer) ListEnd(index int)
ListEnd ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
ListEnd 方法接受一个整型参数index,该方法在编码列表数据结束之后被调用,其目的就是更新 EncodeBuffer.buf.lHeads 上给定 index索引位值处的 listHead.size 和 EncodeBuffer.buf.lHeadsSize 两个字段。实际上,该方法的逻辑通过调用如下函数来实现:
EncodeBuffer.buf.listEnd(index)
func (EncodeBuffer) ListStart ¶
func (encBuf EncodeBuffer) ListStart() int
ListStart ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
ListStart 方法用来往 EncodeBuffer.buf.lHeads 里添加一个 listHead 实例,该方法在编码列表数据前被调用,用来为编码列表数据 作准备,实际上,该方法的逻辑通过调用如下函数来实现:
EncodeBuffer.buf.listStart()
func (*EncodeBuffer) Reset ¶
func (encBuf *EncodeBuffer) Reset(dst io.Writer)
Reset ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
Reset 方法接受一个实现了 io.Writer 接口的对象实例dst,如果当前 EncodeBuffer.buf 是通过 encBufferFromWriter 方法获得的,那么调用 Reset 方法会panic,如果给定的dst参数不为空,且dst的底层实现是 EncodeBuffer 或 *EncodeBuffer 或 *encBuffer,则重置 EncodeBuffer.buf 为dst,并且 EncodeBuffer.ownBuffer 置为false,到此,直接退出 Reset方 法;否则就从 encBufferPool 里面重新获取一个 *encBuffer 实例,并赋值给 EncodeBuffer.buf,然后将 EncodeBuffer.ownBuffer 置为true,最后调用 encBuffer.reset 方法重置 EncodeBuffer.buf。
func (*EncodeBuffer) ToBytes ¶
func (encBuf *EncodeBuffer) ToBytes() []byte
ToBytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
ToBytes 方法调用 EncodeBuffer.buf.makeBytes() 方法,将编码结果完整的返回出来。
func (EncodeBuffer) Write ¶
func (encBuf EncodeBuffer) Write(bz []byte) (int, error)
Write ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
Write 方法接受一个字节切片参数bz,该方法实际上调用 encBuffer.Write 方法实现将bz追加到 encBuffer.str 后面。
func (EncodeBuffer) WriteBigInt ¶
func (encBuf EncodeBuffer) WriteBigInt(i *big.Int)
WriteBigInt ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
WriteBigInt 方法接受一个大整数i,i的类型是*big.Int,该方法的作用就是将大整数编码到 EncodeBuffer.buf.str 里。事实上,大整数不 一定就比最大的64位无符号整数大,在这种情况下,我们可以调用 writeUint64 方法将该所谓的大整数编码到str里;但是,如果给定的大整数大于 最大的64位无符号整数,在这种情况下,我们需要将其看成是一个字节切片进行编码,此时该大整数需要超过8个字节来存储。
func (EncodeBuffer) WriteBool ¶
func (encBuf EncodeBuffer) WriteBool(b bool)
WriteBool ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
WriteBool 方法接受一个bool类型的变量,然后根据其值将其编码到 EncodeBuffer.buf.str 里,如果给的值等于true,那么 就往str里写入0x01,否则写入0x80,0x80表示的是一个空值。
func (EncodeBuffer) WriteBytes ¶
func (encBuf EncodeBuffer) WriteBytes(bz []byte)
WriteBytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
WriteBytes 方法接受一个字节切片bz,该方法的目的就是将字节切片bz编码到 EncodeBuffer.buf.str 里。当bz满足不同情况时,编码 方式也不同,具体会遇到以下两种方式:
- 给定的字节切片bz长度等于1,并且里面唯一的字节小于或等于0x7F,即127,那么该字节切片(或者说该字节更准确)会被直接追加到str后。
- 给定的字节切片长度大于1,那么会将bz的长度先编码到str里,这里又会遇到两种情况:1.长度小于56;2.长度大于55。面对不同的情况, 如何对字节长度进行编码必须遵守以下准则: · 当长度size小于56,则将0x80+size的值追加到str后 · 当长度size大于55,例如1024,存储1024最少需要2个字节,并且这两个字节分别是00000100和00000000,那么就将0xB7+2和这 两个字节追加到str后,字节的长度被编码到str里后,剩下的工作则是直接将切片bz追加到str后。
func (EncodeBuffer) WriteString ¶
func (encBuf EncodeBuffer) WriteString(s string)
WriteString ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
WriteString 方法接受一个字符串参数s,该方法的作用就是将s编码到 EncodeBuffer.buf.str 里,实际上,该方法的逻辑是调用了如下 函数,来实现将s编码到str里:
EncodeBuffer.buf.writeString(s)
func (EncodeBuffer) WriteUint64 ¶
func (encBuf EncodeBuffer) WriteUint64(i uint64)
WriteUint64 ♏ |作者:吴翔宇| 🍁 |日期:2022/11/5|
WriteUint64 方法接受一个64位的无符号整数作为输入参数,然后将其编码到 EncodeBuffer.buf.str 里,如果输入的整数大小小于 128,则可以将其看成是一个单独的ASCII码,那么该整数自身就可以作为编码结果写入到str里;如果给定的整数大于或等于128,则会计算 需要多少个字节才能存储这个数,例如需要n个,那么编码结果就是(0x80+n||整数的字节表现形式);如果给定的整数等于0,则将0x80写 入到str里,代表空值,下面给出三个示例来对该方法的逻辑进行解释:
- 0:append(str, 0x80)
- 123:append(str, byte(123))
- 1024:append(str, []byte{0x80+2, 000000100, 00000000})
type Kind ¶
type Kind int8
func Split ¶
Split ♏ |作者:吴翔宇| 🍁 |日期:2022/11/7|
Split 方法接受一个字节切片bz作为入参,bz是一个rlp编码结果,Split 方法解析bz,返回被编码的对象是何种类型, Byte 、 String 或 List,然后第二个参数返回的是编码结果除编码前缀外剩下的编码内容,第三个参数返回的是其他 编码数据,第四个参数返回的是 Split 方法在执行过程中可能遇到的错误,这里只会遇到两种错误,一个是 ErrCanonSize, 另一个是 ErrValueTooLarge。
给一个例子:bz = [204 131 97 97 97 8 198 133 72 101 102 101 105] 对给定的bz进行解析,返回的结果将是:List, [131 97 97 97 8 198 133 72 101 102 101 105], [], nil
type RawValue ¶
type RawValue []byte
RawValue ♏ |作者:吴翔宇| 🍁 |日期:2022/11/6|
RawValue 官方对其解释是:
RawValue代表一个已编码的RLP值,可用于延迟RLP解码或预先计算一个编码。请注意,解码器并不验证RawValues的内容是否是有效的RLP。
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
Stream ♏ |作者:吴翔宇| 🍁 |日期:2022/10/30|
Stream
func NewListStream ¶
NewListStream ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
NewListStream 与 NewStream 方法相比,该方法有两处不同,一是 *Stream.kind 被设置为 List,二是 *Stream.size 被设置为该方法的第二个入参:inputLimit。值得一提的是,该方法只在测试文件中被调用。
func NewStream ¶
NewStream ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
NewStream 方法接受两个入参:io.Reader 和一个64位无符号整数 inputLimit,这两个参数用来实例化 *Stream, *Stream 的读取源 *Stream.r 会被设置为 io.Reader,然后如果 inputLimit 大于0,则 *Stream.limited 会被置为 true,而 *Stream.remaining 会被置为 inputLimit,否则 *Stream.remaining 会被设置为 io.Reader 的长度
func (*Stream) Bytes ¶
Bytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/11|
Bytes 方法返回底层stream中存储的接下来的字符串解码结果,不能是列表数据。
func (*Stream) Decode ¶
Decode ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
Decode 这个方法非常类似于 json.Unmarshal 方法,接受某个类型的指针,然后将底层stream存储的rlp编码内容解码到 给定类型指针指向的空间里。实际上,给定某个类型的指针,我们首先要从 typeCache 缓冲区里寻找针对该类型的解码器,找 到的话就直接用,找不到的话就生成一个。
func (*Stream) Kind ¶
Kind ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
Kind 方法返回下一个编码数据的类型和其EC部分的大小,类型就三类:Byte、String、List。 如果每次在 ListStart 方法被调用之后再调用此方法,会从底层stream中读取一个字节的TMB(类型标记位),因此, Stream.remaining 和 Stream.stack 里的最后一个元素会被减一。
func (*Stream) ListStart ¶
ListStart ♏ |作者:吴翔宇| 🍁 |日期:2022/11/10|
ListStart 官方源码的写法是:"List",我将其改成了:"ListStart",该方法返回的第一个参数表示list 编码数据EC部分的长度。
接下来要解码的数据是一个list的RLP编码结果,在解码前,需要做一些准备工作。
func (*Stream) ReadBytes ¶
ReadBytes ♏ |作者:吴翔宇| 🍁 |日期:2022/11/11|
ReadBytes 方法接受一个字节切片bz,从底层stream解码出相应长度的字符串,非列表数据。