OSDN Git Service

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