You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

429 lines
11 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package consensus
  2. import (
  3. "errors"
  4. "sync"
  5. "time"
  6. . "github.com/tendermint/tendermint/binary"
  7. . "github.com/tendermint/tendermint/blocks"
  8. . "github.com/tendermint/tendermint/common"
  9. . "github.com/tendermint/tendermint/mempool"
  10. . "github.com/tendermint/tendermint/state"
  11. )
  12. const (
  13. RoundStepStart = uint8(0x00) // Round started.
  14. RoundStepPropose = uint8(0x01) // Did propose, broadcasting proposal.
  15. RoundStepVote = uint8(0x02) // Did vote, broadcasting votes.
  16. RoundStepPrecommit = uint8(0x03) // Did precommit, broadcasting precommits.
  17. RoundStepCommit = uint8(0x04) // We committed at this round -- do not progress to the next round.
  18. )
  19. var (
  20. ErrInvalidProposalSignature = errors.New("Error invalid proposal signature")
  21. consensusStateKey = []byte("consensusState")
  22. )
  23. // Immutable when returned from ConsensusState.GetRoundState()
  24. type RoundState struct {
  25. Height uint32 // Height we are working on
  26. Round uint16
  27. Step uint8
  28. StartTime time.Time
  29. Validators *ValidatorSet
  30. Proposer *Validator
  31. Proposal *Proposal
  32. ProposalBlock *Block
  33. ProposalBlockPartSet *PartSet
  34. ProposalPOL *POL
  35. ProposalPOLPartSet *PartSet
  36. LockedBlock *Block
  37. LockedPOL *POL
  38. Votes *VoteSet
  39. Precommits *VoteSet
  40. Commits *VoteSet
  41. PrivValidator *PrivValidator
  42. }
  43. //-------------------------------------
  44. // Tracks consensus state across block heights and rounds.
  45. type ConsensusState struct {
  46. blockStore *BlockStore
  47. mempool *Mempool
  48. mtx sync.Mutex
  49. RoundState
  50. state *State // State until height-1.
  51. stagedBlock *Block // Cache last staged block.
  52. stagedState *State // Cache result of staged block.
  53. }
  54. func NewConsensusState(state *State, blockStore *BlockStore, mempool *Mempool) *ConsensusState {
  55. cs := &ConsensusState{
  56. blockStore: blockStore,
  57. mempool: mempool,
  58. }
  59. cs.updateToState(state)
  60. return cs
  61. }
  62. func (cs *ConsensusState) GetRoundState() *RoundState {
  63. cs.mtx.Lock()
  64. defer cs.mtx.Unlock()
  65. rs := cs.RoundState // copy
  66. return &rs
  67. }
  68. func (cs *ConsensusState) updateToState(state *State) {
  69. // Sanity check state.
  70. stateHeight := state.Height
  71. if stateHeight > 0 && stateHeight != cs.Height+1 {
  72. Panicf("updateToState() expected state height of %v but found %v", cs.Height+1, stateHeight)
  73. }
  74. // Reset fields based on state.
  75. height := state.Height
  76. validators := state.Validators
  77. cs.Height = height
  78. cs.Round = 0
  79. cs.Step = RoundStepStart
  80. cs.StartTime = state.CommitTime.Add(newBlockWaitDuration)
  81. cs.Validators = validators
  82. cs.Proposer = validators.GetProposer()
  83. cs.Proposal = nil
  84. cs.ProposalBlock = nil
  85. cs.ProposalBlockPartSet = nil
  86. cs.ProposalPOL = nil
  87. cs.ProposalPOLPartSet = nil
  88. cs.LockedBlock = nil
  89. cs.LockedPOL = nil
  90. cs.Votes = NewVoteSet(height, 0, VoteTypeBare, validators)
  91. cs.Precommits = NewVoteSet(height, 0, VoteTypePrecommit, validators)
  92. cs.Commits = NewVoteSet(height, 0, VoteTypeCommit, validators)
  93. cs.state = state
  94. cs.stagedBlock = nil
  95. cs.stagedState = nil
  96. // Update the round if we need to.
  97. round := calcRound(cs.StartTime)
  98. if round > 0 {
  99. cs.setupRound(round)
  100. }
  101. }
  102. func (cs *ConsensusState) SetupRound(round uint16) {
  103. cs.mtx.Lock()
  104. defer cs.mtx.Unlock()
  105. if cs.Round >= round {
  106. Panicf("ConsensusState round %v not lower than desired round %v", cs.Round, round)
  107. }
  108. cs.setupRound(round)
  109. }
  110. func (cs *ConsensusState) setupRound(round uint16) {
  111. // Increment all the way to round.
  112. validators := cs.Validators.Copy()
  113. for r := cs.Round; r < round; r++ {
  114. validators.IncrementAccum()
  115. }
  116. cs.Round = round
  117. cs.Step = RoundStepStart
  118. cs.Validators = validators
  119. cs.Proposer = validators.GetProposer()
  120. cs.Proposal = nil
  121. cs.ProposalBlock = nil
  122. cs.ProposalBlockPartSet = nil
  123. cs.ProposalPOL = nil
  124. cs.ProposalPOLPartSet = nil
  125. cs.Votes = NewVoteSet(cs.Height, round, VoteTypeBare, validators)
  126. cs.Votes.AddVotesFromCommits(cs.Commits)
  127. cs.Precommits = NewVoteSet(cs.Height, round, VoteTypePrecommit, validators)
  128. cs.Precommits.AddVotesFromCommits(cs.Commits)
  129. }
  130. func (cs *ConsensusState) SetStep(step byte) {
  131. cs.mtx.Lock()
  132. defer cs.mtx.Unlock()
  133. if cs.Step < step {
  134. cs.Step = step
  135. } else {
  136. panic("step regression")
  137. }
  138. }
  139. func (cs *ConsensusState) SetPrivValidator(priv *PrivValidator) {
  140. cs.mtx.Lock()
  141. defer cs.mtx.Unlock()
  142. cs.PrivValidator = priv
  143. }
  144. func (cs *ConsensusState) SetProposal(proposal *Proposal) error {
  145. cs.mtx.Lock()
  146. defer cs.mtx.Unlock()
  147. // Already have one
  148. if cs.Proposal != nil {
  149. return nil
  150. }
  151. // Invalid.
  152. if proposal.Height != cs.Height || proposal.Round != cs.Round {
  153. return nil
  154. }
  155. // Verify signature
  156. if !cs.Proposer.Verify(proposal) {
  157. return ErrInvalidProposalSignature
  158. }
  159. cs.Proposal = proposal
  160. cs.ProposalBlockPartSet = NewPartSetFromMetadata(proposal.BlockPartsTotal, proposal.BlockPartsHash)
  161. cs.ProposalPOLPartSet = NewPartSetFromMetadata(proposal.POLPartsTotal, proposal.POLPartsHash)
  162. return nil
  163. }
  164. func (cs *ConsensusState) MakeProposal() {
  165. cs.mtx.Lock()
  166. defer cs.mtx.Unlock()
  167. if cs.PrivValidator == nil || cs.Proposer.Id != cs.PrivValidator.Id {
  168. return
  169. }
  170. var block *Block
  171. var blockPartSet *PartSet
  172. var pol *POL
  173. var polPartSet *PartSet
  174. // Decide on block and POL
  175. if cs.LockedBlock != nil {
  176. // If we're locked onto a block, just choose that.
  177. block = cs.LockedBlock
  178. pol = cs.LockedPOL
  179. } else {
  180. // TODO: make use of state returned from MakeProposalBlock()
  181. block, _ = cs.mempool.MakeProposalBlock()
  182. pol = cs.LockedPOL // If exists, is a PoUnlock.
  183. }
  184. blockPartSet = NewPartSetFromData(BinaryBytes(block))
  185. if pol != nil {
  186. polPartSet = NewPartSetFromData(BinaryBytes(pol))
  187. }
  188. // Make proposal
  189. proposal := NewProposal(cs.Height, cs.Round, blockPartSet.Total(), blockPartSet.RootHash(),
  190. polPartSet.Total(), polPartSet.RootHash())
  191. cs.PrivValidator.Sign(proposal)
  192. // Set fields
  193. cs.Proposal = proposal
  194. cs.ProposalBlock = block
  195. cs.ProposalBlockPartSet = blockPartSet
  196. cs.ProposalPOL = pol
  197. cs.ProposalPOLPartSet = polPartSet
  198. }
  199. // NOTE: block is not necessarily valid.
  200. func (cs *ConsensusState) AddProposalBlockPart(height uint32, round uint16, part *Part) (added bool, err error) {
  201. cs.mtx.Lock()
  202. defer cs.mtx.Unlock()
  203. // Blocks might be reused, so round mismatch is OK
  204. if cs.Height != height {
  205. return false, nil
  206. }
  207. // We're not expecting a block part.
  208. if cs.ProposalBlockPartSet != nil {
  209. return false, nil // TODO: bad peer? Return error?
  210. }
  211. added, err = cs.ProposalBlockPartSet.AddPart(part)
  212. if err != nil {
  213. return added, err
  214. }
  215. if added && cs.ProposalBlockPartSet.IsComplete() {
  216. var n int64
  217. var err error
  218. cs.ProposalBlock = ReadBlock(cs.ProposalBlockPartSet.GetReader(), &n, &err)
  219. return true, err
  220. }
  221. return true, nil
  222. }
  223. // NOTE: POL is not necessarily valid.
  224. func (cs *ConsensusState) AddProposalPOLPart(height uint32, round uint16, part *Part) (added bool, err error) {
  225. cs.mtx.Lock()
  226. defer cs.mtx.Unlock()
  227. if cs.Height != height || cs.Round != round {
  228. return false, nil
  229. }
  230. // We're not expecting a POL part.
  231. if cs.ProposalPOLPartSet != nil {
  232. return false, nil // TODO: bad peer? Return error?
  233. }
  234. added, err = cs.ProposalPOLPartSet.AddPart(part)
  235. if err != nil {
  236. return added, err
  237. }
  238. if added && cs.ProposalPOLPartSet.IsComplete() {
  239. var n int64
  240. var err error
  241. cs.ProposalPOL = ReadPOL(cs.ProposalPOLPartSet.GetReader(), &n, &err)
  242. return true, err
  243. }
  244. return true, nil
  245. }
  246. func (cs *ConsensusState) AddVote(vote *Vote) (added bool, err error) {
  247. switch vote.Type {
  248. case VoteTypeBare:
  249. // Votes checks for height+round match.
  250. return cs.Votes.AddVote(vote)
  251. case VoteTypePrecommit:
  252. // Precommits checks for height+round match.
  253. return cs.Precommits.AddVote(vote)
  254. case VoteTypeCommit:
  255. // Commits checks for height match.
  256. cs.Votes.AddVote(vote)
  257. cs.Precommits.AddVote(vote)
  258. return cs.Commits.AddVote(vote)
  259. default:
  260. panic("Unknown vote type")
  261. }
  262. }
  263. // Lock the ProposalBlock if we have enough votes for it,
  264. // or unlock an existing lock if +2/3 of votes were nil.
  265. // Returns a blockhash if a block was locked.
  266. func (cs *ConsensusState) LockOrUnlock(height uint32, round uint16) []byte {
  267. cs.mtx.Lock()
  268. defer cs.mtx.Unlock()
  269. if cs.Height != height || cs.Round != round {
  270. return nil
  271. }
  272. if hash, _, ok := cs.Votes.TwoThirdsMajority(); ok {
  273. // Remember this POL. (hash may be nil)
  274. cs.LockedPOL = cs.Votes.MakePOL()
  275. if len(hash) == 0 {
  276. // +2/3 voted nil. Just unlock.
  277. cs.LockedBlock = nil
  278. return nil
  279. } else if cs.ProposalBlock.HashesTo(hash) {
  280. // +2/3 voted for proposal block
  281. // Validate the block.
  282. // See note on ZombieValidators to see why.
  283. if cs.stageBlock(cs.ProposalBlock) != nil {
  284. log.Warning("+2/3 voted for an invalid block.")
  285. return nil
  286. }
  287. cs.LockedBlock = cs.ProposalBlock
  288. return hash
  289. } else if cs.LockedBlock.HashesTo(hash) {
  290. // +2/3 voted for already locked block
  291. // cs.LockedBlock = cs.LockedBlock
  292. return hash
  293. } else {
  294. // We don't have the block that hashes to hash.
  295. // Unlock if we're locked.
  296. cs.LockedBlock = nil
  297. return nil
  298. }
  299. } else {
  300. return nil
  301. }
  302. }
  303. func (cs *ConsensusState) Commit(height uint32, round uint16) *Block {
  304. cs.mtx.Lock()
  305. defer cs.mtx.Unlock()
  306. if cs.Height != height || cs.Round != round {
  307. return nil
  308. }
  309. if hash, commitTime, ok := cs.Precommits.TwoThirdsMajority(); ok {
  310. // There are some strange cases that shouldn't happen
  311. // (unless voters are duplicitous).
  312. // For example, the hash may not be the one that was
  313. // proposed this round. These cases should be identified
  314. // and warn the administrator. We should err on the side of
  315. // caution and not, for example, sign a block.
  316. // TODO: Identify these strange cases.
  317. var block *Block
  318. if cs.LockedBlock.HashesTo(hash) {
  319. block = cs.LockedBlock
  320. } else if cs.ProposalBlock.HashesTo(hash) {
  321. block = cs.ProposalBlock
  322. } else {
  323. return nil
  324. }
  325. // The proposal must be valid.
  326. if err := cs.stageBlock(block); err != nil {
  327. log.Warning("Network is commiting an invalid proposal? %v", err)
  328. return nil
  329. }
  330. // Save to blockStore
  331. err := cs.blockStore.SaveBlock(block)
  332. if err != nil {
  333. return nil
  334. }
  335. // What was staged becomes committed.
  336. state := cs.stagedState
  337. state.Save(commitTime)
  338. cs.updateToState(state)
  339. // Update mempool.
  340. cs.mempool.ResetForBlockAndState(block, state)
  341. return block
  342. }
  343. return nil
  344. }
  345. func (cs *ConsensusState) stageBlock(block *Block) error {
  346. // Already staged?
  347. if cs.stagedBlock == block {
  348. return nil
  349. }
  350. // Basic validation is done in state.CommitBlock().
  351. //err := block.ValidateBasic()
  352. //if err != nil {
  353. // return err
  354. //}
  355. // Create a copy of the state for staging
  356. stateCopy := cs.state.Copy() // Deep copy the state before staging.
  357. // Commit block onto the copied state.
  358. err := stateCopy.AppendBlock(block)
  359. if err != nil {
  360. return err
  361. } else {
  362. cs.stagedBlock = block
  363. cs.stagedState = stateCopy
  364. return nil
  365. }
  366. }