Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

node.gno

3.09 Kb · 138 lines
  1package mpt
  2
  3import (
  4	"gno.land/p/onbloc/encoding/rlp"
  5)
  6
  7// isDataNode reports whether v is a string/byte payload rather than a list.
  8func isDataNode(v rlp.Value) bool {
  9	return v.Kind == rlp.KindString || v.Kind == rlp.KindByte
 10}
 11
 12// node mirrors go-ethereum's node interface (marker only; cache/encode/
 13// fstring are for trie construction, unneeded for verification).
 14// Reference:
 15// https://github.com/ethereum/go-ethereum/blob/v1.10.26/trie/node.go#L30-L48
 16type node interface{}
 17
 18// flags nodeFlag (cached hash + dirty bit, for incremental rehashing on
 19// mutation) is dropped from both structs below: never read by decodeNode,
 20// get, or verifyProof.
 21type (
 22	fullNode struct {
 23		Children [17]node
 24	}
 25	shortNode struct {
 26		Key []byte
 27		Val node
 28	}
 29	hashNode  []byte
 30	valueNode []byte
 31)
 32
 33// decodeNode mirrors decodeNode (hash argument dropped: cache-only, unused
 34// by verification).
 35// Reference:
 36// https://github.com/ethereum/go-ethereum/blob/v1.10.26/trie/node.go#L133-L151
 37func decodeNode(buf []byte) (node, error) {
 38	v, err := rlp.DecodeValue(buf)
 39	if err != nil {
 40		return nil, err
 41	}
 42
 43	return decodeNodeValue(v)
 44}
 45
 46// decodeNodeValue is decodeNode's dispatch step, split out so decodeRef can
 47// resolve an already-decoded embedded child without re-parsing raw bytes.
 48func decodeNodeValue(v rlp.Value) (node, error) {
 49	if v.Kind != rlp.KindList {
 50		return nil, ErrUnexpectedNode
 51	}
 52
 53	switch len(v.List) {
 54	case 2:
 55		return decodeShort(v)
 56	case 17:
 57		return decodeFull(v)
 58	default:
 59		return nil, ErrUnexpectedNode
 60	}
 61}
 62
 63// decodeShort mirrors decodeShort.
 64// Reference:
 65// https://github.com/ethereum/go-ethereum/blob/v1.10.26/trie/node.go#L153-L173
 66func decodeShort(elems rlp.Value) (node, error) {
 67	kbuf := elems.List[0]
 68	if !isDataNode(kbuf) {
 69		return nil, ErrUnexpectedNode
 70	}
 71
 72	key := compactToHex(kbuf.Bytes)
 73
 74	if hasTerm(key) {
 75		val := elems.List[1]
 76		if !isDataNode(val) {
 77			return nil, ErrUnexpectedNode
 78		}
 79
 80		return &shortNode{Key: key, Val: valueNode(val.Bytes)}, nil
 81	}
 82
 83	r, err := decodeRef(elems.List[1])
 84	if err != nil {
 85		return nil, err
 86	}
 87
 88	return &shortNode{Key: key, Val: r}, nil
 89}
 90
 91// decodeFull mirrors decodeFull.
 92// Reference:
 93// https://github.com/ethereum/go-ethereum/blob/v1.10.26/trie/node.go#L175-L192
 94func decodeFull(elems rlp.Value) (*fullNode, error) {
 95	n := &fullNode{}
 96
 97	for i := 0; i < 16; i++ {
 98		cld, err := decodeRef(elems.List[i])
 99		if err != nil {
100			return n, err
101		}
102
103		n.Children[i] = cld
104	}
105
106	val := elems.List[16]
107	if !isDataNode(val) {
108		return n, ErrUnexpectedNode
109	}
110
111	if len(val.Bytes) > 0 {
112		n.Children[16] = valueNode(val.Bytes)
113	}
114
115	return n, nil
116}
117
118// decodeRef mirrors decodeRef, minus its "oversized embedded node" size
119// check (no verifier-side security benefit: the parent hash already covers
120// these bytes regardless of embed size).
121// Reference:
122// https://github.com/ethereum/go-ethereum/blob/v1.10.26/trie/node.go#L196-L218
123func decodeRef(buf rlp.Value) (node, error) {
124	if buf.Kind == rlp.KindList {
125		return decodeNodeValue(buf)
126	}
127
128	switch len(buf.Bytes) {
129	case 0:
130		return nil, nil
131
132	case 32:
133		return hashNode(buf.Bytes), nil
134
135	default:
136		return nil, ErrInvalidReference
137	}
138}