OSDN Git Service

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