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.3 KiB

10 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
  1. package state
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "sync"
  6. "time"
  7. abci "github.com/tendermint/abci/types"
  8. . "github.com/tendermint/go-common"
  9. cfg "github.com/tendermint/go-config"
  10. dbm "github.com/tendermint/go-db"
  11. "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. // NOTE: not goroutine-safe.
  22. type State struct {
  23. // mtx for writing to db
  24. mtx sync.Mutex
  25. db dbm.DB
  26. // should not change
  27. GenesisDoc *types.GenesisDoc
  28. ChainID string
  29. // updated at end of SetBlockAndValidators
  30. LastBlockHeight int // Genesis state has this set to 0. So, Block(H=0) does not exist.
  31. LastBlockID types.BlockID
  32. LastBlockTime time.Time
  33. Validators *types.ValidatorSet
  34. LastValidators *types.ValidatorSet // block.LastCommit validated against this
  35. // AppHash is updated after Commit
  36. AppHash []byte
  37. TxIndexer txindex.TxIndexer `json:"-"` // Transaction indexer.
  38. // Intermediate results from processing
  39. // Persisted separately from the state
  40. abciResponses *ABCIResponses
  41. }
  42. func LoadState(db dbm.DB) *State {
  43. return loadState(db, stateKey)
  44. }
  45. func loadState(db dbm.DB, key []byte) *State {
  46. s := &State{db: db, TxIndexer: &null.TxIndex{}}
  47. buf := db.Get(key)
  48. if len(buf) == 0 {
  49. return nil
  50. } else {
  51. r, n, err := bytes.NewReader(buf), new(int), new(error)
  52. wire.ReadBinaryPtr(&s, r, 0, n, err)
  53. if *err != nil {
  54. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  55. Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err))
  56. }
  57. // TODO: ensure that buf is completely read.
  58. }
  59. s.LoadABCIResponses()
  60. return s
  61. }
  62. func (s *State) Copy() *State {
  63. return &State{
  64. db: s.db,
  65. GenesisDoc: s.GenesisDoc,
  66. ChainID: s.ChainID,
  67. LastBlockHeight: s.LastBlockHeight,
  68. LastBlockID: s.LastBlockID,
  69. LastBlockTime: s.LastBlockTime,
  70. Validators: s.Validators.Copy(),
  71. LastValidators: s.LastValidators.Copy(),
  72. AppHash: s.AppHash,
  73. abciResponses: s.abciResponses, // pointer here, not value
  74. TxIndexer: s.TxIndexer, // pointer here, not value
  75. }
  76. }
  77. func (s *State) Save() {
  78. s.mtx.Lock()
  79. defer s.mtx.Unlock()
  80. s.db.SetSync(stateKey, s.Bytes())
  81. }
  82. // Sets the ABCIResponses in the state and writes them to disk
  83. func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
  84. s.abciResponses = abciResponses
  85. // save the validators to the db
  86. s.db.SetSync(abciResponsesKey, s.abciResponses.Bytes())
  87. // save the tx results using the TxIndexer
  88. batch := txindexer.NewBatch()
  89. for i, r := range s.abciResponses.TxResults {
  90. tx := s.abciResponses.Txs[i]
  91. batch.Index(tx.Hash(), *r)
  92. }
  93. s.TxIndexer.Batch(batch)
  94. }
  95. func (s *State) LoadABCIResponses() {
  96. s.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(&s.abciResponses.Validators, r, 0, n, err)
  101. if *err != nil {
  102. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  103. Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err))
  104. }
  105. // TODO: ensure that buf is completely read.
  106. }
  107. }
  108. func (s *State) Equals(s2 *State) bool {
  109. return bytes.Equal(s.Bytes(), s2.Bytes())
  110. }
  111. func (s *State) Bytes() []byte {
  112. buf, n, err := new(bytes.Buffer), new(int), new(error)
  113. wire.WriteBinary(s, buf, n, err)
  114. if *err != nil {
  115. PanicCrisis(*err)
  116. }
  117. return buf.Bytes()
  118. }
  119. // Mutate state variables to match block and validators
  120. // after running EndBlock
  121. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader) {
  122. // copy the valset
  123. prevValSet := s.Validators.Copy()
  124. nextValSet := prevValSet.Copy()
  125. // update the validator set
  126. err := updateValidators(nextValSet, s.abciResponses.Validators)
  127. if err != nil {
  128. log.Warn("Error changing validator set", "error", err)
  129. // TODO: err or carry on?
  130. }
  131. // Update validator accums and set state variables
  132. nextValSet.IncrementAccum(1)
  133. s.setBlockAndValidators(header.Height,
  134. types.BlockID{header.Hash(), blockPartsHeader}, header.Time,
  135. prevValSet, nextValSet)
  136. }
  137. func (s *State) setBlockAndValidators(
  138. height int, blockID types.BlockID, blockTime time.Time,
  139. prevValSet, nextValSet *types.ValidatorSet) {
  140. s.LastBlockHeight = height
  141. s.LastBlockID = blockID
  142. s.LastBlockTime = blockTime
  143. s.Validators = nextValSet
  144. s.LastValidators = prevValSet
  145. }
  146. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
  147. return s.LastValidators, s.Validators
  148. }
  149. // Load the most recent state from "state" db,
  150. // or create a new one (and save) from genesis.
  151. func GetState(config cfg.Config, stateDB dbm.DB) *State {
  152. state := LoadState(stateDB)
  153. if state == nil {
  154. state = MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
  155. state.Save()
  156. }
  157. return state
  158. }
  159. //--------------------------------------------------
  160. // ABCIResponses holds intermediate state during block processing
  161. type ABCIResponses struct {
  162. Validators []*abci.Validator // changes to the validator set
  163. Txs types.Txs // for reference later
  164. TxResults []*types.TxResult // results of the txs, populated in the proxyCb
  165. }
  166. func NewABCIResponses(block *types.Block) *ABCIResponses {
  167. return &ABCIResponses{
  168. Txs: block.Data.Txs,
  169. TxResults: make([]*types.TxResult, block.NumTxs),
  170. }
  171. }
  172. // Serialize the list of validators
  173. func (a *ABCIResponses) Bytes() []byte {
  174. buf, n, err := new(bytes.Buffer), new(int), new(error)
  175. wire.WriteBinary(a.Validators, buf, n, err)
  176. if *err != nil {
  177. PanicCrisis(*err)
  178. }
  179. return buf.Bytes()
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Genesis
  183. // MakeGenesisStateFromFile reads and unmarshals state from the given file.
  184. //
  185. // Used during replay and in tests.
  186. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
  187. genDocJSON, err := ioutil.ReadFile(genDocFile)
  188. if err != nil {
  189. Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
  190. }
  191. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  192. if err != nil {
  193. Exit(Fmt("Error reading GenesisDoc: %v", err))
  194. }
  195. return MakeGenesisState(db, genDoc)
  196. }
  197. // MakeGenesisState creates state from types.GenesisDoc.
  198. //
  199. // Used in tests.
  200. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
  201. if len(genDoc.Validators) == 0 {
  202. Exit(Fmt("The genesis file has no validators"))
  203. }
  204. if genDoc.GenesisTime.IsZero() {
  205. genDoc.GenesisTime = time.Now()
  206. }
  207. // Make validators slice
  208. validators := make([]*types.Validator, len(genDoc.Validators))
  209. for i, val := range genDoc.Validators {
  210. pubKey := val.PubKey
  211. address := pubKey.Address()
  212. // Make validator
  213. validators[i] = &types.Validator{
  214. Address: address,
  215. PubKey: pubKey,
  216. VotingPower: val.Amount,
  217. }
  218. }
  219. return &State{
  220. db: db,
  221. GenesisDoc: genDoc,
  222. ChainID: genDoc.ChainID,
  223. LastBlockHeight: 0,
  224. LastBlockID: types.BlockID{},
  225. LastBlockTime: genDoc.GenesisTime,
  226. Validators: types.NewValidatorSet(validators),
  227. LastValidators: types.NewValidatorSet(nil),
  228. AppHash: genDoc.AppHash,
  229. TxIndexer: &null.TxIndex{}, // we do not need indexer during replay and in tests
  230. }
  231. }