9 "github.com/bytom/encoding/blockchain"
10 "github.com/bytom/encoding/bufpool"
11 "github.com/bytom/errors"
12 "github.com/bytom/protocol/bc"
15 // BlockHeader describes necessary data of the block.
16 type BlockHeader struct {
17 // Version of the block.
18 Version uint64 `json:"version"`
20 // Height of the block in the block chain.
21 // Initial block has height 1.
22 Height uint64 `json:"height"`
24 // Hash of the previous block in the block chain.
25 PreviousBlockHash bc.Hash `json:"previous_block_hash"`
27 // Time of the block in seconds.
28 Timestamp uint64 `json:"timestamp"`
32 Nonce uint64 `json:"nonce"`
33 Bits uint64 `json:"bits"`
36 // Time returns the time represented by the Timestamp in bh.
37 func (bh *BlockHeader) Time() time.Time {
38 tsNano := bh.Timestamp * uint64(time.Second)
39 return time.Unix(0, int64(tsNano)).UTC()
42 // Scan validates the input byte slice is a valid block header
43 func (bh *BlockHeader) Scan(val interface{}) error {
44 driverBuf, ok := val.([]byte)
46 return errors.New("Scan must receive a byte slice")
48 buf := make([]byte, len(driverBuf))
49 copy(buf[:], driverBuf)
50 _, err := bh.readFrom(blockchain.NewReader(buf))
54 // Hash returns complete hash of the block header.
55 func (bh *BlockHeader) Hash() bc.Hash {
56 h, _ := mapBlockHeader(bh)
60 // MarshalText fulfills the json.Marshaler interface.
61 // This guarantees that block headers will get deserialized correctly
62 // when being parsed from HTTP requests.
63 func (bh *BlockHeader) MarshalText() ([]byte, error) {
65 defer bufpool.Put(buf)
66 if _, err := bh.WriteTo(buf); err != nil {
70 enc := make([]byte, hex.EncodedLen(buf.Len()))
71 hex.Encode(enc, buf.Bytes())
75 // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
76 func (bh *BlockHeader) UnmarshalText(text []byte) error {
77 decoded := make([]byte, hex.DecodedLen(len(text)))
78 if _, err := hex.Decode(decoded, text); err != nil {
81 _, err := bh.readFrom(blockchain.NewReader(decoded))
85 func (bh *BlockHeader) readFrom(r *blockchain.Reader) (serflag uint8, err error) {
87 io.ReadFull(r, serflags[:])
90 case SerBlockHeader, SerBlockFull:
92 return 0, fmt.Errorf("unsupported serialization flags 0x%x", serflags)
95 if bh.Version, err = blockchain.ReadVarint63(r); err != nil {
98 if bh.Height, err = blockchain.ReadVarint63(r); err != nil {
101 if _, err = bh.PreviousBlockHash.ReadFrom(r); err != nil {
104 if bh.Timestamp, err = blockchain.ReadVarint63(r); err != nil {
107 if _, err = blockchain.ReadExtensibleString(r, bh.BlockCommitment.readFrom); err != nil {
110 if bh.Nonce, err = blockchain.ReadVarint63(r); err != nil {
113 if bh.Bits, err = blockchain.ReadVarint63(r); err != nil {
119 // WriteTo writes the block header to the input io.Writer
120 func (bh *BlockHeader) WriteTo(w io.Writer) (int64, error) {
121 ew := errors.NewWriter(w)
122 bh.writeTo(ew, SerBlockHeader)
123 return ew.Written(), ew.Err()
126 // writeTo writes bh to w.
127 func (bh *BlockHeader) writeTo(w io.Writer, serflags uint8) (err error) {
128 w.Write([]byte{serflags})
130 if _, err = blockchain.WriteVarint63(w, bh.Version); err != nil {
133 if _, err = blockchain.WriteVarint63(w, bh.Height); err != nil {
136 if _, err = bh.PreviousBlockHash.WriteTo(w); err != nil {
139 if _, err = blockchain.WriteVarint63(w, bh.Timestamp); err != nil {
142 if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockCommitment.writeTo); err != nil {
145 if _, err = blockchain.WriteVarint63(w, bh.Nonce); err != nil {
148 if _, err = blockchain.WriteVarint63(w, bh.Bits); err != nil {