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.

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