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.

426 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. 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.Changes) > 0 {
  203. err := updateValidators(nextValSet, abciResponses.EndBlock.Changes)
  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. nextParams := applyChanges(s.Params,
  214. abciResponses.EndBlock.ConsensusParamChanges)
  215. s.setBlockAndValidators(header.Height,
  216. header.NumTxs,
  217. types.BlockID{header.Hash(), blockPartsHeader},
  218. header.Time,
  219. prevValSet, nextValSet,
  220. nextParams)
  221. }
  222. // applyChanges returns a new param set, overriding any
  223. // parameter that is non-zero in argument
  224. func applyChanges(p types.ConsensusParams,
  225. c *abci.ConsensusParams) types.ConsensusParams {
  226. if c == nil {
  227. return p
  228. }
  229. res := p
  230. // we must defensively consider any structs may be nil
  231. if c.BlockSizeParams != nil {
  232. if c.BlockSizeParams.MaxBytes != 0 {
  233. res.BlockSizeParams.MaxBytes = int(c.BlockSizeParams.MaxBytes)
  234. }
  235. if c.BlockSizeParams.MaxTxs != 0 {
  236. res.BlockSizeParams.MaxTxs = int(c.BlockSizeParams.MaxTxs)
  237. }
  238. if c.BlockSizeParams.MaxGas != 0 {
  239. res.BlockSizeParams.MaxGas = int(c.BlockSizeParams.MaxGas)
  240. }
  241. }
  242. if c.TxSizeParams != nil {
  243. if c.TxSizeParams.MaxBytes != 0 {
  244. res.TxSizeParams.MaxBytes = int(c.TxSizeParams.MaxBytes)
  245. }
  246. if c.TxSizeParams.MaxGas != 0 {
  247. res.TxSizeParams.MaxGas = int(c.TxSizeParams.MaxGas)
  248. }
  249. }
  250. if c.BlockGossipParams != nil {
  251. if c.BlockGossipParams.BlockPartSizeBytes != 0 {
  252. res.BlockGossipParams.BlockPartSizeBytes = int(c.BlockGossipParams.BlockPartSizeBytes)
  253. }
  254. }
  255. return res
  256. }
  257. func (s *State) setBlockAndValidators(height int64,
  258. newTxs int64, blockID types.BlockID, blockTime time.Time,
  259. prevValSet, nextValSet *types.ValidatorSet,
  260. nextParams types.ConsensusParams) {
  261. s.LastBlockHeight = height
  262. s.LastBlockTotalTx += newTxs
  263. s.LastBlockID = blockID
  264. s.LastBlockTime = blockTime
  265. s.Validators = nextValSet
  266. s.LastValidators = prevValSet
  267. s.Params = nextParams
  268. }
  269. // GetValidators returns the last and current validator sets.
  270. func (s *State) GetValidators() (last *types.ValidatorSet, current *types.ValidatorSet) {
  271. return s.LastValidators, s.Validators
  272. }
  273. //------------------------------------------------------------------------
  274. // ABCIResponses retains the responses of the various ABCI calls during block processing.
  275. // It is persisted to disk before calling Commit.
  276. type ABCIResponses struct {
  277. Height int64
  278. DeliverTx []*abci.ResponseDeliverTx
  279. EndBlock *abci.ResponseEndBlock
  280. txs types.Txs // reference for indexing results by hash
  281. }
  282. // NewABCIResponses returns a new ABCIResponses
  283. func NewABCIResponses(block *types.Block) *ABCIResponses {
  284. return &ABCIResponses{
  285. Height: block.Height,
  286. DeliverTx: make([]*abci.ResponseDeliverTx, block.NumTxs),
  287. txs: block.Data.Txs,
  288. }
  289. }
  290. // Bytes serializes the ABCIResponse using go-wire
  291. func (a *ABCIResponses) Bytes() []byte {
  292. return wire.BinaryBytes(*a)
  293. }
  294. //-----------------------------------------------------------------------------
  295. // ValidatorsInfo represents the latest validator set, or the last height it changed
  296. type ValidatorsInfo struct {
  297. ValidatorSet *types.ValidatorSet
  298. LastHeightChanged int64
  299. }
  300. // Bytes serializes the ValidatorsInfo using go-wire
  301. func (valInfo *ValidatorsInfo) Bytes() []byte {
  302. return wire.BinaryBytes(*valInfo)
  303. }
  304. //------------------------------------------------------------------------
  305. // Genesis
  306. // MakeGenesisStateFromFile reads and unmarshals state from the given
  307. // file.
  308. //
  309. // Used during replay and in tests.
  310. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*State, error) {
  311. genDoc, err := MakeGenesisDocFromFile(genDocFile)
  312. if err != nil {
  313. return nil, err
  314. }
  315. return MakeGenesisState(db, genDoc)
  316. }
  317. // MakeGenesisDocFromFile reads and unmarshals genesis doc from the given file.
  318. func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
  319. genDocJSON, err := ioutil.ReadFile(genDocFile)
  320. if err != nil {
  321. return nil, fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
  322. }
  323. genDoc, err := types.GenesisDocFromJSON(genDocJSON)
  324. if err != nil {
  325. return nil, fmt.Errorf("Error reading GenesisDoc: %v", err)
  326. }
  327. return genDoc, nil
  328. }
  329. // MakeGenesisState creates state from types.GenesisDoc.
  330. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) (*State, error) {
  331. err := genDoc.ValidateAndComplete()
  332. if err != nil {
  333. return nil, fmt.Errorf("Error in genesis file: %v", err)
  334. }
  335. // Make validators slice
  336. validators := make([]*types.Validator, len(genDoc.Validators))
  337. for i, val := range genDoc.Validators {
  338. pubKey := val.PubKey
  339. address := pubKey.Address()
  340. // Make validator
  341. validators[i] = &types.Validator{
  342. Address: address,
  343. PubKey: pubKey,
  344. VotingPower: val.Power,
  345. }
  346. }
  347. return &State{
  348. db: db,
  349. ChainID: genDoc.ChainID,
  350. Params: *genDoc.ConsensusParams,
  351. LastBlockHeight: 0,
  352. LastBlockID: types.BlockID{},
  353. LastBlockTime: genDoc.GenesisTime,
  354. Validators: types.NewValidatorSet(validators),
  355. LastValidators: types.NewValidatorSet(nil),
  356. AppHash: genDoc.AppHash,
  357. LastHeightValidatorsChanged: 1,
  358. }, nil
  359. }