OSDN Git Service

Small edit (#241)
[bytom/vapor.git] / protocol / bc / types / block.go
1 package types
2
3 import (
4         "encoding/hex"
5         "fmt"
6         "io"
7
8         "github.com/vapor/encoding/blockchain"
9         "github.com/vapor/encoding/bufpool"
10         "github.com/vapor/errors"
11 )
12
13 // serflag variables, start with 1
14 const (
15         _ = iota
16         SerBlockHeader
17         SerBlockTransactions
18         SerBlockFull
19 )
20
21 // Block describes a complete block, including its header and the transactions
22 // it contains.
23 type Block struct {
24         BlockHeader
25         Transactions []*Tx
26 }
27
28 func (b *Block) marshalText(serflags uint8) ([]byte, error) {
29         buf := bufpool.Get()
30         defer bufpool.Put(buf)
31
32         ew := errors.NewWriter(buf)
33         if err := b.writeTo(ew, serflags); err != nil {
34                 return nil, err
35         }
36         if err := ew.Err(); err != nil {
37                 return nil, err
38         }
39
40         enc := make([]byte, hex.EncodedLen(buf.Len()))
41         hex.Encode(enc, buf.Bytes())
42         return enc, nil
43 }
44
45 // MarshalText fulfills the json.Marshaler interface. This guarantees that
46 // blocks will get deserialized correctly when being parsed from HTTP requests.
47 func (b *Block) MarshalText() ([]byte, error) {
48         return b.marshalText(SerBlockFull)
49 }
50
51 // MarshalTextForBlockHeader fulfills the json.Marshaler interface.
52 func (b *Block) MarshalTextForBlockHeader() ([]byte, error) {
53         return b.marshalText(SerBlockHeader)
54 }
55
56 // MarshalTextForTransactions fulfills the json.Marshaler interface.
57 func (b *Block) MarshalTextForTransactions() ([]byte, error) {
58         return b.marshalText(SerBlockTransactions)
59 }
60
61 // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
62 func (b *Block) UnmarshalText(text []byte) error {
63         decoded := make([]byte, hex.DecodedLen(len(text)))
64         if _, err := hex.Decode(decoded, text); err != nil {
65                 return err
66         }
67
68         r := blockchain.NewReader(decoded)
69         if err := b.readFrom(r); err != nil {
70                 return err
71         }
72
73         if trailing := r.Len(); trailing > 0 {
74                 return fmt.Errorf("trailing garbage (%d bytes)", trailing)
75         }
76         return nil
77 }
78
79 func (b *Block) readFrom(r *blockchain.Reader) error {
80         serflag, err := b.BlockHeader.readFrom(r)
81         if err != nil {
82                 return err
83         }
84
85         if serflag == SerBlockHeader {
86                 return nil
87         }
88
89         n, err := blockchain.ReadVarint31(r)
90         if err != nil {
91                 return errors.Wrap(err, "reading number of transactions")
92         }
93
94         for ; n > 0; n-- {
95                 data := TxData{}
96                 if err = data.readFrom(r); err != nil {
97                         return errors.Wrapf(err, "reading transaction %d", len(b.Transactions))
98                 }
99
100                 b.Transactions = append(b.Transactions, NewTx(data))
101         }
102         return nil
103 }
104
105 func (b *Block) WriteTo(w io.Writer) (int64, error) {
106         ew := errors.NewWriter(w)
107         if err := b.writeTo(ew, SerBlockFull); err != nil {
108                 return 0, err
109         }
110         return ew.Written(), ew.Err()
111 }
112
113 func (b *Block) writeTo(w io.Writer, serflags uint8) error {
114         if err := b.BlockHeader.writeTo(w, serflags); err != nil {
115                 return err
116         }
117
118         if serflags == SerBlockHeader {
119                 return nil
120         }
121
122         if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil {
123                 return err
124         }
125
126         for _, tx := range b.Transactions {
127                 if _, err := tx.WriteTo(w); err != nil {
128                         return err
129                 }
130         }
131         return nil
132 }