OSDN Git Service

Mov (#518)
[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/bytom/vapor/encoding/blockchain"
9         "github.com/bytom/vapor/encoding/bufpool"
10         "github.com/bytom/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 // WriteTo write block to io.Writer
106 func (b *Block) WriteTo(w io.Writer) (int64, error) {
107         ew := errors.NewWriter(w)
108         if err := b.writeTo(ew, SerBlockFull); err != nil {
109                 return 0, err
110         }
111         return ew.Written(), ew.Err()
112 }
113
114 func (b *Block) writeTo(w io.Writer, serflags uint8) error {
115         if err := b.BlockHeader.writeTo(w, serflags); err != nil {
116                 return err
117         }
118
119         if serflags == SerBlockHeader {
120                 return nil
121         }
122
123         if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil {
124                 return err
125         }
126
127         for _, tx := range b.Transactions {
128                 if _, err := tx.WriteTo(w); err != nil {
129                         return err
130                 }
131         }
132         return nil
133 }