OSDN Git Service

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