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.

371 lines
11 KiB

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