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.

274 lines
7.7 KiB

8 years ago
8 years ago
8 years ago
10 years ago
8 years ago
8 years ago
10 years ago
10 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "sync"
  6. "time"
  7. abci "github.com/tendermint/abci/types"
  8. cmn "github.com/tendermint/tmlibs/common"
  9. dbm "github.com/tendermint/tmlibs/db"
  10. "github.com/tendermint/tmlibs/log"
  11. wire "github.com/tendermint/go-wire"
  12. "github.com/tendermint/tendermint/state/txindex"
  13. "github.com/tendermint/tendermint/state/txindex/null"
  14. "github.com/tendermint/tendermint/types"
  15. )
  16. var (
  17. stateKey = []byte("stateKey")
  18. abciResponsesKey = []byte("abciResponsesKey")
  19. )
  20. //-----------------------------------------------------------------------------
  21. // State represents the latest committed state of the Tendermint consensus,
  22. // including the last committed block and validator set.
  23. // Newly committed blocks are validated and executed against the State.
  24. // NOTE: not goroutine-safe.
  25. type State struct {
  26. // mtx for writing to db
  27. mtx sync.Mutex
  28. db dbm.DB
  29. // should not change
  30. GenesisDoc *types.GenesisDoc
  31. ChainID string
  32. // updated at end of SetBlockAndValidators
  33. LastBlockHeight int // Genesis state has this set to 0. So, Block(H=0) does not exist.
  34. LastBlockID types.BlockID
  35. LastBlockTime time.Time
  36. Validators *types.ValidatorSet
  37. LastValidators *types.ValidatorSet // block.LastCommit validated against this
  38. // AppHash is updated after Commit
  39. AppHash []byte
  40. TxIndexer txindex.TxIndexer `json:"-"` // Transaction indexer.
  41. logger log.Logger
  42. }
  43. // LoadState loads the State from the database.
  44. func LoadState(db dbm.DB) *State {
  45. return loadState(db, stateKey)
  46. }
  47. func loadState(db dbm.DB, key []byte) *State {
  48. s := &State{db: db, TxIndexer: &null.TxIndex{}}
  49. buf := db.Get(key)
  50. if len(buf) == 0 {
  51. return nil
  52. } else {
  53. r, n, err := bytes.NewReader(buf), new(int), new(error)
  54. wire.ReadBinaryPtr(&s, r, 0, n, err)
  55. if *err != nil {
  56. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  57. cmn.Exit(cmn.Fmt("LoadState: Data has been corrupted or its spec has changed: %v\n", *err))
  58. }
  59. // TODO: ensure that buf is completely read.
  60. }
  61. return s
  62. }
  63. // SetLogger sets the logger on the State.
  64. func (s *State) SetLogger(l log.Logger) {
  65. s.logger = l
  66. }
  67. // Copy makes a copy of the State for mutating.
  68. func (s *State) Copy() *State {
  69. return &State{
  70. db: s.db,
  71. GenesisDoc: s.GenesisDoc,
  72. ChainID: s.ChainID,
  73. LastBlockHeight: s.LastBlockHeight,
  74. LastBlockID: s.LastBlockID,
  75. LastBlockTime: s.LastBlockTime,
  76. Validators: s.Validators.Copy(),
  77. LastValidators: s.LastValidators.Copy(),
  78. AppHash: s.AppHash,
  79. TxIndexer: s.TxIndexer, // pointer here, not value
  80. logger: s.logger,
  81. }
  82. }
  83. // Save persists the State to the database.
  84. func (s *State) Save() {
  85. s.mtx.Lock()
  86. defer s.mtx.Unlock()
  87. s.db.SetSync(stateKey, s.Bytes())
  88. }
  89. // SaveABCIResponses persists the ABCIResponses to the database.
  90. // This is useful in case we crash after app.Commit and before s.Save().
  91. func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
  92. s.db.SetSync(abciResponsesKey, abciResponses.Bytes())
  93. }
  94. // LoadABCIResponses loads the ABCIResponses from the database.
  95. func (s *State) LoadABCIResponses() *ABCIResponses {
  96. abciResponses := new(ABCIResponses)
  97. buf := s.db.Get(abciResponsesKey)
  98. if len(buf) != 0 {
  99. r, n, err := bytes.NewReader(buf), new(int), new(error)
  100. wire.ReadBinaryPtr(abciResponses, r, 0, n, err)
  101. if *err != nil {
  102. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  103. cmn.Exit(cmn.Fmt("LoadABCIResponses: Data has been corrupted or its spec has changed: %v\n", *err))
  104. }
  105. // TODO: ensure that buf is completely read.
  106. }
  107. return abciResponses
  108. }
  109. // Equals returns true if the States are identical.
  110. func (s *State) Equals(s2 *State) bool {
  111. return bytes.Equal(s.Bytes(), s2.Bytes())
  112. }
  113. // Bytes serializes the State using go-wire.
  114. func (s *State) Bytes() []byte {
  115. return wire.BinaryBytes(s)
  116. }
  117. // SetBlockAndValidators mutates State variables to update block and validators after running EndBlock.
  118. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader, abciResponses *ABCIResponses) {
  119. // copy the valset so we can apply changes from EndBlock
  120. // and update s.LastValidators and s.Validators
  121. prevValSet := s.Validators.Copy()
  122. nextValSet := prevValSet.Copy()
  123. err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs)
  124. if err != nil {
  125. s.logger.Error("Error changing validator set", "err", err)
  126. // TODO: err or carry on?
  127. }
  128. // Update validator accums and set state variables
  129. nextValSet.IncrementAccum(1)
  130. s.setBlockAndValidators(header.Height,
  131. types.BlockID{header.Hash(), blockPartsHeader}, header.Time,
  132. prevValSet, nextValSet)
  133. }
  134. func (s *State) setBlockAndValidators(
  135. height int, blockID types.BlockID, blockTime time.Time,
  136. prevValSet, nextValSet *types.ValidatorSet) {
  137. s.LastBlockHeight = height
  138. s.LastBlockID = blockID
  139. s.LastBlockTime = blockTime
  140. s.Validators = nextValSet
  141. s.LastValidators = prevValSet
  142. }
  143. // GetValidators returns the last and current validator sets.
  144. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
  145. return s.LastValidators, s.Validators
  146. }
  147. // GetState loads the most recent state from the database,
  148. // or creates a new one from the given genesisFile and persists the result
  149. // to the database.
  150. func GetState(stateDB dbm.DB, genesisFile string) *State {
  151. state := LoadState(stateDB)
  152. if state == nil {
  153. state = MakeGenesisStateFromFile(stateDB, genesisFile)
  154. state.Save()
  155. }
  156. return state
  157. }
  158. //--------------------------------------------------
  159. // ABCIResponses retains the responses of the various ABCI calls during block processing.
  160. // It is persisted to disk before calling Commit.
  161. type ABCIResponses struct {
  162. Height int
  163. DeliverTx []*abci.ResponseDeliverTx
  164. EndBlock abci.ResponseEndBlock
  165. txs types.Txs // reference for indexing results by hash
  166. }
  167. // NewABCIResponses returns a new ABCIResponses
  168. func NewABCIResponses(block *types.Block) *ABCIResponses {
  169. return &ABCIResponses{
  170. Height: block.Height,
  171. DeliverTx: make([]*abci.ResponseDeliverTx, block.NumTxs),
  172. txs: block.Data.Txs,
  173. }
  174. }
  175. // Bytes serializes the ABCIResponse using go-wire
  176. func (a *ABCIResponses) Bytes() []byte {
  177. return wire.BinaryBytes(*a)
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Genesis
  181. // MakeGenesisStateFromFile reads and unmarshals state from the given file.
  182. //
  183. // Used during replay and in tests.
  184. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
  185. genDocJSON, err := ioutil.ReadFile(genDocFile)
  186. if err != nil {
  187. cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err))
  188. }
  189. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  190. if err != nil {
  191. cmn.Exit(cmn.Fmt("Error reading GenesisDoc: %v", err))
  192. }
  193. return MakeGenesisState(db, genDoc)
  194. }
  195. // MakeGenesisState creates state from types.GenesisDoc.
  196. //
  197. // Used in tests.
  198. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
  199. if len(genDoc.Validators) == 0 {
  200. cmn.Exit(cmn.Fmt("The genesis file has no validators"))
  201. }
  202. if genDoc.GenesisTime.IsZero() {
  203. genDoc.GenesisTime = time.Now()
  204. }
  205. // Make validators slice
  206. validators := make([]*types.Validator, len(genDoc.Validators))
  207. for i, val := range genDoc.Validators {
  208. pubKey := val.PubKey
  209. address := pubKey.Address()
  210. // Make validator
  211. validators[i] = &types.Validator{
  212. Address: address,
  213. PubKey: pubKey,
  214. VotingPower: val.Amount,
  215. }
  216. }
  217. return &State{
  218. db: db,
  219. GenesisDoc: genDoc,
  220. ChainID: genDoc.ChainID,
  221. LastBlockHeight: 0,
  222. LastBlockID: types.BlockID{},
  223. LastBlockTime: genDoc.GenesisTime,
  224. Validators: types.NewValidatorSet(validators),
  225. LastValidators: types.NewValidatorSet(nil),
  226. AppHash: genDoc.AppHash,
  227. TxIndexer: &null.TxIndex{}, // we do not need indexer during replay and in tests
  228. }
  229. }