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 }