github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/netsync/consensusmgr/handle.go (about)

     1  package consensusmgr
     2  
     3  import (
     4  	"encoding/hex"
     5  	"reflect"
     6  
     7  	"github.com/sirupsen/logrus"
     8  
     9  	"github.com/bytom/bytom/event"
    10  	"github.com/bytom/bytom/netsync/peers"
    11  	"github.com/bytom/bytom/p2p"
    12  	"github.com/bytom/bytom/p2p/security"
    13  	"github.com/bytom/bytom/protocol/bc"
    14  	"github.com/bytom/bytom/protocol/bc/types"
    15  	"github.com/bytom/bytom/protocol/casper"
    16  )
    17  
    18  // Switch is the interface for p2p switch.
    19  type Switch interface {
    20  	AddReactor(name string, reactor p2p.Reactor) p2p.Reactor
    21  }
    22  
    23  // Chain is the interface for Bytom core.
    24  type Chain interface {
    25  	BestBlockHeight() uint64
    26  	GetHeaderByHash(*bc.Hash) (*types.BlockHeader, error)
    27  	ProcessBlock(*types.Block) (bool, error)
    28  	ProcessBlockVerification(*casper.ValidCasperSignMsg) error
    29  }
    30  
    31  type Peers interface {
    32  	AddPeer(peer peers.BasePeer)
    33  	BroadcastMsg(bm peers.BroadcastMsg) error
    34  	GetPeer(id string) *peers.Peer
    35  	MarkBlock(peerID string, hash *bc.Hash)
    36  	MarkBlockVerification(peerID string, signature []byte)
    37  	ProcessIllegal(peerID string, level byte, reason string)
    38  	RemovePeer(peerID string)
    39  	SetStatus(peerID string, height uint64, hash *bc.Hash)
    40  }
    41  
    42  type blockMsg struct {
    43  	block  *types.Block
    44  	peerID string
    45  }
    46  
    47  // Manager is the consensus message network synchronization manager.
    48  type Manager struct {
    49  	sw              Switch
    50  	chain           Chain
    51  	peers           Peers
    52  	blockFetcher    *blockFetcher
    53  	eventDispatcher *event.Dispatcher
    54  
    55  	quit chan struct{}
    56  }
    57  
    58  // NewManager create new manager.
    59  func NewManager(sw Switch, chain Chain, peers Peers, dispatcher *event.Dispatcher) *Manager {
    60  	manager := &Manager{
    61  		sw:              sw,
    62  		chain:           chain,
    63  		peers:           peers,
    64  		blockFetcher:    newBlockFetcher(chain, peers),
    65  		eventDispatcher: dispatcher,
    66  		quit:            make(chan struct{}),
    67  	}
    68  	protocolReactor := NewConsensusReactor(manager)
    69  	manager.sw.AddReactor("CONSENSUS", protocolReactor)
    70  	return manager
    71  }
    72  
    73  func (m *Manager) addPeer(peer peers.BasePeer) {
    74  	m.peers.AddPeer(peer)
    75  }
    76  
    77  func (m *Manager) processMsg(peerID string, msgType byte, msg ConsensusMessage) {
    78  	peer := m.peers.GetPeer(peerID)
    79  	if peer == nil {
    80  		return
    81  	}
    82  
    83  	logrus.WithFields(logrus.Fields{"module": logModule, "peer": peer.Addr(), "type": reflect.TypeOf(msg), "message": msg.String()}).Debug("receive message from peer")
    84  
    85  	switch msg := msg.(type) {
    86  	case *BlockProposeMsg:
    87  		m.handleBlockProposeMsg(peerID, msg)
    88  
    89  	case *BlockVerificationMsg:
    90  		m.handleBlockVerificationMsg(peerID, msg)
    91  
    92  	default:
    93  		logrus.WithFields(logrus.Fields{"module": logModule, "peer": peerID, "message_type": reflect.TypeOf(msg)}).Error("unhandled message type")
    94  	}
    95  }
    96  
    97  func (m *Manager) handleBlockProposeMsg(peerID string, msg *BlockProposeMsg) {
    98  	block, err := msg.GetProposeBlock()
    99  	if err != nil {
   100  		logrus.WithFields(logrus.Fields{"module": logModule, "err": err}).Warning("failed on get propose block")
   101  		return
   102  	}
   103  
   104  	hash := block.Hash()
   105  	m.peers.MarkBlock(peerID, &hash)
   106  	m.blockFetcher.processNewBlock(&blockMsg{peerID: peerID, block: block})
   107  	m.peers.SetStatus(peerID, block.Height, &hash)
   108  }
   109  
   110  func (m *Manager) handleBlockVerificationMsg(peerID string, msg *BlockVerificationMsg) {
   111  	m.peers.MarkBlockVerification(peerID, msg.Signature)
   112  	if err := m.chain.ProcessBlockVerification(&casper.ValidCasperSignMsg{
   113  		SourceHash: msg.SourceHash,
   114  		TargetHash: msg.TargetHash,
   115  		Signature:  msg.Signature,
   116  		PubKey:     hex.EncodeToString(msg.PubKey),
   117  	}); err != nil {
   118  		m.peers.ProcessIllegal(peerID, security.LevelMsgIllegal, err.Error())
   119  	}
   120  }
   121  
   122  func (m *Manager) blockProposeMsgBroadcastLoop() {
   123  	m.msgBroadcastLoop(event.NewProposedBlockEvent{}, func(data interface{}) (ConsensusMessage, error) {
   124  		ev := data.(event.NewProposedBlockEvent)
   125  		return NewBlockProposeMsg(&ev.Block)
   126  	})
   127  }
   128  
   129  func (m *Manager) blockVerificationMsgBroadcastLoop() {
   130  	m.msgBroadcastLoop(casper.ValidCasperSignMsg{}, func(data interface{}) (ConsensusMessage, error) {
   131  		v := data.(casper.ValidCasperSignMsg)
   132  		pubKey, err := hex.DecodeString(v.PubKey)
   133  		if err != nil {
   134  			return nil, err
   135  		}
   136  
   137  		return NewBlockVerificationMsg(v.SourceHash, v.TargetHash, pubKey, v.Signature), nil
   138  	})
   139  }
   140  
   141  func (m *Manager) msgBroadcastLoop(msgType interface{}, newMsg func(event interface{}) (ConsensusMessage, error)) {
   142  	subscribeType := reflect.TypeOf(msgType)
   143  	msgSub, err := m.eventDispatcher.Subscribe(msgType)
   144  	if err != nil {
   145  		logrus.WithFields(logrus.Fields{"module": logModule, "err": err}).Errorf("failed on subscribe %s", subscribeType)
   146  		return
   147  	}
   148  	defer msgSub.Unsubscribe()
   149  	for {
   150  		select {
   151  		case obj, ok := <-msgSub.Chan():
   152  			if !ok {
   153  				logrus.WithFields(logrus.Fields{"module": logModule}).Warningf("%sSub channel closed", subscribeType)
   154  				return
   155  			}
   156  
   157  			if reflect.TypeOf(obj.Data) != subscribeType {
   158  				logrus.WithFields(logrus.Fields{"module": logModule}).Error("event type error")
   159  				continue
   160  			}
   161  
   162  			msg, err := newMsg(obj.Data)
   163  			if err != nil {
   164  				logrus.WithFields(logrus.Fields{"module": logModule, "err": err}).Errorf("failed on create %s message", subscribeType)
   165  				return
   166  			}
   167  
   168  			message := NewBroadcastMsg(msg, consensusChannel)
   169  			if err := m.peers.BroadcastMsg(message); err != nil {
   170  				logrus.WithFields(logrus.Fields{"module": logModule, "err": err}).Errorf("failed on broadcast %s message.", subscribeType)
   171  				continue
   172  			}
   173  
   174  		case <-m.quit:
   175  			return
   176  		}
   177  	}
   178  }
   179  
   180  func (m *Manager) removePeer(peerID string) {
   181  	m.peers.RemovePeer(peerID)
   182  }
   183  
   184  // Start consensus manager service.
   185  func (m *Manager) Start() error {
   186  	go m.blockFetcher.blockProcessorLoop()
   187  	go m.blockProposeMsgBroadcastLoop()
   188  	go m.blockVerificationMsgBroadcastLoop()
   189  	return nil
   190  }
   191  
   192  // Stop consensus manager service.
   193  func (m *Manager) Stop() {
   194  	close(m.quit)
   195  }