rlp

package
v0.0.0-...-ac8b7ce Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 27, 2021 License: GPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package rlp implements the RLP serialization format.

The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily nested arrays of binary data, and RLP is the main encoding method used to serialize objects in Ethereum. The only purpose of RLP is to encode structure; encoding specific atomic data types (eg. strings, ints, floats) is left up to higher-order protocols; in Ethereum integers must be represented in big endian binary form with no leading zeroes (thus making the integer value zero equivalent to the empty byte array).

RLP values are distinguished by a type tag. The type tag precedes the value in the input stream and defines the size and kind of the bytes that follow.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// EOL is returned when the end of the current list
	// has been reached during streaming.
	EOL = errors.New("rlp: end of list")

	// Actual Errors
	ErrExpectedString = errors.New("rlp: expected String or Byte")
	ErrExpectedList   = errors.New("rlp: expected List")
	ErrCanonInt       = errors.New("rlp: non-canonical integer format")
	// 非规范尺寸信息错误
	ErrCanonSize        = errors.New("rlp: non-canonical size information")
	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")
)

todo 解码器,用于将rlp数据解码为原始数据

View Source
var (

	// 常见的编码值。
	// 这些在实施EncodeRLP时非常有用。
	EmptyString = []byte{0x80} // 128,定义了序列化时候的空字符串,空的时候对应的是编码128
	EmptyList   = []byte{0xC0} // 192,定义了序列化时候的空集合,空的时候对应的编码192
)

Functions

func CountValues

func CountValues(b []byte) (int, error)

CountValues counts the number of encoded values in b. todo CountValues: 计算b中编码值的数量. todo 其实就是说, todo 其实就是说, todo 取出第一个字节 <前缀>

  如果有多个字段,则编码格式为:
 [list总前缀, 第一个元素前缀, 第一个元素[]byte, 第二个元素前缀, 第二个元素[]byte, ...]
所以入参应该为: 第一个元素前缀, 第一个元素[]byte, 第二个元素前缀, 第二个元素[]byte, ...]
才可以知道,得到的num是 几

func Decode

func Decode(r io.Reader, val interface{}) error

Decode uses the following type-dependent decoding rules:

解码使用以下与类型有关的解码规则:

If the type implements the Decoder interface, decode calls DecodeRLP.

如果该类型实现了Decoder接口,则解码调用DecodeRLP。

To decode into a pointer, Decode will decode into the value pointed to. If the pointer is nil, a new value of the pointer's element type is allocated. If the pointer is non-nil, the existing value will be reused.

要解码为指针,解码将解码为指向的值。 如果指针为nil,则分配该指针的元素类型的新值。 如果指针为非零,则现有值将被重用。

To decode into a struct, Decode expects the input to be an RLP list. The decoded elements of the list are assigned to each public field in the order given by the struct's definition. The input list must contain an element for each decoded field. Decode returns an error if there are too few or too many elements.

为了解码成结构,Decode希望输入是RLP列表。 列表的解码元素按照结构定义给出的顺序分配给每个公共字段。 输入列表必须为每个解码字段包含一个元素。 如果元素太多或太多,解码将返回错误。

The decoding of struct fields honours certain struct tags, "tail", "nil" and "-".

结构字段的解码采用某些结构标签“ tail”,“ nil”和“-”。

The "-" tag ignores fields.

“-”标签忽略字段。

For an explanation of "tail", see the example.

有关“尾巴”的说明,请参见示例。

The "nil" tag applies to pointer-typed fields and changes the decoding rules for the field such that input values of size zero decode as a nil pointer. This tag can be useful when decoding recursive types.

“ nil”标签应用于指针类型的字段,并更改该字段的解码规则,以使大小为零的输入值解码为nil指针。 解码递归类型时,此标记很有用。

type StructWithEmptyOK struct {
    Foo *[20]byte `rlp:"nil"`
}

To decode into a slice, the input must be a list and the resulting slice will contain the input elements in order. For byte slices, the input must be an RLP string. Array types decode similarly, with the additional restriction that the number of input elements (or bytes) must match the array's length.

要解码为切片,输入必须是列表,并且所得切片将按顺序包含输入元素。 对于字节片,输入必须是RLP字符串。 数组类型的解码方式类似, 但附加的限制是输入元素(或字节)的数量必须与数组的长度匹配。

To decode into a Go string, the input must be an RLP string. The input bytes are taken as-is and will not necessarily be valid UTF-8.

要解码为 `Go字符串`,输入必须是RLP字符串。 输入字节按原样使用,不一定是有效的UTF-8。

To decode into an unsigned integer type, the input must also be an RLP string. The bytes are interpreted as a big endian representation of the integer. If the RLP string is larger than the bit size of the type, Decode will return an error. Decode also supports *big.Int. There is no size limit for big integers.

要解码为无符号整数类型,输入还必须是RLP字符串。 字节被解释为整数的 todo 【大端】表示。 如果RLP字符串大于该类型的位大小,则Decode将返回错误。 解码还支持* big.Int。 大整数没有大小限制。

To decode into an interface value, Decode stores one of these in the value:

要将解码为 `interface{}` 值,Decode将其中之一存储在值中:

[]interface{}, for RLP lists
[]byte, for RLP strings

Non-empty interface types are not supported, nor are booleans, signed integers, floating point numbers, maps, channels and functions.

todo 不支持非空 `interface{}`类型,也不支持 bool值<额, 看下面的代码 bool 其实是支持的>,带符号整数,float,map,chan和 func。

Note that Decode does not set an input limit for all readers and may be vulnerable to panics cause by huge value sizes. If you need an input limit, use

请注意,“解码” 并未为所有 `readers` 设置输入限制,并且可能因【值巨大】而引起恐慌。 如果需要输入限制,请使用

NewStream(r, limit).Decode(val)
Example
input, _ := hex.DecodeString("C90A1486666F6F626172")

type example struct {
	A, B    uint
	private uint // private fields are ignored
	String  string
}

var s example
err := Decode(bytes.NewReader(input), &s)
if err != nil {
	fmt.Printf("Error: %v\n", err)
} else {
	fmt.Printf("Decoded value: %#v\n", s)
}
Output:

Decoded value: rlp.example{A:0xa, B:0x14, private:0x0, String:"foobar"}
Example (StructTagNil)
// In this example, we'll use the "nil" struct tag to change
// how a pointer-typed field is decoded. The input contains an RLP
// list of one element, an empty string.
input := []byte{0xC1, 0x80}

// This type uses the normal rules.
// The empty input string is decoded as a pointer to an empty Go string.
var normalRules struct {
	String *string
}
Decode(bytes.NewReader(input), &normalRules)
fmt.Printf("normal: String = %q\n", *normalRules.String)

// This type uses the struct tag.
// The empty input string is decoded as a nil pointer.
var withEmptyOK struct {
	String *string `rlp:"nil"`
}
Decode(bytes.NewReader(input), &withEmptyOK)
fmt.Printf("with nil tag: String = %v\n", withEmptyOK.String)
Output:

normal: String = ""
with nil tag: String = <nil>
Example (StructTagTail)
package main

import (
	"bytes"
	"fmt"
)

type structWithTail struct {
	A, B uint
	C    []uint `rlp:"tail"`
}

func main() {
	// In this example, the "tail" struct tag is used to decode lists of
	// differing length into a struct.
	var val structWithTail

	err := Decode(bytes.NewReader([]byte{0xC4, 0x01, 0x02, 0x03, 0x04}), &val)
	fmt.Printf("with 4 elements: err=%v val=%v\n", err, val)

	err = Decode(bytes.NewReader([]byte{0xC6, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), &val)
	fmt.Printf("with 6 elements: err=%v val=%v\n", err, val)

	// Note that at least two list elements must be present to
	// fill fields A and B:
	err = Decode(bytes.NewReader([]byte{0xC1, 0x01}), &val)
	fmt.Printf("with 1 element: err=%q\n", err)

}
Output:

with 4 elements: err=<nil> val={1 2 [3 4]}
with 6 elements: err=<nil> val={1 2 [3 4 5 6]}
with 1 element: err="rlp: too few elements for rlp.structWithTail"

func DecodeBytes

func DecodeBytes(b []byte, val interface{}) error

DecodeBytes parses RLP data from b into val. Please see the documentation of Decode for the decoding rules. The input must contain exactly one value and no trailing data.

todo DecodeBytes:

将RLP数据从 `b` 解析到 `val`。 请参阅解码文档以获取解码规则。 输入必须仅包含一个值,并且不包含尾随数据。

func Encode

func Encode(w io.Writer, val interface{}) error

Boolean values are not supported, nor are signed integers, floating point numbers, maps, channels and functions.

不支持布尔值,也不支持有符号整数、浮点数、映射、通道和函数。

func EncodeToBytes

func EncodeToBytes(val interface{}) ([]byte, error)

func EncodeToReader

func EncodeToReader(val interface{}) (size int, r io.Reader, err error)

func ListSize

func ListSize(contentSize uint64) uint64

ListSize returns the encoded size of an RLP list with the given content size.

func SplitList

func SplitList(b []byte) (content, rest []byte, err error)

SplitList splits b into the content of a list and any remaining bytes after the list.

SplitList: 将b拆分为列表的内容和列表之后的所有剩余字节

todo 主要用来解 多字段编码的第一层list

			拆出   [list总前缀, 第一个元素前缀, 第一个元素[]byte, 第二个元素前缀, 第二个元素[]byte, ...]   中的
 		list前缀 并将 后面的内容 <就是第一前缀到 末尾> 作为第一个元素并返回, 第二个元素是个空<这里不管>

@return content: rlp中第一个元素内容 (不是首个代表长度的元素哦,是指首个代表内容的元素) rest: 剩余的元素 err: 错误信息

func SplitString

func SplitString(b []byte) (content, rest []byte, err error)

SplitString splits b into the content of an RLP string and any remaining bytes after the string.

SplitString: 将b拆分为RLP字符串的内容以及该字符串之后的所有剩余字节

todo 主要用来解 多字段编码的第二层内容

用经过拆出 [list总前缀, 第一个元素前缀, 第一个元素[]byte, 第二个元素前缀, 第二个元素[]byte, ...] 中的
list前缀 之后的 后面的内容 作为 第一个元素并返回作为入参,返回里面第一个字段和后面的N个字段的rlp

@return content: rlp中第一个元素内容 (不是首个代表长度的元素哦,是指首个代表内容的元素) rest: 剩余的元素 err: 错误信息

Types

type ByteReader

type ByteReader interface {
	io.Reader
	io.ByteReader
}

ByteReader must be implemented by any input reader for a Stream. It is implemented by e.g. bufio.Reader and bytes.Reader.

ByteReader: 必须由Stream的任何 输入阅读器 实现。 它是由例如 bufio.Reader和bytes.Reader。

type Decoder

type Decoder interface {
	DecodeRLP(*Stream) error
}

Decoder is implemented by types that require custom RLP decoding rules or need to decode into private fields.

The DecodeRLP method should read one value from the given Stream. It is not forbidden to read less or more, but it might be confusing. * 解码器接口, 由需要自定义RLP解码规则或需要解码为私有字段的类型实现。

DecodeRLP方法应从给定的Stream中读取一个值。 禁止少读或多读,但这可能会造成混淆。

type Encoder

type Encoder interface {

	// 实施过程中应生成有效的RLP。编写的数据目前还没有验证,但未来的版本可能会有。
	// 建议只写一个值,但也允许写多个值或根本不写值。
	//
	EncodeRLP(io.Writer) error
}

Encoder is implemented by types that require custom encoding rules or want to encode private fields.

可以理解为,任何拥有下面接口中函数的`结构体`,都表示继承并实现了该接口

Example
package main

import (
	"fmt"
	"io"
)

type MyCoolType struct {
	Name string
	a, b uint
}

// EncodeRLP writes x as RLP list [a, b] that omits the Name field.
func (x *MyCoolType) EncodeRLP(w io.Writer) (err error) {
	// Note: the receiver can be a nil pointer. This allows you to
	// control the encoding of nil, but it also means that you have to
	// check for a nil receiver.
	if x == nil {
		err = Encode(w, []uint{0, 0})
	} else {
		err = Encode(w, []uint{x.a, x.b})
	}
	return err
}

func main() {
	var t *MyCoolType // t is nil pointer to MyCoolType
	bytes, _ := EncodeToBytes(t)
	fmt.Printf("%v → %X\n", t, bytes)

	t = &MyCoolType{Name: "foobar", a: 5, b: 6}
	bytes, _ = EncodeToBytes(t)
	fmt.Printf("%v → %X\n", t, bytes)

}
Output:

<nil> → C28080
&{foobar 5 6} → C20506

type Kind

type Kind int

Kind represents the kind of value contained in an RLP stream.

const (
	// 单个字节
	Byte Kind = iota
	// 字符串
	String
	// 列表
	List
)

* todo RLP 解码 规则

todo RLP编码的解码规则是编码规则的逆运算。首先根据编码结果的第一个字节f,执行以下的规则判断:

todo 判断1:如果f∈[0,127],那么反序列化后是一个字节,就是f。

todo 判断2:如果f∈[128,183],那么反序列化后是一个长度len<=55的字节数组,字节数组的长度为len=f-128。

todo 判断3:如果f∈[184,191],那么反序列化后是一个长度len>55的字节数组,字节数组长度的编码的长度lenOfLen=f-183,然后从第二个字节开始读取lenOfLen个字节,按照大端模式转换成整数len,len即为字节数组的长度。

todo 判断4:如果f∈[193,247],那么反序列化后是一个编码后长度len<=55的列表,列表长度为len=f-192。递归使用判断1~4进行解码。

todo 判断5:如果f∈[247,255],那么反序列化后是编码后长度len>55的列表,列表长度的编码的长度lenOfLen=f-247,然后从第二个字节开始读取lenOfLen个字节,按照大端模式转换成整数len,len即为子列表总长度。然后递归使用判断1~5进行解码。

func Split

func Split(b []byte) (k Kind, content, rest []byte, err error)

Split returns the content of first RLP value and any bytes after the value as subslices of b.

todo Split:

返回第一个RLP值的内容以及该值之后的任何字节,作为b的子切片

@return k: b中的首个元素(也就是代表b内容前缀, 即b的内容类型) content: b 中除掉首个代表内容类型的剩余内容中的第一个元素 rest: 剩余下的内容

func (Kind) String

func (k Kind) String() string

type RawValue

type RawValue []byte

RawValue represents an encoded RLP value and can be used to delay RLP decoding or to precompute an encoding. Note that the decoder does not verify whether the content of RawValues is valid RLP.

todo RawValue: 表示已编码的RLP值,可用于延迟RLP解码或预编码.

todo 注意,解码器不会验证RawValues的内容是否为有效的RLP.

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream can be used for piecemeal decoding of an input stream. This is useful if the input is very large or if the decoding rules for a type depend on the input structure. Stream does not keep an internal buffer. After decoding a value, the input reader will be positioned just before the type information for the next value.

`Stream` 可用于 todo 输入流的逐段解码。 如果输入很大或类型的解码规则取决于输入结构,这将很有用。 `Stream` 不保留内部缓冲区。 解码一个值后,输入阅读器 (input reader) 将位于下一个值的类型信息之前。 【类似于 游标】

When decoding a list and the input position reaches the declared length of the list, all operations will return error EOL. The end of the list must be acknowledged using ListEnd to continue reading the enclosing list.

当解码一个 list 并且输入位置达到 list 的声明 len 时,所有操作将返回错误EOL。 必须使用 `ListEnd` 确认列表的末尾,以继续读取封闭的列表。

Stream is not safe for concurrent use.

`Stream` 不适合同时(并发)使用。

Example
input, _ := hex.DecodeString("C90A1486666F6F626172")
s := NewStream(bytes.NewReader(input), 0)

// Check what kind of value lies ahead
kind, size, _ := s.Kind()
fmt.Printf("Kind: %v size:%d\n", kind, size)

// Enter the list
if _, err := s.List(); err != nil {
	fmt.Printf("List error: %v\n", err)
	return
}

// Decode elements
fmt.Println(s.Uint())
fmt.Println(s.Uint())
fmt.Println(s.Bytes())

// Acknowledge end of list
if err := s.ListEnd(); err != nil {
	fmt.Printf("ListEnd error: %v\n", err)
}
Output:

Kind: List size:9
10 <nil>
20 <nil>
[102 111 111 98 97 114] <nil>

func NewListStream

func NewListStream(r io.Reader, len uint64) *Stream

NewListStream creates a new stream that pretends to be positioned at an encoded list of the given length.

func NewStream

func NewStream(r io.Reader, inputLimit uint64) *Stream

NewStream creates a new decoding stream reading from r.

If r implements the ByteReader interface, Stream will not introduce any buffering.

For non-toplevel values, Stream returns ErrElemTooLarge for values that do not fit into the enclosing list.

Stream supports an optional input limit. If a limit is set, the size of any toplevel value will be checked against the remaining input length. Stream operations that encounter a value exceeding the remaining input length will return ErrValueTooLarge. The limit can be set by passing a non-zero value for inputLimit.

If r is a bytes.Reader or strings.Reader, the input limit is set to the length of r's underlying data unless an explicit limit is provided.

func (*Stream) Bool

func (s *Stream) Bool() (bool, error)

Bool reads an RLP string of up to 1 byte and returns its contents as a boolean. If the input does not contain an RLP string, the returned error will be ErrExpectedString.

Bool: 读取最多1个字节的RLP字符串,并将其内容作为布尔值返回。 如果输入不包含RLP字符串,则返回的错误将为 ErrExpectedString。

func (*Stream) Bytes

func (s *Stream) Bytes() ([]byte, error)

Bytes reads an RLP string and returns its contents as a byte slice. If the input does not contain an RLP string, the returned error will be ErrExpectedString.

func (*Stream) Decode

func (s *Stream) Decode(val interface{}) error

Decode decodes a value and stores the result in the value pointed to by val. Please see the documentation for the Decode function to learn about the decoding rules.

Decode: 解码一个值,并将结果存储在val指向的值中。 请参阅解码功能的文档以了解解码规则。

func (*Stream) Kind

func (s *Stream) Kind() (kind Kind, size uint64, err error)

Kind returns the kind and size of the next value in the input stream.

todo Kind: 返回 输入流 中下一个值的 `种类` 和 `大小`。

The returned size is the number of bytes that make up the value. For kind == Byte, the size is zero because the value is contained in the type tag.

todo 返回的大小是 组成该值的字节数。

对于 kind == Byte,大小为零,因为该值包含在type标记中。

The first call to Kind will read size information from the input reader and leave it positioned at the start of the actual bytes of the value. Subsequent calls to Kind (until the value is decoded) will not advance the input reader and return cached information.

todo 首次调用 `Kind` 将从 输入流的Reader 中读取大小信息,并将其放置在该值实际字节的开头。

随后对 `Kind` 的调用(直到对值进行解码)将不会使 输入流的Reader 前进,也不会返回缓存的信息。

func (*Stream) List

func (s *Stream) List() (size uint64, err error)

List starts decoding an RLP list. If the input does not contain a list, the returned error will be ErrExpectedList. When the list's end has been reached, any Stream operation will return EOL.

todo List: 开始解码RLP列表。

如果输入不包含 list,则返回的错误将为 `ErrExpectedList`。
到达列表的末尾时,任何Stream操作都将返回 `EOL`。

func (*Stream) ListEnd

func (s *Stream) ListEnd() error

ListEnd returns to the enclosing list. The input reader must be positioned at the end of a list.

ListEnd: 返回到 封闭列表。 输入阅读器 必须位于列表的末尾。

func (*Stream) Raw

func (s *Stream) Raw() ([]byte, error)

Raw reads a raw encoded value including RLP type information.

todo Raw:

读取包含RLP类型信息的原始编码值。

func (*Stream) Reset

func (s *Stream) Reset(r io.Reader, inputLimit uint64)

Reset discards any information about the current decoding context and starts reading from r. This method is meant to facilitate reuse of a preallocated Stream across many decoding operations.

If r does not also implement ByteReader, Stream will do its own buffering.

func (*Stream) Uint

func (s *Stream) Uint() (uint64, error)

Uint reads an RLP string of up to 8 bytes and returns its contents as an unsigned integer. If the input does not contain an RLP string, the returned error will be ErrExpectedString.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL