OSDN Git Service

ec6e1c94fcd26e2e700b8ecb09e663ae0a992fc3
[bytom/bytom.git] / netsync / message.go
1 package netsync
2
3 import (
4         "bytes"
5         "errors"
6         "fmt"
7
8         "github.com/tendermint/go-wire"
9
10         "github.com/bytom/protocol/bc"
11         "github.com/bytom/protocol/bc/types"
12 )
13
14 //protocol msg
15 const (
16         BlockRequestByte   = byte(0x10)
17         BlockResponseByte  = byte(0x11)
18         StatusRequestByte  = byte(0x20)
19         StatusResponseByte = byte(0x21)
20         NewTransactionByte = byte(0x30)
21         NewMineBlockByte   = byte(0x40)
22
23         maxBlockchainResponseSize = 22020096 + 2
24 )
25
26 // BlockchainMessage is a generic message for this reactor.
27 type BlockchainMessage interface{}
28
29 var _ = wire.RegisterInterface(
30         struct{ BlockchainMessage }{},
31         wire.ConcreteType{&BlockRequestMessage{}, BlockRequestByte},
32         wire.ConcreteType{&BlockResponseMessage{}, BlockResponseByte},
33         wire.ConcreteType{&StatusRequestMessage{}, StatusRequestByte},
34         wire.ConcreteType{&StatusResponseMessage{}, StatusResponseByte},
35         wire.ConcreteType{&TransactionNotifyMessage{}, NewTransactionByte},
36         wire.ConcreteType{&MineBlockMessage{}, NewMineBlockByte},
37 )
38
39 type blockPending struct {
40         block  *types.Block
41         peerID string
42 }
43
44 type txsNotify struct {
45         tx     *types.Tx
46         peerID string
47 }
48
49 //DecodeMessage decode msg
50 func DecodeMessage(bz []byte) (msgType byte, msg BlockchainMessage, err error) {
51         msgType = bz[0]
52         n := int(0)
53         r := bytes.NewReader(bz)
54         msg = wire.ReadBinary(struct{ BlockchainMessage }{}, r, maxBlockchainResponseSize, &n, &err).(struct{ BlockchainMessage }).BlockchainMessage
55         if err != nil && n != len(bz) {
56                 err = errors.New("DecodeMessage() had bytes left over")
57         }
58         return
59 }
60
61 //BlockRequestMessage request blocks from remote peers by height/hash
62 type BlockRequestMessage struct {
63         Height  uint64
64         RawHash [32]byte
65 }
66
67 //GetHash get hash
68 func (m *BlockRequestMessage) GetHash() *bc.Hash {
69         hash := bc.NewHash(m.RawHash)
70         return &hash
71 }
72
73 //String convert msg to string
74 func (m *BlockRequestMessage) String() string {
75         if m.Height > 0 {
76                 return fmt.Sprintf("BlockRequestMessage{Height: %d}", m.Height)
77         }
78         hash := m.GetHash()
79         return fmt.Sprintf("BlockRequestMessage{Hash: %s}", hash.String())
80 }
81
82 //BlockResponseMessage response get block msg
83 type BlockResponseMessage struct {
84         RawBlock []byte
85 }
86
87 //NewBlockResponseMessage construct bock response msg
88 func NewBlockResponseMessage(block *types.Block) (*BlockResponseMessage, error) {
89         rawBlock, err := block.MarshalText()
90         if err != nil {
91                 return nil, err
92         }
93         return &BlockResponseMessage{RawBlock: rawBlock}, nil
94 }
95
96 //GetBlock get block from msg
97 func (m *BlockResponseMessage) GetBlock() *types.Block {
98         block := &types.Block{
99                 BlockHeader:  types.BlockHeader{},
100                 Transactions: []*types.Tx{},
101         }
102         block.UnmarshalText(m.RawBlock)
103         return block
104 }
105
106 //String convert msg to string
107 func (m *BlockResponseMessage) String() string {
108         return fmt.Sprintf("BlockResponseMessage{Size: %d}", len(m.RawBlock))
109 }
110
111 //TransactionNotifyMessage notify new tx msg
112 type TransactionNotifyMessage struct {
113         RawTx []byte
114 }
115
116 //NewTransactionNotifyMessage construct notify new tx msg
117 func NewTransactionNotifyMessage(tx *types.Tx) (*TransactionNotifyMessage, error) {
118         rawTx, err := tx.TxData.MarshalText()
119         if err != nil {
120                 return nil, err
121         }
122         return &TransactionNotifyMessage{RawTx: rawTx}, nil
123 }
124
125 //GetTransaction get tx from msg
126 func (m *TransactionNotifyMessage) GetTransaction() (*types.Tx, error) {
127         tx := &types.Tx{}
128         if err := tx.UnmarshalText(m.RawTx); err != nil {
129                 return nil, err
130         }
131         return tx, nil
132 }
133
134 //String
135 func (m *TransactionNotifyMessage) String() string {
136         return fmt.Sprintf("TransactionNotifyMessage{Size: %d}", len(m.RawTx))
137 }
138
139 //StatusRequestMessage status request msg
140 type StatusRequestMessage struct{}
141
142 //String
143 func (m *StatusRequestMessage) String() string {
144         return "StatusRequestMessage"
145 }
146
147 //StatusResponseMessage get status response msg
148 type StatusResponseMessage struct {
149         Height      uint64
150         RawHash     [32]byte
151         GenesisHash [32]byte
152 }
153
154 //NewStatusResponseMessage construct get status response msg
155 func NewStatusResponseMessage(blockHeader *types.BlockHeader, hash *bc.Hash) *StatusResponseMessage {
156         return &StatusResponseMessage{
157                 Height:      blockHeader.Height,
158                 RawHash:     blockHeader.Hash().Byte32(),
159                 GenesisHash: hash.Byte32(),
160         }
161 }
162
163 //GetHash get hash from msg
164 func (m *StatusResponseMessage) GetHash() *bc.Hash {
165         hash := bc.NewHash(m.RawHash)
166         return &hash
167 }
168
169 //GetGenesisHash get hash from msg
170 func (m *StatusResponseMessage) GetGenesisHash() *bc.Hash {
171         hash := bc.NewHash(m.GenesisHash)
172         return &hash
173 }
174
175 //String convert msg to string
176 func (m *StatusResponseMessage) String() string {
177         hash := m.GetHash()
178         genesisHash := m.GetGenesisHash()
179         return fmt.Sprintf("StatusResponseMessage{Height: %d, Best hash: %s, Genesis hash: %s}", m.Height, hash.String(), genesisHash.String())
180 }
181
182 //MineBlockMessage new mined block msg
183 type MineBlockMessage struct {
184         RawBlock []byte
185 }
186
187 //NewMinedBlockMessage construct new mined block msg
188 func NewMinedBlockMessage(block *types.Block) (*MineBlockMessage, error) {
189         rawBlock, err := block.MarshalText()
190         if err != nil {
191                 return nil, err
192         }
193         return &MineBlockMessage{RawBlock: rawBlock}, nil
194 }
195
196 //GetMineBlock get mine block from msg
197 func (m *MineBlockMessage) GetMineBlock() (*types.Block, error) {
198         block := &types.Block{}
199         if err := block.UnmarshalText(m.RawBlock); err != nil {
200                 return nil, err
201         }
202         return block, nil
203 }
204
205 //String convert msg to string
206 func (m *MineBlockMessage) String() string {
207         return fmt.Sprintf("NewMineBlockMessage{Size: %d}", len(m.RawBlock))
208 }