OSDN Git Service

Small edit (#241)
[bytom/vapor.git] / protocol / bc / types / block_header.go
1 package types
2
3 import (
4         "encoding/hex"
5         "fmt"
6         "io"
7         "time"
8
9         "github.com/vapor/encoding/blockchain"
10         "github.com/vapor/encoding/bufpool"
11         "github.com/vapor/errors"
12         "github.com/vapor/protocol/bc"
13 )
14
15 // BlockHeader defines information about a block and is used in the Bytom
16 type BlockHeader struct {
17         Version           uint64  // The version of the block.
18         Height            uint64  // The height of the block.
19         PreviousBlockHash bc.Hash // The hash of the previous block.
20         Timestamp         uint64  // The time of the block in milliseconds.
21         BlockCommitment
22         BlockWitness
23 }
24
25 // Time returns the time represented by the Timestamp in block header.
26 func (bh *BlockHeader) Time() time.Time {
27         return time.Unix(0, int64(bh.Timestamp)*int64(time.Millisecond)).UTC()
28 }
29
30 // Hash returns complete hash of the block header.
31 func (bh *BlockHeader) Hash() bc.Hash {
32         h, _ := mapBlockHeader(bh)
33         return h
34 }
35
36 // MarshalText fulfills the json.Marshaler interface. This guarantees that
37 // block headers will get deserialized correctly when being parsed from HTTP
38 // requests.
39 func (bh *BlockHeader) MarshalText() ([]byte, error) {
40         buf := bufpool.Get()
41         defer bufpool.Put(buf)
42
43         if _, err := bh.WriteTo(buf); err != nil {
44                 return nil, err
45         }
46
47         enc := make([]byte, hex.EncodedLen(buf.Len()))
48         hex.Encode(enc, buf.Bytes())
49         return enc, nil
50 }
51
52 // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
53 func (bh *BlockHeader) UnmarshalText(text []byte) error {
54         decoded := make([]byte, hex.DecodedLen(len(text)))
55         if _, err := hex.Decode(decoded, text); err != nil {
56                 return err
57         }
58
59         serflag, err := bh.readFrom(blockchain.NewReader(decoded))
60         if err != nil {
61                 return err
62         }
63
64         if serflag == SerBlockTransactions {
65                 return fmt.Errorf("unsupported serialization flags 0x%02x", serflag)
66         }
67         return nil
68 }
69
70 func (bh *BlockHeader) readFrom(r *blockchain.Reader) (serflag uint8, err error) {
71         var serflags [1]byte
72         if _, err := io.ReadFull(r, serflags[:]); err != nil {
73                 return 0, err
74         }
75
76         serflag = serflags[0]
77         switch serflag {
78         case SerBlockHeader, SerBlockFull:
79         case SerBlockTransactions:
80                 return
81         default:
82                 return 0, fmt.Errorf("unsupported serialization flags 0x%x", serflags)
83         }
84
85         if bh.Version, err = blockchain.ReadVarint63(r); err != nil {
86                 return 0, err
87         }
88         if bh.Height, err = blockchain.ReadVarint63(r); err != nil {
89                 return 0, err
90         }
91         if _, err = bh.PreviousBlockHash.ReadFrom(r); err != nil {
92                 return 0, err
93         }
94         if bh.Timestamp, err = blockchain.ReadVarint63(r); err != nil {
95                 return 0, err
96         }
97         if _, err = blockchain.ReadExtensibleString(r, bh.BlockCommitment.readFrom); err != nil {
98                 return 0, err
99         }
100
101         if _, err = blockchain.ReadExtensibleString(r, bh.BlockWitness.readFrom); err != nil {
102                 return 0, err
103         }
104         return
105 }
106
107 // WriteTo writes the block header to the input io.Writer
108 func (bh *BlockHeader) WriteTo(w io.Writer) (int64, error) {
109         ew := errors.NewWriter(w)
110         if err := bh.writeTo(ew, SerBlockHeader); err != nil {
111                 return 0, err
112         }
113         return ew.Written(), ew.Err()
114 }
115
116 func (bh *BlockHeader) writeTo(w io.Writer, serflags uint8) (err error) {
117         w.Write([]byte{serflags})
118         if serflags == SerBlockTransactions {
119                 return nil
120         }
121
122         if _, err = blockchain.WriteVarint63(w, bh.Version); err != nil {
123                 return err
124         }
125         if _, err = blockchain.WriteVarint63(w, bh.Height); err != nil {
126                 return err
127         }
128         if _, err = bh.PreviousBlockHash.WriteTo(w); err != nil {
129                 return err
130         }
131         if _, err = blockchain.WriteVarint63(w, bh.Timestamp); err != nil {
132                 return err
133         }
134         if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockCommitment.writeTo); err != nil {
135                 return err
136         }
137
138         if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockWitness.writeTo); err != nil {
139                 return err
140         }
141         return nil
142 }