OSDN Git Service

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