mirror of https://github.com/poanetwork/gecko.git
274 lines
7.9 KiB
Go
274 lines
7.9 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package router
|
|
|
|
import (
|
|
"github.com/ava-labs/gecko/ids"
|
|
"github.com/ava-labs/gecko/snow"
|
|
"github.com/ava-labs/gecko/snow/engine/common"
|
|
)
|
|
|
|
// Handler passes incoming messages from the network to the consensus engine
|
|
// (Actually, it receives the incoming messages from a ChainRouter, but same difference)
|
|
type Handler struct {
|
|
msgs chan message
|
|
closed chan struct{}
|
|
engine common.Engine
|
|
msgChan <-chan common.Message
|
|
|
|
toClose func()
|
|
}
|
|
|
|
// Initialize this consensus handler
|
|
func (h *Handler) Initialize(engine common.Engine, msgChan <-chan common.Message, bufferSize int) {
|
|
h.msgs = make(chan message, bufferSize)
|
|
h.closed = make(chan struct{})
|
|
h.engine = engine
|
|
h.msgChan = msgChan
|
|
}
|
|
|
|
// Context of this Handler
|
|
func (h *Handler) Context() *snow.Context { return h.engine.Context() }
|
|
|
|
// Dispatch waits for incoming messages from the network
|
|
// and, when they arrive, sends them to the consensus engine
|
|
func (h *Handler) Dispatch() {
|
|
log := h.Context().Log
|
|
defer func() {
|
|
log.Info("finished shutting down chain")
|
|
close(h.closed)
|
|
}()
|
|
|
|
closing := false
|
|
for {
|
|
select {
|
|
case msg, ok := <-h.msgs:
|
|
if !ok {
|
|
return
|
|
}
|
|
if closing {
|
|
log.Debug("dropping message due to closing:\n%s", msg)
|
|
continue
|
|
}
|
|
if h.dispatchMsg(msg) {
|
|
closing = true
|
|
}
|
|
case msg := <-h.msgChan:
|
|
if closing {
|
|
log.Debug("dropping internal message due to closing:\n%s", msg)
|
|
continue
|
|
}
|
|
if h.dispatchMsg(message{messageType: notifyMsg, notification: msg}) {
|
|
closing = true
|
|
}
|
|
}
|
|
if closing && h.toClose != nil {
|
|
go h.toClose()
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dispatch a message to the consensus engine.
|
|
// Returns true iff this consensus handler (and its associated engine) should shutdown
|
|
// (due to receipt of a shutdown message)
|
|
func (h *Handler) dispatchMsg(msg message) bool {
|
|
ctx := h.engine.Context()
|
|
|
|
ctx.Lock.Lock()
|
|
defer ctx.Lock.Unlock()
|
|
|
|
ctx.Log.Verbo("Forwarding message to consensus: %s", msg)
|
|
var (
|
|
err error
|
|
done bool
|
|
)
|
|
switch msg.messageType {
|
|
case getAcceptedFrontierMsg:
|
|
err = h.engine.GetAcceptedFrontier(msg.validatorID, msg.requestID)
|
|
case acceptedFrontierMsg:
|
|
err = h.engine.AcceptedFrontier(msg.validatorID, msg.requestID, msg.containerIDs)
|
|
case getAcceptedFrontierFailedMsg:
|
|
err = h.engine.GetAcceptedFrontierFailed(msg.validatorID, msg.requestID)
|
|
case getAcceptedMsg:
|
|
err = h.engine.GetAccepted(msg.validatorID, msg.requestID, msg.containerIDs)
|
|
case acceptedMsg:
|
|
err = h.engine.Accepted(msg.validatorID, msg.requestID, msg.containerIDs)
|
|
case getAcceptedFailedMsg:
|
|
err = h.engine.GetAcceptedFailed(msg.validatorID, msg.requestID)
|
|
case getMsg:
|
|
err = h.engine.Get(msg.validatorID, msg.requestID, msg.containerID)
|
|
case getFailedMsg:
|
|
err = h.engine.GetFailed(msg.validatorID, msg.requestID)
|
|
case putMsg:
|
|
err = h.engine.Put(msg.validatorID, msg.requestID, msg.containerID, msg.container)
|
|
case pushQueryMsg:
|
|
err = h.engine.PushQuery(msg.validatorID, msg.requestID, msg.containerID, msg.container)
|
|
case pullQueryMsg:
|
|
err = h.engine.PullQuery(msg.validatorID, msg.requestID, msg.containerID)
|
|
case queryFailedMsg:
|
|
err = h.engine.QueryFailed(msg.validatorID, msg.requestID)
|
|
case chitsMsg:
|
|
err = h.engine.Chits(msg.validatorID, msg.requestID, msg.containerIDs)
|
|
case notifyMsg:
|
|
err = h.engine.Notify(msg.notification)
|
|
case gossipMsg:
|
|
err = h.engine.Gossip()
|
|
case shutdownMsg:
|
|
err = h.engine.Shutdown()
|
|
done = true
|
|
}
|
|
|
|
if err != nil {
|
|
ctx.Log.Fatal("forcing chain to shutdown due to %s", err)
|
|
}
|
|
return done || err != nil
|
|
}
|
|
|
|
// GetAcceptedFrontier passes a GetAcceptedFrontier message received from the
|
|
// network to the consensus engine.
|
|
func (h *Handler) GetAcceptedFrontier(validatorID ids.ShortID, requestID uint32) {
|
|
h.msgs <- message{
|
|
messageType: getAcceptedFrontierMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
}
|
|
}
|
|
|
|
// AcceptedFrontier passes a AcceptedFrontier message received from the network
|
|
// to the consensus engine.
|
|
func (h *Handler) AcceptedFrontier(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) {
|
|
h.msgs <- message{
|
|
messageType: acceptedFrontierMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerIDs: containerIDs,
|
|
}
|
|
}
|
|
|
|
// GetAcceptedFrontierFailed passes a GetAcceptedFrontierFailed message received
|
|
// from the network to the consensus engine.
|
|
func (h *Handler) GetAcceptedFrontierFailed(validatorID ids.ShortID, requestID uint32) {
|
|
h.msgs <- message{
|
|
messageType: getAcceptedFrontierFailedMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
}
|
|
}
|
|
|
|
// GetAccepted passes a GetAccepted message received from the
|
|
// network to the consensus engine.
|
|
func (h *Handler) GetAccepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) {
|
|
h.msgs <- message{
|
|
messageType: getAcceptedMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerIDs: containerIDs,
|
|
}
|
|
}
|
|
|
|
// Accepted passes a Accepted message received from the network to the consensus
|
|
// engine.
|
|
func (h *Handler) Accepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) {
|
|
h.msgs <- message{
|
|
messageType: acceptedMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerIDs: containerIDs,
|
|
}
|
|
}
|
|
|
|
// GetAcceptedFailed passes a GetAcceptedFailed message received from the
|
|
// network to the consensus engine.
|
|
func (h *Handler) GetAcceptedFailed(validatorID ids.ShortID, requestID uint32) {
|
|
h.msgs <- message{
|
|
messageType: getAcceptedFailedMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
}
|
|
}
|
|
|
|
// Get passes a Get message received from the network to the consensus engine.
|
|
func (h *Handler) Get(validatorID ids.ShortID, requestID uint32, containerID ids.ID) {
|
|
h.msgs <- message{
|
|
messageType: getMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerID: containerID,
|
|
}
|
|
}
|
|
|
|
// Put passes a Put message received from the network to the consensus engine.
|
|
func (h *Handler) Put(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) {
|
|
h.msgs <- message{
|
|
messageType: putMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerID: containerID,
|
|
container: container,
|
|
}
|
|
}
|
|
|
|
// GetFailed passes a GetFailed message to the consensus engine.
|
|
func (h *Handler) GetFailed(validatorID ids.ShortID, requestID uint32) {
|
|
h.msgs <- message{
|
|
messageType: getFailedMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
}
|
|
}
|
|
|
|
// PushQuery passes a PushQuery message received from the network to the consensus engine.
|
|
func (h *Handler) PushQuery(validatorID ids.ShortID, requestID uint32, blockID ids.ID, block []byte) {
|
|
h.msgs <- message{
|
|
messageType: pushQueryMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerID: blockID,
|
|
container: block,
|
|
}
|
|
}
|
|
|
|
// PullQuery passes a PullQuery message received from the network to the consensus engine.
|
|
func (h *Handler) PullQuery(validatorID ids.ShortID, requestID uint32, blockID ids.ID) {
|
|
h.msgs <- message{
|
|
messageType: pullQueryMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerID: blockID,
|
|
}
|
|
}
|
|
|
|
// Chits passes a Chits message received from the network to the consensus engine.
|
|
func (h *Handler) Chits(validatorID ids.ShortID, requestID uint32, votes ids.Set) {
|
|
h.msgs <- message{
|
|
messageType: chitsMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
containerIDs: votes,
|
|
}
|
|
}
|
|
|
|
// QueryFailed passes a QueryFailed message received from the network to the consensus engine.
|
|
func (h *Handler) QueryFailed(validatorID ids.ShortID, requestID uint32) {
|
|
h.msgs <- message{
|
|
messageType: queryFailedMsg,
|
|
validatorID: validatorID,
|
|
requestID: requestID,
|
|
}
|
|
}
|
|
|
|
// Gossip passes a gossip request to the consensus engine
|
|
func (h *Handler) Gossip() { h.msgs <- message{messageType: gossipMsg} }
|
|
|
|
// Shutdown shuts down the dispatcher
|
|
func (h *Handler) Shutdown() { h.msgs <- message{messageType: shutdownMsg} }
|
|
|
|
// Notify ...
|
|
func (h *Handler) Notify(msg common.Message) {
|
|
h.msgs <- message{
|
|
messageType: notifyMsg,
|
|
notification: msg,
|
|
}
|
|
}
|