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  }