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.

201 lines
6.0 KiB

10 years ago
7 years ago
6 years ago
8 years ago
6 years ago
8 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "time"
  7. "github.com/tendermint/tendermint/types"
  8. )
  9. // database keys
  10. var (
  11. stateKey = []byte("stateKey")
  12. )
  13. //-----------------------------------------------------------------------------
  14. // State is a short description of the latest committed block of the Tendermint consensus.
  15. // It keeps all information necessary to validate new blocks,
  16. // including the last validator set and the consensus params.
  17. // All fields are exposed so the struct can be easily serialized,
  18. // but none of them should be mutated directly.
  19. // Instead, use state.Copy() or state.NextState(...).
  20. // NOTE: not goroutine-safe.
  21. type State struct {
  22. // immutable
  23. ChainID string
  24. // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist)
  25. LastBlockHeight int64
  26. LastBlockTotalTx int64
  27. LastBlockID types.BlockID
  28. LastBlockTime time.Time
  29. // LastValidators is used to validate block.LastCommit.
  30. // Validators are persisted to the database separately every time they change,
  31. // so we can query for historical validator sets.
  32. // Note that if s.LastBlockHeight causes a valset change,
  33. // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1
  34. NextValidators *types.ValidatorSet
  35. Validators *types.ValidatorSet
  36. LastValidators *types.ValidatorSet
  37. LastHeightValidatorsChanged int64
  38. // Consensus parameters used for validating blocks.
  39. // Changes returned by EndBlock and updated after Commit.
  40. ConsensusParams types.ConsensusParams
  41. LastHeightConsensusParamsChanged int64
  42. // Merkle root of the results from executing prev block
  43. LastResultsHash []byte
  44. // the latest AppHash we've received from calling abci.Commit()
  45. AppHash []byte
  46. }
  47. // Copy makes a copy of the State for mutating.
  48. func (state State) Copy() State {
  49. return State{
  50. ChainID: state.ChainID,
  51. LastBlockHeight: state.LastBlockHeight,
  52. LastBlockTotalTx: state.LastBlockTotalTx,
  53. LastBlockID: state.LastBlockID,
  54. LastBlockTime: state.LastBlockTime,
  55. NextValidators: state.NextValidators.Copy(),
  56. Validators: state.Validators.Copy(),
  57. LastValidators: state.LastValidators.Copy(),
  58. LastHeightValidatorsChanged: state.LastHeightValidatorsChanged,
  59. ConsensusParams: state.ConsensusParams,
  60. LastHeightConsensusParamsChanged: state.LastHeightConsensusParamsChanged,
  61. AppHash: state.AppHash,
  62. LastResultsHash: state.LastResultsHash,
  63. }
  64. }
  65. // Equals returns true if the States are identical.
  66. func (state State) Equals(state2 State) bool {
  67. sbz, s2bz := state.Bytes(), state2.Bytes()
  68. return bytes.Equal(sbz, s2bz)
  69. }
  70. // Bytes serializes the State using go-amino.
  71. func (state State) Bytes() []byte {
  72. return cdc.MustMarshalBinaryBare(state)
  73. }
  74. // IsEmpty returns true if the State is equal to the empty State.
  75. func (state State) IsEmpty() bool {
  76. return state.Validators == nil // XXX can't compare to Empty
  77. }
  78. //------------------------------------------------------------------------
  79. // Create a block from the latest state
  80. // MakeBlock builds a block from the current state with the given txs, commit,
  81. // and evidence. Note it also takes a proposerAddress because the state does not
  82. // track rounds, and hence doesn't know the correct proposer. TODO: alleviate this!
  83. func (state State) MakeBlock(
  84. height int64,
  85. txs []types.Tx,
  86. commit *types.Commit,
  87. evidence []types.Evidence,
  88. proposerAddress []byte,
  89. ) (*types.Block, *types.PartSet) {
  90. // Build base block with block data.
  91. block := types.MakeBlock(height, txs, commit, evidence)
  92. // Fill rest of header with state data.
  93. block.ChainID = state.ChainID
  94. block.LastBlockID = state.LastBlockID
  95. block.TotalTxs = state.LastBlockTotalTx + block.NumTxs
  96. block.ValidatorsHash = state.Validators.Hash()
  97. block.NextValidatorsHash = state.NextValidators.Hash()
  98. block.ConsensusHash = state.ConsensusParams.Hash()
  99. block.AppHash = state.AppHash
  100. block.LastResultsHash = state.LastResultsHash
  101. // NOTE: we can't use the state.Validators because we don't
  102. // IncrementAccum for rounds there.
  103. block.ProposerAddress = proposerAddress
  104. return block, block.MakePartSet(state.ConsensusParams.BlockGossip.BlockPartSizeBytes)
  105. }
  106. //------------------------------------------------------------------------
  107. // Genesis
  108. // MakeGenesisStateFromFile reads and unmarshals state from the given
  109. // file.
  110. //
  111. // Used during replay and in tests.
  112. func MakeGenesisStateFromFile(genDocFile string) (State, error) {
  113. genDoc, err := MakeGenesisDocFromFile(genDocFile)
  114. if err != nil {
  115. return State{}, err
  116. }
  117. return MakeGenesisState(genDoc)
  118. }
  119. // MakeGenesisDocFromFile reads and unmarshals genesis doc from the given file.
  120. func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
  121. genDocJSON, err := ioutil.ReadFile(genDocFile)
  122. if err != nil {
  123. return nil, fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
  124. }
  125. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  126. if err != nil {
  127. return nil, fmt.Errorf("Error reading GenesisDoc: %v", err)
  128. }
  129. return genDoc, nil
  130. }
  131. // MakeGenesisState creates state from types.GenesisDoc.
  132. func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) {
  133. err := genDoc.ValidateAndComplete()
  134. if err != nil {
  135. return State{}, fmt.Errorf("Error in genesis file: %v", err)
  136. }
  137. // Make validators slice
  138. validators := make([]*types.Validator, len(genDoc.Validators))
  139. for i, val := range genDoc.Validators {
  140. pubKey := val.PubKey
  141. address := pubKey.Address()
  142. // Make validator
  143. validators[i] = &types.Validator{
  144. Address: address,
  145. PubKey: pubKey,
  146. VotingPower: val.Power,
  147. }
  148. }
  149. return State{
  150. ChainID: genDoc.ChainID,
  151. LastBlockHeight: 0,
  152. LastBlockID: types.BlockID{},
  153. LastBlockTime: genDoc.GenesisTime,
  154. NextValidators: types.NewValidatorSet(validators).CopyIncrementAccum(1),
  155. Validators: types.NewValidatorSet(validators),
  156. LastValidators: types.NewValidatorSet(nil),
  157. LastHeightValidatorsChanged: 1,
  158. ConsensusParams: *genDoc.ConsensusParams,
  159. LastHeightConsensusParamsChanged: 1,
  160. AppHash: genDoc.AppHash,
  161. }, nil
  162. }