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  }