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.

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