github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/dpoa/transaction.go (about) 1 package dpoa 2 3 import ( 4 "bytes" 5 "fmt" 6 "sync" 7 8 "github.com/sixexorg/magnetic-ring/common" 9 "github.com/sixexorg/magnetic-ring/log" 10 11 //"github.com/sixexorg/magnetic-ring/core/signature" 12 //"github.com/ontio/ontology-crypto/keypair" 13 actorTypes "github.com/sixexorg/magnetic-ring/consense/actor" 14 "github.com/sixexorg/magnetic-ring/consense/dpoa/comm" 15 p2pmsg "github.com/sixexorg/magnetic-ring/p2pserver/common" 16 msgpack "github.com/sixexorg/magnetic-ring/p2pserver/message" 17 "time" 18 ) 19 20 21 22 type TransAction struct { 23 msgpool *MsgPool 24 peerpool *PeerPool 25 stateMgr *StateMgr 26 dpoaMgr *DpoaMgr 27 p2p *actorTypes.P2PActor 28 msgSendC chan *SendMsgEvent 29 msgRecvC map[string]chan *comm.P2pMsgPayload 30 cfg *Config 31 quitWg sync.WaitGroup 32 quitC chan struct{} 33 } 34 35 func NewtransAction(msgpool *MsgPool, peerpool *PeerPool, stateMgr *StateMgr, dpoaMgr *DpoaMgr, p2p *actorTypes.P2PActor, cfg *Config) *TransAction { 36 return &TransAction{msgpool: msgpool, peerpool: peerpool, stateMgr: stateMgr, dpoaMgr: dpoaMgr, p2p: p2p, cfg: cfg, 37 msgRecvC: make(map[string]chan *comm.P2pMsgPayload), msgSendC: make(chan *SendMsgEvent, 16)} 38 } 39 40 func (t *TransAction) start() { 41 go t.sendLoop() 42 t.receiveLoop() 43 } 44 45 func (t *TransAction) sendLoop() { 46 t.quitWg.Add(1) 47 defer t.quitWg.Done() 48 49 for { 50 select { 51 case evt := <-t.msgSendC: 52 payload, err := SerializeVbftMsg(evt.Msg) 53 if err != nil { 54 log.Error("server %d failed to serialized msg (type: %d): %s", t.cfg.accountStr, evt.Msg.Type(), err) 55 continue 56 } 57 //log.Info("func dpoa transaction sendLoop", "msg type", evt.Msg.Type()) 58 if evt.ToPeer == comm.BroadCast { 59 // broadcast 60 if err := t.broadcastToAll(payload); err != nil { 61 log.Error("server %v xmit msg (type %d): %s", 62 t.cfg.accountStr, evt.Msg.Type(), err) 63 } 64 } else { 65 if err := t.sendToPeer(evt.ToPeer, payload); err != nil { 66 log.Error("server %v xmit to peer %v failed: %s", t.cfg.accountStr, evt.ToPeer, err) 67 } 68 } 69 case <-t.quitC: 70 log.Info("server %d msgSendLoop quit", t.cfg.accountStr) 71 return 72 } 73 } 74 } 75 76 func (t *TransAction) broadcastToAll(data []byte) error { 77 msg := &p2pmsg.ConsensusPayload{ 78 Data: data, 79 Owner: t.cfg.account.PublicKey(), 80 } 81 82 buf := new(bytes.Buffer) 83 if err := msg.SerializeUnsigned(buf); err != nil { 84 return fmt.Errorf("failed to serialize consensus msg", "err", err) 85 } 86 var err error 87 msg.Signature, err = t.cfg.account.Sign(common.Sha256(buf.Bytes())) 88 if err != nil { 89 log.Error("sign transaction transaction91 occured error","error",err) 90 return err 91 } 92 t.p2p.Broadcast(msg) 93 return nil 94 } 95 96 func (t *TransAction) sendToPeer(peerIdx string, data []byte) error { 97 peer := t.peerpool.getPeer(peerIdx) 98 if peer == nil { 99 return fmt.Errorf("send peer failed: failed to get peer", "peerIdx", peerIdx) 100 } 101 msg := &p2pmsg.ConsensusPayload{ 102 Data: data, 103 Owner: t.cfg.account.PublicKey(), 104 } 105 106 buf := new(bytes.Buffer) 107 if err := msg.SerializeUnsigned(buf); err != nil { 108 return fmt.Errorf("failed to serialize consensus msg", "err", err) 109 } 110 var err error 111 msg.Signature, err = t.cfg.account.Sign(common.Sha256(buf.Bytes())) 112 113 if err != nil { 114 log.Error("t.cfg.account.sign transaction116",) 115 return err 116 } 117 118 cons := msgpack.NewConsensus(msg) 119 p2pid, present := t.peerpool.getP2pId(peerIdx) 120 if present { 121 t.p2p.Transmit(p2pid, cons) 122 } else { 123 log.Error("sendToPeer transmit failed index:", "peerIdx", peerIdx) 124 } 125 return nil 126 } 127 128 func (t *TransAction) receiveLoop() { 129 for _, p := range t.cfg.Peers { 130 if _, present := t.msgRecvC[p]; !present { 131 t.msgRecvC[string(p)] = make(chan *comm.P2pMsgPayload, 1024) 132 } 133 134 go func(pname string) { 135 if err := t.run(pname); err != nil { 136 log.Error("server %d, processor on peer failed: %s", 137 "accountStr", t.cfg.accountStr, "err", err) 138 } 139 }(p) 140 } 141 } 142 func (t *TransAction) receiveFromPeer(peerIdx string) (string, []byte, error) { 143 if C, present := t.msgRecvC[peerIdx]; present { 144 select { 145 case payload := <-C: 146 if payload != nil { 147 return payload.FromPeer, payload.Payload.Data, nil 148 } 149 150 case <-t.quitC: 151 return "", nil, fmt.Errorf("server %d quit", t.cfg.accountStr) 152 } 153 } 154 155 return "", nil, fmt.Errorf("nil consensus payload") 156 } 157 158 func (t *TransAction) run(peerPubKey string) error { 159 // broadcast heartbeat 160 t.heartbeat() 161 162 if err := t.peerpool.waitPeerConnected(peerPubKey); err != nil { 163 return err 164 } 165 166 defer func() { 167 // TODO: handle peer disconnection here 168 log.Warn("server %d: disconnected with peer", "accountStr", t.cfg.accountStr) 169 close(t.msgRecvC[peerPubKey]) 170 delete(t.msgRecvC, peerPubKey) 171 172 t.peerpool.peerDisconnected(peerPubKey) 173 t.stateMgr.StateEventC <- &StateEvent{ 174 Type: UpdatePeerState, 175 peerState: &PeerState{ 176 peerIdx: peerPubKey, 177 connected: false, 178 }, 179 } 180 }() 181 errC := make(chan error) 182 go func() { 183 for { 184 fromPeer, msgData, err := t.receiveFromPeer(peerPubKey) 185 if err != nil { 186 errC <- err 187 return 188 } 189 msg, err := DeserializeVbftMsg(msgData) 190 191 if err != nil { 192 log.Error("server %d failed to deserialize vbft msg (len %d): %s", "accountStr", t.cfg.accountStr, "len(msgData)", len(msgData), "err", err) 193 } else { 194 pk := t.peerpool.GetPeerPubKey(fromPeer) 195 if pk == nil { 196 log.Error("server %d failed to get peer %d pubkey", "accountStr", t.cfg.accountStr, "fromPeer", fromPeer) 197 continue 198 } 199 200 if err := msg.Verify(pk); err != nil { 201 log.Error("server %d failed to verify msg, type %d, err: %s", 202 "accountStr", t.cfg.accountStr, "type", msg.Type(), "err", err) 203 continue 204 } 205 206 t.handleRecvMsg(fromPeer, msg, hashData(msgData)) 207 } 208 } 209 }() 210 211 return <-errC 212 } 213 214 func (t *TransAction) handleRecvMsg(peerIdx string, msg comm.ConsensusMsg, msgHash common.Hash) { 215 if t.msgpool.HasMsg(msg, msgHash) { 216 // dup msg checking 217 log.Debug("dup msg with msg type %d from %d", "type", msg.Type(), "peeridx", peerIdx) 218 return 219 } 220 221 switch msg.Type() { 222 case comm.ConsenseDone: 223 t.ConsenseDone(peerIdx, msg, msgHash) 224 case comm.ConsensePrepare: 225 t.ConsensePrepare(peerIdx, msg, msgHash) 226 case comm.ConsensePromise: 227 t.ConsensePromise(peerIdx, msg, msgHash) 228 case comm.ConsenseProposer: 229 t.ConsenseProposer(peerIdx, msg, msgHash) 230 case comm.ConsenseAccept: 231 t.ConsenseAccept(peerIdx, msg, msgHash) 232 case comm.ViewTimeout: 233 t.ViewTimeout(peerIdx, msg, msgHash) 234 case comm.EvilEvent: 235 236 case comm.EventFetchMessage: 237 238 case comm.EventFetchRspMessage: 239 240 case comm.EvilFetchMessage: 241 242 case comm.EvilFetchRspMessage: 243 244 case comm.EarthFetchRspSigs: 245 t.EarthFetchRspSigs(peerIdx, msg, msgHash) 246 case comm.PeerHeartbeatMessage: 247 t.PeerHeartbeatMessage(peerIdx, msg, msgHash) 248 case comm.BlockFetchMessage: 249 250 case comm.BlockFetchRespMessage: 251 252 case comm.BlockInfoFetchMessage: 253 t.BlockInfoFetchMessage(peerIdx, msg, msgHash) 254 case comm.BlockInfoFetchRespMessage: 255 256 case comm.TimeoutFetchMessage: 257 258 case comm.TimeoutFetchRspMessage: 259 } 260 } 261 func (t *TransAction) GetCurrentBlockNo() uint64 { 262 return t.dpoaMgr.store.db.GetCurrentBlockHeight() + 1 263 } 264 265 func (t *TransAction) GetCommittedBlockNo() uint64 { 266 return t.dpoaMgr.store.getLatestBlockNumber() 267 } 268 269 func (t *TransAction) heartbeat() { 270 fmt.Println("TransActionheartbeat=========>>>>>>>>>>",time.Now().String()) 271 log.Info("TransActionheartbeat=========>>>>>>>>>>", "time:", time.Now().String()) 272 // build heartbeat msg 273 msg, err := constructHeartbeatMsg(t.dpoaMgr.store) 274 if err != nil { 275 log.Error("failed to build heartbeat msg", "err", err) 276 return 277 } 278 279 // send to peer 280 t.msgSendC <- &SendMsgEvent{ 281 ToPeer: comm.BroadCast, 282 Msg: msg, 283 } 284 } 285 286 func (t *TransAction) processHeartbeatMsg(peerIdx string, msg *comm.PeerHeartbeatMsg) error { 287 288 if err := t.peerpool.peerHeartbeat(peerIdx, msg); err != nil { 289 return fmt.Errorf("failed to update peer %d: %s", peerIdx, err) 290 } 291 //log.Debug("server %v received heartbeat from peer %d, blkNum %d", peerIdx, msg.CommittedBlockNumber) 292 t.stateMgr.StateEventC <- &StateEvent{ 293 Type: UpdatePeerState, 294 peerState: &PeerState{ 295 peerIdx: peerIdx, 296 connected: true, 297 //chainConfigView: msg.ChainConfigView, 298 committedBlockNum: msg.CommittedBlockNumber, 299 }, 300 } 301 302 return nil 303 } 304 305 func (t *TransAction) recvMsg(peer string, msg *comm.P2pMsgPayload) { 306 if C, present := t.msgRecvC[peer]; present { 307 C <- msg 308 } else { 309 log.Error("consensus msg without receiver node", "peerid", peer) 310 return 311 } 312 } 313 314 func (t *TransAction) sendMsg(data *SendMsgEvent) { 315 t.msgSendC <- data 316 }