2020-05-22 07:37:07 +00:00
|
|
|
package mpt
|
|
|
|
|
|
|
|
import (
|
2020-05-28 05:55:12 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
|
2020-05-22 07:37:07 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// childrenCount represents a number of children of a branch node.
|
|
|
|
childrenCount = 17
|
|
|
|
// lastChild is the index of the last child.
|
|
|
|
lastChild = childrenCount - 1
|
|
|
|
)
|
|
|
|
|
|
|
|
// BranchNode represents MPT's branch node.
|
|
|
|
type BranchNode struct {
|
2020-06-02 20:49:46 +00:00
|
|
|
BaseNode
|
2020-05-22 07:37:07 +00:00
|
|
|
Children [childrenCount]Node
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ Node = (*BranchNode)(nil)
|
|
|
|
|
|
|
|
// NewBranchNode returns new branch node.
|
|
|
|
func NewBranchNode() *BranchNode {
|
|
|
|
b := new(BranchNode)
|
|
|
|
for i := 0; i < childrenCount; i++ {
|
2021-08-03 14:10:46 +00:00
|
|
|
b.Children[i] = EmptyNode{}
|
2020-05-22 07:37:07 +00:00
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements Node interface.
|
|
|
|
func (b *BranchNode) Type() NodeType { return BranchT }
|
|
|
|
|
2020-06-02 20:49:46 +00:00
|
|
|
// Hash implements BaseNode interface.
|
2020-05-22 07:37:07 +00:00
|
|
|
func (b *BranchNode) Hash() util.Uint256 {
|
2020-06-02 20:49:46 +00:00
|
|
|
return b.getHash(b)
|
2020-05-22 07:37:07 +00:00
|
|
|
}
|
|
|
|
|
2020-06-02 20:49:46 +00:00
|
|
|
// Bytes implements BaseNode interface.
|
|
|
|
func (b *BranchNode) Bytes() []byte {
|
|
|
|
return b.getBytes(b)
|
2020-05-22 07:37:07 +00:00
|
|
|
}
|
|
|
|
|
2021-08-03 15:50:13 +00:00
|
|
|
// Size implements Node interface.
|
|
|
|
func (b *BranchNode) Size() int {
|
|
|
|
sz := childrenCount
|
|
|
|
for i := range b.Children {
|
|
|
|
if !isEmpty(b.Children[i]) {
|
|
|
|
sz += util.Uint256Size
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sz
|
|
|
|
}
|
|
|
|
|
2020-05-22 07:37:07 +00:00
|
|
|
// EncodeBinary implements io.Serializable.
|
|
|
|
func (b *BranchNode) EncodeBinary(w *io.BinWriter) {
|
|
|
|
for i := 0; i < childrenCount; i++ {
|
2021-08-03 11:19:50 +00:00
|
|
|
encodeBinaryAsChild(b.Children[i], w)
|
2020-05-22 07:37:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeBinary implements io.Serializable.
|
|
|
|
func (b *BranchNode) DecodeBinary(r *io.BinReader) {
|
|
|
|
for i := 0; i < childrenCount; i++ {
|
2021-03-31 08:04:42 +00:00
|
|
|
no := new(NodeObject)
|
|
|
|
no.DecodeBinary(r)
|
|
|
|
b.Children[i] = no.Node
|
2020-05-22 07:37:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-28 05:55:12 +00:00
|
|
|
// MarshalJSON implements json.Marshaler.
|
|
|
|
func (b *BranchNode) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(b.Children)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler.
|
|
|
|
func (b *BranchNode) UnmarshalJSON(data []byte) error {
|
|
|
|
var obj NodeObject
|
|
|
|
if err := obj.UnmarshalJSON(data); err != nil {
|
|
|
|
return err
|
|
|
|
} else if u, ok := obj.Node.(*BranchNode); ok {
|
|
|
|
*b = *u
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return errors.New("expected branch node")
|
|
|
|
}
|
|
|
|
|
2020-05-22 07:37:07 +00:00
|
|
|
// splitPath splits path for a branch node.
|
|
|
|
func splitPath(path []byte) (byte, []byte) {
|
|
|
|
if len(path) != 0 {
|
|
|
|
return path[0], path[1:]
|
|
|
|
}
|
|
|
|
return lastChild, path
|
|
|
|
}
|