roundstate.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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. package core
  17. import (
  18. "io"
  19. "math/big"
  20. "sync"
  21. "github.com/ethereum/go-ethereum/common"
  22. "github.com/ethereum/go-ethereum/consensus/istanbul"
  23. "github.com/ethereum/go-ethereum/rlp"
  24. )
  25. // newRoundState creates a new roundState instance with the given view and validatorSet
  26. // lockedHash and preprepare are for round change when lock exists,
  27. // we need to keep a reference of preprepare in order to propose locked proposal when there is a lock and itself is the proposer
  28. func newRoundState(view *istanbul.View, validatorSet istanbul.ValidatorSet, lockedHash common.Hash, preprepare *istanbul.Preprepare, pendingRequest *istanbul.Request, hasBadProposal func(hash common.Hash) bool) *roundState {
  29. return &roundState{
  30. round: view.Round,
  31. sequence: view.Sequence,
  32. Preprepare: preprepare,
  33. Prepares: newMessageSet(validatorSet),
  34. Commits: newMessageSet(validatorSet),
  35. lockedHash: lockedHash,
  36. mu: new(sync.RWMutex),
  37. pendingRequest: pendingRequest,
  38. hasBadProposal: hasBadProposal,
  39. }
  40. }
  41. // roundState stores the consensus state
  42. type roundState struct {
  43. round *big.Int
  44. sequence *big.Int
  45. Preprepare *istanbul.Preprepare
  46. Prepares *messageSet
  47. Commits *messageSet
  48. lockedHash common.Hash
  49. pendingRequest *istanbul.Request
  50. mu *sync.RWMutex
  51. hasBadProposal func(hash common.Hash) bool
  52. }
  53. func (s *roundState) GetPrepareOrCommitSize() int {
  54. s.mu.RLock()
  55. defer s.mu.RUnlock()
  56. result := s.Prepares.Size() + s.Commits.Size()
  57. // find duplicate one
  58. for _, m := range s.Prepares.Values() {
  59. if s.Commits.Get(m.Address) != nil {
  60. result--
  61. }
  62. }
  63. return result
  64. }
  65. func (s *roundState) Subject() *istanbul.Subject {
  66. s.mu.RLock()
  67. defer s.mu.RUnlock()
  68. if s.Preprepare == nil {
  69. return nil
  70. }
  71. return &istanbul.Subject{
  72. View: &istanbul.View{
  73. Round: new(big.Int).Set(s.round),
  74. Sequence: new(big.Int).Set(s.sequence),
  75. },
  76. Digest: s.Preprepare.Proposal.Hash(),
  77. }
  78. }
  79. func (s *roundState) SetPreprepare(preprepare *istanbul.Preprepare) {
  80. s.mu.Lock()
  81. defer s.mu.Unlock()
  82. s.Preprepare = preprepare
  83. }
  84. func (s *roundState) Proposal() istanbul.Proposal {
  85. s.mu.RLock()
  86. defer s.mu.RUnlock()
  87. if s.Preprepare != nil {
  88. return s.Preprepare.Proposal
  89. }
  90. return nil
  91. }
  92. func (s *roundState) SetRound(r *big.Int) {
  93. s.mu.Lock()
  94. defer s.mu.Unlock()
  95. s.round = new(big.Int).Set(r)
  96. }
  97. func (s *roundState) Round() *big.Int {
  98. s.mu.RLock()
  99. defer s.mu.RUnlock()
  100. return s.round
  101. }
  102. func (s *roundState) SetSequence(seq *big.Int) {
  103. s.mu.Lock()
  104. defer s.mu.Unlock()
  105. s.sequence = seq
  106. }
  107. func (s *roundState) Sequence() *big.Int {
  108. s.mu.RLock()
  109. defer s.mu.RUnlock()
  110. return s.sequence
  111. }
  112. func (s *roundState) LockHash() {
  113. s.mu.Lock()
  114. defer s.mu.Unlock()
  115. if s.Preprepare != nil {
  116. s.lockedHash = s.Preprepare.Proposal.Hash()
  117. }
  118. }
  119. func (s *roundState) UnlockHash() {
  120. s.mu.Lock()
  121. defer s.mu.Unlock()
  122. s.lockedHash = common.Hash{}
  123. }
  124. func (s *roundState) IsHashLocked() bool {
  125. s.mu.RLock()
  126. defer s.mu.RUnlock()
  127. if common.EmptyHash(s.lockedHash) {
  128. return false
  129. }
  130. return !s.hasBadProposal(s.GetLockedHash())
  131. }
  132. func (s *roundState) GetLockedHash() common.Hash {
  133. s.mu.RLock()
  134. defer s.mu.RUnlock()
  135. return s.lockedHash
  136. }
  137. // The DecodeRLP method should read one value from the given
  138. // Stream. It is not forbidden to read less or more, but it might
  139. // be confusing.
  140. func (s *roundState) DecodeRLP(stream *rlp.Stream) error {
  141. var ss struct {
  142. Round *big.Int
  143. Sequence *big.Int
  144. Preprepare *istanbul.Preprepare
  145. Prepares *messageSet
  146. Commits *messageSet
  147. lockedHash common.Hash
  148. pendingRequest *istanbul.Request
  149. }
  150. if err := stream.Decode(&ss); err != nil {
  151. return err
  152. }
  153. s.round = ss.Round
  154. s.sequence = ss.Sequence
  155. s.Preprepare = ss.Preprepare
  156. s.Prepares = ss.Prepares
  157. s.Commits = ss.Commits
  158. s.lockedHash = ss.lockedHash
  159. s.pendingRequest = ss.pendingRequest
  160. s.mu = new(sync.RWMutex)
  161. return nil
  162. }
  163. // EncodeRLP should write the RLP encoding of its receiver to w.
  164. // If the implementation is a pointer method, it may also be
  165. // called for nil pointers.
  166. //
  167. // Implementations should generate valid RLP. The data written is
  168. // not verified at the moment, but a future version might. It is
  169. // recommended to write only a single value but writing multiple
  170. // values or no value at all is also permitted.
  171. func (s *roundState) EncodeRLP(w io.Writer) error {
  172. s.mu.RLock()
  173. defer s.mu.RUnlock()
  174. return rlp.Encode(w, []interface{}{
  175. s.round,
  176. s.sequence,
  177. s.Preprepare,
  178. s.Prepares,
  179. s.Commits,
  180. s.lockedHash,
  181. s.pendingRequest,
  182. })
  183. }