OSDN Git Service

:sparkles: Add version notification (#1258)
[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         FilterClearByte     = byte(0x51)
31         MerkleRequestByte   = byte(0x60)
32         MerkleResponseByte  = byte(0x61)
33
34         maxBlockchainResponseSize = 22020096 + 2
35 )
36
37 //BlockchainMessage is a generic message for this reactor.
38 type BlockchainMessage interface{}
39
40 var _ = wire.RegisterInterface(
41         struct{ BlockchainMessage }{},
42         wire.ConcreteType{&GetBlockMessage{}, BlockRequestByte},
43         wire.ConcreteType{&BlockMessage{}, BlockResponseByte},
44         wire.ConcreteType{&GetHeadersMessage{}, HeadersRequestByte},
45         wire.ConcreteType{&HeadersMessage{}, HeadersResponseByte},
46         wire.ConcreteType{&GetBlocksMessage{}, BlocksRequestByte},
47         wire.ConcreteType{&BlocksMessage{}, BlocksResponseByte},
48         wire.ConcreteType{&StatusRequestMessage{}, StatusRequestByte},
49         wire.ConcreteType{&StatusResponseMessage{}, StatusResponseByte},
50         wire.ConcreteType{&TransactionMessage{}, NewTransactionByte},
51         wire.ConcreteType{&MineBlockMessage{}, NewMineBlockByte},
52         wire.ConcreteType{&FilterLoadMessage{}, FilterLoadByte},
53         wire.ConcreteType{&FilterClearMessage{}, FilterClearByte},
54         wire.ConcreteType{&GetMerkleBlockMessage{}, MerkleRequestByte},
55         wire.ConcreteType{&MerkleBlockMessage{}, MerkleResponseByte},
56 )
57
58 //DecodeMessage decode msg
59 func DecodeMessage(bz []byte) (msgType byte, msg BlockchainMessage, err error) {
60         msgType = bz[0]
61         n := int(0)
62         r := bytes.NewReader(bz)
63         msg = wire.ReadBinary(struct{ BlockchainMessage }{}, r, maxBlockchainResponseSize, &n, &err).(struct{ BlockchainMessage }).BlockchainMessage
64         if err != nil && n != len(bz) {
65                 err = errors.New("DecodeMessage() had bytes left over")
66         }
67         return
68 }
69
70 //GetBlockMessage request blocks from remote peers by height/hash
71 type GetBlockMessage struct {
72         Height  uint64
73         RawHash [32]byte
74 }
75
76 //GetHash reutrn the hash of the request
77 func (m *GetBlockMessage) GetHash() *bc.Hash {
78         hash := bc.NewHash(m.RawHash)
79         return &hash
80 }
81
82 //String convert msg to string
83 func (m *GetBlockMessage) String() string {
84         if m.Height > 0 {
85                 return fmt.Sprintf("GetBlockMessage{Height: %d}", m.Height)
86         }
87         hash := m.GetHash()
88         return fmt.Sprintf("GetBlockMessage{Hash: %s}", hash.String())
89 }
90
91 //BlockMessage response get block msg
92 type BlockMessage struct {
93         RawBlock []byte
94 }
95
96 //NewBlockMessage construct bock response msg
97 func NewBlockMessage(block *types.Block) (*BlockMessage, error) {
98         rawBlock, err := block.MarshalText()
99         if err != nil {
100                 return nil, err
101         }
102         return &BlockMessage{RawBlock: rawBlock}, nil
103 }
104
105 //GetBlock get block from msg
106 func (m *BlockMessage) GetBlock() *types.Block {
107         block := &types.Block{
108                 BlockHeader:  types.BlockHeader{},
109                 Transactions: []*types.Tx{},
110         }
111         block.UnmarshalText(m.RawBlock)
112         return block
113 }
114
115 //String convert msg to string
116 func (m *BlockMessage) String() string {
117         return fmt.Sprintf("BlockMessage{Size: %d}", len(m.RawBlock))
118 }
119
120 //GetHeadersMessage is one of the bytom msg type
121 type GetHeadersMessage struct {
122         RawBlockLocator [][32]byte
123         RawStopHash     [32]byte
124 }
125
126 //NewGetHeadersMessage return a new GetHeadersMessage
127 func NewGetHeadersMessage(blockLocator []*bc.Hash, stopHash *bc.Hash) *GetHeadersMessage {
128         msg := &GetHeadersMessage{
129                 RawStopHash: stopHash.Byte32(),
130         }
131         for _, hash := range blockLocator {
132                 msg.RawBlockLocator = append(msg.RawBlockLocator, hash.Byte32())
133         }
134         return msg
135 }
136
137 //GetBlockLocator return the locator of the msg
138 func (msg *GetHeadersMessage) GetBlockLocator() []*bc.Hash {
139         blockLocator := []*bc.Hash{}
140         for _, rawHash := range msg.RawBlockLocator {
141                 hash := bc.NewHash(rawHash)
142                 blockLocator = append(blockLocator, &hash)
143         }
144         return blockLocator
145 }
146
147 //GetStopHash return the stop hash of the msg
148 func (msg *GetHeadersMessage) GetStopHash() *bc.Hash {
149         hash := bc.NewHash(msg.RawStopHash)
150         return &hash
151 }
152
153 //HeadersMessage is one of the bytom msg type
154 type HeadersMessage struct {
155         RawHeaders [][]byte
156 }
157
158 //NewHeadersMessage create a new HeadersMessage
159 func NewHeadersMessage(headers []*types.BlockHeader) (*HeadersMessage, error) {
160         RawHeaders := [][]byte{}
161         for _, header := range headers {
162                 data, err := json.Marshal(header)
163                 if err != nil {
164                         return nil, err
165                 }
166
167                 RawHeaders = append(RawHeaders, data)
168         }
169         return &HeadersMessage{RawHeaders: RawHeaders}, nil
170 }
171
172 //GetHeaders return the headers in the msg
173 func (msg *HeadersMessage) GetHeaders() ([]*types.BlockHeader, error) {
174         headers := []*types.BlockHeader{}
175         for _, data := range msg.RawHeaders {
176                 header := &types.BlockHeader{}
177                 if err := json.Unmarshal(data, header); err != nil {
178                         return nil, err
179                 }
180
181                 headers = append(headers, header)
182         }
183         return headers, nil
184 }
185
186 //GetBlocksMessage is one of the bytom msg type
187 type GetBlocksMessage struct {
188         RawBlockLocator [][32]byte
189         RawStopHash     [32]byte
190 }
191
192 //NewGetBlocksMessage create a new GetBlocksMessage
193 func NewGetBlocksMessage(blockLocator []*bc.Hash, stopHash *bc.Hash) *GetBlocksMessage {
194         msg := &GetBlocksMessage{
195                 RawStopHash: stopHash.Byte32(),
196         }
197         for _, hash := range blockLocator {
198                 msg.RawBlockLocator = append(msg.RawBlockLocator, hash.Byte32())
199         }
200         return msg
201 }
202
203 //GetBlockLocator return the locator of the msg
204 func (msg *GetBlocksMessage) GetBlockLocator() []*bc.Hash {
205         blockLocator := []*bc.Hash{}
206         for _, rawHash := range msg.RawBlockLocator {
207                 hash := bc.NewHash(rawHash)
208                 blockLocator = append(blockLocator, &hash)
209         }
210         return blockLocator
211 }
212
213 //GetStopHash return the stop hash of the msg
214 func (msg *GetBlocksMessage) GetStopHash() *bc.Hash {
215         hash := bc.NewHash(msg.RawStopHash)
216         return &hash
217 }
218
219 //BlocksMessage is one of the bytom msg type
220 type BlocksMessage struct {
221         RawBlocks [][]byte
222 }
223
224 //NewBlocksMessage create a new BlocksMessage
225 func NewBlocksMessage(blocks []*types.Block) (*BlocksMessage, error) {
226         rawBlocks := [][]byte{}
227         for _, block := range blocks {
228                 data, err := json.Marshal(block)
229                 if err != nil {
230                         return nil, err
231                 }
232
233                 rawBlocks = append(rawBlocks, data)
234         }
235         return &BlocksMessage{RawBlocks: rawBlocks}, nil
236 }
237
238 //GetBlocks returns the blocks in the msg
239 func (msg *BlocksMessage) GetBlocks() ([]*types.Block, error) {
240         blocks := []*types.Block{}
241         for _, data := range msg.RawBlocks {
242                 block := &types.Block{}
243                 if err := json.Unmarshal(data, block); err != nil {
244                         return nil, err
245                 }
246
247                 blocks = append(blocks, block)
248         }
249         return blocks, nil
250 }
251
252 //StatusRequestMessage status request msg
253 type StatusRequestMessage struct{}
254
255 //String
256 func (m *StatusRequestMessage) String() string {
257         return "StatusRequestMessage"
258 }
259
260 //StatusResponseMessage get status response msg
261 type StatusResponseMessage struct {
262         Height      uint64
263         RawHash     [32]byte
264         GenesisHash [32]byte
265 }
266
267 //NewStatusResponseMessage construct get status response msg
268 func NewStatusResponseMessage(blockHeader *types.BlockHeader, hash *bc.Hash) *StatusResponseMessage {
269         return &StatusResponseMessage{
270                 Height:      blockHeader.Height,
271                 RawHash:     blockHeader.Hash().Byte32(),
272                 GenesisHash: hash.Byte32(),
273         }
274 }
275
276 //GetHash get hash from msg
277 func (m *StatusResponseMessage) GetHash() *bc.Hash {
278         hash := bc.NewHash(m.RawHash)
279         return &hash
280 }
281
282 //GetGenesisHash get hash from msg
283 func (m *StatusResponseMessage) GetGenesisHash() *bc.Hash {
284         hash := bc.NewHash(m.GenesisHash)
285         return &hash
286 }
287
288 //String convert msg to string
289 func (m *StatusResponseMessage) String() string {
290         hash := m.GetHash()
291         genesisHash := m.GetGenesisHash()
292         return fmt.Sprintf("StatusResponseMessage{Height: %d, Best hash: %s, Genesis hash: %s}", m.Height, hash.String(), genesisHash.String())
293 }
294
295 //TransactionMessage notify new tx msg
296 type TransactionMessage struct {
297         RawTx []byte
298 }
299
300 //NewTransactionMessage construct notify new tx msg
301 func NewTransactionMessage(tx *types.Tx) (*TransactionMessage, error) {
302         rawTx, err := tx.TxData.MarshalText()
303         if err != nil {
304                 return nil, err
305         }
306         return &TransactionMessage{RawTx: rawTx}, nil
307 }
308
309 //GetTransaction get tx from msg
310 func (m *TransactionMessage) GetTransaction() (*types.Tx, error) {
311         tx := &types.Tx{}
312         if err := tx.UnmarshalText(m.RawTx); err != nil {
313                 return nil, err
314         }
315         return tx, nil
316 }
317
318 //String
319 func (m *TransactionMessage) String() string {
320         return fmt.Sprintf("TransactionMessage{Size: %d}", len(m.RawTx))
321 }
322
323 //MineBlockMessage new mined block msg
324 type MineBlockMessage struct {
325         RawBlock []byte
326 }
327
328 //NewMinedBlockMessage construct new mined block msg
329 func NewMinedBlockMessage(block *types.Block) (*MineBlockMessage, error) {
330         rawBlock, err := block.MarshalText()
331         if err != nil {
332                 return nil, err
333         }
334         return &MineBlockMessage{RawBlock: rawBlock}, nil
335 }
336
337 //GetMineBlock get mine block from msg
338 func (m *MineBlockMessage) GetMineBlock() (*types.Block, error) {
339         block := &types.Block{}
340         if err := block.UnmarshalText(m.RawBlock); err != nil {
341                 return nil, err
342         }
343         return block, nil
344 }
345
346 //String convert msg to string
347 func (m *MineBlockMessage) String() string {
348         return fmt.Sprintf("NewMineBlockMessage{Size: %d}", len(m.RawBlock))
349 }
350
351 //FilterLoadMessage tells the receiving peer to filter the transactions according to address.
352 type FilterLoadMessage struct {
353         Addresses [][]byte
354 }
355
356 //FilterClearMessage tells the receiving peer to remove a previously-set filter.
357 type FilterClearMessage struct{}
358
359 //GetMerkleBlockMessage request merkle blocks from remote peers by height/hash
360 type GetMerkleBlockMessage struct {
361         Height  uint64
362         RawHash [32]byte
363 }
364
365 //MerkleBlockMessage return the merkle block to client
366 type MerkleBlockMessage struct {
367         RawBlockHeader   []byte
368         TransactionCount uint64
369         TxHashes         [][32]byte
370         TxFlags          []byte
371         RawTxDatas       [][]byte
372         StatusHashes     [][32]byte
373         StatusFlags      []byte
374         RawTxStatuses    [][]byte
375 }