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.

438 lines
12 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. // LastConsensusHash is updated after Commit
  51. LastConsensusHash []byte
  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. buf := db.Get(key)
  75. if len(buf) == 0 {
  76. return nil
  77. }
  78. s := &State{db: db}
  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:
  84. %v\n`, *err))
  85. }
  86. // TODO: ensure that buf is completely read.
  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. LastBlockTotalTx: s.LastBlockTotalTx,
  99. LastBlockID: s.LastBlockID,
  100. LastBlockTime: s.LastBlockTime,
  101. Validators: s.Validators.Copy(),
  102. LastValidators: s.LastValidators.Copy(),
  103. AppHash: s.AppHash,
  104. LastConsensusHash: s.LastConsensusHash,
  105. LastHeightValidatorsChanged: s.LastHeightValidatorsChanged,
  106. logger: s.logger,
  107. ChainID: s.ChainID,
  108. Params: s.Params,
  109. }
  110. }
  111. // Save persists the State to the database.
  112. func (s *State) Save() {
  113. s.mtx.Lock()
  114. defer s.mtx.Unlock()
  115. s.saveValidatorsInfo()
  116. s.db.SetSync(stateKey, s.Bytes())
  117. }
  118. // SaveABCIResponses persists the ABCIResponses to the database.
  119. // This is useful in case we crash after app.Commit and before s.Save().
  120. func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
  121. s.db.SetSync(abciResponsesKey, abciResponses.Bytes())
  122. }
  123. // LoadABCIResponses loads the ABCIResponses from the database.
  124. // This is useful for recovering from crashes where we called app.Commit and before we called
  125. // s.Save()
  126. func (s *State) LoadABCIResponses() *ABCIResponses {
  127. buf := s.db.Get(abciResponsesKey)
  128. if len(buf) == 0 {
  129. return nil
  130. }
  131. abciResponses := new(ABCIResponses)
  132. r, n, err := bytes.NewReader(buf), new(int), new(error)
  133. wire.ReadBinaryPtr(abciResponses, r, 0, n, err)
  134. if *err != nil {
  135. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  136. cmn.Exit(cmn.Fmt(`LoadABCIResponses: Data has been corrupted or its spec has
  137. changed: %v\n`, *err))
  138. }
  139. // TODO: ensure that buf is completely read.
  140. return abciResponses
  141. }
  142. // LoadValidators loads the ValidatorSet for a given height.
  143. func (s *State) LoadValidators(height int64) (*types.ValidatorSet, error) {
  144. valInfo := s.loadValidators(height)
  145. if valInfo == nil {
  146. return nil, ErrNoValSetForHeight{height}
  147. }
  148. if valInfo.ValidatorSet == nil {
  149. valInfo = s.loadValidators(valInfo.LastHeightChanged)
  150. if valInfo == nil {
  151. cmn.PanicSanity(fmt.Sprintf(`Couldn't find validators at height %d as
  152. last changed from height %d`, valInfo.LastHeightChanged, height))
  153. }
  154. }
  155. return valInfo.ValidatorSet, nil
  156. }
  157. func (s *State) loadValidators(height int64) *ValidatorsInfo {
  158. buf := s.db.Get(calcValidatorsKey(height))
  159. if len(buf) == 0 {
  160. return nil
  161. }
  162. v := new(ValidatorsInfo)
  163. r, n, err := bytes.NewReader(buf), new(int), new(error)
  164. wire.ReadBinaryPtr(v, r, 0, n, err)
  165. if *err != nil {
  166. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  167. cmn.Exit(cmn.Fmt(`LoadValidators: Data has been corrupted or its spec has changed:
  168. %v\n`, *err))
  169. }
  170. // TODO: ensure that buf is completely read.
  171. return v
  172. }
  173. // saveValidatorsInfo persists the validator set for the next block to disk.
  174. // It should be called from s.Save(), right before the state itself is persisted.
  175. // If the validator set did not change after processing the latest block,
  176. // only the last height for which the validators changed is persisted.
  177. func (s *State) saveValidatorsInfo() {
  178. changeHeight := s.LastHeightValidatorsChanged
  179. nextHeight := s.LastBlockHeight + 1
  180. valInfo := &ValidatorsInfo{
  181. LastHeightChanged: changeHeight,
  182. }
  183. if changeHeight == nextHeight {
  184. valInfo.ValidatorSet = s.Validators
  185. }
  186. s.db.SetSync(calcValidatorsKey(nextHeight), valInfo.Bytes())
  187. }
  188. // Equals returns true if the States are identical.
  189. func (s *State) Equals(s2 *State) bool {
  190. return bytes.Equal(s.Bytes(), s2.Bytes())
  191. }
  192. // Bytes serializes the State using go-wire.
  193. func (s *State) Bytes() []byte {
  194. return wire.BinaryBytes(s)
  195. }
  196. // SetBlockAndValidators mutates State variables
  197. // to update block and validators after running EndBlock.
  198. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader,
  199. abciResponses *ABCIResponses) {
  200. // copy the valset so we can apply changes from EndBlock
  201. // and update s.LastValidators and s.Validators
  202. prevValSet := s.Validators.Copy()
  203. nextValSet := prevValSet.Copy()
  204. // update the validator set with the latest abciResponses
  205. if len(abciResponses.EndBlock.ValidatorUpdates) > 0 {
  206. err := updateValidators(nextValSet, abciResponses.EndBlock.ValidatorUpdates)
  207. if err != nil {
  208. s.logger.Error("Error changing validator set", "err", err)
  209. // TODO: err or carry on?
  210. }
  211. // change results from this height but only applies to the next height
  212. s.LastHeightValidatorsChanged = header.Height + 1
  213. }
  214. // Update validator accums and set state variables
  215. nextValSet.IncrementAccum(1)
  216. nextParams := applyUpdates(s.Params,
  217. abciResponses.EndBlock.ConsensusParamUpdates)
  218. err := nextParams.Validate()
  219. if err != nil {
  220. s.logger.Error("Error updating consensus params", "err", err)
  221. // TODO: err or carry on?
  222. nextParams = s.Params
  223. }
  224. s.setBlockAndValidators(header.Height,
  225. header.NumTxs,
  226. types.BlockID{header.Hash(), blockPartsHeader},
  227. header.Time,
  228. prevValSet, nextValSet,
  229. nextParams)
  230. }
  231. // applyUpdates returns new ConsensusParams
  232. // whose fields are set to any non-zero fields of c.
  233. // If c is nil, it returns p unmodified, as it was passed in.
  234. func applyUpdates(p types.ConsensusParams,
  235. c *abci.ConsensusParams) types.ConsensusParams {
  236. if c == nil {
  237. return p
  238. }
  239. res := p
  240. // we must defensively consider any structs may be nil
  241. if c.BlockSize != nil {
  242. if c.BlockSize.MaxBytes != 0 {
  243. res.BlockSize.MaxBytes = int(c.BlockSize.MaxBytes)
  244. }
  245. if c.BlockSize.MaxTxs != 0 {
  246. res.BlockSize.MaxTxs = int(c.BlockSize.MaxTxs)
  247. }
  248. if c.BlockSize.MaxGas != 0 {
  249. res.BlockSize.MaxGas = int(c.BlockSize.MaxGas)
  250. }
  251. }
  252. if c.TxSize != nil {
  253. if c.TxSize.MaxBytes != 0 {
  254. res.TxSize.MaxBytes = int(c.TxSize.MaxBytes)
  255. }
  256. if c.TxSize.MaxGas != 0 {
  257. res.TxSize.MaxGas = int(c.TxSize.MaxGas)
  258. }
  259. }
  260. if c.BlockGossip != nil {
  261. if c.BlockGossip.BlockPartSizeBytes != 0 {
  262. res.BlockGossip.BlockPartSizeBytes = int(c.BlockGossip.BlockPartSizeBytes)
  263. }
  264. }
  265. return res
  266. }
  267. func (s *State) setBlockAndValidators(height int64,
  268. newTxs int64, blockID types.BlockID, blockTime time.Time,
  269. prevValSet, nextValSet *types.ValidatorSet,
  270. nextParams types.ConsensusParams) {
  271. s.LastBlockHeight = height
  272. s.LastBlockTotalTx += newTxs
  273. s.LastBlockID = blockID
  274. s.LastBlockTime = blockTime
  275. s.Validators = nextValSet
  276. s.LastValidators = prevValSet
  277. s.LastConsensusHash = s.Params.Hash()
  278. s.Params = nextParams
  279. }
  280. // GetValidators returns the last and current validator sets.
  281. func (s *State) GetValidators() (last *types.ValidatorSet, current *types.ValidatorSet) {
  282. return s.LastValidators, s.Validators
  283. }
  284. //------------------------------------------------------------------------
  285. // ABCIResponses retains the responses of the various ABCI calls during block processing.
  286. // It is persisted to disk before calling Commit.
  287. type ABCIResponses struct {
  288. Height int64
  289. DeliverTx []*abci.ResponseDeliverTx
  290. EndBlock *abci.ResponseEndBlock
  291. txs types.Txs // reference for indexing results by hash
  292. }
  293. // NewABCIResponses returns a new ABCIResponses
  294. func NewABCIResponses(block *types.Block) *ABCIResponses {
  295. return &ABCIResponses{
  296. Height: block.Height,
  297. DeliverTx: make([]*abci.ResponseDeliverTx, block.NumTxs),
  298. txs: block.Data.Txs,
  299. }
  300. }
  301. // Bytes serializes the ABCIResponse using go-wire
  302. func (a *ABCIResponses) Bytes() []byte {
  303. return wire.BinaryBytes(*a)
  304. }
  305. //-----------------------------------------------------------------------------
  306. // ValidatorsInfo represents the latest validator set, or the last height it changed
  307. type ValidatorsInfo struct {
  308. ValidatorSet *types.ValidatorSet
  309. LastHeightChanged int64
  310. }
  311. // Bytes serializes the ValidatorsInfo using go-wire
  312. func (valInfo *ValidatorsInfo) Bytes() []byte {
  313. return wire.BinaryBytes(*valInfo)
  314. }
  315. //------------------------------------------------------------------------
  316. // Genesis
  317. // MakeGenesisStateFromFile reads and unmarshals state from the given
  318. // file.
  319. //
  320. // Used during replay and in tests.
  321. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*State, error) {
  322. genDoc, err := MakeGenesisDocFromFile(genDocFile)
  323. if err != nil {
  324. return nil, err
  325. }
  326. return MakeGenesisState(db, genDoc)
  327. }
  328. // MakeGenesisDocFromFile reads and unmarshals genesis doc from the given file.
  329. func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
  330. genDocJSON, err := ioutil.ReadFile(genDocFile)
  331. if err != nil {
  332. return nil, fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
  333. }
  334. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  335. if err != nil {
  336. return nil, fmt.Errorf("Error reading GenesisDoc: %v", err)
  337. }
  338. return genDoc, nil
  339. }
  340. // MakeGenesisState creates state from types.GenesisDoc.
  341. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) (*State, error) {
  342. err := genDoc.ValidateAndComplete()
  343. if err != nil {
  344. return nil, fmt.Errorf("Error in genesis file: %v", err)
  345. }
  346. // Make validators slice
  347. validators := make([]*types.Validator, len(genDoc.Validators))
  348. for i, val := range genDoc.Validators {
  349. pubKey := val.PubKey
  350. address := pubKey.Address()
  351. // Make validator
  352. validators[i] = &types.Validator{
  353. Address: address,
  354. PubKey: pubKey,
  355. VotingPower: val.Power,
  356. }
  357. }
  358. return &State{
  359. db: db,
  360. ChainID: genDoc.ChainID,
  361. Params: *genDoc.ConsensusParams,
  362. LastBlockHeight: 0,
  363. LastBlockID: types.BlockID{},
  364. LastBlockTime: genDoc.GenesisTime,
  365. Validators: types.NewValidatorSet(validators),
  366. LastValidators: types.NewValidatorSet(nil),
  367. AppHash: genDoc.AppHash,
  368. LastConsensusHash: genDoc.ConsensusParams.Hash(),
  369. LastHeightValidatorsChanged: 1,
  370. }, nil
  371. }