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.

279 lines
7.4 KiB

7 years ago
7 years ago
7 years ago
10 years ago
8 years ago
7 years ago
10 years ago
10 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
7 years ago
7 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) GetLogger() log.Logger {
  66. return s.logger
  67. }
  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. func (s *State) Save() {
  84. s.mtx.Lock()
  85. defer s.mtx.Unlock()
  86. s.db.SetSync(stateKey, s.Bytes())
  87. }
  88. // Sets the ABCIResponses in the state and writes them to disk
  89. // in case we crash after app.Commit and before s.Save()
  90. func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
  91. // save the validators to the db
  92. s.db.SetSync(abciResponsesKey, abciResponses.Bytes())
  93. }
  94. func (s *State) LoadABCIResponses() *ABCIResponses {
  95. abciResponses := new(ABCIResponses)
  96. buf := s.db.Get(abciResponsesKey)
  97. if len(buf) != 0 {
  98. r, n, err := bytes.NewReader(buf), new(int), new(error)
  99. wire.ReadBinaryPtr(abciResponses, r, 0, n, err)
  100. if *err != nil {
  101. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  102. cmn.Exit(cmn.Fmt("LoadABCIResponses: Data has been corrupted or its spec has changed: %v\n", *err))
  103. }
  104. // TODO: ensure that buf is completely read.
  105. }
  106. return abciResponses
  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. cmn.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, abciResponses *ABCIResponses) {
  122. // copy the valset so we can apply changes from EndBlock
  123. // and update s.LastValidators and s.Validators
  124. prevValSet := s.Validators.Copy()
  125. nextValSet := prevValSet.Copy()
  126. // update the validator set with the latest abciResponses
  127. err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs)
  128. if err != nil {
  129. s.logger.Error("Error changing validator set", "error", err)
  130. // TODO: err or carry on?
  131. }
  132. // Update validator accums and set state variables
  133. nextValSet.IncrementAccum(1)
  134. s.setBlockAndValidators(header.Height,
  135. types.BlockID{header.Hash(), blockPartsHeader}, header.Time,
  136. prevValSet, nextValSet)
  137. }
  138. func (s *State) setBlockAndValidators(
  139. height int, blockID types.BlockID, blockTime time.Time,
  140. prevValSet, nextValSet *types.ValidatorSet) {
  141. s.LastBlockHeight = height
  142. s.LastBlockID = blockID
  143. s.LastBlockTime = blockTime
  144. s.Validators = nextValSet
  145. s.LastValidators = prevValSet
  146. }
  147. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
  148. return s.LastValidators, s.Validators
  149. }
  150. // Load the most recent state from "state" db,
  151. // or create a new one (and save) from genesis.
  152. func GetState(stateDB dbm.DB, genesisFile string) *State {
  153. state := LoadState(stateDB)
  154. if state == nil {
  155. state = MakeGenesisStateFromFile(stateDB, genesisFile)
  156. state.Save()
  157. }
  158. return state
  159. }
  160. //--------------------------------------------------
  161. // ABCIResponses holds intermediate state during block processing
  162. type ABCIResponses struct {
  163. Height int
  164. DeliverTx []*abci.ResponseDeliverTx
  165. EndBlock abci.ResponseEndBlock
  166. txs types.Txs // reference for indexing results by hash
  167. }
  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. // Serialize the ABCIResponse
  176. func (a *ABCIResponses) Bytes() []byte {
  177. buf, n, err := new(bytes.Buffer), new(int), new(error)
  178. wire.WriteBinary(*a, buf, n, err)
  179. if *err != nil {
  180. cmn.PanicCrisis(*err)
  181. }
  182. return buf.Bytes()
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Genesis
  186. // MakeGenesisStateFromFile reads and unmarshals state from the given file.
  187. //
  188. // Used during replay and in tests.
  189. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
  190. genDocJSON, err := ioutil.ReadFile(genDocFile)
  191. if err != nil {
  192. cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err))
  193. }
  194. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  195. if err != nil {
  196. cmn.Exit(cmn.Fmt("Error reading GenesisDoc: %v", err))
  197. }
  198. return MakeGenesisState(db, genDoc)
  199. }
  200. // MakeGenesisState creates state from types.GenesisDoc.
  201. //
  202. // Used in tests.
  203. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
  204. if len(genDoc.Validators) == 0 {
  205. cmn.Exit(cmn.Fmt("The genesis file has no validators"))
  206. }
  207. if genDoc.GenesisTime.IsZero() {
  208. genDoc.GenesisTime = time.Now()
  209. }
  210. // Make validators slice
  211. validators := make([]*types.Validator, len(genDoc.Validators))
  212. for i, val := range genDoc.Validators {
  213. pubKey := val.PubKey
  214. address := pubKey.Address()
  215. // Make validator
  216. validators[i] = &types.Validator{
  217. Address: address,
  218. PubKey: pubKey,
  219. VotingPower: val.Amount,
  220. }
  221. }
  222. return &State{
  223. db: db,
  224. GenesisDoc: genDoc,
  225. ChainID: genDoc.ChainID,
  226. LastBlockHeight: 0,
  227. LastBlockID: types.BlockID{},
  228. LastBlockTime: genDoc.GenesisTime,
  229. Validators: types.NewValidatorSet(validators),
  230. LastValidators: types.NewValidatorSet(nil),
  231. AppHash: genDoc.AppHash,
  232. TxIndexer: &null.TxIndex{}, // we do not need indexer during replay and in tests
  233. }
  234. }