github.com/annchain/OG@v0.0.9/consensus/annsensus/annsensus_processor.go (about)

     1  package annsensus
     2  
     3  import (
     4  	"errors"
     5  	"github.com/annchain/OG/common/crypto"
     6  	"github.com/annchain/OG/consensus/bft"
     7  	"github.com/annchain/OG/consensus/dkg"
     8  	"github.com/sirupsen/logrus"
     9  	"sync"
    10  )
    11  
    12  // AnnsensusPartner integrates dkg, bft and term change with vrf.
    13  type AnnsensusPartner struct {
    14  	Config                   AnnsensusProcessorConfig
    15  	BftAdapter               BftMessageAdapter // message handlers in common. Injected into commuinicator
    16  	DkgAdapter               DkgMessageAdapter // message handlers in common. Injected into commuinicator
    17  	TermProvider             TermIdProvider
    18  	TermHolder               HistoricalTermsHolder // hold information for each term
    19  	BftPartnerProvider       BftPartnerProvider    // factory method to generate a bft partner for each term
    20  	DkgPartnerProvider       DkgPartnerProvider    // factory method to generate a dkg partner for each term
    21  	ConsensusContextProvider ConsensusContextProvider
    22  	PeerOutgoing             AnnsensusPeerCommunicatorOutgoing
    23  	PeerIncoming             AnnsensusPeerCommunicatorIncoming
    24  
    25  	quit   chan bool
    26  	quitWg sync.WaitGroup
    27  }
    28  
    29  func (a *AnnsensusPartner) InitDefault() {
    30  	a.quitWg = sync.WaitGroup{}
    31  	a.quit = make(chan bool)
    32  }
    33  
    34  type AnnsensusProcessorConfig struct {
    35  	DisableTermChange  bool
    36  	DisabledConsensus  bool
    37  	TermChangeInterval int
    38  	GenesisAccounts    crypto.PublicKeys
    39  	//PartnerNum         int
    40  }
    41  
    42  func checkConfig(config AnnsensusProcessorConfig) {
    43  	if config.DisabledConsensus {
    44  		config.DisableTermChange = true
    45  	}
    46  	if !config.DisabledConsensus {
    47  		if config.TermChangeInterval <= 0 && !config.DisableTermChange {
    48  			panic("require termChangeInterval")
    49  		}
    50  		//if len(config.GenesisAccounts) < config.PartnerNum && !config.DisableTermChange {
    51  		//	panic("need more account")
    52  		//}
    53  		//if config.PartnerNum < 2 {
    54  		//	panic(fmt.Sprintf("BFT needs at least 2 nodes, currently %d", config.PartnerNum))
    55  		//}
    56  	}
    57  }
    58  
    59  //func NewAnnsensusPartner(Config AnnsensusProcessorConfig,
    60  //	signatureProvider account.SignatureProvider,
    61  //	TermProvider TermIdProvider,
    62  //	annsensusCommunicator *AnnsensusPeerCommunicator,
    63  //) *AnnsensusPartner {
    64  //	// Prepare common facilities that will be reused during each term
    65  //	// Prepare adapters
    66  //	BftAdapter := NewTrustfulBftAdapter(signatureProvider, TermProvider)
    67  //	DkgAdapter := NewTrustfulDkgAdapter()
    68  //	TermHolder := NewAnnsensusTermHolder(TermProvider)
    69  //
    70  //	// Prepare process itself.
    71  //	ap := &AnnsensusPartner{
    72  //		Config:                Config,
    73  //		BftAdapter:            BftAdapter,
    74  //		DkgAdapter:            DkgAdapter,
    75  //		annsensusCommunicator: annsensusCommunicator,
    76  //		TermHolder:            TermHolder,
    77  //	}
    78  //	return ap
    79  //}
    80  
    81  // Start makes AnnsensusPartner receive and handle consensus messages.
    82  func (ap *AnnsensusPartner) Start() {
    83  	if ap.quit == nil {
    84  		panic("not initialized.")
    85  	}
    86  	if ap.Config.DisabledConsensus {
    87  		log.Warn("annsensus disabled")
    88  		return
    89  	}
    90  	// start the receiver
    91  	go ap.loop()
    92  	log.Info("AnnSensus Started")
    93  }
    94  
    95  // buildTerm collects information from the info provider, to start a new term
    96  //func (ap *AnnsensusPartner) buildTerm(termId uint32) *term.Term {
    97  //	//TODO
    98  //	t := term.Term{
    99  //		Id:                0,
   100  //		PartsNum:          ap.Config.PartnerNum,
   101  //		Threshold:         ap.Config.PartnerNum*2/3 + 1,
   102  //		Senators:          nil,
   103  //		AllPartPublicKeys: nil,
   104  //		PublicKey:         nil,
   105  //		ActivateHeight:    0,
   106  //		Suite:             nil,
   107  //	}
   108  //	return t
   109  //}
   110  
   111  func (ap *AnnsensusPartner) StartNewTerm(context ConsensusContext) error { // build a new Term
   112  	// may need lots of information to build this term
   113  	//newTerm := ap.buildTerm(termId)
   114  
   115  	//build a reliable bft, dkg and term
   116  	//bftComm := communicator.NewTrustfulPeerCommunicator(ap.signatureProvider, ap.TermProvider, ap.p2pSender)
   117  
   118  	// check if the term is already there
   119  	if _, ok := ap.TermHolder.GetTermById(context.GetTerm().Id); ok {
   120  		return errors.New("term already there")
   121  	}
   122  
   123  	logrus.WithField("context", context).Debug("starting new term")
   124  	// the bft instance for this term
   125  	bftPartner := ap.BftPartnerProvider.GetBftPartnerInstance(context)
   126  	// the dkg instance for this term to generate next term
   127  	dkgPartner, err := ap.DkgPartnerProvider.GetDkgPartnerInstance(context)
   128  	if err != nil {
   129  		return err
   130  	}
   131  
   132  	tc := NewTermCollection(context, bftPartner, dkgPartner)
   133  	ap.TermHolder.SetTerm(context.GetTerm().Id, tc)
   134  	// start to generate proposals, vote and generate sequencers
   135  	go bftPartner.Start()
   136  	bftPartner.StartNewEra(context.GetTerm().ActivateHeight, 0)
   137  	// start to discuss next committee
   138  	go dkgPartner.Start()
   139  	return nil
   140  }
   141  
   142  func (ap *AnnsensusPartner) Stop() {
   143  	ap.quit <- true
   144  	ap.quitWg.Wait()
   145  	logrus.Debug("AnnsensusPartner stopped")
   146  }
   147  
   148  func (ap *AnnsensusPartner) loop() {
   149  	for {
   150  		select {
   151  		case <-ap.quit:
   152  			ap.quitWg.Done()
   153  			logrus.Debug("AnnsensusPartner quit")
   154  			return
   155  		case context := <-ap.TermProvider.GetTermChangeEventChannel():
   156  			// new term is coming.
   157  			// it is coming because of either:
   158  			// 1, someone told you that you are keeping up-to-date with latest seq
   159  			// 2, (just for debugging) bootstrap
   160  			// Note that in real case, bootstrap will not trigger a direct term change event
   161  			// Since there must be a communication first to get the latest seq.
   162  			err := ap.StartNewTerm(context)
   163  			if err != nil {
   164  				logrus.WithError(err).WithField("context", context).Error("failed to start a new term")
   165  			}
   166  		case msgEvent := <-ap.PeerIncoming.GetPipeOut():
   167  			ap.HandleAnnsensusMessage(msgEvent)
   168  		}
   169  	}
   170  }
   171  
   172  // HandleConsensusMessage is a sub-router for routing consensus message to either bft,dkg or term.
   173  // As part of Annsensus, bft,dkg and term may not be regarded as a separate component of OG.
   174  // Annsensus itself is also a plugin of OG supporting consensus messages.
   175  // Do not block the pipe for any message processing. Router should not be blocked. Use channel.
   176  func (ap *AnnsensusPartner) HandleAnnsensusMessage(msgEvent *AnnsensusMessageEvent) {
   177  	annsensusMessage := msgEvent.Message
   178  	peer := msgEvent.Peer
   179  
   180  	switch annsensusMessage.GetType() {
   181  	case AnnsensusMessageTypeBftPlain:
   182  		// let adapter handle plain and signed
   183  		fallthrough
   184  	case AnnsensusMessageTypeBftSigned:
   185  		bftMessage, err := ap.BftAdapter.AdaptAnnsensusMessage(annsensusMessage)
   186  		if err != nil {
   187  			logrus.WithError(err).WithField("msg", annsensusMessage).
   188  				Error("error adapting annsensus to bft msg")
   189  			return
   190  		}
   191  		bftPeer, err := ap.BftAdapter.AdaptAnnsensusPeer(peer)
   192  		if err != nil {
   193  			logrus.WithError(err).WithField("peer", peer).
   194  				Error("error adapting annsensus to bft peer")
   195  			return
   196  		}
   197  		// judge height
   198  		msgTerm, ok := ap.TermHolder.GetTermByHeight(bftMessage)
   199  		if !ok {
   200  			logrus.WithError(err).WithField("msg", bftMessage).
   201  				Error("error finding or building msgTerm")
   202  			return
   203  		}
   204  		// route to correspondant BFTPartner
   205  		msgTerm.BftPartner.GetBftPeerCommunicatorIncoming().GetPipeIn() <- &bft.BftMessageEvent{
   206  			Message: bftMessage,
   207  			Peer:    bftPeer,
   208  		}
   209  
   210  	case AnnsensusMessageTypeDkgPlain:
   211  		fallthrough
   212  	case AnnsensusMessageTypeDkgSigned:
   213  		dkgMessage, err := ap.DkgAdapter.AdaptAnnsensusMessage(annsensusMessage)
   214  		if err != nil {
   215  			logrus.WithError(err).WithField("msg", annsensusMessage).
   216  				Error("error adapting annsensus to dkg msg")
   217  			return
   218  		}
   219  		dkgPeer, err := ap.DkgAdapter.AdaptAnnsensusPeer(peer)
   220  		if err != nil {
   221  			logrus.WithError(err).WithField("peer", peer).
   222  				Error("error adapting annsensus to dkg peer")
   223  			return
   224  		}
   225  		msgTerm, ok := ap.TermHolder.GetTermByHeight(dkgMessage)
   226  		if !ok {
   227  			logrus.WithError(err).WithField("msg", dkgMessage).
   228  				Error("error finding msgTerm")
   229  			return
   230  		}
   231  		msgTerm.DkgPartner.GetDkgPeerCommunicatorIncoming().GetPipeIn() <- &dkg.DkgMessageEvent{
   232  			Message: dkgMessage,
   233  			Peer:    dkgPeer,
   234  		}
   235  
   236  	case AnnsensusMessageTypeBftEncrypted:
   237  		// decrypt first and then send to handler
   238  	case AnnsensusMessageTypeDkgEncrypted:
   239  		// decrypt first and then send to handler
   240  	default:
   241  		logrus.WithField("msg", annsensusMessage).WithField("IM", ap.TermHolder.DebugMyId()).Warn("unsupported annsensus message type")
   242  	}
   243  	return
   244  }