github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/mpt/extension.go (about) 1 package mpt 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "errors" 7 "fmt" 8 9 "github.com/nspcc-dev/neo-go/pkg/config/limits" 10 "github.com/nspcc-dev/neo-go/pkg/io" 11 "github.com/nspcc-dev/neo-go/pkg/util" 12 ) 13 14 const ( 15 // maxPathLength is the max length of the extension node key. 16 maxPathLength = (limits.MaxStorageKeyLen + 4) * 2 17 18 // MaxKeyLength is the max length of the key to put in the trie 19 // before transforming to nibbles. 20 MaxKeyLength = maxPathLength / 2 21 ) 22 23 // ExtensionNode represents an MPT's extension node. 24 type ExtensionNode struct { 25 BaseNode 26 key []byte 27 next Node 28 } 29 30 var _ Node = (*ExtensionNode)(nil) 31 32 // NewExtensionNode returns a hash node with the specified key and the next node. 33 // Note: since it is a part of a Trie, the key must be mangled, i.e. must contain only bytes with high half = 0. 34 func NewExtensionNode(key []byte, next Node) *ExtensionNode { 35 return &ExtensionNode{ 36 key: key, 37 next: next, 38 } 39 } 40 41 // Type implements Node interface. 42 func (e ExtensionNode) Type() NodeType { return ExtensionT } 43 44 // Hash implements BaseNode interface. 45 func (e *ExtensionNode) Hash() util.Uint256 { 46 return e.getHash(e) 47 } 48 49 // Bytes implements BaseNode interface. 50 func (e *ExtensionNode) Bytes() []byte { 51 return e.getBytes(e) 52 } 53 54 // DecodeBinary implements io.Serializable. 55 func (e *ExtensionNode) DecodeBinary(r *io.BinReader) { 56 sz := r.ReadVarUint() 57 if sz > maxPathLength { 58 r.Err = fmt.Errorf("extension node key is too big: %d", sz) 59 return 60 } 61 e.key = make([]byte, sz) 62 r.ReadBytes(e.key) 63 no := new(NodeObject) 64 no.DecodeBinary(r) 65 e.next = no.Node 66 e.invalidateCache() 67 } 68 69 // EncodeBinary implements io.Serializable. 70 func (e ExtensionNode) EncodeBinary(w *io.BinWriter) { 71 w.WriteVarBytes(e.key) 72 encodeBinaryAsChild(e.next, w) 73 } 74 75 // Size implements Node interface. 76 func (e *ExtensionNode) Size() int { 77 return io.GetVarSize(len(e.key)) + len(e.key) + 78 1 + util.Uint256Size // e.next is never empty 79 } 80 81 // MarshalJSON implements the json.Marshaler. 82 func (e *ExtensionNode) MarshalJSON() ([]byte, error) { 83 m := map[string]any{ 84 "key": hex.EncodeToString(e.key), 85 "next": e.next, 86 } 87 return json.Marshal(m) 88 } 89 90 // UnmarshalJSON implements the json.Unmarshaler. 91 func (e *ExtensionNode) UnmarshalJSON(data []byte) error { 92 var obj NodeObject 93 if err := obj.UnmarshalJSON(data); err != nil { 94 return err 95 } else if u, ok := obj.Node.(*ExtensionNode); ok { 96 *e = *u 97 return nil 98 } 99 return errors.New("expected extension node") 100 } 101 102 // Clone implements Node interface. 103 func (e *ExtensionNode) Clone() Node { 104 res := *e 105 return &res 106 }