github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/mpt/node.go (about) 1 package mpt 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "errors" 7 8 "github.com/nspcc-dev/neo-go/pkg/io" 9 "github.com/nspcc-dev/neo-go/pkg/util" 10 ) 11 12 // NodeType represents a node type.. 13 type NodeType byte 14 15 // Node types definitions. 16 const ( 17 BranchT NodeType = 0x00 18 ExtensionT NodeType = 0x01 19 LeafT NodeType = 0x02 20 HashT NodeType = 0x03 21 EmptyT NodeType = 0x04 22 ) 23 24 // NodeObject represents a Node together with it's type. 25 // It is used for serialization/deserialization where type info 26 // is also expected. 27 type NodeObject struct { 28 Node 29 } 30 31 // Node represents a common interface of all MPT nodes. 32 type Node interface { 33 io.Serializable 34 json.Marshaler 35 json.Unmarshaler 36 Size() int 37 Clone() Node 38 BaseNodeIface 39 } 40 41 // EncodeBinary implements io.Serializable. 42 func (n NodeObject) EncodeBinary(w *io.BinWriter) { 43 encodeNodeWithType(n.Node, w) 44 } 45 46 // DecodeBinary implements io.Serializable. 47 func (n *NodeObject) DecodeBinary(r *io.BinReader) { 48 n.Node = DecodeNodeWithType(r) 49 } 50 51 // UnmarshalJSON implements the json.Unmarshaler. 52 func (n *NodeObject) UnmarshalJSON(data []byte) error { 53 var m map[string]json.RawMessage 54 err := json.Unmarshal(data, &m) 55 if err != nil { // it can be a branch node 56 var nodes []NodeObject 57 if err := json.Unmarshal(data, &nodes); err != nil { 58 return err 59 } else if len(nodes) != childrenCount { 60 return errors.New("invalid length of branch node") 61 } 62 63 b := NewBranchNode() 64 for i := range b.Children { 65 b.Children[i] = nodes[i].Node 66 } 67 n.Node = b 68 return nil 69 } 70 71 switch len(m) { 72 case 0: 73 n.Node = EmptyNode{} 74 case 1: 75 if v, ok := m["hash"]; ok { 76 var h util.Uint256 77 if err := json.Unmarshal(v, &h); err != nil { 78 return err 79 } 80 n.Node = NewHashNode(h) 81 } else if v, ok = m["value"]; ok { 82 b, err := unmarshalHex(v) 83 if err != nil { 84 return err 85 } else if len(b) > MaxValueLength { 86 return errors.New("leaf value is too big") 87 } 88 n.Node = NewLeafNode(b) 89 } else { 90 return errors.New("invalid field") 91 } 92 case 2: 93 keyRaw, ok1 := m["key"] 94 nextRaw, ok2 := m["next"] 95 if !ok1 || !ok2 { 96 return errors.New("invalid field") 97 } 98 key, err := unmarshalHex(keyRaw) 99 if err != nil { 100 return err 101 } else if len(key) > maxPathLength { 102 return errors.New("extension key is too big") 103 } 104 105 var next NodeObject 106 if err := json.Unmarshal(nextRaw, &next); err != nil { 107 return err 108 } 109 n.Node = NewExtensionNode(key, next.Node) 110 default: 111 return errors.New("0, 1 or 2 fields expected") 112 } 113 return nil 114 } 115 116 func unmarshalHex(data json.RawMessage) ([]byte, error) { 117 var s string 118 if err := json.Unmarshal(data, &s); err != nil { 119 return nil, err 120 } 121 return hex.DecodeString(s) 122 }