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.

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