github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/core/roundstate.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "bytes" 21 "errors" 22 "io" 23 "math/big" 24 "sync" 25 26 "github.com/ethereum/go-ethereum/consensus/istanbul/validator" 27 "github.com/ethereum/go-ethereum/log" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/consensus/istanbul" 31 "github.com/ethereum/go-ethereum/rlp" 32 ) 33 34 var ( 35 // errFailedCreatePreparedCertificate is returned when there aren't enough PREPARE messages to create a PREPARED certificate. 36 errFailedCreatePreparedCertificate = errors.New("failed to create PREPARED certficate") 37 ) 38 39 type RoundState interface { 40 // mutation functions 41 StartNewRound(nextRound *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator) error 42 StartNewSequence(nextSequence *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator, parentCommits MessageSet) error 43 TransitionToPreprepared(preprepare *istanbul.Preprepare) error 44 TransitionToWaitingForNewRound(r *big.Int, nextProposer istanbul.Validator) error 45 TransitionToCommitted() error 46 TransitionToPrepared(quorumSize int) error 47 AddCommit(msg *istanbul.Message) error 48 AddPrepare(msg *istanbul.Message) error 49 AddParentCommit(msg *istanbul.Message) error 50 SetPendingRequest(pendingRequest *istanbul.Request) error 51 SetProposalVerificationStatus(proposalHash common.Hash, verificationStatus error) 52 53 // view functions 54 DesiredRound() *big.Int 55 State() State 56 GetPrepareOrCommitSize() int 57 GetValidatorByAddress(address common.Address) istanbul.Validator 58 ValidatorSet() istanbul.ValidatorSet 59 Proposer() istanbul.Validator 60 IsProposer(address common.Address) bool 61 Subject() *istanbul.Subject 62 Preprepare() *istanbul.Preprepare 63 Proposal() istanbul.Proposal 64 Round() *big.Int 65 Commits() MessageSet 66 Prepares() MessageSet 67 ParentCommits() MessageSet 68 PendingRequest() *istanbul.Request 69 Sequence() *big.Int 70 View() *istanbul.View 71 PreparedCertificate() istanbul.PreparedCertificate 72 GetProposalVerificationStatus(proposalHash common.Hash) (verificationStatus error, isCached bool) 73 Summary() *RoundStateSummary 74 } 75 76 // RoundState stores the consensus state 77 type roundStateImpl struct { 78 state State 79 round *big.Int 80 desiredRound *big.Int 81 sequence *big.Int 82 83 // data for current round 84 preprepare *istanbul.Preprepare 85 prepares MessageSet 86 commits MessageSet 87 proposer istanbul.Validator 88 89 // data saves across rounds, same sequence 90 validatorSet istanbul.ValidatorSet 91 parentCommits MessageSet 92 pendingRequest *istanbul.Request 93 preparedCertificate istanbul.PreparedCertificate 94 95 // Verification status for proposals seen in this view 96 // Note that this field will not get RLP enoded and persisted, since it contains an error type, 97 // which doesn't have a native RLP encoding. Also, this is a cache, so it's not necessary for it 98 // to be persisted. 99 proposalVerificationStatus map[common.Hash]error 100 101 mu *sync.RWMutex 102 logger log.Logger 103 } 104 105 type RoundStateSummary struct { 106 State string `json:"state"` 107 Sequence *big.Int `json:"sequence"` 108 Round *big.Int `json:"round"` 109 DesiredRound *big.Int `json:"desiredRound"` 110 PendingRequestHash *common.Hash `json:"pendingRequestHash"` 111 112 ValidatorSet []common.Address `json:"validatorSet"` 113 Proposer common.Address `json:"proposer"` 114 115 Prepares []common.Address `json:"prepares"` 116 Commits []common.Address `json:"commits"` 117 ParentCommits []common.Address `json:"parentCommits"` 118 119 Preprepare *istanbul.PreprepareSummary `json:"preprepare"` 120 PreparedCertificate *istanbul.PreparedCertificateSummary `json:"preparedCertificate"` 121 } 122 123 func newRoundState(view *istanbul.View, validatorSet istanbul.ValidatorSet, proposer istanbul.Validator) RoundState { 124 return &roundStateImpl{ 125 state: StateAcceptRequest, 126 round: view.Round, 127 desiredRound: view.Round, 128 sequence: view.Sequence, 129 130 // data for current round 131 // preprepare: nil, 132 prepares: newMessageSet(validatorSet), 133 commits: newMessageSet(validatorSet), 134 proposer: proposer, 135 136 // data saves across rounds, same sequence 137 validatorSet: validatorSet, 138 parentCommits: newMessageSet(validatorSet), 139 pendingRequest: nil, 140 preparedCertificate: istanbul.EmptyPreparedCertificate(), 141 142 mu: new(sync.RWMutex), 143 logger: log.New(), 144 } 145 } 146 147 func (rs *roundStateImpl) Commits() MessageSet { return rs.commits } 148 func (rs *roundStateImpl) Prepares() MessageSet { return rs.prepares } 149 func (rs *roundStateImpl) ParentCommits() MessageSet { return rs.parentCommits } 150 151 func (rs *roundStateImpl) State() State { 152 rs.mu.RLock() 153 defer rs.mu.RUnlock() 154 return rs.state 155 } 156 157 func (rs *roundStateImpl) View() *istanbul.View { 158 rs.mu.RLock() 159 defer rs.mu.RUnlock() 160 161 return &istanbul.View{ 162 Sequence: new(big.Int).Set(rs.sequence), 163 Round: new(big.Int).Set(rs.round), 164 } 165 } 166 167 func (rs *roundStateImpl) GetPrepareOrCommitSize() int { 168 rs.mu.RLock() 169 defer rs.mu.RUnlock() 170 171 result := rs.prepares.Size() + rs.commits.Size() 172 173 // find duplicate one 174 for _, m := range rs.prepares.Values() { 175 if rs.commits.Get(m.Address) != nil { 176 result-- 177 } 178 } 179 return result 180 } 181 182 func (rs *roundStateImpl) Subject() *istanbul.Subject { 183 rs.mu.RLock() 184 defer rs.mu.RUnlock() 185 186 if rs.preprepare == nil { 187 return nil 188 } 189 190 return &istanbul.Subject{ 191 View: &istanbul.View{ 192 Round: new(big.Int).Set(rs.round), 193 Sequence: new(big.Int).Set(rs.sequence), 194 }, 195 Digest: rs.preprepare.Proposal.Hash(), 196 } 197 } 198 199 func (rs *roundStateImpl) IsProposer(address common.Address) bool { 200 rs.mu.RLock() 201 defer rs.mu.RUnlock() 202 203 return rs.proposer.Address() == address 204 } 205 206 func (rs *roundStateImpl) Proposer() istanbul.Validator { 207 rs.mu.RLock() 208 defer rs.mu.RUnlock() 209 210 return rs.proposer 211 } 212 213 func (rs *roundStateImpl) ValidatorSet() istanbul.ValidatorSet { 214 rs.mu.RLock() 215 defer rs.mu.RUnlock() 216 217 return rs.validatorSet 218 } 219 220 func (rs *roundStateImpl) GetValidatorByAddress(address common.Address) istanbul.Validator { 221 rs.mu.RLock() 222 defer rs.mu.RUnlock() 223 224 _, validator := rs.validatorSet.GetByAddress(address) 225 return validator 226 } 227 228 func (rs *roundStateImpl) Preprepare() *istanbul.Preprepare { 229 rs.mu.RLock() 230 defer rs.mu.RUnlock() 231 232 return rs.preprepare 233 } 234 235 func (rs *roundStateImpl) Proposal() istanbul.Proposal { 236 rs.mu.RLock() 237 defer rs.mu.RUnlock() 238 239 if rs.preprepare != nil { 240 return rs.preprepare.Proposal 241 } 242 243 return nil 244 } 245 246 func (rs *roundStateImpl) Round() *big.Int { 247 rs.mu.RLock() 248 defer rs.mu.RUnlock() 249 250 return rs.round 251 } 252 253 func (rs *roundStateImpl) changeRound(nextRound *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator) { 254 rs.state = StateAcceptRequest 255 rs.round = nextRound 256 rs.desiredRound = nextRound 257 258 // TODO MC use old valset 259 rs.prepares = newMessageSet(validatorSet) 260 rs.commits = newMessageSet(validatorSet) 261 rs.proposer = nextProposer 262 263 // ?? 264 rs.preprepare = nil 265 } 266 267 func (rs *roundStateImpl) StartNewRound(nextRound *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator) error { 268 rs.mu.Lock() 269 defer rs.mu.Unlock() 270 logger := rs.newLogger() 271 rs.changeRound(nextRound, validatorSet, nextProposer) 272 logger.Debug("Starting new round", "next_round", nextRound, "next_proposer", nextProposer.Address().Hex()) 273 return nil 274 } 275 276 func (rs *roundStateImpl) StartNewSequence(nextSequence *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator, parentCommits MessageSet) error { 277 rs.mu.Lock() 278 defer rs.mu.Unlock() 279 logger := rs.newLogger() 280 281 rs.validatorSet = validatorSet 282 283 rs.changeRound(big.NewInt(0), validatorSet, nextProposer) 284 285 rs.sequence = nextSequence 286 rs.preparedCertificate = istanbul.EmptyPreparedCertificate() 287 rs.pendingRequest = nil 288 rs.parentCommits = parentCommits 289 rs.proposalVerificationStatus = nil 290 291 logger.Debug("Starting new sequence", "next_sequence", nextSequence, "next_proposer", nextProposer.Address().Hex()) 292 return nil 293 } 294 295 func (rs *roundStateImpl) TransitionToCommitted() error { 296 rs.mu.Lock() 297 defer rs.mu.Unlock() 298 299 rs.state = StateCommitted 300 return nil 301 } 302 303 func (rs *roundStateImpl) TransitionToPreprepared(preprepare *istanbul.Preprepare) error { 304 rs.mu.Lock() 305 defer rs.mu.Unlock() 306 307 rs.preprepare = preprepare 308 rs.state = StatePreprepared 309 return nil 310 } 311 312 func (rs *roundStateImpl) TransitionToWaitingForNewRound(r *big.Int, nextProposer istanbul.Validator) error { 313 rs.mu.Lock() 314 defer rs.mu.Unlock() 315 316 rs.desiredRound = new(big.Int).Set(r) 317 rs.proposer = nextProposer 318 rs.state = StateWaitingForNewRound 319 return nil 320 } 321 322 // TransitionToPrepared will create a PreparedCertificate and change state to Prepared 323 func (rs *roundStateImpl) TransitionToPrepared(quorumSize int) error { 324 rs.mu.Lock() 325 defer rs.mu.Unlock() 326 327 messages := make([]istanbul.Message, quorumSize) 328 i := 0 329 for _, message := range rs.prepares.Values() { 330 if i == quorumSize { 331 break 332 } 333 messages[i] = *message 334 i++ 335 } 336 for _, message := range rs.commits.Values() { 337 if i == quorumSize { 338 break 339 } 340 if rs.prepares.Get(message.Address) == nil { 341 messages[i] = *message 342 i++ 343 } 344 } 345 if i != quorumSize { 346 return errFailedCreatePreparedCertificate 347 } 348 rs.preparedCertificate = istanbul.PreparedCertificate{ 349 Proposal: rs.preprepare.Proposal, 350 PrepareOrCommitMessages: messages, 351 } 352 353 rs.state = StatePrepared 354 return nil 355 } 356 357 func (rs *roundStateImpl) AddCommit(msg *istanbul.Message) error { 358 rs.mu.Lock() 359 defer rs.mu.Unlock() 360 return rs.commits.Add(msg) 361 } 362 363 func (rs *roundStateImpl) AddPrepare(msg *istanbul.Message) error { 364 rs.mu.Lock() 365 defer rs.mu.Unlock() 366 return rs.prepares.Add(msg) 367 } 368 369 func (rs *roundStateImpl) AddParentCommit(msg *istanbul.Message) error { 370 rs.mu.Lock() 371 defer rs.mu.Unlock() 372 return rs.parentCommits.Add(msg) 373 } 374 375 func (rs *roundStateImpl) DesiredRound() *big.Int { 376 rs.mu.RLock() 377 defer rs.mu.RUnlock() 378 379 return rs.desiredRound 380 } 381 382 func (rs *roundStateImpl) SetPendingRequest(pendingRequest *istanbul.Request) error { 383 rs.mu.Lock() 384 defer rs.mu.Unlock() 385 386 rs.pendingRequest = pendingRequest 387 return nil 388 } 389 390 func (rs *roundStateImpl) PendingRequest() *istanbul.Request { 391 rs.mu.RLock() 392 defer rs.mu.RUnlock() 393 return rs.pendingRequest 394 } 395 396 func (rs *roundStateImpl) Sequence() *big.Int { 397 rs.mu.RLock() 398 defer rs.mu.RUnlock() 399 400 return rs.sequence 401 } 402 403 func (rs *roundStateImpl) PreparedCertificate() istanbul.PreparedCertificate { 404 rs.mu.RLock() 405 defer rs.mu.RUnlock() 406 return rs.preparedCertificate 407 } 408 409 func (rs *roundStateImpl) SetProposalVerificationStatus(proposalHash common.Hash, verificationStatus error) { 410 rs.mu.Lock() 411 defer rs.mu.Unlock() 412 413 if rs.proposalVerificationStatus == nil { 414 rs.proposalVerificationStatus = make(map[common.Hash]error) 415 } 416 417 rs.proposalVerificationStatus[proposalHash] = verificationStatus 418 } 419 420 func (rs *roundStateImpl) GetProposalVerificationStatus(proposalHash common.Hash) (verificationStatus error, isCached bool) { 421 rs.mu.RLock() 422 defer rs.mu.RUnlock() 423 424 verificationStatus, isCached = nil, false 425 426 if rs.proposalVerificationStatus != nil { 427 verificationStatus, isCached = rs.proposalVerificationStatus[proposalHash] 428 } 429 430 return 431 } 432 433 func (rs *roundStateImpl) Summary() *RoundStateSummary { 434 rs.mu.RLock() 435 defer rs.mu.RUnlock() 436 437 summary := &RoundStateSummary{ 438 State: rs.state.String(), 439 Sequence: rs.sequence, 440 Round: rs.round, 441 DesiredRound: rs.desiredRound, 442 443 Proposer: rs.proposer.Address(), 444 ValidatorSet: istanbul.MapValidatorsToAddresses(rs.validatorSet.List()), 445 446 Prepares: rs.prepares.Addresses(), 447 Commits: rs.commits.Addresses(), 448 ParentCommits: rs.parentCommits.Addresses(), 449 } 450 451 if rs.pendingRequest != nil { 452 hash := rs.pendingRequest.Proposal.Hash() 453 summary.PendingRequestHash = &hash 454 } 455 456 if rs.preprepare != nil { 457 summary.Preprepare = rs.preprepare.Summary() 458 } 459 460 if !rs.preparedCertificate.IsEmpty() { 461 summary.PreparedCertificate = rs.preparedCertificate.Summary() 462 } 463 464 return summary 465 } 466 467 func (rs *roundStateImpl) newLogger(ctx ...interface{}) log.Logger { 468 logger := rs.logger.New(ctx...) 469 return logger.New("cur_seq", rs.sequence, "cur_round", rs.round, "state", rs.state) 470 } 471 472 type roundStateRLP struct { 473 State State 474 Round *big.Int 475 DesiredRound *big.Int 476 Sequence *big.Int 477 PreparedCertificate *istanbul.PreparedCertificate 478 479 // custom serialized fields 480 SerializedValSet []byte 481 SerializedProposer []byte 482 SerializedParentCommits []byte 483 SerializedPrepares []byte 484 SerializedCommits []byte 485 SerializedPreprepare []byte 486 SerializedPendingRequest []byte 487 } 488 489 // EncodeRLP should write the RLP encoding of its receiver to w. 490 // If the implementation is a pointer method, it may also be 491 // called for nil pointers. 492 // 493 // Implementations should generate valid RLP. The data written is 494 // not verified at the moment, but a future version might. It is 495 // recommended to write only a single value but writing multiple 496 // values or no value at all is also permitted. 497 func (rs *roundStateImpl) EncodeRLP(w io.Writer) error { 498 rs.mu.RLock() 499 defer rs.mu.RUnlock() 500 501 serializedValSet, err := rs.validatorSet.Serialize() 502 if err != nil { 503 return err 504 } 505 serializedProposer, err := rs.proposer.Serialize() 506 if err != nil { 507 return err 508 } 509 510 serializedParentCommits, err := rs.parentCommits.Serialize() 511 if err != nil { 512 return err 513 } 514 serializedPrepares, err := rs.prepares.Serialize() 515 if err != nil { 516 return err 517 } 518 serializedCommits, err := rs.commits.Serialize() 519 if err != nil { 520 return err 521 } 522 523 // handle nullable field. Serialized them to rlp.EmptyList or the rlp version of them 524 var serializedPendingRequest []byte 525 if rs.pendingRequest == nil { 526 serializedPendingRequest = rlp.EmptyList 527 } else { 528 serializedPendingRequest, err = rlp.EncodeToBytes(rs.pendingRequest) 529 if err != nil { 530 return err 531 } 532 } 533 534 var serializedPreprepare []byte 535 if rs.preprepare == nil { 536 serializedPreprepare = rlp.EmptyList 537 } else { 538 serializedPreprepare, err = rlp.EncodeToBytes(rs.preprepare) 539 if err != nil { 540 return err 541 } 542 } 543 544 entry := roundStateRLP{ 545 State: rs.state, 546 Round: rs.round, 547 DesiredRound: rs.desiredRound, 548 Sequence: rs.sequence, 549 PreparedCertificate: &rs.preparedCertificate, 550 551 SerializedValSet: serializedValSet, 552 SerializedProposer: serializedProposer, 553 SerializedParentCommits: serializedParentCommits, 554 SerializedPrepares: serializedPrepares, 555 SerializedCommits: serializedCommits, 556 SerializedPendingRequest: serializedPendingRequest, 557 SerializedPreprepare: serializedPreprepare, 558 } 559 return rlp.Encode(w, entry) 560 } 561 562 // The DecodeRLP method should read one value from the given 563 // Stream. It is not forbidden to read less or more, but it might 564 // be confusing. 565 func (rs *roundStateImpl) DecodeRLP(stream *rlp.Stream) error { 566 var data roundStateRLP 567 err := stream.Decode(&data) 568 if err != nil { 569 return err 570 } 571 572 rs.logger = log.New() 573 rs.mu = new(sync.RWMutex) 574 rs.state = data.State 575 rs.round = data.Round 576 rs.desiredRound = data.DesiredRound 577 rs.sequence = data.Sequence 578 rs.preparedCertificate = *data.PreparedCertificate 579 580 rs.prepares, err = deserializeMessageSet(data.SerializedPrepares) 581 if err != nil { 582 return err 583 } 584 rs.parentCommits, err = deserializeMessageSet(data.SerializedParentCommits) 585 if err != nil { 586 return err 587 } 588 rs.commits, err = deserializeMessageSet(data.SerializedCommits) 589 if err != nil { 590 return err 591 } 592 rs.validatorSet, err = validator.DeserializeValidatorSet(data.SerializedValSet) 593 if err != nil { 594 return err 595 } 596 rs.proposer, err = validator.DeserializeValidator(data.SerializedProposer) 597 if err != nil { 598 return err 599 } 600 601 if !bytes.Equal(data.SerializedPendingRequest, rlp.EmptyList) { 602 var value istanbul.Request 603 err := rlp.DecodeBytes(data.SerializedPendingRequest, &value) 604 if err != nil { 605 return err 606 } 607 rs.pendingRequest = &value 608 609 } 610 611 if !bytes.Equal(data.SerializedPreprepare, rlp.EmptyList) { 612 var value istanbul.Preprepare 613 err := rlp.DecodeBytes(data.SerializedPreprepare, &value) 614 if err != nil { 615 return err 616 } 617 rs.preprepare = &value 618 } 619 620 return nil 621 }