|
|
- package mempool
-
- import (
- "bytes"
- "fmt"
- "reflect"
-
- . "github.com/tendermint/tendermint/common"
- "github.com/tendermint/tendermint/events"
- "github.com/tendermint/tendermint/p2p"
- "github.com/tendermint/tendermint/types"
- "github.com/tendermint/tendermint/wire"
- )
-
- var (
- MempoolChannel = byte(0x30)
- )
-
- // MempoolReactor handles mempool tx broadcasting amongst peers.
- type MempoolReactor struct {
- p2p.BaseReactor
-
- sw *p2p.Switch
- Mempool *Mempool
-
- evsw events.Fireable
- }
-
- func NewMempoolReactor(mempool *Mempool) *MempoolReactor {
- memR := &MempoolReactor{
- Mempool: mempool,
- }
- memR.BaseReactor = *p2p.NewBaseReactor(log, "MempoolReactor", memR)
- return memR
- }
-
- // Implements Reactor
- func (memR *MempoolReactor) GetChannels() []*p2p.ChannelDescriptor {
- return []*p2p.ChannelDescriptor{
- &p2p.ChannelDescriptor{
- ID: MempoolChannel,
- Priority: 5,
- },
- }
- }
-
- // Implements Reactor
- func (pexR *MempoolReactor) AddPeer(peer *p2p.Peer) {
- }
-
- // Implements Reactor
- func (pexR *MempoolReactor) RemovePeer(peer *p2p.Peer, reason interface{}) {
- }
-
- // Implements Reactor
- func (memR *MempoolReactor) Receive(chID byte, src *p2p.Peer, msgBytes []byte) {
- _, msg, err := DecodeMessage(msgBytes)
- if err != nil {
- log.Warn("Error decoding message", "error", err)
- return
- }
- log.Notice("MempoolReactor received message", "msg", msg)
-
- switch msg := msg.(type) {
- case *TxMessage:
- err := memR.Mempool.AddTx(msg.Tx)
- if err != nil {
- // Bad, seen, or conflicting tx.
- log.Info("Could not add tx", "tx", msg.Tx)
- return
- } else {
- log.Info("Added valid tx", "tx", msg.Tx)
- }
- // Share tx.
- // We use a simple shotgun approach for now.
- // TODO: improve efficiency
- for _, peer := range memR.Switch.Peers().List() {
- if peer.Key == src.Key {
- continue
- }
- peer.TrySend(MempoolChannel, msg)
- }
-
- default:
- log.Warn(Fmt("Unknown message type %v", reflect.TypeOf(msg)))
- }
- }
-
- func (memR *MempoolReactor) BroadcastTx(tx types.Tx) error {
- err := memR.Mempool.AddTx(tx)
- if err != nil {
- return err
- }
- msg := &TxMessage{Tx: tx}
- memR.Switch.Broadcast(MempoolChannel, msg)
- return nil
- }
-
- // implements events.Eventable
- func (memR *MempoolReactor) SetFireable(evsw events.Fireable) {
- memR.evsw = evsw
- }
-
- //-----------------------------------------------------------------------------
- // Messages
-
- const (
- msgTypeTx = byte(0x01)
- )
-
- type MempoolMessage interface{}
-
- var _ = wire.RegisterInterface(
- struct{ MempoolMessage }{},
- wire.ConcreteType{&TxMessage{}, msgTypeTx},
- )
-
- func DecodeMessage(bz []byte) (msgType byte, msg MempoolMessage, err error) {
- msgType = bz[0]
- n := new(int64)
- r := bytes.NewReader(bz)
- msg = wire.ReadBinary(struct{ MempoolMessage }{}, r, n, &err).(struct{ MempoolMessage }).MempoolMessage
- return
- }
-
- //-------------------------------------
-
- type TxMessage struct {
- Tx types.Tx
- }
-
- func (m *TxMessage) String() string {
- return fmt.Sprintf("[TxMessage %v]", m.Tx)
- }
|