func (b *OpenBlock) UnmarshalBinary(data []byte) error {
	reader := bytes.NewReader(data)
	var err error
	if _, err = reader.Read(b.SourceHash[:]); err != nil {
		return err
	}
	if _, err = reader.Read(b.Representative[:]); err != nil {
		return err
	}
	if _, err = reader.Read(b.Address[:]); err != nil {
		return err
	}
	commonBytes := make([]byte, blockSizeCommon)
	if _, err = reader.Read(commonBytes); err != nil {
		return err
	}
	return unmarshalCommon(commonBytes, binary.LittleEndian, &b.Signature, &b.Work)
}
UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
package block
import (
	"bytes"
	"encoding"
	"encoding/binary"
	"errors"
	"github.com/alexbakker/gonano/nano"
	"github.com/alexbakker/gonano/nano/internal/util"
)
const (
	idBlockInvalid byte = iota
	idBlockNotABlock
	idBlockSend
	idBlockReceive
	idBlockOpen
	idBlockChange
	idBlockState
)
var (
	ErrBadBlockType = errors.New("bad block type")
	ErrNotABlock    = errors.New("block type is not_a_block")
	blockNames = map[byte]string{
		idBlockInvalid:   "invalid",
		idBlockNotABlock: "not_a_block",
		idBlockSend:      "send",
		idBlockReceive:   "receive",
		idBlockOpen:      "open",
		idBlockChange:    "change",
		idBlockState:     "state",
	}
)
const (
	preambleSize     = 32
	blockSizeCommon  = SignatureSize + WorkSize
	blockSizeOpen    = blockSizeCommon + HashSize + nano.AddressSize*2
	blockSizeSend    = blockSizeCommon + HashSize + nano.AddressSize + nano.BalanceSize
	blockSizeReceive = blockSizeCommon + HashSize*2
	blockSizeChange  = blockSizeCommon + HashSize + nano.AddressSize
	blockSizeState   = blockSizeCommon + HashSize*2 + nano.AddressSize*2 + nano.BalanceSize
)
type Block interface {
	encoding.BinaryMarshaler
	encoding.BinaryUnmarshaler
	Hash() Hash
	Root() Hash
	Size() int
	ID() byte
	Valid(threshold uint64) bool
}
type OpenBlock struct {
	SourceHash     Hash         `json:"source"`
	Representative nano.Address `json:"representative"`
	Address        nano.Address `json:"address"`
	Signature      Signature    `json:"signature"`
	Work           Work         `json:"work"`
}
type SendBlock struct {
	PreviousHash Hash         `json:"previous"`
	Destination  nano.Address `json:"destination"`
	Balance      nano.Balance `json:"balance"`
	Signature    Signature    `json:"signature"`
	Work         Work         `json:"work"`
}
type ReceiveBlock struct {
	PreviousHash Hash      `json:"previous"`
	SourceHash   Hash      `json:"source"`
	Signature    Signature `json:"signature"`
	Work         Work      `json:"work"`
}
type ChangeBlock struct {
	PreviousHash   Hash         `json:"previous"`
	Representative nano.Address `json:"representative"`
	Signature      Signature    `json:"signature"`
	Work           Work         `json:"work"`
}
type StateBlock struct {
	Address        nano.Address `json:"address"`
	PreviousHash   Hash         `json:"previous"`
	Representative nano.Address `json:"representative"`
	Balance        nano.Balance `json:"balance"`
	Link           Hash         `json:"link"`
	Signature      Signature    `json:"signature"`
	Work           Work         `json:"work"`
}
func New(blockType byte) (Block, error) {
	switch blockType {
	case idBlockOpen:
		return new(OpenBlock), nil
	case idBlockSend:
		return new(SendBlock), nil
	case idBlockReceive:
		return new(ReceiveBlock), nil
	case idBlockChange:
		return new(ChangeBlock), nil
	case idBlockState:
		return new(StateBlock), nil
	case idBlockNotABlock:
		return nil, ErrNotABlock
	default:
		return nil, ErrBadBlockType
	}
}
func Name(id byte) string {
	return blockNames[id]
}
func marshalCommon(sig Signature, work Work, order binary.ByteOrder) ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error
	if _, err = buf.Write(sig[:]); err != nil {
		return nil, err
	}
	if err = binary.Write(buf, order, work); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func unmarshalCommon(data []byte, order binary.ByteOrder, sig *Signature, work *Work) error {
	reader := bytes.NewReader(data)
	var s Signature
	if _, err := reader.Read(s[:]); err != nil {
		return err
	}
	*sig = s
	var w Work
	if err := binary.Read(reader, order, &w); err != nil {
		return err
	}
	*work = w
	if err := util.AssertReaderEOF(reader); err != nil {
		return err
	}
	return nil
}
func (b *OpenBlock) MarshalBinary() ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error
	if _, err = buf.Write(b.SourceHash[:]); err != nil {
		return nil, err
	}
	if _, err = buf.Write(b.Representative[:]); err != nil {
		return nil, err
	}
	if _, err = buf.Write(b.Address[:]); err != nil {
		return nil, err
	}
	commonBytes, err := marshalCommon(b.Signature, b.Work, binary.LittleEndian)
	if err != nil {
		return nil, err
	}
	if _, err = buf.Write(commonBytes); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}