OSDN Git Service

opt trace service
[bytom/bytom.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/bytom/bytom/encoding/blockchain"
10         "github.com/bytom/bytom/encoding/bufpool"
11         "github.com/bytom/bytom/errors"
12         "github.com/bytom/bytom/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 seconds.
21         BlockWitness
22         SupLinks
23         BlockCommitment
24 }
25
26 // Hash returns complete hash of the block header.
27 func (bh *BlockHeader) Hash() bc.Hash {
28         h, _ := mapBlockHeader(bh)
29         return h
30 }
31
32 // Time returns the time represented by the Timestamp in block header.
33 func (bh *BlockHeader) Time() time.Time {
34         return time.Unix(int64(bh.Timestamp/1000), 0).UTC()
35 }
36
37 // MarshalText fulfills the json.Marshaler interface. This guarantees that
38 // block headers will get deserialized correctly when being parsed from HTTP
39 // requests.
40 func (bh *BlockHeader) MarshalText() ([]byte, error) {
41         buf := bufpool.Get()
42         defer bufpool.Put(buf)
43
44         if _, err := bh.WriteTo(buf); err != nil {
45                 return nil, err
46         }
47
48         enc := make([]byte, hex.EncodedLen(buf.Len()))
49         hex.Encode(enc, buf.Bytes())
50         return enc, nil
51 }
52
53 // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
54 func (bh *BlockHeader) UnmarshalText(text []byte) error {
55         decoded := make([]byte, hex.DecodedLen(len(text)))
56         if _, err := hex.Decode(decoded, text); err != nil {
57                 return err
58         }
59
60         serflag, err := bh.readFrom(blockchain.NewReader(decoded))
61         if err != nil {
62                 return err
63         }
64
65         if serflag == SerBlockTransactions {
66                 return fmt.Errorf("unsupported serialization flags 0x%02x", serflag)
67         }
68
69         return nil
70 }
71
72 // WriteTo writes the block header to the input io.Writer
73 func (bh *BlockHeader) WriteTo(w io.Writer) (int64, error) {
74         ew := errors.NewWriter(w)
75         if err := bh.writeTo(ew, SerBlockHeader); err != nil {
76                 return 0, err
77         }
78         return ew.Written(), ew.Err()
79 }
80
81 func (bh *BlockHeader) readFrom(r *blockchain.Reader) (serflag uint8, err error) {
82         var serflags [1]byte
83         if _, err := io.ReadFull(r, serflags[:]); err != nil {
84                 return 0, err
85         }
86
87         serflag = serflags[0]
88         switch serflag {
89         case SerBlockHeader, SerBlockFull:
90         case SerBlockTransactions:
91                 return
92         default:
93                 return 0, fmt.Errorf("unsupported serialization flags 0x%x", serflags)
94         }
95
96         if bh.Version, err = blockchain.ReadVarint63(r); err != nil {
97                 return 0, err
98         }
99
100         if bh.Height, err = blockchain.ReadVarint63(r); err != nil {
101                 return 0, err
102         }
103
104         if _, err = bh.PreviousBlockHash.ReadFrom(r); err != nil {
105                 return 0, err
106         }
107
108         if bh.Timestamp, err = blockchain.ReadVarint63(r); err != nil {
109                 return 0, err
110         }
111
112         if _, err = blockchain.ReadExtensibleString(r, bh.BlockCommitment.readFrom); err != nil {
113                 return 0, err
114         }
115
116         if _, err = blockchain.ReadExtensibleString(r, bh.BlockWitness.readFrom); err != nil {
117                 return 0, err
118         }
119
120         if _, err = blockchain.ReadExtensibleString(r, bh.SupLinks.readFrom); err != nil {
121                 return 0, err
122         }
123
124         return
125 }
126
127 func (bh *BlockHeader) writeTo(w io.Writer, serflags uint8) (err error) {
128         w.Write([]byte{serflags})
129         if serflags == SerBlockTransactions {
130                 return nil
131         }
132
133         if _, err = blockchain.WriteVarint63(w, bh.Version); err != nil {
134                 return err
135         }
136
137         if _, err = blockchain.WriteVarint63(w, bh.Height); err != nil {
138                 return err
139         }
140
141         if _, err = bh.PreviousBlockHash.WriteTo(w); err != nil {
142                 return err
143         }
144
145         if _, err = blockchain.WriteVarint63(w, bh.Timestamp); err != nil {
146                 return err
147         }
148
149         if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockCommitment.writeTo); err != nil {
150                 return err
151         }
152
153         if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockWitness.writeTo); err != nil {
154                 return err
155         }
156
157         if _, err = blockchain.WriteExtensibleString(w, nil, bh.SupLinks.writeTo); err != nil {
158                 return err
159         }
160
161         return
162 }