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.

505 lines
15 KiB

8 years ago
8 years ago
8 years ago
10 years ago
8 years ago
10 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 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/types"
  14. )
  15. // database keys
  16. var (
  17. stateKey = []byte("stateKey")
  18. )
  19. func calcValidatorsKey(height int64) []byte {
  20. return []byte(cmn.Fmt("validatorsKey:%v", height))
  21. }
  22. func calcConsensusParamsKey(height int64) []byte {
  23. return []byte(cmn.Fmt("consensusParamsKey:%v", height))
  24. }
  25. func calcABCIResponsesKey(height int64) []byte {
  26. return []byte(cmn.Fmt("abciResponsesKey:%v", height))
  27. }
  28. //-----------------------------------------------------------------------------
  29. // State is a short description of the latest committed block of the Tendermint consensus.
  30. // It keeps all information necessary to validate new blocks,
  31. // including the last validator set and the consensus params.
  32. // All fields are exposed so the struct can be easily serialized,
  33. // but the fields should only be changed by calling state.SetBlockAndValidators.
  34. // NOTE: not goroutine-safe.
  35. type State struct {
  36. // mtx for writing to db
  37. mtx sync.Mutex
  38. db dbm.DB
  39. // Immutable
  40. ChainID string
  41. // Exposed fields are updated by SetBlockAndValidators.
  42. // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist)
  43. LastBlockHeight int64
  44. LastBlockTotalTx int64
  45. LastBlockID types.BlockID
  46. LastBlockTime time.Time
  47. // LastValidators is used to validate block.LastCommit.
  48. // Validators are persisted to the database separately every time they change,
  49. // so we can query for historical validator sets.
  50. // Note that if s.LastBlockHeight causes a valset change,
  51. // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1
  52. Validators *types.ValidatorSet
  53. LastValidators *types.ValidatorSet
  54. LastHeightValidatorsChanged int64
  55. // Consensus parameters used for validating blocks.
  56. // Changes returned by EndBlock and updated after Commit.
  57. ConsensusParams types.ConsensusParams
  58. LastHeightConsensusParamsChanged int64
  59. // Merkle root of the results from executing prev block
  60. LastResultsHash []byte
  61. // The latest AppHash we've received from calling abci.Commit()
  62. AppHash []byte
  63. logger log.Logger
  64. }
  65. // GetState loads the most recent state from the database,
  66. // or creates a new one from the given genesisFile and persists the result
  67. // to the database.
  68. func GetState(stateDB dbm.DB, genesisFile string) (*State, error) {
  69. state := LoadState(stateDB)
  70. if state == nil {
  71. var err error
  72. state, err = MakeGenesisStateFromFile(stateDB, genesisFile)
  73. if err != nil {
  74. return nil, err
  75. }
  76. state.Save()
  77. }
  78. return state, nil
  79. }
  80. // LoadState loads the State from the database.
  81. func LoadState(db dbm.DB) *State {
  82. return loadState(db, stateKey)
  83. }
  84. func loadState(db dbm.DB, key []byte) *State {
  85. buf := db.Get(key)
  86. if len(buf) == 0 {
  87. return nil
  88. }
  89. s := &State{db: db}
  90. r, n, err := bytes.NewReader(buf), new(int), new(error)
  91. wire.ReadBinaryPtr(&s, r, 0, n, err)
  92. if *err != nil {
  93. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  94. cmn.Exit(cmn.Fmt(`LoadState: Data has been corrupted or its spec has changed:
  95. %v\n`, *err))
  96. }
  97. // TODO: ensure that buf is completely read.
  98. return s
  99. }
  100. // SetLogger sets the logger on the State.
  101. func (s *State) SetLogger(l log.Logger) {
  102. s.logger = l
  103. }
  104. // Copy makes a copy of the State for mutating.
  105. func (s *State) Copy() *State {
  106. return &State{
  107. db: s.db,
  108. ChainID: s.ChainID,
  109. LastBlockHeight: s.LastBlockHeight,
  110. LastBlockTotalTx: s.LastBlockTotalTx,
  111. LastBlockID: s.LastBlockID,
  112. LastBlockTime: s.LastBlockTime,
  113. Validators: s.Validators.Copy(),
  114. LastValidators: s.LastValidators.Copy(),
  115. LastHeightValidatorsChanged: s.LastHeightValidatorsChanged,
  116. ConsensusParams: s.ConsensusParams,
  117. LastHeightConsensusParamsChanged: s.LastHeightConsensusParamsChanged,
  118. AppHash: s.AppHash,
  119. LastResultsHash: s.LastResultsHash,
  120. logger: s.logger,
  121. }
  122. }
  123. // Save persists the State to the database.
  124. func (s *State) Save() {
  125. s.mtx.Lock()
  126. defer s.mtx.Unlock()
  127. s.saveValidatorsInfo()
  128. s.saveConsensusParamsInfo()
  129. s.db.SetSync(stateKey, s.Bytes())
  130. }
  131. // SaveABCIResponses persists the ABCIResponses to the database.
  132. // This is useful in case we crash after app.Commit and before s.Save().
  133. // Responses are indexed by height so they can also be loaded later to produce Merkle proofs.
  134. func (s *State) SaveABCIResponses(height int64, abciResponses *ABCIResponses) {
  135. s.db.SetSync(calcABCIResponsesKey(height), abciResponses.Bytes())
  136. }
  137. // LoadABCIResponses loads the ABCIResponses for the given height from the database.
  138. // This is useful for recovering from crashes where we called app.Commit and before we called
  139. // s.Save(). It can also be used to produce Merkle proofs of the result of txs.
  140. func (s *State) LoadABCIResponses(height int64) (*ABCIResponses, error) {
  141. buf := s.db.Get(calcABCIResponsesKey(height))
  142. if len(buf) == 0 {
  143. return nil, ErrNoABCIResponsesForHeight{height}
  144. }
  145. abciResponses := new(ABCIResponses)
  146. r, n, err := bytes.NewReader(buf), new(int), new(error)
  147. wire.ReadBinaryPtr(abciResponses, r, 0, n, err)
  148. if *err != nil {
  149. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  150. cmn.Exit(cmn.Fmt(`LoadABCIResponses: Data has been corrupted or its spec has
  151. changed: %v\n`, *err))
  152. }
  153. // TODO: ensure that buf is completely read.
  154. return abciResponses, nil
  155. }
  156. // LoadValidators loads the ValidatorSet for a given height.
  157. func (s *State) LoadValidators(height int64) (*types.ValidatorSet, error) {
  158. valInfo := s.loadValidatorsInfo(height)
  159. if valInfo == nil {
  160. return nil, ErrNoValSetForHeight{height}
  161. }
  162. if valInfo.ValidatorSet == nil {
  163. valInfo = s.loadValidatorsInfo(valInfo.LastHeightChanged)
  164. if valInfo == nil {
  165. cmn.PanicSanity(fmt.Sprintf(`Couldn't find validators at height %d as
  166. last changed from height %d`, valInfo.LastHeightChanged, height))
  167. }
  168. }
  169. return valInfo.ValidatorSet, nil
  170. }
  171. func (s *State) loadValidatorsInfo(height int64) *ValidatorsInfo {
  172. buf := s.db.Get(calcValidatorsKey(height))
  173. if len(buf) == 0 {
  174. return nil
  175. }
  176. v := new(ValidatorsInfo)
  177. r, n, err := bytes.NewReader(buf), new(int), new(error)
  178. wire.ReadBinaryPtr(v, r, 0, n, err)
  179. if *err != nil {
  180. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  181. cmn.Exit(cmn.Fmt(`LoadValidators: Data has been corrupted or its spec has changed:
  182. %v\n`, *err))
  183. }
  184. // TODO: ensure that buf is completely read.
  185. return v
  186. }
  187. // saveValidatorsInfo persists the validator set for the next block to disk.
  188. // It should be called from s.Save(), right before the state itself is persisted.
  189. // If the validator set did not change after processing the latest block,
  190. // only the last height for which the validators changed is persisted.
  191. func (s *State) saveValidatorsInfo() {
  192. changeHeight := s.LastHeightValidatorsChanged
  193. nextHeight := s.LastBlockHeight + 1
  194. valInfo := &ValidatorsInfo{
  195. LastHeightChanged: changeHeight,
  196. }
  197. if changeHeight == nextHeight {
  198. valInfo.ValidatorSet = s.Validators
  199. }
  200. s.db.SetSync(calcValidatorsKey(nextHeight), valInfo.Bytes())
  201. }
  202. // LoadConsensusParams loads the ConsensusParams for a given height.
  203. func (s *State) LoadConsensusParams(height int64) (types.ConsensusParams, error) {
  204. empty := types.ConsensusParams{}
  205. paramsInfo := s.loadConsensusParamsInfo(height)
  206. if paramsInfo == nil {
  207. return empty, ErrNoConsensusParamsForHeight{height}
  208. }
  209. if paramsInfo.ConsensusParams == empty {
  210. paramsInfo = s.loadConsensusParamsInfo(paramsInfo.LastHeightChanged)
  211. if paramsInfo == nil {
  212. cmn.PanicSanity(fmt.Sprintf(`Couldn't find consensus params at height %d as
  213. last changed from height %d`, paramsInfo.LastHeightChanged, height))
  214. }
  215. }
  216. return paramsInfo.ConsensusParams, nil
  217. }
  218. func (s *State) loadConsensusParamsInfo(height int64) *ConsensusParamsInfo {
  219. buf := s.db.Get(calcConsensusParamsKey(height))
  220. if len(buf) == 0 {
  221. return nil
  222. }
  223. paramsInfo := new(ConsensusParamsInfo)
  224. r, n, err := bytes.NewReader(buf), new(int), new(error)
  225. wire.ReadBinaryPtr(paramsInfo, r, 0, n, err)
  226. if *err != nil {
  227. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  228. cmn.Exit(cmn.Fmt(`LoadConsensusParams: Data has been corrupted or its spec has changed:
  229. %v\n`, *err))
  230. }
  231. // TODO: ensure that buf is completely read.
  232. return paramsInfo
  233. }
  234. // saveConsensusParamsInfo persists the consensus params for the next block to disk.
  235. // It should be called from s.Save(), right before the state itself is persisted.
  236. // If the consensus params did not change after processing the latest block,
  237. // only the last height for which they changed is persisted.
  238. func (s *State) saveConsensusParamsInfo() {
  239. changeHeight := s.LastHeightConsensusParamsChanged
  240. nextHeight := s.LastBlockHeight + 1
  241. paramsInfo := &ConsensusParamsInfo{
  242. LastHeightChanged: changeHeight,
  243. }
  244. if changeHeight == nextHeight {
  245. paramsInfo.ConsensusParams = s.ConsensusParams
  246. }
  247. s.db.SetSync(calcConsensusParamsKey(nextHeight), paramsInfo.Bytes())
  248. }
  249. // Equals returns true if the States are identical.
  250. func (s *State) Equals(s2 *State) bool {
  251. return bytes.Equal(s.Bytes(), s2.Bytes())
  252. }
  253. // Bytes serializes the State using go-wire.
  254. func (s *State) Bytes() []byte {
  255. return wire.BinaryBytes(s)
  256. }
  257. // SetBlockAndValidators mutates State variables
  258. // to update block and validators after running EndBlock.
  259. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader,
  260. abciResponses *ABCIResponses) error {
  261. // copy the valset so we can apply changes from EndBlock
  262. // and update s.LastValidators and s.Validators
  263. prevValSet := s.Validators.Copy()
  264. nextValSet := prevValSet.Copy()
  265. // update the validator set with the latest abciResponses
  266. if len(abciResponses.EndBlock.ValidatorUpdates) > 0 {
  267. err := updateValidators(nextValSet, abciResponses.EndBlock.ValidatorUpdates)
  268. if err != nil {
  269. return fmt.Errorf("Error changing validator set: %v", err)
  270. }
  271. // change results from this height but only applies to the next height
  272. s.LastHeightValidatorsChanged = header.Height + 1
  273. }
  274. // Update validator accums and set state variables
  275. nextValSet.IncrementAccum(1)
  276. // update the params with the latest abciResponses
  277. nextParams := s.ConsensusParams
  278. if abciResponses.EndBlock.ConsensusParamUpdates != nil {
  279. // NOTE: must not mutate s.ConsensusParams
  280. nextParams = s.ConsensusParams.Update(abciResponses.EndBlock.ConsensusParamUpdates)
  281. err := nextParams.Validate()
  282. if err != nil {
  283. return fmt.Errorf("Error updating consensus params: %v", err)
  284. }
  285. // change results from this height but only applies to the next height
  286. s.LastHeightConsensusParamsChanged = header.Height + 1
  287. }
  288. s.setBlockAndValidators(header.Height,
  289. header.NumTxs,
  290. types.BlockID{header.Hash(), blockPartsHeader},
  291. header.Time,
  292. nextValSet,
  293. nextParams,
  294. abciResponses.ResultsHash())
  295. return nil
  296. }
  297. func (s *State) setBlockAndValidators(height int64,
  298. newTxs int64, blockID types.BlockID, blockTime time.Time,
  299. valSet *types.ValidatorSet,
  300. params types.ConsensusParams,
  301. resultsHash []byte) {
  302. s.LastBlockHeight = height
  303. s.LastBlockTotalTx += newTxs
  304. s.LastBlockID = blockID
  305. s.LastBlockTime = blockTime
  306. s.LastValidators = s.Validators.Copy()
  307. s.Validators = valSet
  308. s.ConsensusParams = params
  309. s.LastResultsHash = resultsHash
  310. }
  311. // GetValidators returns the last and current validator sets.
  312. func (s *State) GetValidators() (last *types.ValidatorSet, current *types.ValidatorSet) {
  313. return s.LastValidators, s.Validators
  314. }
  315. //------------------------------------------------------------------------
  316. // ABCIResponses retains the responses
  317. // of the various ABCI calls during block processing.
  318. // It is persisted to disk for each height before calling Commit.
  319. type ABCIResponses struct {
  320. DeliverTx []*abci.ResponseDeliverTx
  321. EndBlock *abci.ResponseEndBlock
  322. }
  323. // NewABCIResponses returns a new ABCIResponses
  324. func NewABCIResponses(block *types.Block) *ABCIResponses {
  325. return &ABCIResponses{
  326. DeliverTx: make([]*abci.ResponseDeliverTx, block.NumTxs),
  327. }
  328. }
  329. // Bytes serializes the ABCIResponse using go-wire
  330. func (a *ABCIResponses) Bytes() []byte {
  331. return wire.BinaryBytes(*a)
  332. }
  333. func (a *ABCIResponses) ResultsHash() []byte {
  334. results := types.NewResults(a.DeliverTx)
  335. return results.Hash()
  336. }
  337. //-----------------------------------------------------------------------------
  338. // ValidatorsInfo represents the latest validator set, or the last height it changed
  339. type ValidatorsInfo struct {
  340. ValidatorSet *types.ValidatorSet
  341. LastHeightChanged int64
  342. }
  343. // Bytes serializes the ValidatorsInfo using go-wire
  344. func (valInfo *ValidatorsInfo) Bytes() []byte {
  345. return wire.BinaryBytes(*valInfo)
  346. }
  347. //-----------------------------------------------------------------------------
  348. // ConsensusParamsInfo represents the latest consensus params, or the last height it changed
  349. type ConsensusParamsInfo struct {
  350. ConsensusParams types.ConsensusParams
  351. LastHeightChanged int64
  352. }
  353. // Bytes serializes the ConsensusParamsInfo using go-wire
  354. func (params ConsensusParamsInfo) Bytes() []byte {
  355. return wire.BinaryBytes(params)
  356. }
  357. //------------------------------------------------------------------------
  358. // Genesis
  359. // MakeGenesisStateFromFile reads and unmarshals state from the given
  360. // file.
  361. //
  362. // Used during replay and in tests.
  363. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*State, error) {
  364. genDoc, err := MakeGenesisDocFromFile(genDocFile)
  365. if err != nil {
  366. return nil, err
  367. }
  368. return MakeGenesisState(db, genDoc)
  369. }
  370. // MakeGenesisDocFromFile reads and unmarshals genesis doc from the given file.
  371. func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
  372. genDocJSON, err := ioutil.ReadFile(genDocFile)
  373. if err != nil {
  374. return nil, fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
  375. }
  376. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  377. if err != nil {
  378. return nil, fmt.Errorf("Error reading GenesisDoc: %v", err)
  379. }
  380. return genDoc, nil
  381. }
  382. // MakeGenesisState creates state from types.GenesisDoc.
  383. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) (*State, error) {
  384. err := genDoc.ValidateAndComplete()
  385. if err != nil {
  386. return nil, fmt.Errorf("Error in genesis file: %v", err)
  387. }
  388. // Make validators slice
  389. validators := make([]*types.Validator, len(genDoc.Validators))
  390. for i, val := range genDoc.Validators {
  391. pubKey := val.PubKey
  392. address := pubKey.Address()
  393. // Make validator
  394. validators[i] = &types.Validator{
  395. Address: address,
  396. PubKey: pubKey,
  397. VotingPower: val.Power,
  398. }
  399. }
  400. return &State{
  401. db: db,
  402. ChainID: genDoc.ChainID,
  403. LastBlockHeight: 0,
  404. LastBlockID: types.BlockID{},
  405. LastBlockTime: genDoc.GenesisTime,
  406. Validators: types.NewValidatorSet(validators),
  407. LastValidators: types.NewValidatorSet(nil),
  408. LastHeightValidatorsChanged: 1,
  409. ConsensusParams: *genDoc.ConsensusParams,
  410. LastHeightConsensusParamsChanged: 1,
  411. AppHash: genDoc.AppHash,
  412. }, nil
  413. }