OSDN Git Service

8431dcac2568f9df4cd5f0d93030769dd5e133bf
[bytom/bytom-spv.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         FilterAddByte       = 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{&FilterClearMessage{}, FilterClearByte},
55         wire.ConcreteType{&FilterAddMessage{}, FilterAddByte},
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 {
109         block := &types.Block{
110                 BlockHeader:  types.BlockHeader{},
111                 Transactions: []*types.Tx{},
112         }
113         block.UnmarshalText(m.RawBlock)
114         return block
115 }
116
117 //String convert msg to string
118 func (m *BlockMessage) String() string {
119         return fmt.Sprintf("BlockMessage{Size: %d}", len(m.RawBlock))
120 }
121
122 //GetHeadersMessage is one of the bytom msg type
123 type GetHeadersMessage struct {
124         RawBlockLocator [][32]byte
125         RawStopHash     [32]byte
126 }
127
128 //NewGetHeadersMessage return a new GetHeadersMessage
129 func NewGetHeadersMessage(blockLocator []*bc.Hash, stopHash *bc.Hash) *GetHeadersMessage {
130         msg := &GetHeadersMessage{
131                 RawStopHash: stopHash.Byte32(),
132         }
133         for _, hash := range blockLocator {
134                 msg.RawBlockLocator = append(msg.RawBlockLocator, hash.Byte32())
135         }
136         return msg
137 }
138
139 //GetBlockLocator return the locator of the msg
140 func (msg *GetHeadersMessage) GetBlockLocator() []*bc.Hash {
141         blockLocator := []*bc.Hash{}
142         for _, rawHash := range msg.RawBlockLocator {
143                 hash := bc.NewHash(rawHash)
144                 blockLocator = append(blockLocator, &hash)
145         }
146         return blockLocator
147 }
148
149 //GetStopHash return the stop hash of the msg
150 func (msg *GetHeadersMessage) GetStopHash() *bc.Hash {
151         hash := bc.NewHash(msg.RawStopHash)
152         return &hash
153 }
154
155 //HeadersMessage is one of the bytom msg type
156 type HeadersMessage struct {
157         RawHeaders [][]byte
158 }
159
160 //NewHeadersMessage create a new HeadersMessage
161 func NewHeadersMessage(headers []*types.BlockHeader) (*HeadersMessage, error) {
162         RawHeaders := [][]byte{}
163         for _, header := range headers {
164                 data, err := json.Marshal(header)
165                 if err != nil {
166                         return nil, err
167                 }
168
169                 RawHeaders = append(RawHeaders, data)
170         }
171         return &HeadersMessage{RawHeaders: RawHeaders}, nil
172 }
173
174 //GetHeaders return the headers in the msg
175 func (msg *HeadersMessage) GetHeaders() ([]*types.BlockHeader, error) {
176         headers := []*types.BlockHeader{}
177         for _, data := range msg.RawHeaders {
178                 header := &types.BlockHeader{}
179                 if err := json.Unmarshal(data, header); err != nil {
180                         return nil, err
181                 }
182
183                 headers = append(headers, header)
184         }
185         return headers, nil
186 }
187
188 //GetBlocksMessage is one of the bytom msg type
189 type GetBlocksMessage struct {
190         RawBlockLocator [][32]byte
191         RawStopHash     [32]byte
192 }
193
194 //NewGetBlocksMessage create a new GetBlocksMessage
195 func NewGetBlocksMessage(blockLocator []*bc.Hash, stopHash *bc.Hash) *GetBlocksMessage {
196         msg := &GetBlocksMessage{
197                 RawStopHash: stopHash.Byte32(),
198         }
199         for _, hash := range blockLocator {
200                 msg.RawBlockLocator = append(msg.RawBlockLocator, hash.Byte32())
201         }
202         return msg
203 }
204
205 //GetBlockLocator return the locator of the msg
206 func (msg *GetBlocksMessage) GetBlockLocator() []*bc.Hash {
207         blockLocator := []*bc.Hash{}
208         for _, rawHash := range msg.RawBlockLocator {
209                 hash := bc.NewHash(rawHash)
210                 blockLocator = append(blockLocator, &hash)
211         }
212         return blockLocator
213 }
214
215 //GetStopHash return the stop hash of the msg
216 func (msg *GetBlocksMessage) GetStopHash() *bc.Hash {
217         hash := bc.NewHash(msg.RawStopHash)
218         return &hash
219 }
220
221 //BlocksMessage is one of the bytom msg type
222 type BlocksMessage struct {
223         RawBlocks [][]byte
224 }
225
226 //NewBlocksMessage create a new BlocksMessage
227 func NewBlocksMessage(blocks []*types.Block) (*BlocksMessage, error) {
228         rawBlocks := [][]byte{}
229         for _, block := range blocks {
230                 data, err := json.Marshal(block)
231                 if err != nil {
232                         return nil, err
233                 }
234
235                 rawBlocks = append(rawBlocks, data)
236         }
237         return &BlocksMessage{RawBlocks: rawBlocks}, nil
238 }
239
240 //GetBlocks returns the blocks in the msg
241 func (msg *BlocksMessage) GetBlocks() ([]*types.Block, error) {
242         blocks := []*types.Block{}
243         for _, data := range msg.RawBlocks {
244                 block := &types.Block{}
245                 if err := json.Unmarshal(data, block); err != nil {
246                         return nil, err
247                 }
248
249                 blocks = append(blocks, block)
250         }
251         return blocks, nil
252 }
253
254 //StatusRequestMessage status request msg
255 type StatusRequestMessage struct{}
256
257 //String
258 func (m *StatusRequestMessage) String() string {
259         return "StatusRequestMessage"
260 }
261
262 //StatusResponseMessage get status response msg
263 type StatusResponseMessage struct {
264         Height      uint64
265         RawHash     [32]byte
266         GenesisHash [32]byte
267 }
268
269 //NewStatusResponseMessage construct get status response msg
270 func NewStatusResponseMessage(blockHeader *types.BlockHeader, hash *bc.Hash) *StatusResponseMessage {
271         return &StatusResponseMessage{
272                 Height:      blockHeader.Height,
273                 RawHash:     blockHeader.Hash().Byte32(),
274                 GenesisHash: hash.Byte32(),
275         }
276 }
277
278 //GetHash get hash from msg
279 func (m *StatusResponseMessage) GetHash() *bc.Hash {
280         hash := bc.NewHash(m.RawHash)
281         return &hash
282 }
283
284 //GetGenesisHash get hash from msg
285 func (m *StatusResponseMessage) GetGenesisHash() *bc.Hash {
286         hash := bc.NewHash(m.GenesisHash)
287         return &hash
288 }
289
290 //String convert msg to string
291 func (m *StatusResponseMessage) String() string {
292         hash := m.GetHash()
293         genesisHash := m.GetGenesisHash()
294         return fmt.Sprintf("StatusResponseMessage{Height: %d, Best hash: %s, Genesis hash: %s}", m.Height, hash.String(), genesisHash.String())
295 }
296
297 //TransactionMessage notify new tx msg
298 type TransactionMessage struct {
299         RawTx []byte
300 }
301
302 //NewTransactionMessage construct notify new tx msg
303 func NewTransactionMessage(tx *types.Tx) (*TransactionMessage, error) {
304         rawTx, err := tx.TxData.MarshalText()
305         if err != nil {
306                 return nil, err
307         }
308         return &TransactionMessage{RawTx: rawTx}, nil
309 }
310
311 //GetTransaction get tx from msg
312 func (m *TransactionMessage) GetTransaction() (*types.Tx, error) {
313         tx := &types.Tx{}
314         if err := tx.UnmarshalText(m.RawTx); err != nil {
315                 return nil, err
316         }
317         return tx, nil
318 }
319
320 //String
321 func (m *TransactionMessage) String() string {
322         return fmt.Sprintf("TransactionMessage{Size: %d}", len(m.RawTx))
323 }
324
325 //MineBlockMessage new mined block msg
326 type MineBlockMessage struct {
327         RawBlock []byte
328 }
329
330 //NewMinedBlockMessage construct new mined block msg
331 func NewMinedBlockMessage(block *types.Block) (*MineBlockMessage, error) {
332         rawBlock, err := block.MarshalText()
333         if err != nil {
334                 return nil, err
335         }
336         return &MineBlockMessage{RawBlock: rawBlock}, nil
337 }
338
339 //GetMineBlock get mine block from msg
340 func (m *MineBlockMessage) GetMineBlock() (*types.Block, error) {
341         block := &types.Block{}
342         if err := block.UnmarshalText(m.RawBlock); err != nil {
343                 return nil, err
344         }
345         return block, nil
346 }
347
348 //String convert msg to string
349 func (m *MineBlockMessage) String() string {
350         return fmt.Sprintf("NewMineBlockMessage{Size: %d}", len(m.RawBlock))
351 }
352
353 //FilterLoadMessage new load addresses msg
354 type FilterLoadMessage struct {
355         Addresses [][]byte
356 }
357
358 //NewMinedBlockMessage construct new mined block msg
359 func NewFilterLoadMessage(addresses [][]byte) (*FilterLoadMessage, error) {
360         return &FilterLoadMessage{Addresses: addresses}, nil
361 }
362
363 //FilterLoadMessage new load addresses msg
364 type FilterAddMessage struct {
365         Addresse []byte
366 }
367
368 //NewMinedBlockMessage construct new mined block msg
369 func NewFilterAddMessage(addresse []byte) (*FilterAddMessage, error) {
370         return &FilterAddMessage{Addresse: addresse}, nil
371 }
372
373 //FilterClearMessage tells the receiving peer to remove a previously-set filter.
374 type FilterClearMessage struct{}
375
376 //GetMerkleBlockMessage request merkle blocks from remote peers by height/hash
377 type GetMerkleBlockMessage struct {
378         Height  uint64
379         RawHash [32]byte
380 }
381
382 //NewMinedBlockMessage construct new mined block msg
383 func NewGetMerkleBlockMessage(height uint64, rawHash [32]byte) *GetMerkleBlockMessage {
384         return &GetMerkleBlockMessage{Height: height, RawHash: rawHash}
385 }
386
387 //MerkleBlockMessage return the merkle block to client
388 type MerkleBlockMessage struct {
389         RawBlockHeader   []byte
390         TransactionCount uint64
391         TxHashes         [][32]byte
392         TxFlags          []byte
393         RawTxDatas       [][]byte
394         StatusHashes     [][32]byte
395         StatusFlags      []byte
396         RawTxStatuses    [][]byte
397 }
398
399 //GetBlock get block from msg
400 func (m *MerkleBlockMessage) GetMerkleBlock() *types.MerkleBlock {
401         merkleBlock := &types.MerkleBlock{
402                 BlockHeader:  types.BlockHeader{},
403                 Transactions: []*types.Tx{},
404         }
405
406         merkleBlock.BlockHeader.UnmarshalText(m.RawBlockHeader)
407         for _, rawTx := range m.RawTxDatas {
408                 tx := &types.Tx{}
409                 tx.UnmarshalText(rawTx)
410                 merkleBlock.Transactions = append(merkleBlock.Transactions, tx)
411         }
412         return merkleBlock
413 }