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.

272 lines
7.2 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
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. logger log.Logger
  39. }
  40. func LoadState(db dbm.DB) *State {
  41. return loadState(db, stateKey)
  42. }
  43. func loadState(db dbm.DB, key []byte) *State {
  44. s := &State{db: db, TxIndexer: &null.TxIndex{}}
  45. buf := db.Get(key)
  46. if len(buf) == 0 {
  47. return nil
  48. } else {
  49. r, n, err := bytes.NewReader(buf), new(int), new(error)
  50. wire.ReadBinaryPtr(&s, r, 0, n, err)
  51. if *err != nil {
  52. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  53. cmn.Exit(cmn.Fmt("LoadState: Data has been corrupted or its spec has changed: %v\n", *err))
  54. }
  55. // TODO: ensure that buf is completely read.
  56. }
  57. return s
  58. }
  59. func (s *State) SetLogger(l log.Logger) {
  60. s.logger = l
  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. TxIndexer: s.TxIndexer, // pointer here, not value
  74. logger: s.logger,
  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. // in case we crash after app.Commit and before s.Save()
  84. func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
  85. // save the validators to the db
  86. s.db.SetSync(abciResponsesKey, abciResponses.Bytes())
  87. }
  88. func (s *State) LoadABCIResponses() *ABCIResponses {
  89. abciResponses := new(ABCIResponses)
  90. buf := s.db.Get(abciResponsesKey)
  91. if len(buf) != 0 {
  92. r, n, err := bytes.NewReader(buf), new(int), new(error)
  93. wire.ReadBinaryPtr(abciResponses, r, 0, n, err)
  94. if *err != nil {
  95. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  96. cmn.Exit(cmn.Fmt("LoadABCIResponses: Data has been corrupted or its spec has changed: %v\n", *err))
  97. }
  98. // TODO: ensure that buf is completely read.
  99. }
  100. return abciResponses
  101. }
  102. func (s *State) Equals(s2 *State) bool {
  103. return bytes.Equal(s.Bytes(), s2.Bytes())
  104. }
  105. func (s *State) Bytes() []byte {
  106. buf, n, err := new(bytes.Buffer), new(int), new(error)
  107. wire.WriteBinary(s, buf, n, err)
  108. if *err != nil {
  109. cmn.PanicCrisis(*err)
  110. }
  111. return buf.Bytes()
  112. }
  113. // Mutate state variables to match block and validators
  114. // after running EndBlock
  115. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader, abciResponses *ABCIResponses) {
  116. // copy the valset so we can apply changes from EndBlock
  117. // and update s.LastValidators and s.Validators
  118. prevValSet := s.Validators.Copy()
  119. nextValSet := prevValSet.Copy()
  120. // update the validator set with the latest abciResponses
  121. err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs)
  122. if err != nil {
  123. s.logger.Error("Error changing validator set", "err", err)
  124. // TODO: err or carry on?
  125. }
  126. // Update validator accums and set state variables
  127. nextValSet.IncrementAccum(1)
  128. s.setBlockAndValidators(header.Height,
  129. types.BlockID{header.Hash(), blockPartsHeader}, header.Time,
  130. prevValSet, nextValSet)
  131. }
  132. func (s *State) setBlockAndValidators(
  133. height int, blockID types.BlockID, blockTime time.Time,
  134. prevValSet, nextValSet *types.ValidatorSet) {
  135. s.LastBlockHeight = height
  136. s.LastBlockID = blockID
  137. s.LastBlockTime = blockTime
  138. s.Validators = nextValSet
  139. s.LastValidators = prevValSet
  140. }
  141. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
  142. return s.LastValidators, s.Validators
  143. }
  144. // Load the most recent state from "state" db,
  145. // or create a new one (and save) from genesis.
  146. func GetState(stateDB dbm.DB, genesisFile string) *State {
  147. state := LoadState(stateDB)
  148. if state == nil {
  149. state = MakeGenesisStateFromFile(stateDB, genesisFile)
  150. state.Save()
  151. }
  152. return state
  153. }
  154. //--------------------------------------------------
  155. // ABCIResponses holds intermediate state during block processing
  156. type ABCIResponses struct {
  157. Height int
  158. DeliverTx []*abci.ResponseDeliverTx
  159. EndBlock abci.ResponseEndBlock
  160. txs types.Txs // reference for indexing results by hash
  161. }
  162. func NewABCIResponses(block *types.Block) *ABCIResponses {
  163. return &ABCIResponses{
  164. Height: block.Height,
  165. DeliverTx: make([]*abci.ResponseDeliverTx, block.NumTxs),
  166. txs: block.Data.Txs,
  167. }
  168. }
  169. // Serialize the ABCIResponse
  170. func (a *ABCIResponses) Bytes() []byte {
  171. buf, n, err := new(bytes.Buffer), new(int), new(error)
  172. wire.WriteBinary(*a, buf, n, err)
  173. if *err != nil {
  174. cmn.PanicCrisis(*err)
  175. }
  176. return buf.Bytes()
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Genesis
  180. // MakeGenesisStateFromFile reads and unmarshals state from the given file.
  181. //
  182. // Used during replay and in tests.
  183. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
  184. genDocJSON, err := ioutil.ReadFile(genDocFile)
  185. if err != nil {
  186. cmn.Exit(cmn.Fmt("Couldn't read GenesisDoc file: %v", err))
  187. }
  188. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  189. if err != nil {
  190. cmn.Exit(cmn.Fmt("Error reading GenesisDoc: %v", err))
  191. }
  192. return MakeGenesisState(db, genDoc)
  193. }
  194. // MakeGenesisState creates state from types.GenesisDoc.
  195. //
  196. // Used in tests.
  197. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
  198. if len(genDoc.Validators) == 0 {
  199. cmn.Exit(cmn.Fmt("The genesis file has no validators"))
  200. }
  201. if genDoc.GenesisTime.IsZero() {
  202. genDoc.GenesisTime = time.Now()
  203. }
  204. // Make validators slice
  205. validators := make([]*types.Validator, len(genDoc.Validators))
  206. for i, val := range genDoc.Validators {
  207. pubKey := val.PubKey
  208. address := pubKey.Address()
  209. // Make validator
  210. validators[i] = &types.Validator{
  211. Address: address,
  212. PubKey: pubKey,
  213. VotingPower: val.Amount,
  214. }
  215. }
  216. return &State{
  217. db: db,
  218. GenesisDoc: genDoc,
  219. ChainID: genDoc.ChainID,
  220. LastBlockHeight: 0,
  221. LastBlockID: types.BlockID{},
  222. LastBlockTime: genDoc.GenesisTime,
  223. Validators: types.NewValidatorSet(validators),
  224. LastValidators: types.NewValidatorSet(nil),
  225. AppHash: genDoc.AppHash,
  226. TxIndexer: &null.TxIndex{}, // we do not need indexer during replay and in tests
  227. }
  228. }