github.com/okex/exchain@v1.8.0/libs/tendermint/mempool/reactor.go (about)

     1  package mempool
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math"
     7  	"reflect"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  
    13  	abci "github.com/okex/exchain/libs/tendermint/abci/types"
    14  	cfg "github.com/okex/exchain/libs/tendermint/config"
    15  	"github.com/okex/exchain/libs/tendermint/libs/clist"
    16  	"github.com/okex/exchain/libs/tendermint/libs/log"
    17  	"github.com/okex/exchain/libs/tendermint/p2p"
    18  	"github.com/okex/exchain/libs/tendermint/types"
    19  	"github.com/tendermint/go-amino"
    20  )
    21  
    22  const (
    23  	MempoolChannel = byte(0x30)
    24  
    25  	aminoOverheadForTxMessage = 8
    26  
    27  	peerCatchupSleepIntervalMS = 100 // If peer is behind, sleep this amount
    28  
    29  	// UnknownPeerID is the peer ID to use when running CheckTx when there is
    30  	// no peer (e.g. RPC)
    31  	UnknownPeerID uint16 = 0
    32  
    33  	maxActiveIDs = math.MaxUint16
    34  )
    35  
    36  // Reactor handles mempool tx broadcasting amongst peers.
    37  // It maintains a map from peer ID to counter, to prevent gossiping txs to the
    38  // peers you received it from.
    39  type Reactor struct {
    40  	p2p.BaseReactor
    41  	config           *cfg.MempoolConfig
    42  	mempool          *CListMempool
    43  	ids              *mempoolIDs
    44  	nodeKey          *p2p.NodeKey
    45  	nodeKeyWhitelist map[string]struct{}
    46  	enableWtx        bool
    47  }
    48  
    49  func (memR *Reactor) SetNodeKey(key *p2p.NodeKey) {
    50  	memR.nodeKey = key
    51  }
    52  
    53  type mempoolIDs struct {
    54  	mtx       sync.RWMutex
    55  	peerMap   map[p2p.ID]uint16
    56  	nextID    uint16              // assumes that a node will never have over 65536 active peers
    57  	activeIDs map[uint16]struct{} // used to check if a given peerID key is used, the value doesn't matter
    58  }
    59  
    60  // Reserve searches for the next unused ID and assigns it to the
    61  // peer.
    62  func (ids *mempoolIDs) ReserveForPeer(peer p2p.Peer) {
    63  	ids.mtx.Lock()
    64  	defer ids.mtx.Unlock()
    65  
    66  	curID := ids.nextPeerID()
    67  	ids.peerMap[peer.ID()] = curID
    68  	ids.activeIDs[curID] = struct{}{}
    69  }
    70  
    71  // nextPeerID returns the next unused peer ID to use.
    72  // This assumes that ids's mutex is already locked.
    73  func (ids *mempoolIDs) nextPeerID() uint16 {
    74  	if len(ids.activeIDs) == maxActiveIDs {
    75  		panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", maxActiveIDs))
    76  	}
    77  
    78  	_, idExists := ids.activeIDs[ids.nextID]
    79  	for idExists {
    80  		ids.nextID++
    81  		_, idExists = ids.activeIDs[ids.nextID]
    82  	}
    83  	curID := ids.nextID
    84  	ids.nextID++
    85  	return curID
    86  }
    87  
    88  // Reclaim returns the ID reserved for the peer back to unused pool.
    89  func (ids *mempoolIDs) Reclaim(peer p2p.Peer) {
    90  	ids.mtx.Lock()
    91  	defer ids.mtx.Unlock()
    92  
    93  	removedID, ok := ids.peerMap[peer.ID()]
    94  	if ok {
    95  		delete(ids.activeIDs, removedID)
    96  		delete(ids.peerMap, peer.ID())
    97  	}
    98  }
    99  
   100  // GetForPeer returns an ID reserved for the peer.
   101  func (ids *mempoolIDs) GetForPeer(peer p2p.Peer) uint16 {
   102  	ids.mtx.RLock()
   103  	defer ids.mtx.RUnlock()
   104  
   105  	return ids.peerMap[peer.ID()]
   106  }
   107  
   108  func newMempoolIDs() *mempoolIDs {
   109  	return &mempoolIDs{
   110  		peerMap:   make(map[p2p.ID]uint16),
   111  		activeIDs: map[uint16]struct{}{0: {}},
   112  		nextID:    1, // reserve unknownPeerID(0) for mempoolReactor.BroadcastTx
   113  	}
   114  }
   115  
   116  // NewReactor returns a new Reactor with the given config and mempool.
   117  func NewReactor(config *cfg.MempoolConfig, mempool *CListMempool) *Reactor {
   118  	memR := &Reactor{
   119  		config:           config,
   120  		mempool:          mempool,
   121  		ids:              newMempoolIDs(),
   122  		nodeKeyWhitelist: make(map[string]struct{}),
   123  		enableWtx:        cfg.DynamicConfig.GetEnableWtx(),
   124  	}
   125  	for _, nodeKey := range config.GetNodeKeyWhitelist() {
   126  		memR.nodeKeyWhitelist[nodeKey] = struct{}{}
   127  	}
   128  	memR.BaseReactor = *p2p.NewBaseReactor("Mempool", memR)
   129  	memR.press()
   130  	return memR
   131  }
   132  
   133  // InitPeer implements Reactor by creating a state for the peer.
   134  func (memR *Reactor) InitPeer(peer p2p.Peer) p2p.Peer {
   135  	memR.ids.ReserveForPeer(peer)
   136  	return peer
   137  }
   138  
   139  // SetLogger sets the Logger on the reactor and the underlying mempool.
   140  func (memR *Reactor) SetLogger(l log.Logger) {
   141  	memR.Logger = l
   142  	memR.mempool.SetLogger(l)
   143  }
   144  
   145  // OnStart implements p2p.BaseReactor.
   146  func (memR *Reactor) OnStart() error {
   147  	if !memR.config.Broadcast {
   148  		memR.Logger.Info("Tx broadcasting is disabled")
   149  	}
   150  	return nil
   151  }
   152  
   153  // GetChannels implements Reactor.
   154  // It returns the list of channels for this reactor.
   155  func (memR *Reactor) GetChannels() []*p2p.ChannelDescriptor {
   156  	return []*p2p.ChannelDescriptor{
   157  		{
   158  			ID:       MempoolChannel,
   159  			Priority: 5,
   160  		},
   161  	}
   162  }
   163  
   164  // AddPeer implements Reactor.
   165  // It starts a broadcast routine ensuring all txs are forwarded to the given peer.
   166  func (memR *Reactor) AddPeer(peer p2p.Peer) {
   167  	go memR.broadcastTxRoutine(peer)
   168  }
   169  
   170  // RemovePeer implements Reactor.
   171  func (memR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) {
   172  	memR.ids.Reclaim(peer)
   173  	// broadcast routine checks if peer is gone and returns
   174  }
   175  
   176  // txMessageDecodePool is a sync.Pool of *TxMessage.
   177  // memR.decodeMsg will call txMessageDeocdePool.Get, and memR.Receive will reset the Msg after use, then call txMessageDeocdePool.Put.
   178  var txMessageDeocdePool = &sync.Pool{
   179  	New: func() interface{} {
   180  		return &TxMessage{}
   181  	},
   182  }
   183  
   184  var logParamsPool = &sync.Pool{
   185  	New: func() interface{} {
   186  		return &[6]interface{}{}
   187  	},
   188  }
   189  
   190  func (memR *Reactor) logReceive(peer p2p.Peer, chID byte, msg Message) {
   191  	logParams := logParamsPool.Get().(*[6]interface{})
   192  
   193  	logParams[0] = "src"
   194  	logParams[1] = peer
   195  	logParams[2] = "chId"
   196  	logParams[3] = chID
   197  	logParams[4] = "msg"
   198  	logParams[5] = msg
   199  
   200  	memR.Logger.Debug("Receive", logParams[:]...)
   201  
   202  	logParamsPool.Put(logParams)
   203  }
   204  
   205  var txIDStringerPool = &sync.Pool{
   206  	New: func() interface{} {
   207  		return &txIDStringer{}
   208  	},
   209  }
   210  
   211  func (memR *Reactor) logCheckTxError(tx []byte, height int64, err error) {
   212  	logParams := logParamsPool.Get().(*[6]interface{})
   213  	txStr := txIDStringerPool.Get().(*txIDStringer)
   214  	txStr.tx = tx
   215  	txStr.height = height
   216  
   217  	logParams[0] = "tx"
   218  	logParams[1] = txStr
   219  	logParams[2] = "err"
   220  	logParams[3] = err
   221  
   222  	memR.Logger.Info("Could not check tx", logParams[:4]...)
   223  
   224  	txIDStringerPool.Put(txStr)
   225  	logParamsPool.Put(logParams)
   226  }
   227  
   228  // Receive implements Reactor.
   229  // It adds any received transactions to the mempool.
   230  func (memR *Reactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) {
   231  	if memR.mempool.config.Sealed {
   232  		return
   233  	}
   234  	msg, err := memR.decodeMsg(msgBytes)
   235  	if err != nil {
   236  		memR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes)
   237  		memR.Switch.StopPeerForError(src, err)
   238  		return
   239  	}
   240  	memR.logReceive(src, chID, msg)
   241  
   242  	txInfo := TxInfo{SenderID: memR.ids.GetForPeer(src)}
   243  	if src != nil {
   244  		txInfo.SenderP2PID = src.ID()
   245  	}
   246  	var tx types.Tx
   247  
   248  	switch msg := msg.(type) {
   249  	case *TxMessage:
   250  		tx = msg.Tx
   251  		if _, isInWhiteList := memR.nodeKeyWhitelist[string(src.ID())]; isInWhiteList && msg.From != "" {
   252  			txInfo.from = msg.From
   253  		}
   254  		*msg = TxMessage{}
   255  		txMessageDeocdePool.Put(msg)
   256  	case *WtxMessage:
   257  		tx = msg.Wtx.Payload
   258  		if err := msg.Wtx.verify(memR.nodeKeyWhitelist); err != nil {
   259  			memR.Logger.Error("wtx.verify", "error", err, "txhash",
   260  				common.BytesToHash(types.Tx(msg.Wtx.Payload).Hash(memR.mempool.Height())),
   261  			)
   262  		} else {
   263  			txInfo.wtx = msg.Wtx
   264  			txInfo.checkType = abci.CheckTxType_WrappedCheck
   265  		}
   266  	case *WrapCMTxMessage:
   267  		tx = msg.Wtx.GetTx()
   268  		if _, isInWhiteList := memR.nodeKeyWhitelist[string(src.ID())]; isInWhiteList && msg.From != "" {
   269  			txInfo.from = msg.From
   270  		}
   271  		txInfo.wrapCMTx = msg.Wtx
   272  	default:
   273  		memR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
   274  		return
   275  	}
   276  
   277  	err = memR.mempool.CheckTx(tx, nil, txInfo)
   278  	if err != nil {
   279  		memR.logCheckTxError(tx, memR.mempool.height, err)
   280  	}
   281  }
   282  
   283  // PeerState describes the state of a peer.
   284  type PeerState interface {
   285  	GetHeight() int64
   286  }
   287  
   288  // Send new mempool txs to peer.
   289  func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) {
   290  	if !memR.config.Broadcast {
   291  		return
   292  	}
   293  	_, isInWhiteList := memR.nodeKeyWhitelist[string(peer.ID())]
   294  
   295  	peerID := memR.ids.GetForPeer(peer)
   296  	var next *clist.CElement
   297  	for {
   298  		// In case of both next.NextWaitChan() and peer.Quit() are variable at the same time
   299  		if !memR.IsRunning() || !peer.IsRunning() {
   300  			return
   301  		}
   302  		// This happens because the CElement we were looking at got garbage
   303  		// collected (removed). That is, .NextWait() returned nil. Go ahead and
   304  		// start from the beginning.
   305  		if next == nil {
   306  			select {
   307  			case <-memR.mempool.TxsWaitChan(): // Wait until a tx is available
   308  				if next = memR.mempool.BroadcastTxsFront(); next == nil {
   309  					continue
   310  				}
   311  			case <-peer.Quit():
   312  				return
   313  			case <-memR.Quit():
   314  				return
   315  			}
   316  		}
   317  
   318  		memTx := next.Value.(*mempoolTx)
   319  
   320  		// make sure the peer is up to date
   321  		peerState, ok := peer.Get(types.PeerStateKey).(PeerState)
   322  		if !ok {
   323  			// Peer does not have a state yet. We set it in the consensus reactor, but
   324  			// when we add peer in Switch, the order we call reactors#AddPeer is
   325  			// different every time due to us using a map. Sometimes other reactors
   326  			// will be initialized before the consensus reactor. We should wait a few
   327  			// milliseconds and retry.
   328  			time.Sleep(peerCatchupSleepIntervalMS * time.Millisecond)
   329  			continue
   330  		}
   331  		if peerState.GetHeight() < memTx.Height()-1 { // Allow for a lag of 1 block
   332  			time.Sleep(peerCatchupSleepIntervalMS * time.Millisecond)
   333  			continue
   334  		}
   335  
   336  		// ensure peer hasn't already sent us this tx
   337  		memTx.senderMtx.RLock()
   338  		_, ok = memTx.senders[peerID]
   339  		memTx.senderMtx.RUnlock()
   340  		if !ok {
   341  			var getFromPool bool
   342  			// send memTx
   343  			var msg Message
   344  			if memTx.nodeKey != nil && memTx.signature != nil {
   345  				msg = &WtxMessage{
   346  					Wtx: &WrappedTx{
   347  						Payload:   memTx.tx,
   348  						From:      memTx.from,
   349  						Signature: memTx.signature,
   350  						NodeKey:   memTx.nodeKey,
   351  					},
   352  				}
   353  			} else if memR.enableWtx {
   354  				if wtx, err := memR.wrapTx(memTx.tx, memTx.from); err == nil {
   355  					msg = &WtxMessage{
   356  						Wtx: wtx,
   357  					}
   358  				}
   359  			} else if memTx.isWrapCMTx {
   360  				wmsg := &WrapCMTxMessage{Wtx: &types.WrapCMTx{Tx: memTx.tx, Nonce: memTx.wrapCMNonce}}
   361  				if isInWhiteList {
   362  					wmsg.From = memTx.from
   363  				} else {
   364  					wmsg.From = ""
   365  				}
   366  				msg = wmsg
   367  			} else {
   368  				txMsg := txMessageDeocdePool.Get().(*TxMessage)
   369  				txMsg.Tx = memTx.tx
   370  				if isInWhiteList {
   371  					txMsg.From = memTx.from
   372  				} else {
   373  					txMsg.From = ""
   374  				}
   375  				msg = txMsg
   376  				getFromPool = true
   377  			}
   378  
   379  			msgBz := memR.encodeMsg(msg)
   380  			if getFromPool {
   381  				getFromPool = false
   382  				txMessageDeocdePool.Put(msg)
   383  			}
   384  
   385  			success := peer.Send(MempoolChannel, msgBz)
   386  			if !success {
   387  				time.Sleep(peerCatchupSleepIntervalMS * time.Millisecond)
   388  				continue
   389  			}
   390  		}
   391  
   392  		select {
   393  		case <-next.NextWaitChan():
   394  			// see the start of the for loop for nil check
   395  			next = next.Next()
   396  		case <-peer.Quit():
   397  			return
   398  		case <-memR.Quit():
   399  			return
   400  		}
   401  	}
   402  }
   403  
   404  //-----------------------------------------------------------------------------
   405  // Messages
   406  
   407  // Message is a message sent or received by the Reactor.
   408  type Message interface{}
   409  
   410  func RegisterMessages(cdc *amino.Codec) {
   411  	cdc.RegisterInterface((*Message)(nil), nil)
   412  	cdc.RegisterConcrete(&TxMessage{}, "tendermint/mempool/TxMessage", nil)
   413  	cdc.RegisterConcrete(&WtxMessage{}, "tendermint/mempool/WtxMessage", nil)
   414  	cdc.RegisterConcrete(&WrapCMTxMessage{}, "tendermint/mempool/WrapTxMessage", nil)
   415  
   416  	cdc.RegisterConcreteMarshaller("tendermint/mempool/TxMessage", func(codec *amino.Codec, i interface{}) ([]byte, error) {
   417  		txmp, ok := i.(*TxMessage)
   418  		if ok {
   419  			return txmp.MarshalToAmino(codec)
   420  		}
   421  		txm, ok := i.(TxMessage)
   422  		if ok {
   423  			return txm.MarshalToAmino(codec)
   424  		}
   425  		return nil, fmt.Errorf("%T is not a TxMessage", i)
   426  	})
   427  	cdc.RegisterConcreteUnmarshaller("tendermint/mempool/TxMessage", func(cdc *amino.Codec, bz []byte) (interface{}, int, error) {
   428  		m := &TxMessage{}
   429  		err := m.UnmarshalFromAmino(cdc, bz)
   430  		if err != nil {
   431  			return nil, 0, err
   432  		}
   433  		return m, len(bz), nil
   434  	})
   435  }
   436  
   437  // decodeMsg decodes the bz bytes into a Message,
   438  // if err is nil and Message is a TxMessage, you must put Message to txMessageDeocdePool after use.
   439  func (memR *Reactor) decodeMsg(bz []byte) (Message, error) {
   440  	maxMsgSize := calcMaxMsgSize(memR.config.MaxTxBytes)
   441  	l := len(bz)
   442  	if l > maxMsgSize {
   443  		return nil, ErrTxTooLarge{maxMsgSize, l}
   444  	}
   445  
   446  	tp := getTxMessageAminoTypePrefix()
   447  	if l >= len(tp) && bytes.Equal(bz[:len(tp)], tp) {
   448  		txmsg := txMessageDeocdePool.Get().(*TxMessage)
   449  		err := txmsg.UnmarshalFromAmino(cdc, bz[len(tp):])
   450  		if err == nil {
   451  			return txmsg, nil
   452  		}
   453  		txmsg.Tx = nil
   454  		txMessageDeocdePool.Put(txmsg)
   455  	}
   456  	var msg Message
   457  	err := cdc.UnmarshalBinaryBare(bz, &msg)
   458  	return msg, err
   459  }
   460  
   461  func (memR *Reactor) encodeMsg(msg Message) []byte {
   462  	var ok bool
   463  	var txmp *TxMessage
   464  	var txm TxMessage
   465  	if txmp, ok = msg.(*TxMessage); !ok {
   466  		txmp = nil
   467  		if txm, ok = msg.(TxMessage); ok {
   468  			txmp = &txm
   469  		}
   470  	}
   471  	if txmp != nil {
   472  		buf := &bytes.Buffer{}
   473  		tp := getTxMessageAminoTypePrefix()
   474  		buf.Grow(len(tp) + txmp.AminoSize(cdc))
   475  		// we manually assemble the encoded bytes for performance
   476  		buf.Write(tp)
   477  		err := txmp.MarshalAminoTo(cdc, buf)
   478  		if err == nil {
   479  			return buf.Bytes()
   480  		}
   481  	}
   482  	return cdc.MustMarshalBinaryBare(msg)
   483  }
   484  
   485  //-------------------------------------
   486  
   487  // TxMessage is a Message containing a transaction.
   488  type TxMessage struct {
   489  	Tx   types.Tx
   490  	From string
   491  }
   492  
   493  func (m TxMessage) AminoSize(_ *amino.Codec) int {
   494  	size := 0
   495  	if len(m.Tx) > 0 {
   496  		size += 1 + amino.ByteSliceSize(m.Tx)
   497  	}
   498  	if m.From != "" {
   499  		size += 1 + amino.EncodedStringSize(m.From)
   500  	}
   501  	return size
   502  }
   503  
   504  func (m TxMessage) MarshalToAmino(cdc *amino.Codec) ([]byte, error) {
   505  	buf := new(bytes.Buffer)
   506  	buf.Grow(m.AminoSize(cdc))
   507  	err := m.MarshalAminoTo(cdc, buf)
   508  	if err != nil {
   509  		return nil, err
   510  	}
   511  	return buf.Bytes(), nil
   512  }
   513  
   514  func (m TxMessage) MarshalAminoTo(_ *amino.Codec, buf *bytes.Buffer) error {
   515  	if len(m.Tx) != 0 {
   516  		const pbKey = byte(1<<3 | amino.Typ3_ByteLength)
   517  		err := amino.EncodeByteSliceWithKeyToBuffer(buf, m.Tx, pbKey)
   518  		if err != nil {
   519  			return err
   520  		}
   521  	}
   522  	if m.From != "" {
   523  		const pbKey = byte(2<<3 | amino.Typ3_ByteLength)
   524  		err := amino.EncodeStringWithKeyToBuffer(buf, m.From, pbKey)
   525  		if err != nil {
   526  			return err
   527  		}
   528  	}
   529  	return nil
   530  }
   531  
   532  func (m *TxMessage) UnmarshalFromAmino(_ *amino.Codec, data []byte) error {
   533  	const fieldCount = 2
   534  	var currentField int
   535  	var currentType amino.Typ3
   536  	var err error
   537  
   538  	for cur := 1; cur <= fieldCount; cur++ {
   539  		if len(data) != 0 && (currentField == 0 || currentField < cur) {
   540  			var nextField int
   541  			if nextField, currentType, err = amino.ParseProtoPosAndTypeMustOneByte(data[0]); err != nil {
   542  				return err
   543  			}
   544  			if nextField < currentField {
   545  				return fmt.Errorf("next field should greater than %d, got %d", currentField, nextField)
   546  			} else {
   547  				currentField = nextField
   548  			}
   549  		}
   550  		if len(data) == 0 || currentField != cur {
   551  			switch cur {
   552  			case 1:
   553  				m.Tx = nil
   554  			case 2:
   555  				m.From = ""
   556  			default:
   557  				return fmt.Errorf("unexpect feild num %d", cur)
   558  			}
   559  		} else {
   560  			pbk := data[0]
   561  			data = data[1:]
   562  			var subData []byte
   563  			if currentType == amino.Typ3_ByteLength {
   564  				if subData, err = amino.DecodeByteSliceWithoutCopy(&data); err != nil {
   565  					return err
   566  				}
   567  			}
   568  			switch pbk {
   569  			case 1<<3 | byte(amino.Typ3_ByteLength):
   570  				if len(subData) == 0 {
   571  					m.Tx = nil
   572  				} else {
   573  					m.Tx = make([]byte, len(subData))
   574  					copy(m.Tx, subData)
   575  				}
   576  			case 2<<3 | byte(amino.Typ3_ByteLength):
   577  				m.From = string(subData)
   578  			default:
   579  				return fmt.Errorf("unexpect pb key %d", pbk)
   580  			}
   581  		}
   582  	}
   583  	if len(data) != 0 {
   584  		return fmt.Errorf("unexpect data remain %X", data)
   585  	}
   586  	return nil
   587  }
   588  
   589  // String returns a string representation of the TxMessage.
   590  func (m *TxMessage) String() string {
   591  	return fmt.Sprintf("[TxMessage %v]", m.Tx)
   592  }
   593  
   594  // calcMaxMsgSize returns the max size of TxMessage
   595  // account for amino overhead of TxMessage
   596  func calcMaxMsgSize(maxTxSize int) int {
   597  	return maxTxSize + aminoOverheadForTxMessage
   598  }
   599  
   600  // WtxMessage is a Message containing a transaction.
   601  type WtxMessage struct {
   602  	Wtx *WrappedTx
   603  }
   604  
   605  // String returns a string representation of the WtxMessage.
   606  func (m *WtxMessage) String() string {
   607  	return fmt.Sprintf("[WtxMessage %v]", m.Wtx)
   608  }
   609  
   610  type WrappedTx struct {
   611  	Payload   []byte `json:"payload"`   // std tx or evm tx
   612  	From      string `json:"from"`      // from address of evm tx or ""
   613  	Signature []byte `json:"signature"` // signature for payload
   614  	NodeKey   []byte `json:"nodeKey"`   // pub key of the node who signs the tx
   615  }
   616  
   617  func (wtx *WrappedTx) GetPayload() []byte {
   618  	if wtx != nil {
   619  		return wtx.Payload
   620  	}
   621  	return nil
   622  }
   623  
   624  func (wtx *WrappedTx) GetSignature() []byte {
   625  	if wtx != nil {
   626  		return wtx.Signature
   627  	}
   628  	return nil
   629  }
   630  
   631  func (wtx *WrappedTx) GetNodeKey() []byte {
   632  	if wtx != nil {
   633  		return wtx.NodeKey
   634  	}
   635  	return nil
   636  }
   637  
   638  func (wtx *WrappedTx) GetFrom() string {
   639  	if wtx != nil {
   640  		return wtx.From
   641  	}
   642  	return ""
   643  }
   644  
   645  func (w *WrappedTx) verify(whitelist map[string]struct{}) error {
   646  	pub := p2p.BytesToPubKey(w.NodeKey)
   647  	if _, ok := whitelist[string(p2p.PubKeyToID(pub))]; !ok {
   648  		return fmt.Errorf("node key [%s] not in whitelist", p2p.PubKeyToID(pub))
   649  	}
   650  	if !pub.VerifyBytes(append(w.Payload, w.From...), w.Signature) {
   651  		return fmt.Errorf("invalid signature of wtx")
   652  	}
   653  	return nil
   654  }
   655  
   656  func (memR *Reactor) wrapTx(tx types.Tx, from string) (*WrappedTx, error) {
   657  	wtx := &WrappedTx{
   658  		Payload: tx,
   659  		From:    from,
   660  		NodeKey: memR.nodeKey.PubKey().Bytes(),
   661  	}
   662  	sig, err := memR.nodeKey.PrivKey.Sign(append(wtx.Payload, from...))
   663  	if err != nil {
   664  		return nil, err
   665  	}
   666  	wtx.Signature = sig
   667  	return wtx, nil
   668  }
   669  
   670  func GetRealTxFromWrapCMTx(data types.Tx) types.Tx {
   671  	wtx := &types.WrapCMTx{}
   672  	err := cdc.UnmarshalJSON(data, &wtx)
   673  	if err == nil {
   674  		return wtx.Tx
   675  	}
   676  	return data
   677  }
   678  
   679  type WrapCMTxMessage struct {
   680  	Wtx  *types.WrapCMTx `json:"wtx"`
   681  	From string          `json:"from"`
   682  }