OSDN Git Service

modify block serialize (#184)
[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 // MarshalText fulfills the json.Marshaler interface. This guarantees that
29 // blocks will get deserialized correctly when being parsed from HTTP requests.
30 func (b *Block) MarshalText() ([]byte, error) {
31         buf := bufpool.Get()
32         defer bufpool.Put(buf)
33
34         if _, err := b.WriteTo(buf); err != nil {
35                 return nil, err
36         }
37
38         enc := make([]byte, hex.EncodedLen(buf.Len()))
39         hex.Encode(enc, buf.Bytes())
40         return enc, nil
41 }
42
43 // UnmarshalText fulfills the encoding.TextUnmarshaler interface.
44 func (b *Block) UnmarshalText(text []byte) error {
45         decoded := make([]byte, hex.DecodedLen(len(text)))
46         if _, err := hex.Decode(decoded, text); err != nil {
47                 return err
48         }
49
50         r := blockchain.NewReader(decoded)
51         if err := b.readFrom(r); err != nil {
52                 return err
53         }
54
55         if trailing := r.Len(); trailing > 0 {
56                 return fmt.Errorf("trailing garbage (%d bytes)", trailing)
57         }
58         return nil
59 }
60
61 // MarshalTextForBlockHeader fulfills the json.Marshaler interface.
62 func (b *Block) MarshalTextForBlockHeader() ([]byte, error) {
63         buf := bufpool.Get()
64         defer bufpool.Put(buf)
65
66         ew := errors.NewWriter(buf)
67         if err := b.writeTo(ew, SerBlockHeader); err != nil {
68                 return nil, err
69         }
70         if err := ew.Err(); err != nil {
71                 return nil, err
72         }
73
74         enc := make([]byte, hex.EncodedLen(buf.Len()))
75         hex.Encode(enc, buf.Bytes())
76         return enc, nil
77 }
78
79 // MarshalTextForTransactions fulfills the json.Marshaler interface.
80 func (b *Block) MarshalTextForTransactions() ([]byte, error) {
81         buf := bufpool.Get()
82         defer bufpool.Put(buf)
83
84         ew := errors.NewWriter(buf)
85         if err := b.writeTo(ew, SerBlockTransactions); err != nil {
86                 return nil, err
87         }
88         if err := ew.Err(); err != nil {
89                 return nil, err
90         }
91
92         enc := make([]byte, hex.EncodedLen(buf.Len()))
93         hex.Encode(enc, buf.Bytes())
94         return enc, nil
95 }
96
97 func (b *Block) readFrom(r *blockchain.Reader) error {
98         serflag, err := b.BlockHeader.readFrom(r)
99         if err != nil {
100                 return err
101         }
102
103         if serflag == SerBlockHeader {
104                 return nil
105         }
106
107         n, err := blockchain.ReadVarint31(r)
108         if err != nil {
109                 return errors.Wrap(err, "reading number of transactions")
110         }
111
112         for ; n > 0; n-- {
113                 data := TxData{}
114                 if err = data.readFrom(r); err != nil {
115                         return errors.Wrapf(err, "reading transaction %d", len(b.Transactions))
116                 }
117
118                 b.Transactions = append(b.Transactions, NewTx(data))
119         }
120         return nil
121 }
122
123 // WriteTo will write block to input io.Writer
124 func (b *Block) WriteTo(w io.Writer) (int64, error) {
125         ew := errors.NewWriter(w)
126         if err := b.writeTo(ew, SerBlockFull); err != nil {
127                 return 0, err
128         }
129         return ew.Written(), ew.Err()
130 }
131
132 func (b *Block) writeTo(w io.Writer, serflags uint8) error {
133         if serflags != SerBlockTransactions {
134                 if err := b.BlockHeader.writeTo(w, serflags); err != nil {
135                         return err
136                 }
137
138                 if serflags == SerBlockHeader {
139                         return nil
140                 }
141         } else {
142                 w.Write([]byte{serflags})
143         }
144
145         if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil {
146                 return err
147         }
148
149         for _, tx := range b.Transactions {
150                 if _, err := tx.WriteTo(w); err != nil {
151                         return err
152                 }
153         }
154         return nil
155 }