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 }