github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/chains/tm34/handlerTM34.go (about) 1 package tm34 2 3 import ( 4 5 // "bytes" 6 7 "bufio" 8 "encoding/hex" 9 "errors" 10 "fmt" 11 "io" 12 "net" 13 "os" 14 "time" 15 16 "github.com/gogo/protobuf/proto" 17 lru "github.com/hashicorp/golang-lru" 18 log "github.com/sirupsen/logrus" 19 "github.com/supragya/TendermintConnector/chains" 20 "github.com/supragya/TendermintConnector/chains/tm34/conn" 21 "github.com/supragya/TendermintConnector/chains/tm34/crypto/ed25519" 22 "github.com/supragya/TendermintConnector/chains/tm34/crypto/merkle" 23 "github.com/supragya/TendermintConnector/chains/tm34/libs/bits" 24 flow "github.com/supragya/TendermintConnector/chains/tm34/libs/flowrate" 25 tmmath "github.com/supragya/TendermintConnector/chains/tm34/libs/math" 26 "github.com/supragya/TendermintConnector/chains/tm34/libs/protoio" 27 "github.com/supragya/TendermintConnector/chains/tm34/libs/timer" 28 tmcons "github.com/supragya/TendermintConnector/chains/tm34/proto/tendermint/consensus" 29 tmp2p "github.com/supragya/TendermintConnector/chains/tm34/proto/tendermint/p2p" 30 tmproto "github.com/supragya/TendermintConnector/chains/tm34/proto/tendermint/types" 31 "github.com/supragya/TendermintConnector/marlin" 32 marlinTypes "github.com/supragya/TendermintConnector/types" 33 ) 34 35 // ServicedTMCore is a string associated with each TM core handler 36 // to decipher which handler is to be attached. 37 var ServicedTMCore chains.NodeType = chains.NodeType{Version: "0.34.7", Network: "tmv34", ProtocolVersionApp: "1", ProtocolVersionBlock: "11", ProtocolVersionP2p: "8"} 38 39 // ---------------------- DATA CONNECT INTERFACE -------------------------------- 40 41 func RunDataConnect(peerAddr string, 42 marlinTo chan marlinTypes.MarlinMessage, 43 marlinFrom chan marlinTypes.MarlinMessage, 44 isConnectionOutgoing bool, 45 keyFile string, 46 listenPort int) { 47 log.Info("Starting TM34 Tendermint Core Handler - Vanilla Tendermint") 48 49 if keyFile != "" { 50 isKeyFileUsed = true 51 keyFileLocation = keyFile 52 } 53 54 for { 55 handler, err := createTMHandler(peerAddr, "0.0.0.0:0", marlinTo, marlinFrom, isConnectionOutgoing, listenPort, true) 56 57 if err != nil { 58 log.Error("Error encountered while creating TM Handler: ", err) 59 os.Exit(1) 60 } 61 62 if isConnectionOutgoing { 63 err = handler.dialPeer() 64 } 65 // else { 66 // err = handler.acceptPeer() 67 // } 68 if err != nil { 69 log.Error("Base Connection establishment with peer unsuccessful: ", err) 70 goto REATTEMPT_CONNECTION 71 } 72 73 err = handler.upgradeConnectionAndHandshake() 74 if err != nil { 75 log.Error("Error while upgrading connection and handshaking with peer: ", err) 76 goto REATTEMPT_CONNECTION 77 } 78 79 handler.beginServicing() 80 81 select { 82 case <-handler.signalConnError: 83 handler.signalShutSend <- struct{}{} 84 handler.signalShutRecv <- struct{}{} 85 handler.signalShutThroughput <- struct{}{} 86 goto REATTEMPT_CONNECTION 87 } 88 89 REATTEMPT_CONNECTION: 90 handler.baseConnection.Close() 91 handler.secretConnection.Close() 92 log.Info("Error encountered with connection to the peer. Attempting reconnect post 1 second.") 93 time.Sleep(1 * time.Second) 94 } 95 } 96 97 func (h *TendermintHandler) dialPeer() error { 98 var err error 99 h.baseConnection, err = net.DialTimeout("tcp", h.peerAddr, 2000*time.Millisecond) 100 if err != nil { 101 return err 102 } 103 104 return nil 105 } 106 107 func (h *TendermintHandler) upgradeConnectionAndHandshake() error { 108 log.Info("Handshaking procedure") 109 var err error 110 h.secretConnection, err = conn.MakeSecretConnection(h.baseConnection, h.privateKey) 111 if err != nil { 112 return err 113 } 114 115 err = h.handshake() 116 if err != nil { 117 return err 118 } 119 120 log.Info("Established connection with TM peer [" + 121 string(hex.EncodeToString(h.secretConnection.RemotePubKey().Address())) + 122 "] a.k.a. " + h.peerNodeInfo.Moniker) 123 return nil 124 } 125 126 func (h *TendermintHandler) handshake() error { 127 var ( 128 errc = make(chan error, 2) 129 ourNodeInfo tmp2p.DefaultNodeInfo = tmp2p.DefaultNodeInfo{ 130 tmp2p.ProtocolVersion{App: 1, Block: 11, P2P: 8}, 131 string(hex.EncodeToString(h.privateKey.PubKey().Address())), 132 "tcp://127.0.0.1:20016", //TODO Correct this - v0.2 prerelease 133 "tmv34", 134 "0.34.7", 135 []byte{channelBc, channelCsSt, channelCsDc, channelCsVo, 136 channelCsVs, channelMm, channelEv}, 137 "marlin-tendermint-connector", 138 tmp2p.DefaultNodeInfoOther{"on", "tcp://0.0.0.0:26667"}, // TODO: Correct this - v0.2 prerelease 139 } 140 ) 141 142 go func(errc chan<- error, c net.Conn) { 143 _, err := protoio.NewDelimitedWriter(c).WriteMsg(&ourNodeInfo) 144 if err != nil { 145 log.Error("Error encountered while sending handshake message ", err) 146 } 147 errc <- err 148 }(errc, h.secretConnection) 149 150 go func(errc chan<- error, c net.Conn) { 151 protoReader := protoio.NewDelimitedReader(c, 10240) 152 _, err := protoReader.ReadMsg(&h.peerNodeInfo) 153 if err != nil { 154 log.Error("Error encountered while recieving handshake message ", err) 155 } 156 errc <- err 157 }(errc, h.secretConnection) 158 159 for i := 0; i < cap(errc); i++ { 160 err := <-errc 161 if err != nil { 162 log.Error("Encountered error in handshake with TM core: ", err) 163 return err 164 } 165 } 166 return nil 167 } 168 169 func (h *TendermintHandler) beginServicing() error { 170 // Create a P2P Connection 171 h.p2pConnection = P2PConnection{ 172 conn: h.secretConnection, 173 bufConnReader: bufio.NewReaderSize(h.secretConnection, 65535), 174 bufConnWriter: bufio.NewWriterSize(h.secretConnection, 65535), 175 sendMonitor: flow.New(0, 0), 176 recvMonitor: flow.New(0, 0), 177 send: make(chan struct{}, 1), 178 pong: make(chan struct{}, 1), 179 doneSendRoutine: make(chan struct{}, 1), 180 quitSendRoutine: make(chan struct{}, 1), 181 quitRecvRoutine: make(chan struct{}, 1), 182 flushTimer: timer.NewThrottleTimer("flush", 100*time.Millisecond), 183 pingTimer: time.NewTicker(30 * time.Second), 184 pongTimeoutCh: make(chan bool, 1), 185 } 186 187 // Start P2P Send and recieve routines + Status messages for message throughput 188 go h.sendRoutine() 189 go h.recvRoutine() 190 go h.throughput.presentThroughput(5, h.signalShutThroughput) 191 192 // Allow Irisnet messages from marlin Relay 193 marlin.AllowServicedChainMessages(h.servicedChainId) 194 return nil 195 } 196 197 func (h *TendermintHandler) sendRoutine() { 198 protoWriter := protoio.NewDelimitedWriter(h.p2pConnection.bufConnWriter) 199 for { 200 var _n int 201 var err error 202 SELECTION: 203 select { 204 case <-h.p2pConnection.pong: 205 // log.Info("Send Pong") 206 _n, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) 207 if err != nil { 208 log.Error("Failed to send PacketPong", "err", err) 209 break SELECTION 210 } 211 h.p2pConnection.sendMonitor.Update(_n) 212 h.flush() 213 } 214 } 215 } 216 217 func (h *TendermintHandler) flush() { 218 err := h.p2pConnection.bufConnWriter.Flush() 219 if err != nil { 220 log.Error("BufConnWriter flush failed", "err", err) 221 } 222 } 223 224 func (h *TendermintHandler) recvRoutine() { 225 log.Info("TMCore -> Connector Routine Started") 226 protoReader := protoio.NewDelimitedReader(h.p2pConnection.bufConnReader, 2000) 227 228 FOR_LOOP: 229 for { 230 select { 231 case <-h.signalShutRecv: 232 log.Info("TMCore -> Connector Routine shutdown") 233 break FOR_LOOP 234 default: 235 } 236 h.p2pConnection.recvMonitor.Limit(20000, 5120000, true) 237 238 /* 239 Peek into bufConnReader for debugging 240 241 if numBytes := c.bufConnReader.Buffered(); numBytes > 0 { 242 bz, err := c.bufConnReader.Peek(cmn.MinInt(numBytes, 100)) 243 if err == nil { 244 // return 245 } else { 246 log.Debug("Error peeking connection buffer ", "err ", err) 247 // return nil 248 } 249 log.Info("Peek connection buffer ", "numBytes ", numBytes, " bz ", bz) 250 } 251 */ 252 253 // Read packet type 254 var packet tmp2p.Packet 255 _n, err := protoReader.ReadMsg(&packet) 256 257 h.p2pConnection.recvMonitor.Update(int(_n)) 258 259 // Unmarshalling test 260 if err != nil { 261 if err == io.EOF { 262 log.Error("TMCore -> Connector Connection is closed (likely by the other side) ", err) 263 } else { 264 log.Error("TMCore -> Connector Connection failed (reading byte): ", err) 265 } 266 h.signalConnError <- struct{}{} 267 break FOR_LOOP 268 } 269 270 switch pkt := packet.Sum.(type) { 271 case *tmp2p.Packet_PacketPing: 272 // TODO: prevent abuse, as they cause flush()'s. 273 // https://github.com/tendermint/tendermint/issues/1190 274 // log.Info("Receive Ping ", pkt) 275 select { 276 case h.p2pConnection.pong <- struct{}{}: 277 default: 278 // never block 279 } 280 case *tmp2p.Packet_PacketPong: 281 log.Info("Receive Pong") 282 select { 283 case h.p2pConnection.pongTimeoutCh <- false: 284 default: 285 // never block 286 } 287 case *tmp2p.Packet_PacketMsg: 288 var eof uint32 = 0 289 if pkt.PacketMsg.EOF { 290 eof = 1 291 } 292 h.channelBuffer[byte(pkt.PacketMsg.ChannelID)] = append(h.channelBuffer[byte(pkt.PacketMsg.ChannelID)], 293 marlinTypes.PacketMsg{ 294 ChannelID: uint32(pkt.PacketMsg.ChannelID), 295 EOF: eof, 296 Bytes: pkt.PacketMsg.Data, 297 }) 298 299 // In case of incomplete message 300 if !pkt.PacketMsg.EOF { 301 log.Debug("TMCore -> Connector partial ", byte(pkt.PacketMsg.ChannelID)) 302 break 303 } 304 305 // Reach here only in case message has EOF. At this point the previous 306 // messages are in h.channelBuffer[channel-idx] 307 switch byte(pkt.PacketMsg.ChannelID) { 308 case channelBc: 309 h.throughput.putInfo("from", "=BcMSG", 1) 310 log.Debug("TMCore -> Connector Blockhain is not serviced") 311 h.channelBuffer[channelBc] = h.channelBuffer[channelBc][:0] 312 case channelCsSt: 313 log.Debug("TMCore -> Connector CsSt servicing") 314 submessage, err := h.serviceConsensusStateMessage() 315 if err != nil { 316 log.Warning("Could not service consensus state message due to err: ", err) 317 } 318 h.throughput.putInfo("from", submessage, 1) 319 h.channelBuffer[channelCsSt] = h.channelBuffer[channelCsSt][:0] 320 case channelCsDc: 321 log.Debug("TMCore -> Connector CsDc servicing") 322 submessage, err := h.serviceConsensusDataMessage() 323 if err != nil { 324 log.Warning("Could not service consensus data message due to err: ", err) 325 } 326 h.throughput.putInfo("from", submessage, 1) 327 h.channelBuffer[channelCsDc] = h.channelBuffer[channelCsDc][:0] 328 case channelCsVo: 329 log.Debug("TMCore -> Connector CsDo servicing") 330 submessage, err := h.serviceConsensusVoteMessage() 331 if err != nil { 332 log.Warning("Could not service consensus vote message due to err: ", err) 333 } 334 h.throughput.putInfo("from", submessage, 1) 335 h.channelBuffer[channelCsVo] = h.channelBuffer[channelCsVo][:0] 336 case channelCsVs: 337 h.throughput.putInfo("from", "=CsVsVSB", 1) 338 log.Debug("TMCore -> Connector Consensus Vote Set Bits Channel is not serviced") 339 h.channelBuffer[channelCsVs] = h.channelBuffer[channelCsVs][:0] 340 case channelMm: 341 h.throughput.putInfo("from", "=MmMSG", 1) 342 log.Debug("TMCore -> Connector Mempool Channel is not serviced") 343 h.channelBuffer[channelMm] = h.channelBuffer[channelMm][:0] 344 case channelEv: 345 h.throughput.putInfo("from", "=EvMSG", 1) 346 log.Debug("TMCore -> Connector Evidence Channel is not serviced") 347 h.channelBuffer[channelEv] = h.channelBuffer[channelEv][:0] 348 default: 349 h.throughput.putInfo("from", "=UnkUNK", 1) 350 log.Warning("TMCore -> Connector Unknown ChannelID Message recieved: ", pkt.PacketMsg.ChannelID) 351 h.channelBuffer[byte(pkt.PacketMsg.ChannelID)] = h.channelBuffer[byte(pkt.PacketMsg.ChannelID)][:0] 352 } 353 } 354 } 355 356 // Cleanup 357 close(h.p2pConnection.pong) 358 for range h.p2pConnection.pong { 359 // Drain 360 } 361 } 362 363 func (h *TendermintHandler) getBytesFromChannelBuffer(chanbuf []marlinTypes.PacketMsg) []byte { 364 var databuf []byte 365 for _, pkt := range chanbuf { 366 databuf = append(databuf, pkt.Bytes...) 367 } 368 return databuf 369 } 370 371 func (h *TendermintHandler) serviceConsensusStateMessage() (string, error) { 372 ch := channelCsSt 373 msgBytes := h.getBytesFromChannelBuffer(h.channelBuffer[ch]) 374 msg, err := decodeMsg(msgBytes) 375 if err != nil { 376 return "", err 377 } 378 379 switch msg.(type) { 380 case *NewRoundStepMessage: 381 message := marlinTypes.MarlinMessage{ 382 ChainID: h.servicedChainId, 383 Channel: ch, 384 Packets: h.channelBuffer[ch], 385 } 386 // Send to marlin side 387 select { 388 case h.marlinTo <- message: 389 default: 390 log.Warning("Too many messages in channel marlinTo. Dropping oldest messages") 391 _ = <-h.marlinTo 392 h.marlinTo <- message 393 } 394 // Do we need to send back? 395 return "+CsStNRS", nil 396 case *Proposal: 397 log.Debug("Found proposal, not servicing") 398 return "-CsStPRO", nil 399 case *NewValidBlockMessage: 400 log.Debug("Found NewValidBlock, not servicing") 401 return "-CsStNVB", nil 402 case *HasVoteMessage: 403 log.Debug("Found HasVote, not servicing") 404 return "-CsStHVM", nil 405 case *VoteSetMaj23Message: 406 log.Debug("Found SetMaj23, not servicing") 407 return "-CsStM23", nil 408 default: 409 log.Warning("Unknown Consensus state message ", msg) 410 return "-CsStXXX", nil 411 } 412 } 413 414 func (h *TendermintHandler) serviceConsensusDataMessage() (string, error) { 415 ch := channelCsDc 416 msgBytes := h.getBytesFromChannelBuffer(h.channelBuffer[ch]) 417 msg, err := decodeMsg(msgBytes) 418 if err != nil { 419 return "", err 420 } 421 422 switch msg.(type) { 423 case *ProposalMessage: 424 message := marlinTypes.MarlinMessage{ 425 ChainID: h.servicedChainId, 426 Channel: ch, 427 Packets: h.channelBuffer[ch], 428 } 429 // Send to marlin side 430 select { 431 case h.marlinTo <- message: 432 default: 433 log.Warning("Too many messages in channel marlinTo. Dropping oldest messages") 434 _ = <-h.marlinTo 435 h.marlinTo <- message 436 } 437 return "+CsDcPRO", nil 438 case *ProposalPOLMessage: 439 log.Debug("Found Proposal POL, not servicing") 440 return "-CsDcPOL", nil 441 case *BlockPartMessage: 442 log.Debug("Found BlockPart, not servicing") 443 return "-CsDcBPM", nil 444 default: 445 log.Warning("Unknown Consensus data message ", msg) 446 return "-CsDcXXX", nil 447 } 448 } 449 450 func (h *TendermintHandler) serviceConsensusVoteMessage() (string, error) { 451 ch := channelCsVo 452 msgBytes := h.getBytesFromChannelBuffer(h.channelBuffer[ch]) 453 msg, err := decodeMsg(msgBytes) 454 if err != nil { 455 return "", err 456 } 457 458 switch msg.(type) { 459 case *VoteMessage: 460 message := marlinTypes.MarlinMessage{ 461 ChainID: h.servicedChainId, 462 Channel: ch, 463 Packets: h.channelBuffer[ch], 464 } 465 // Send to marlin side 466 select { 467 case h.marlinTo <- message: 468 default: 469 log.Warning("Too many messages in channel marlinTo. Dropping oldest messages") 470 _ = <-h.marlinTo 471 h.marlinTo <- message 472 } 473 return "+CsVoVOT", nil 474 default: 475 log.Warning("Unknown Consensus vote message ", msg) 476 return "-CsVoXXX", nil 477 } 478 } 479 480 // ---------------------- KEY GENERATION INTERFACE ----------------------------- 481 482 var ServicedKeyFile string = "tm34" 483 var isKeyFileUsed, memoized bool 484 var keyFileLocation string 485 486 var privateKey ed25519.PrivKey 487 488 // ---------------------- COMMON UTILITIES --------------------------------- 489 490 func createTMHandler(peerAddr string, 491 rpcAddr string, 492 marlinTo chan marlinTypes.MarlinMessage, 493 marlinFrom chan marlinTypes.MarlinMessage, 494 isConnectionOutgoing bool, 495 listenPort int, 496 isDataConnect bool) (TendermintHandler, error) { 497 chainId, ok := marlinTypes.ServicedChains["tm34"] 498 if !ok { 499 return TendermintHandler{}, errors.New("Cannot find tm34 in list of serviced chains by marlin connector") 500 } 501 502 privateKey := getPrivateKey() 503 504 vCache, err := lru.New2Q(500) 505 if err != nil { 506 return TendermintHandler{}, err 507 } 508 509 return TendermintHandler{ 510 servicedChainId: chainId, 511 listenPort: listenPort, 512 isConnectionOutgoing: isConnectionOutgoing, 513 peerAddr: peerAddr, 514 rpcAddr: rpcAddr, 515 privateKey: privateKey, 516 // codec: amino.NewCodec(), 517 validatorCache: vCache, 518 marlinTo: marlinTo, 519 marlinFrom: marlinFrom, 520 channelBuffer: make(map[byte][]marlinTypes.PacketMsg), 521 throughput: throughPutData{ 522 isDataConnect: isDataConnect, 523 toTMCore: make(map[string]uint32), 524 fromTMCore: make(map[string]uint32), 525 spam: make(map[string]uint32), 526 }, 527 signalConnError: make(chan struct{}, 1), 528 signalShutSend: make(chan struct{}, 1), 529 signalShutRecv: make(chan struct{}, 1), 530 signalShutThroughput: make(chan struct{}, 1), 531 }, nil 532 } 533 534 func getPrivateKey() ed25519.PrivKey { 535 // if !isKeyFileUsed { 536 return ed25519.GenPrivKey() 537 // } 538 // else { 539 // if !memoized { 540 // valid, err := VerifyKeyFile(keyFileLocation) 541 // if err != nil { 542 // log.Error("Error verifying keyfile integrity: ", keyFileLocation) 543 // os.Exit(1) 544 // } else if !valid { 545 // os.Exit(1) 546 // } 547 // log.Info("Accessing disk to extract info from KeyFile: ", keyFileLocation) 548 // jsonFile, err := os.Open(keyFileLocation) 549 // // if we os.Open returns an error then handle it 550 // if err != nil { 551 // log.Error("Error accessing file KeyFile: ", keyFileLocation, " error: ", err, ". exiting application.") 552 // os.Exit(1) 553 // } 554 // defer jsonFile.Close() 555 556 // byteValue, err := ioutil.ReadAll(jsonFile) 557 // if err != nil { 558 // log.Error("Error decoding KeyFile: ", keyFileLocation, " error: ", err, ". exiting application.") 559 // os.Exit(1) 560 // } 561 // var key keyData 562 // json.Unmarshal(byteValue, &key) 563 // log.Info("Connector assumes for all connections henceforth the ID: ", key.IdString) 564 // privateKey = key.PrivateKey 565 // memoized = true 566 // } 567 // return privateKey 568 // } 569 } 570 571 func (t *throughPutData) putInfo(direction string, key string, count uint32) { 572 t.mu.Lock() 573 switch direction { 574 case "to": 575 t.toTMCore[key] = t.toTMCore[key] + count 576 case "from": 577 t.fromTMCore[key] = t.fromTMCore[key] + count 578 case "spam": 579 t.spam[key] = t.spam[key] + count 580 } 581 t.mu.Unlock() 582 } 583 584 func (t *throughPutData) presentThroughput(sec time.Duration, shutdownCh chan struct{}) { 585 for { 586 time.Sleep(sec * time.Second) 587 588 select { 589 case <-shutdownCh: 590 return 591 default: 592 } 593 t.mu.Lock() 594 if t.isDataConnect { 595 log.Info(fmt.Sprintf("[DataConnect stats] To TMCore %v\tFrom TMCore %v", t.toTMCore, t.fromTMCore)) 596 } else { 597 log.Info(fmt.Sprintf("[SpamFilter stats] Served %v", t.spam)) 598 } 599 t.toTMCore = make(map[string]uint32) 600 t.fromTMCore = make(map[string]uint32) 601 t.spam = make(map[string]uint32) 602 t.mu.Unlock() 603 } 604 } 605 606 //----------------------------------------------------------------------------- 607 // Messages 608 609 // Message is a message that can be sent and received on the Reactor 610 type Message interface { 611 // ValidateBasic() error // No restrictions 612 } 613 614 func decodeMsg(bz []byte) (msg Message, err error) { 615 pb := &tmcons.Message{} 616 if err = proto.Unmarshal(bz, pb); err != nil { 617 return msg, err 618 } 619 620 return MsgFromProto(pb) 621 } 622 623 // MsgFromProto takes a consensus proto message and returns the native go type 624 func MsgFromProto(msg *tmcons.Message) (Message, error) { 625 if msg == nil { 626 return nil, errors.New("consensus: nil message") 627 } 628 var pb Message 629 630 switch msg := msg.Sum.(type) { 631 case *tmcons.Message_NewRoundStep: 632 rs, err := tmmath.SafeConvertUint8(int64(msg.NewRoundStep.Step)) 633 // deny message based on possible overflow 634 if err != nil { 635 return nil, fmt.Errorf("denying message due to possible overflow: %w", err) 636 } 637 pb = &NewRoundStepMessage{ 638 Height: msg.NewRoundStep.Height, 639 Round: msg.NewRoundStep.Round, 640 Step: int8(rs), 641 SecondsSinceStartTime: msg.NewRoundStep.SecondsSinceStartTime, 642 LastCommitRound: msg.NewRoundStep.LastCommitRound, 643 } 644 case *tmcons.Message_NewValidBlock: 645 pbPartSetHeader, err := PartSetHeaderFromProto(&msg.NewValidBlock.BlockPartSetHeader) 646 if err != nil { 647 return nil, fmt.Errorf("parts to proto error: %w", err) 648 } 649 650 pbBits := new(bits.BitArray) 651 pbBits.FromProto(msg.NewValidBlock.BlockParts) 652 653 pb = &NewValidBlockMessage{ 654 Height: msg.NewValidBlock.Height, 655 Round: msg.NewValidBlock.Round, 656 BlockPartSetHeader: *pbPartSetHeader, 657 BlockParts: pbBits, 658 IsCommit: msg.NewValidBlock.IsCommit, 659 } 660 case *tmcons.Message_Proposal: 661 pbP, err := ProposalFromProto(&msg.Proposal.Proposal) 662 if err != nil { 663 return nil, fmt.Errorf("proposal msg to proto error: %w", err) 664 } 665 666 pb = &ProposalMessage{ 667 Proposal: pbP, 668 } 669 case *tmcons.Message_ProposalPol: 670 pbBits := new(bits.BitArray) 671 pbBits.FromProto(&msg.ProposalPol.ProposalPol) 672 pb = &ProposalPOLMessage{ 673 Height: msg.ProposalPol.Height, 674 ProposalPOLRound: msg.ProposalPol.ProposalPolRound, 675 ProposalPOL: pbBits, 676 } 677 case *tmcons.Message_BlockPart: 678 parts, err := PartFromProto(&msg.BlockPart.Part) 679 if err != nil { 680 return nil, fmt.Errorf("blockpart msg to proto error: %w", err) 681 } 682 pb = &BlockPartMessage{ 683 Height: msg.BlockPart.Height, 684 Round: msg.BlockPart.Round, 685 Part: parts, 686 } 687 case *tmcons.Message_Vote: 688 vote, err := VoteFromProto(msg.Vote.Vote) 689 if err != nil { 690 return nil, fmt.Errorf("vote msg to proto error: %w", err) 691 } 692 693 pb = &VoteMessage{ 694 Vote: vote, 695 } 696 case *tmcons.Message_HasVote: 697 pb = &HasVoteMessage{ 698 Height: msg.HasVote.Height, 699 Round: msg.HasVote.Round, 700 Type: msg.HasVote.Type, 701 Index: msg.HasVote.Index, 702 } 703 case *tmcons.Message_VoteSetMaj23: 704 bi, err := BlockIDFromProto(&msg.VoteSetMaj23.BlockID) 705 if err != nil { 706 return nil, fmt.Errorf("voteSetMaj23 msg to proto error: %w", err) 707 } 708 pb = &VoteSetMaj23Message{ 709 Height: msg.VoteSetMaj23.Height, 710 Round: msg.VoteSetMaj23.Round, 711 Type: msg.VoteSetMaj23.Type, 712 BlockID: *bi, 713 } 714 case *tmcons.Message_VoteSetBits: 715 bi, err := BlockIDFromProto(&msg.VoteSetBits.BlockID) 716 if err != nil { 717 return nil, fmt.Errorf("voteSetBits msg to proto error: %w", err) 718 } 719 bits := new(bits.BitArray) 720 bits.FromProto(&msg.VoteSetBits.Votes) 721 722 pb = &VoteSetBitsMessage{ 723 Height: msg.VoteSetBits.Height, 724 Round: msg.VoteSetBits.Round, 725 Type: msg.VoteSetBits.Type, 726 BlockID: *bi, 727 Votes: bits, 728 } 729 default: 730 return nil, fmt.Errorf("consensus: message not recognized: %T", msg) 731 } 732 733 // if err := pb.ValidateBasic(); err != nil { 734 // return nil, err 735 // } 736 737 return pb, nil 738 } 739 740 // FromProto sets a protobuf PartSetHeader to the given pointer 741 func PartSetHeaderFromProto(ppsh *tmproto.PartSetHeader) (*PartSetHeader, error) { 742 if ppsh == nil { 743 return nil, errors.New("nil PartSetHeader") 744 } 745 psh := new(PartSetHeader) 746 psh.Total = ppsh.Total 747 psh.Hash = ppsh.Hash 748 749 return psh, nil 750 } 751 752 // FromProto sets a protobuf BlockID to the given pointer. 753 // It returns an error if the block id is invalid. 754 func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) { 755 if bID == nil { 756 return nil, errors.New("nil BlockID") 757 } 758 759 blockID := new(BlockID) 760 ph, err := PartSetHeaderFromProto(&bID.PartSetHeader) 761 if err != nil { 762 return nil, err 763 } 764 765 blockID.PartSetHeader = *ph 766 blockID.Hash = bID.Hash 767 768 return blockID, nil 769 } 770 771 // FromProto sets a protobuf Proposal to the given pointer. 772 // It returns an error if the proposal is invalid. 773 func ProposalFromProto(pp *tmproto.Proposal) (*Proposal, error) { 774 if pp == nil { 775 return nil, errors.New("nil proposal") 776 } 777 778 p := new(Proposal) 779 780 blockID, err := BlockIDFromProto(&pp.BlockID) 781 if err != nil { 782 return nil, err 783 } 784 785 p.BlockID = *blockID 786 p.Type = pp.Type 787 p.Height = pp.Height 788 p.Round = pp.Round 789 p.POLRound = pp.PolRound 790 p.Timestamp = pp.Timestamp 791 p.Signature = pp.Signature 792 793 return p, nil 794 } 795 796 func PartFromProto(pb *tmproto.Part) (*Part, error) { 797 if pb == nil { 798 return nil, errors.New("nil part") 799 } 800 801 part := new(Part) 802 proof, err := merkle.ProofFromProto(&pb.Proof) 803 if err != nil { 804 return nil, err 805 } 806 part.Index = pb.Index 807 part.Bytes = pb.Bytes 808 part.Proof = *proof 809 810 return part, nil 811 } 812 813 // FromProto converts a proto generetad type to a handwritten type 814 // return type, nil if everything converts safely, otherwise nil, error 815 func VoteFromProto(pv *tmproto.Vote) (*Vote, error) { 816 if pv == nil { 817 return nil, errors.New("nil vote") 818 } 819 820 blockID, err := BlockIDFromProto(&pv.BlockID) 821 if err != nil { 822 return nil, err 823 } 824 825 vote := new(Vote) 826 vote.Type = pv.Type 827 vote.Height = pv.Height 828 vote.Round = pv.Round 829 vote.BlockID = *blockID 830 vote.Timestamp = pv.Timestamp 831 vote.ValidatorAddress = pv.ValidatorAddress 832 vote.ValidatorIndex = pv.ValidatorIndex 833 vote.Signature = pv.Signature 834 835 return vote, nil 836 } 837 838 //---------------------------------------- 839 // Packet 840 841 // mustWrapPacket takes a packet kind (oneof) and wraps it in a tmp2p.Packet message. 842 func mustWrapPacket(pb proto.Message) *tmp2p.Packet { 843 var msg tmp2p.Packet 844 845 switch pb := pb.(type) { 846 case *tmp2p.Packet: // already a packet 847 msg = *pb 848 case *tmp2p.PacketPing: 849 msg = tmp2p.Packet{ 850 Sum: &tmp2p.Packet_PacketPing{ 851 PacketPing: pb, 852 }, 853 } 854 case *tmp2p.PacketPong: 855 msg = tmp2p.Packet{ 856 Sum: &tmp2p.Packet_PacketPong{ 857 PacketPong: pb, 858 }, 859 } 860 case *tmp2p.PacketMsg: 861 msg = tmp2p.Packet{ 862 Sum: &tmp2p.Packet_PacketMsg{ 863 PacketMsg: pb, 864 }, 865 } 866 default: 867 panic(fmt.Errorf("unknown packet type %T", pb)) 868 } 869 870 return &msg 871 }