neoneo-go/pkg/core/mpt/hash.go
Evgenii Stratonikov 9c478378e1 mpt: implement JSON marshaling/unmarshaling
Because there is no distinct type field in JSONized nodes, distinction
is made via payload itself, thus all unmarshaling is done via
NodeObject.
2020-06-01 18:15:13 +03:00

82 lines
1.7 KiB
Go

package mpt
import (
"errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// HashNode represents MPT's hash node.
type HashNode struct {
hash util.Uint256
valid bool
}
var _ Node = (*HashNode)(nil)
// NewHashNode returns hash node with the specified hash.
func NewHashNode(h util.Uint256) *HashNode {
return &HashNode{
hash: h,
valid: true,
}
}
// Type implements Node interface.
func (h *HashNode) Type() NodeType { return HashT }
// Hash implements Node interface.
func (h *HashNode) Hash() util.Uint256 {
if !h.valid {
panic("can't get hash of an empty HashNode")
}
return h.hash
}
// IsEmpty returns true iff h is an empty node i.e. contains no hash.
func (h *HashNode) IsEmpty() bool { return !h.valid }
// DecodeBinary implements io.Serializable.
func (h *HashNode) DecodeBinary(r *io.BinReader) {
sz := r.ReadVarUint()
switch sz {
case 0:
h.valid = false
case util.Uint256Size:
h.valid = true
r.ReadBytes(h.hash[:])
default:
r.Err = fmt.Errorf("invalid hash node size: %d", sz)
}
}
// EncodeBinary implements io.Serializable.
func (h HashNode) EncodeBinary(w *io.BinWriter) {
if !h.valid {
w.WriteVarUint(0)
return
}
w.WriteVarBytes(h.hash[:])
}
// MarshalJSON implements json.Marshaler.
func (h *HashNode) MarshalJSON() ([]byte, error) {
if !h.valid {
return []byte(`{}`), nil
}
return []byte(`{"hash":"` + h.hash.StringLE() + `"}`), nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (h *HashNode) UnmarshalJSON(data []byte) error {
var obj NodeObject
if err := obj.UnmarshalJSON(data); err != nil {
return err
} else if u, ok := obj.Node.(*HashNode); ok {
*h = *u
return nil
}
return errors.New("expected hash node")
}