OSDN Git Service

fix votetx for validation (#75)
[bytom/vapor.git] / netsync / message.go
1 package netsync
2
3 import (
4         "bytes"
5         "encoding/hex"
6         "encoding/json"
7         "errors"
8         "fmt"
9
10         "github.com/tendermint/go-wire"
11
12         "github.com/vapor/protocol/bc"
13         "github.com/vapor/protocol/bc/types"
14 )
15
16 //protocol msg byte
17 const (
18         BlockchainChannel = byte(0x40)
19
20         BlockRequestByte    = byte(0x10)
21         BlockResponseByte   = byte(0x11)
22         HeadersRequestByte  = byte(0x12)
23         HeadersResponseByte = byte(0x13)
24         BlocksRequestByte   = byte(0x14)
25         BlocksResponseByte  = byte(0x15)
26         StatusByte          = byte(0x21)
27         NewTransactionByte  = byte(0x30)
28         NewMineBlockByte    = byte(0x40)
29         FilterLoadByte      = byte(0x50)
30         FilterAddByte       = byte(0x51)
31         FilterClearByte     = byte(0x52)
32         MerkleRequestByte   = byte(0x60)
33         MerkleResponseByte  = byte(0x61)
34
35         maxBlockchainResponseSize = 22020096 + 2
36 )
37
38 //BlockchainMessage is a generic message for this reactor.
39 type BlockchainMessage interface {
40         String() string
41 }
42
43 var _ = wire.RegisterInterface(
44         struct{ BlockchainMessage }{},
45         wire.ConcreteType{&GetBlockMessage{}, BlockRequestByte},
46         wire.ConcreteType{&BlockMessage{}, BlockResponseByte},
47         wire.ConcreteType{&GetHeadersMessage{}, HeadersRequestByte},
48         wire.ConcreteType{&HeadersMessage{}, HeadersResponseByte},
49         wire.ConcreteType{&GetBlocksMessage{}, BlocksRequestByte},
50         wire.ConcreteType{&BlocksMessage{}, BlocksResponseByte},
51         wire.ConcreteType{&StatusMessage{}, StatusByte},
52         wire.ConcreteType{&TransactionMessage{}, NewTransactionByte},
53         wire.ConcreteType{&MineBlockMessage{}, NewMineBlockByte},
54         wire.ConcreteType{&FilterLoadMessage{}, FilterLoadByte},
55         wire.ConcreteType{&FilterAddMessage{}, FilterAddByte},
56         wire.ConcreteType{&FilterClearMessage{}, FilterClearByte},
57         wire.ConcreteType{&GetMerkleBlockMessage{}, MerkleRequestByte},
58         wire.ConcreteType{&MerkleBlockMessage{}, MerkleResponseByte},
59 )
60
61 //DecodeMessage decode msg
62 func DecodeMessage(bz []byte) (msgType byte, msg BlockchainMessage, err error) {
63         msgType = bz[0]
64         n := int(0)
65         r := bytes.NewReader(bz)
66         msg = wire.ReadBinary(struct{ BlockchainMessage }{}, r, maxBlockchainResponseSize, &n, &err).(struct{ BlockchainMessage }).BlockchainMessage
67         if err != nil && n != len(bz) {
68                 err = errors.New("DecodeMessage() had bytes left over")
69         }
70         return
71 }
72
73 //GetBlockMessage request blocks from remote peers by height/hash
74 type GetBlockMessage struct {
75         Height  uint64
76         RawHash [32]byte
77 }
78
79 //GetHash reutrn the hash of the request
80 func (m *GetBlockMessage) GetHash() *bc.Hash {
81         hash := bc.NewHash(m.RawHash)
82         return &hash
83 }
84
85 func (m *GetBlockMessage) String() string {
86         if m.Height > 0 {
87                 return fmt.Sprintf("{height: %d}", m.Height)
88         }
89         return fmt.Sprintf("{hash: %s}", hex.EncodeToString(m.RawHash[:]))
90 }
91
92 //BlockMessage response get block msg
93 type BlockMessage struct {
94         RawBlock []byte
95 }
96
97 //NewBlockMessage construct bock response msg
98 func NewBlockMessage(block *types.Block) (*BlockMessage, error) {
99         rawBlock, err := block.MarshalText()
100         if err != nil {
101                 return nil, err
102         }
103         return &BlockMessage{RawBlock: rawBlock}, nil
104 }
105
106 //GetBlock get block from msg
107 func (m *BlockMessage) GetBlock() (*types.Block, error) {
108         block := &types.Block{
109                 BlockHeader:  types.BlockHeader{},
110                 Transactions: []*types.Tx{},
111         }
112         if err := block.UnmarshalText(m.RawBlock); err != nil {
113                 return nil, err
114         }
115         return block, nil
116 }
117
118 func (m *BlockMessage) String() string {
119         block, err := m.GetBlock()
120         if err != nil {
121                 return "{err: wrong message}"
122         }
123         blockHash := block.Hash()
124         return fmt.Sprintf("{block_height: %d, block_hash: %s}", block.Height, blockHash.String())
125 }
126
127 //GetHeadersMessage is one of the bytom msg type
128 type GetHeadersMessage struct {
129         RawBlockLocator [][32]byte
130         RawStopHash     [32]byte
131 }
132
133 //NewGetHeadersMessage return a new GetHeadersMessage
134 func NewGetHeadersMessage(blockLocator []*bc.Hash, stopHash *bc.Hash) *GetHeadersMessage {
135         msg := &GetHeadersMessage{
136                 RawStopHash: stopHash.Byte32(),
137         }
138         for _, hash := range blockLocator {
139                 msg.RawBlockLocator = append(msg.RawBlockLocator, hash.Byte32())
140         }
141         return msg
142 }
143
144 //GetBlockLocator return the locator of the msg
145 func (m *GetHeadersMessage) GetBlockLocator() []*bc.Hash {
146         blockLocator := []*bc.Hash{}
147         for _, rawHash := range m.RawBlockLocator {
148                 hash := bc.NewHash(rawHash)
149                 blockLocator = append(blockLocator, &hash)
150         }
151         return blockLocator
152 }
153
154 func (m *GetHeadersMessage) String() string {
155         return fmt.Sprintf("{stop_hash: %s}", hex.EncodeToString(m.RawStopHash[:]))
156 }
157
158 //GetStopHash return the stop hash of the msg
159 func (m *GetHeadersMessage) GetStopHash() *bc.Hash {
160         hash := bc.NewHash(m.RawStopHash)
161         return &hash
162 }
163
164 //HeadersMessage is one of the bytom msg type
165 type HeadersMessage struct {
166         RawHeaders [][]byte
167 }
168
169 //NewHeadersMessage create a new HeadersMessage
170 func NewHeadersMessage(headers []*types.BlockHeader) (*HeadersMessage, error) {
171         RawHeaders := [][]byte{}
172         for _, header := range headers {
173                 data, err := json.Marshal(header)
174                 if err != nil {
175                         return nil, err
176                 }
177
178                 RawHeaders = append(RawHeaders, data)
179         }
180         return &HeadersMessage{RawHeaders: RawHeaders}, nil
181 }
182
183 //GetHeaders return the headers in the msg
184 func (m *HeadersMessage) GetHeaders() ([]*types.BlockHeader, error) {
185         headers := []*types.BlockHeader{}
186         for _, data := range m.RawHeaders {
187                 header := &types.BlockHeader{}
188                 if err := json.Unmarshal(data, header); err != nil {
189                         return nil, err
190                 }
191
192                 headers = append(headers, header)
193         }
194         return headers, nil
195 }
196
197 func (m *HeadersMessage) String() string {
198         return fmt.Sprintf("{header_length: %d}", len(m.RawHeaders))
199 }
200
201 //GetBlocksMessage is one of the bytom msg type
202 type GetBlocksMessage struct {
203         RawBlockLocator [][32]byte
204         RawStopHash     [32]byte
205 }
206
207 //NewGetBlocksMessage create a new GetBlocksMessage
208 func NewGetBlocksMessage(blockLocator []*bc.Hash, stopHash *bc.Hash) *GetBlocksMessage {
209         msg := &GetBlocksMessage{
210                 RawStopHash: stopHash.Byte32(),
211         }
212         for _, hash := range blockLocator {
213                 msg.RawBlockLocator = append(msg.RawBlockLocator, hash.Byte32())
214         }
215         return msg
216 }
217
218 //GetBlockLocator return the locator of the msg
219 func (m *GetBlocksMessage) GetBlockLocator() []*bc.Hash {
220         blockLocator := []*bc.Hash{}
221         for _, rawHash := range m.RawBlockLocator {
222                 hash := bc.NewHash(rawHash)
223                 blockLocator = append(blockLocator, &hash)
224         }
225         return blockLocator
226 }
227
228 //GetStopHash return the stop hash of the msg
229 func (m *GetBlocksMessage) GetStopHash() *bc.Hash {
230         hash := bc.NewHash(m.RawStopHash)
231         return &hash
232 }
233
234 func (m *GetBlocksMessage) String() string {
235         return fmt.Sprintf("{stop_hash: %s}", hex.EncodeToString(m.RawStopHash[:]))
236 }
237
238 //BlocksMessage is one of the bytom msg type
239 type BlocksMessage struct {
240         RawBlocks [][]byte
241 }
242
243 //NewBlocksMessage create a new BlocksMessage
244 func NewBlocksMessage(blocks []*types.Block) (*BlocksMessage, error) {
245         rawBlocks := [][]byte{}
246         for _, block := range blocks {
247                 data, err := json.Marshal(block)
248                 if err != nil {
249                         return nil, err
250                 }
251
252                 rawBlocks = append(rawBlocks, data)
253         }
254         return &BlocksMessage{RawBlocks: rawBlocks}, nil
255 }
256
257 //GetBlocks returns the blocks in the msg
258 func (m *BlocksMessage) GetBlocks() ([]*types.Block, error) {
259         blocks := []*types.Block{}
260         for _, data := range m.RawBlocks {
261                 block := &types.Block{}
262                 if err := json.Unmarshal(data, block); err != nil {
263                         return nil, err
264                 }
265
266                 blocks = append(blocks, block)
267         }
268         return blocks, nil
269 }
270
271 func (m *BlocksMessage) String() string {
272         return fmt.Sprintf("{blocks_length: %d}", len(m.RawBlocks))
273 }
274
275 //StatusResponseMessage get status response msg
276 type StatusMessage struct {
277         Height  uint64
278         RawHash [32]byte
279 }
280
281 //NewStatusResponseMessage construct get status response msg
282 func NewStatusMessage(blockHeader *types.BlockHeader) *StatusMessage {
283         return &StatusMessage{
284                 Height:  blockHeader.Height,
285                 RawHash: blockHeader.Hash().Byte32(),
286         }
287 }
288
289 //GetHash get hash from msg
290 func (m *StatusMessage) GetHash() *bc.Hash {
291         hash := bc.NewHash(m.RawHash)
292         return &hash
293 }
294
295 func (m *StatusMessage) String() string {
296         return fmt.Sprintf("{height: %d, hash: %s}", m.Height, hex.EncodeToString(m.RawHash[:]))
297 }
298
299 //TransactionMessage notify new tx msg
300 type TransactionMessage struct {
301         RawTx []byte
302 }
303
304 //NewTransactionMessage construct notify new tx msg
305 func NewTransactionMessage(tx *types.Tx) (*TransactionMessage, error) {
306         rawTx, err := tx.TxData.MarshalText()
307         if err != nil {
308                 return nil, err
309         }
310         return &TransactionMessage{RawTx: rawTx}, nil
311 }
312
313 //GetTransaction get tx from msg
314 func (m *TransactionMessage) GetTransaction() (*types.Tx, error) {
315         tx := &types.Tx{}
316         if err := tx.UnmarshalText(m.RawTx); err != nil {
317                 return nil, err
318         }
319         return tx, nil
320 }
321
322 func (m *TransactionMessage) String() string {
323         tx, err := m.GetTransaction()
324         if err != nil {
325                 return "{err: wrong message}"
326         }
327         return fmt.Sprintf("{tx_size: %d, tx_hash: %s}", len(m.RawTx), tx.ID.String())
328 }
329
330 //MineBlockMessage new mined block msg
331 type MineBlockMessage struct {
332         RawBlock []byte
333 }
334
335 //NewMinedBlockMessage construct new mined block msg
336 func NewMinedBlockMessage(block *types.Block) (*MineBlockMessage, error) {
337         rawBlock, err := block.MarshalText()
338         if err != nil {
339                 return nil, err
340         }
341         return &MineBlockMessage{RawBlock: rawBlock}, nil
342 }
343
344 //GetMineBlock get mine block from msg
345 func (m *MineBlockMessage) GetMineBlock() (*types.Block, error) {
346         block := &types.Block{}
347         if err := block.UnmarshalText(m.RawBlock); err != nil {
348                 return nil, err
349         }
350         return block, nil
351 }
352
353 func (m *MineBlockMessage) String() string {
354         block, err := m.GetMineBlock()
355         if err != nil {
356                 return "{err: wrong message}"
357         }
358         blockHash := block.Hash()
359         return fmt.Sprintf("{block_height: %d, block_hash: %s}", block.Height, blockHash.String())
360 }
361
362 //FilterLoadMessage tells the receiving peer to filter the transactions according to address.
363 type FilterLoadMessage struct {
364         Addresses [][]byte
365 }
366
367 func (m *FilterLoadMessage) String() string {
368         return fmt.Sprintf("{addresses_length: %d}", len(m.Addresses))
369 }
370
371 // FilterAddMessage tells the receiving peer to add address to the filter.
372 type FilterAddMessage struct {
373         Address []byte
374 }
375
376 func (m *FilterAddMessage) String() string {
377         return fmt.Sprintf("{address: %s}", hex.EncodeToString(m.Address))
378 }
379
380 //FilterClearMessage tells the receiving peer to remove a previously-set filter.
381 type FilterClearMessage struct{}
382
383 func (m *FilterClearMessage) String() string {
384         return "{}"
385 }
386
387 //GetMerkleBlockMessage request merkle blocks from remote peers by height/hash
388 type GetMerkleBlockMessage struct {
389         Height  uint64
390         RawHash [32]byte
391 }
392
393 //GetHash reutrn the hash of the request
394 func (m *GetMerkleBlockMessage) GetHash() *bc.Hash {
395         hash := bc.NewHash(m.RawHash)
396         return &hash
397 }
398
399 func (m *GetMerkleBlockMessage) String() string {
400         if m.Height > 0 {
401                 return fmt.Sprintf("{height: %d}", m.Height)
402         }
403         return fmt.Sprintf("{hash: %s}", hex.EncodeToString(m.RawHash[:]))
404 }
405
406 //MerkleBlockMessage return the merkle block to client
407 type MerkleBlockMessage struct {
408         RawBlockHeader []byte
409         TxHashes       [][32]byte
410         RawTxDatas     [][]byte
411         StatusHashes   [][32]byte
412         RawTxStatuses  [][]byte
413         Flags          []byte
414 }
415
416 func (m *MerkleBlockMessage) setRawBlockHeader(bh types.BlockHeader) error {
417         rawHeader, err := bh.MarshalText()
418         if err != nil {
419                 return err
420         }
421
422         m.RawBlockHeader = rawHeader
423         return nil
424 }
425
426 func (m *MerkleBlockMessage) setTxInfo(txHashes []*bc.Hash, txFlags []uint8, relatedTxs []*types.Tx) error {
427         for _, txHash := range txHashes {
428                 m.TxHashes = append(m.TxHashes, txHash.Byte32())
429         }
430         for _, tx := range relatedTxs {
431                 rawTxData, err := tx.MarshalText()
432                 if err != nil {
433                         return err
434                 }
435
436                 m.RawTxDatas = append(m.RawTxDatas, rawTxData)
437         }
438         m.Flags = txFlags
439         return nil
440 }
441
442 func (m *MerkleBlockMessage) setStatusInfo(statusHashes []*bc.Hash, relatedStatuses []*bc.TxVerifyResult) error {
443         for _, statusHash := range statusHashes {
444                 m.StatusHashes = append(m.StatusHashes, statusHash.Byte32())
445         }
446
447         for _, status := range relatedStatuses {
448                 rawStatusData, err := json.Marshal(status)
449                 if err != nil {
450                         return err
451                 }
452
453                 m.RawTxStatuses = append(m.RawTxStatuses, rawStatusData)
454         }
455         return nil
456 }
457
458 func (m *MerkleBlockMessage) String() string {
459         return "{}"
460 }
461
462 //NewMerkleBlockMessage construct merkle block message
463 func NewMerkleBlockMessage() *MerkleBlockMessage {
464         return &MerkleBlockMessage{}
465 }