rlp

package
v0.8.6 Latest Latest
Warning

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

Go to latest
Published: May 28, 2024 License: GPL-3.0 Imports: 13 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 (
	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")
)
View Source
var (
	// Common encoded values.
	// These are useful when implementing EncodeRLP.
	EmptyString = []byte{0x80}
	EmptyList   = []byte{0xC0}
)
View Source
var EOL = errors.New("rlp: end of list")

EOL is returned when the end of the current list has been reached during streaming.

View Source
var ErrNegativeBigInt = errors.New("rlp: cannot encode negative big.Int")

Functions

func CountValues

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

CountValues counts the number of encoded values in b.

func Decode

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

Decode parses RLP-encoded data from r and stores the result in the value pointed to by val. Please see package-level documentation for the decoding rules. Val must be a non-nil pointer.

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

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

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

type example struct {
	A, B   uint
	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, 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 package-level documentation for the decoding rules. The input must contain exactly one value and no trailing data.

func Encode

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

Encode writes the RLP encoding of val to w. Note that Encode may perform many small writes in some cases. Consider making w buffered.

Please see package-level documentation of encoding rules.

func EncodeToBytes

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

EncodeToBytes returns the RLP encoding of val. Please see package-level documentation for the encoding rules.

func EncodeToReader

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

EncodeToReader returns a reader from which the RLP encoding of val can be read. The returned size is the total size of the encoded data.

Please see the documentation of Encode for the encoding rules.

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.

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.

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.

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.

type Encoder

type Encoder interface {
	// EncodeRLP should write the RLP encoding of its receiver to w.
	// If the implementation is a pointer method, it may also be
	// called for nil pointers.
	//
	// Implementations should generate valid RLP. The data written is
	// not verified at the moment, but a future version might. It is
	// recommended to write only a single value but writing multiple
	// values or no value at all is also permitted.
	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 EncoderBuffer added in v0.8.6

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

EncoderBuffer is a buffer for incremental encoding.

The zero value is NOT ready for use. To get a usable buffer, create it using NewEncoderBuffer or call Reset.

Example
package main

import (
	"bytes"
	"fmt"

	"github.com/anduschain/go-anduschain/rlp"
)

func main() {
	var w bytes.Buffer

	// Encode [4, [5, 6]] to w.
	buf := rlp.NewEncoderBuffer(&w)
	l1 := buf.List()
	buf.WriteUint64(4)
	l2 := buf.List()
	buf.WriteUint64(5)
	buf.WriteUint64(6)
	buf.ListEnd(l2)
	buf.ListEnd(l1)

	if err := buf.Flush(); err != nil {
		panic(err)
	}
	fmt.Printf("%X\n", w.Bytes())
}
Output:

C404C20506

func NewEncoderBuffer added in v0.8.6

func NewEncoderBuffer(dst io.Writer) EncoderBuffer

NewEncoderBuffer creates an encoder buffer.

func (*EncoderBuffer) AppendToBytes added in v0.8.6

func (w *EncoderBuffer) AppendToBytes(dst []byte) []byte

AppendToBytes appends the encoded bytes to dst.

func (*EncoderBuffer) Flush added in v0.8.6

func (w *EncoderBuffer) Flush() error

Flush writes encoded RLP data to the output writer. This can only be called once. If you want to re-use the buffer after Flush, you must call Reset.

func (EncoderBuffer) List added in v0.8.6

func (w EncoderBuffer) List() int

List starts a list. It returns an internal index. Call EndList with this index after encoding the content to finish the list.

func (EncoderBuffer) ListEnd added in v0.8.6

func (w EncoderBuffer) ListEnd(index int)

ListEnd finishes the given list.

func (*EncoderBuffer) Reset added in v0.8.6

func (w *EncoderBuffer) Reset(dst io.Writer)

Reset truncates the buffer and sets the output destination.

func (*EncoderBuffer) ToBytes added in v0.8.6

func (w *EncoderBuffer) ToBytes() []byte

ToBytes returns the encoded bytes.

func (EncoderBuffer) Write added in v0.8.6

func (w EncoderBuffer) Write(b []byte) (int, error)

Write appends b directly to the encoder output.

func (EncoderBuffer) WriteBigInt added in v0.8.6

func (w EncoderBuffer) WriteBigInt(i *big.Int)

WriteBigInt encodes a big.Int as an RLP string. Note: Unlike with Encode, the sign of i is ignored.

func (EncoderBuffer) WriteBool added in v0.8.6

func (w EncoderBuffer) WriteBool(b bool)

WriteBool writes b as the integer 0 (false) or 1 (true).

func (EncoderBuffer) WriteBytes added in v0.8.6

func (w EncoderBuffer) WriteBytes(b []byte)

WriteBytes encodes b as an RLP string.

func (EncoderBuffer) WriteString added in v0.8.6

func (w EncoderBuffer) WriteString(s string)

WriteBytes encodes s as an RLP string.

func (EncoderBuffer) WriteUint64 added in v0.8.6

func (w EncoderBuffer) WriteUint64(i uint64)

WriteUint64 encodes an unsigned integer.

type Kind

type Kind int8

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

const (
	Byte Kind = iota
	String
	List
)

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.

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.

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.

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.

Stream is not safe for concurrent use.

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) BigInt added in v0.8.6

func (s *Stream) BigInt() (*big.Int, error)

BigInt decodes an arbitrary-size integer value.

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.

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.

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.

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.

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.

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.

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.

func (*Stream) MoreDataInList added in v0.8.6

func (s *Stream) MoreDataInList() bool

MoreDataInList reports whether the current list context contains more data to be read.

func (*Stream) Raw

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

Raw reads a raw encoded value including RLP type information.

func (*Stream) ReadBytes added in v0.8.6

func (s *Stream) ReadBytes(b []byte) error

ReadBytes decodes the next RLP value and stores the result in b. The value size must match len(b) exactly.

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 deprecated

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.

Deprecated: use s.Uint64 instead.

func (*Stream) Uint16 added in v0.8.6

func (s *Stream) Uint16() (uint16, error)

func (*Stream) Uint32 added in v0.8.6

func (s *Stream) Uint32() (uint32, error)

func (*Stream) Uint64 added in v0.8.6

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

func (*Stream) Uint8 added in v0.8.6

func (s *Stream) Uint8() (uint8, error)

Directories

Path Synopsis
internal
rlpstruct
Package rlpstruct implements struct processing for RLP encoding/decoding.
Package rlpstruct implements struct processing for RLP encoding/decoding.

Jump to

Keyboard shortcuts

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