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.

276 lines
7.3 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
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. // 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. logger log.Logger
  42. }
  43. func LoadState(db dbm.DB) *State {
  44. return loadState(db, stateKey)
  45. }
  46. func loadState(db dbm.DB, key []byte) *State {
  47. s := &State{db: db, TxIndexer: &null.TxIndex{}}
  48. buf := db.Get(key)
  49. if len(buf) == 0 {
  50. return nil
  51. } else {
  52. r, n, err := bytes.NewReader(buf), new(int), new(error)
  53. wire.ReadBinaryPtr(&s, r, 0, n, err)
  54. if *err != nil {
  55. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  56. cmn.Exit(cmn.Fmt("LoadState: Data has been corrupted or its spec has changed: %v\n", *err))
  57. }
  58. // TODO: ensure that buf is completely read.
  59. }
  60. return s
  61. }
  62. func (s *State) SetLogger(l log.Logger) {
  63. s.logger = l
  64. }
  65. func (s *State) Copy() *State {
  66. return &State{
  67. db: s.db,
  68. GenesisDoc: s.GenesisDoc,
  69. ChainID: s.ChainID,
  70. LastBlockHeight: s.LastBlockHeight,
  71. LastBlockID: s.LastBlockID,
  72. LastBlockTime: s.LastBlockTime,
  73. Validators: s.Validators.Copy(),
  74. LastValidators: s.LastValidators.Copy(),
  75. AppHash: s.AppHash,
  76. TxIndexer: s.TxIndexer, // pointer here, not value
  77. logger: s.logger,
  78. }
  79. }
  80. func (s *State) Save() {
  81. s.mtx.Lock()
  82. defer s.mtx.Unlock()
  83. s.db.SetSync(stateKey, s.Bytes())
  84. }
  85. // Sets the ABCIResponses in the state and writes them to disk
  86. // in case we crash after app.Commit and before s.Save()
  87. func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
  88. // save the validators to the db
  89. s.db.SetSync(abciResponsesKey, abciResponses.Bytes())
  90. }
  91. func (s *State) LoadABCIResponses() *ABCIResponses {
  92. abciResponses := new(ABCIResponses)
  93. buf := s.db.Get(abciResponsesKey)
  94. if len(buf) != 0 {
  95. r, n, err := bytes.NewReader(buf), new(int), new(error)
  96. wire.ReadBinaryPtr(abciResponses, r, 0, n, err)
  97. if *err != nil {
  98. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  99. cmn.Exit(cmn.Fmt("LoadABCIResponses: Data has been corrupted or its spec has changed: %v\n", *err))
  100. }
  101. // TODO: ensure that buf is completely read.
  102. }
  103. return abciResponses
  104. }
  105. func (s *State) Equals(s2 *State) bool {
  106. return bytes.Equal(s.Bytes(), s2.Bytes())
  107. }
  108. func (s *State) Bytes() []byte {
  109. buf, n, err := new(bytes.Buffer), new(int), new(error)
  110. wire.WriteBinary(s, buf, n, err)
  111. if *err != nil {
  112. cmn.PanicCrisis(*err)
  113. }
  114. return buf.Bytes()
  115. }
  116. // Mutate state variables to match block and validators
  117. // 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. // update the validator set with the latest abciResponses
  124. err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs)
  125. if err != nil {
  126. s.logger.Error("Error changing validator set", "error", err)
  127. // TODO: err or carry on?
  128. }
  129. // Update validator accums and set state variables
  130. nextValSet.IncrementAccum(1)
  131. s.setBlockAndValidators(header.Height,
  132. types.BlockID{header.Hash(), blockPartsHeader}, header.Time,
  133. prevValSet, nextValSet)
  134. }
  135. func (s *State) setBlockAndValidators(
  136. height int, blockID types.BlockID, blockTime time.Time,
  137. prevValSet, nextValSet *types.ValidatorSet) {
  138. s.LastBlockHeight = height
  139. s.LastBlockID = blockID
  140. s.LastBlockTime = blockTime
  141. s.Validators = nextValSet
  142. s.LastValidators = prevValSet
  143. }
  144. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
  145. return s.LastValidators, s.Validators
  146. }
  147. // Load the most recent state from "state" db,
  148. // or create a new one (and save) from genesis.
  149. func GetState(stateDB dbm.DB, genesisFile string) *State {
  150. state := LoadState(stateDB)
  151. if state == nil {
  152. state = MakeGenesisStateFromFile(stateDB, genesisFile)
  153. state.Save()
  154. }
  155. return state
  156. }
  157. //--------------------------------------------------
  158. // ABCIResponses holds intermediate state during block processing
  159. type ABCIResponses struct {
  160. Height int
  161. DeliverTx []*abci.ResponseDeliverTx
  162. EndBlock abci.ResponseEndBlock
  163. txs types.Txs // reference for indexing results by hash
  164. }
  165. func NewABCIResponses(block *types.Block) *ABCIResponses {
  166. return &ABCIResponses{
  167. Height: block.Height,
  168. DeliverTx: make([]*abci.ResponseDeliverTx, block.NumTxs),
  169. txs: block.Data.Txs,
  170. }
  171. }
  172. // Serialize the ABCIResponse
  173. func (a *ABCIResponses) Bytes() []byte {
  174. buf, n, err := new(bytes.Buffer), new(int), new(error)
  175. wire.WriteBinary(*a, buf, n, err)
  176. if *err != nil {
  177. cmn.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. cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err))
  190. }
  191. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  192. if err != nil {
  193. cmn.Exit(cmn.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. cmn.Exit(cmn.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. }