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.

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