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.

435 lines
14 KiB

7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
6 years ago
6 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
7 years ago
6 years ago
6 years ago
8 years ago
7 years ago
8 years ago
  1. package state
  2. import (
  3. "fmt"
  4. fail "github.com/ebuchman/fail-test"
  5. abci "github.com/tendermint/tendermint/abci/types"
  6. dbm "github.com/tendermint/tendermint/libs/db"
  7. "github.com/tendermint/tendermint/libs/log"
  8. "github.com/tendermint/tendermint/mempool"
  9. "github.com/tendermint/tendermint/proxy"
  10. "github.com/tendermint/tendermint/types"
  11. )
  12. //-----------------------------------------------------------------------------
  13. // BlockExecutor handles block execution and state updates.
  14. // It exposes ApplyBlock(), which validates & executes the block, updates state w/ ABCI responses,
  15. // then commits and updates the mempool atomically, then saves state.
  16. // BlockExecutor provides the context and accessories for properly executing a block.
  17. type BlockExecutor struct {
  18. // save state, validators, consensus params, abci responses here
  19. db dbm.DB
  20. // execute the app against this
  21. proxyApp proxy.AppConnConsensus
  22. // events
  23. eventBus types.BlockEventPublisher
  24. // update these with block results after commit
  25. mempool Mempool
  26. evpool EvidencePool
  27. logger log.Logger
  28. }
  29. // NewBlockExecutor returns a new BlockExecutor with a NopEventBus.
  30. // Call SetEventBus to provide one.
  31. func NewBlockExecutor(db dbm.DB, logger log.Logger, proxyApp proxy.AppConnConsensus,
  32. mempool Mempool, evpool EvidencePool) *BlockExecutor {
  33. return &BlockExecutor{
  34. db: db,
  35. proxyApp: proxyApp,
  36. eventBus: types.NopEventBus{},
  37. mempool: mempool,
  38. evpool: evpool,
  39. logger: logger,
  40. }
  41. }
  42. // SetEventBus - sets the event bus for publishing block related events.
  43. // If not called, it defaults to types.NopEventBus.
  44. func (blockExec *BlockExecutor) SetEventBus(eventBus types.BlockEventPublisher) {
  45. blockExec.eventBus = eventBus
  46. }
  47. // ValidateBlock validates the given block against the given state.
  48. // If the block is invalid, it returns an error.
  49. // Validation does not mutate state, but does require historical information from the stateDB,
  50. // ie. to verify evidence from a validator at an old height.
  51. func (blockExec *BlockExecutor) ValidateBlock(state State, block *types.Block) error {
  52. return validateBlock(blockExec.db, state, block)
  53. }
  54. // ApplyBlock validates the block against the state, executes it against the app,
  55. // fires the relevant events, commits the app, and saves the new state and responses.
  56. // It's the only function that needs to be called
  57. // from outside this package to process and commit an entire block.
  58. // It takes a blockID to avoid recomputing the parts hash.
  59. func (blockExec *BlockExecutor) ApplyBlock(state State, blockID types.BlockID, block *types.Block) (State, error) {
  60. if err := blockExec.ValidateBlock(state, block); err != nil {
  61. return state, ErrInvalidBlock(err)
  62. }
  63. abciResponses, err := execBlockOnProxyApp(blockExec.logger, blockExec.proxyApp, block, state.LastValidators, blockExec.db)
  64. if err != nil {
  65. return state, ErrProxyAppConn(err)
  66. }
  67. fail.Fail() // XXX
  68. // Save the results before we commit.
  69. saveABCIResponses(blockExec.db, block.Height, abciResponses)
  70. fail.Fail() // XXX
  71. // Update the state with the block and responses.
  72. state, err = updateState(state, blockID, &block.Header, abciResponses)
  73. if err != nil {
  74. return state, fmt.Errorf("Commit failed for application: %v", err)
  75. }
  76. // Lock mempool, commit app state, update mempoool.
  77. appHash, err := blockExec.Commit(state, block)
  78. if err != nil {
  79. return state, fmt.Errorf("Commit failed for application: %v", err)
  80. }
  81. // Update evpool with the block and state.
  82. blockExec.evpool.Update(block, state)
  83. fail.Fail() // XXX
  84. // Update the app hash and save the state.
  85. state.AppHash = appHash
  86. SaveState(blockExec.db, state)
  87. fail.Fail() // XXX
  88. // Events are fired after everything else.
  89. // NOTE: if we crash between Commit and Save, events wont be fired during replay
  90. fireEvents(blockExec.logger, blockExec.eventBus, block, abciResponses)
  91. return state, nil
  92. }
  93. // Commit locks the mempool, runs the ABCI Commit message, and updates the
  94. // mempool.
  95. // It returns the result of calling abci.Commit (the AppHash), and an error.
  96. // The Mempool must be locked during commit and update because state is
  97. // typically reset on Commit and old txs must be replayed against committed
  98. // state before new txs are run in the mempool, lest they be invalid.
  99. func (blockExec *BlockExecutor) Commit(
  100. state State,
  101. block *types.Block,
  102. ) ([]byte, error) {
  103. blockExec.mempool.Lock()
  104. defer blockExec.mempool.Unlock()
  105. // while mempool is Locked, flush to ensure all async requests have completed
  106. // in the ABCI app before Commit.
  107. err := blockExec.mempool.FlushAppConn()
  108. if err != nil {
  109. blockExec.logger.Error("Client error during mempool.FlushAppConn", "err", err)
  110. return nil, err
  111. }
  112. // Commit block, get hash back
  113. res, err := blockExec.proxyApp.CommitSync()
  114. if err != nil {
  115. blockExec.logger.Error(
  116. "Client error during proxyAppConn.CommitSync",
  117. "err", err,
  118. )
  119. return nil, err
  120. }
  121. // ResponseCommit has no error code - just data
  122. blockExec.logger.Info(
  123. "Committed state",
  124. "height", block.Height,
  125. "txs", block.NumTxs,
  126. "appHash", fmt.Sprintf("%X", res.Data),
  127. )
  128. // Update mempool.
  129. err = blockExec.mempool.Update(
  130. block.Height,
  131. block.Txs,
  132. mempool.PreCheckAminoMaxBytes(
  133. types.MaxDataBytesUnknownEvidence(
  134. state.ConsensusParams.BlockSize.MaxBytes,
  135. state.Validators.Size(),
  136. ),
  137. ),
  138. mempool.PostCheckMaxGas(state.ConsensusParams.MaxGas),
  139. )
  140. return res.Data, err
  141. }
  142. //---------------------------------------------------------
  143. // Helper functions for executing blocks and updating state
  144. // Executes block's transactions on proxyAppConn.
  145. // Returns a list of transaction results and updates to the validator set
  146. func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus,
  147. block *types.Block, lastValSet *types.ValidatorSet, stateDB dbm.DB) (*ABCIResponses, error) {
  148. var validTxs, invalidTxs = 0, 0
  149. txIndex := 0
  150. abciResponses := NewABCIResponses(block)
  151. // Execute transactions and get hash.
  152. proxyCb := func(req *abci.Request, res *abci.Response) {
  153. switch r := res.Value.(type) {
  154. case *abci.Response_DeliverTx:
  155. // TODO: make use of res.Log
  156. // TODO: make use of this info
  157. // Blocks may include invalid txs.
  158. txRes := r.DeliverTx
  159. if txRes.Code == abci.CodeTypeOK {
  160. validTxs++
  161. } else {
  162. logger.Debug("Invalid tx", "code", txRes.Code, "log", txRes.Log)
  163. invalidTxs++
  164. }
  165. abciResponses.DeliverTx[txIndex] = txRes
  166. txIndex++
  167. }
  168. }
  169. proxyAppConn.SetResponseCallback(proxyCb)
  170. commitInfo, byzVals := getBeginBlockValidatorInfo(block, lastValSet, stateDB)
  171. // Begin block.
  172. _, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
  173. Hash: block.Hash(),
  174. Header: types.TM2PB.Header(&block.Header),
  175. LastCommitInfo: commitInfo,
  176. ByzantineValidators: byzVals,
  177. })
  178. if err != nil {
  179. logger.Error("Error in proxyAppConn.BeginBlock", "err", err)
  180. return nil, err
  181. }
  182. // Run txs of block.
  183. for _, tx := range block.Txs {
  184. proxyAppConn.DeliverTxAsync(tx)
  185. if err := proxyAppConn.Error(); err != nil {
  186. return nil, err
  187. }
  188. }
  189. // End block.
  190. abciResponses.EndBlock, err = proxyAppConn.EndBlockSync(abci.RequestEndBlock{Height: block.Height})
  191. if err != nil {
  192. logger.Error("Error in proxyAppConn.EndBlock", "err", err)
  193. return nil, err
  194. }
  195. logger.Info("Executed block", "height", block.Height, "validTxs", validTxs, "invalidTxs", invalidTxs)
  196. valUpdates := abciResponses.EndBlock.ValidatorUpdates
  197. if len(valUpdates) > 0 {
  198. // TODO: cleanup the formatting
  199. logger.Info("Updates to validators", "updates", valUpdates)
  200. }
  201. return abciResponses, nil
  202. }
  203. func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorSet, stateDB dbm.DB) (abci.LastCommitInfo, []abci.Evidence) {
  204. // Sanity check that commit length matches validator set size -
  205. // only applies after first block
  206. if block.Height > 1 {
  207. precommitLen := len(block.LastCommit.Precommits)
  208. valSetLen := len(lastValSet.Validators)
  209. if precommitLen != valSetLen {
  210. // sanity check
  211. panic(fmt.Sprintf("precommit length (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v",
  212. precommitLen, valSetLen, block.Height, block.LastCommit.Precommits, lastValSet.Validators))
  213. }
  214. }
  215. // Collect the vote info (list of validators and whether or not they signed).
  216. voteInfos := make([]abci.VoteInfo, len(lastValSet.Validators))
  217. for i, val := range lastValSet.Validators {
  218. var vote *types.Vote
  219. if i < len(block.LastCommit.Precommits) {
  220. vote = block.LastCommit.Precommits[i]
  221. }
  222. voteInfo := abci.VoteInfo{
  223. Validator: types.TM2PB.Validator(val),
  224. SignedLastBlock: vote != nil,
  225. }
  226. voteInfos[i] = voteInfo
  227. }
  228. commitInfo := abci.LastCommitInfo{
  229. Round: int32(block.LastCommit.Round()),
  230. Votes: voteInfos,
  231. }
  232. byzVals := make([]abci.Evidence, len(block.Evidence.Evidence))
  233. for i, ev := range block.Evidence.Evidence {
  234. // We need the validator set. We already did this in validateBlock.
  235. // TODO: Should we instead cache the valset in the evidence itself and add
  236. // `SetValidatorSet()` and `ToABCI` methods ?
  237. valset, err := LoadValidators(stateDB, ev.Height())
  238. if err != nil {
  239. panic(err) // shouldn't happen
  240. }
  241. byzVals[i] = types.TM2PB.Evidence(ev, valset, block.Time)
  242. }
  243. return commitInfo, byzVals
  244. }
  245. // If more or equal than 1/3 of total voting power changed in one block, then
  246. // a light client could never prove the transition externally. See
  247. // ./lite/doc.go for details on how a light client tracks validators.
  248. func updateValidators(currentSet *types.ValidatorSet, abciUpdates []abci.ValidatorUpdate) error {
  249. updates, err := types.PB2TM.ValidatorUpdates(abciUpdates)
  250. if err != nil {
  251. return err
  252. }
  253. // these are tendermint types now
  254. for _, valUpdate := range updates {
  255. if valUpdate.VotingPower < 0 {
  256. return fmt.Errorf("Voting power can't be negative %v", valUpdate)
  257. }
  258. address := valUpdate.Address
  259. _, val := currentSet.GetByAddress(address)
  260. if valUpdate.VotingPower == 0 {
  261. // remove val
  262. _, removed := currentSet.Remove(address)
  263. if !removed {
  264. return fmt.Errorf("Failed to remove validator %X", address)
  265. }
  266. } else if val == nil {
  267. // add val
  268. added := currentSet.Add(valUpdate)
  269. if !added {
  270. return fmt.Errorf("Failed to add new validator %v", valUpdate)
  271. }
  272. } else {
  273. // update val
  274. updated := currentSet.Update(valUpdate)
  275. if !updated {
  276. return fmt.Errorf("Failed to update validator %X to %v", address, valUpdate)
  277. }
  278. }
  279. }
  280. return nil
  281. }
  282. // updateState returns a new State updated according to the header and responses.
  283. func updateState(state State, blockID types.BlockID, header *types.Header,
  284. abciResponses *ABCIResponses) (State, error) {
  285. // Copy the valset so we can apply changes from EndBlock
  286. // and update s.LastValidators and s.Validators.
  287. nValSet := state.NextValidators.Copy()
  288. // Update the validator set with the latest abciResponses.
  289. lastHeightValsChanged := state.LastHeightValidatorsChanged
  290. if len(abciResponses.EndBlock.ValidatorUpdates) > 0 {
  291. err := updateValidators(nValSet, abciResponses.EndBlock.ValidatorUpdates)
  292. if err != nil {
  293. return state, fmt.Errorf("Error changing validator set: %v", err)
  294. }
  295. // Change results from this height but only applies to the next next height.
  296. lastHeightValsChanged = header.Height + 1 + 1
  297. }
  298. // Update validator accums and set state variables.
  299. nValSet.IncrementAccum(1)
  300. // Update the params with the latest abciResponses.
  301. nextParams := state.ConsensusParams
  302. lastHeightParamsChanged := state.LastHeightConsensusParamsChanged
  303. if abciResponses.EndBlock.ConsensusParamUpdates != nil {
  304. // NOTE: must not mutate s.ConsensusParams
  305. nextParams = state.ConsensusParams.Update(abciResponses.EndBlock.ConsensusParamUpdates)
  306. err := nextParams.Validate()
  307. if err != nil {
  308. return state, fmt.Errorf("Error updating consensus params: %v", err)
  309. }
  310. // Change results from this height but only applies to the next height.
  311. lastHeightParamsChanged = header.Height + 1
  312. }
  313. // NOTE: the AppHash has not been populated.
  314. // It will be filled on state.Save.
  315. return State{
  316. ChainID: state.ChainID,
  317. LastBlockHeight: header.Height,
  318. LastBlockTotalTx: state.LastBlockTotalTx + header.NumTxs,
  319. LastBlockID: blockID,
  320. LastBlockTime: header.Time,
  321. NextValidators: nValSet,
  322. Validators: state.NextValidators.Copy(),
  323. LastValidators: state.Validators.Copy(),
  324. LastHeightValidatorsChanged: lastHeightValsChanged,
  325. ConsensusParams: nextParams,
  326. LastHeightConsensusParamsChanged: lastHeightParamsChanged,
  327. LastResultsHash: abciResponses.ResultsHash(),
  328. AppHash: nil,
  329. }, nil
  330. }
  331. // Fire NewBlock, NewBlockHeader.
  332. // Fire TxEvent for every tx.
  333. // NOTE: if Tendermint crashes before commit, some or all of these events may be published again.
  334. func fireEvents(logger log.Logger, eventBus types.BlockEventPublisher, block *types.Block, abciResponses *ABCIResponses) {
  335. eventBus.PublishEventNewBlock(types.EventDataNewBlock{block})
  336. eventBus.PublishEventNewBlockHeader(types.EventDataNewBlockHeader{block.Header})
  337. for i, tx := range block.Data.Txs {
  338. eventBus.PublishEventTx(types.EventDataTx{types.TxResult{
  339. Height: block.Height,
  340. Index: uint32(i),
  341. Tx: tx,
  342. Result: *(abciResponses.DeliverTx[i]),
  343. }})
  344. }
  345. abciValUpdates := abciResponses.EndBlock.ValidatorUpdates
  346. if len(abciValUpdates) > 0 {
  347. // if there were an error, we would've stopped in updateValidators
  348. updates, _ := types.PB2TM.ValidatorUpdates(abciValUpdates)
  349. eventBus.PublishEventValidatorSetUpdates(
  350. types.EventDataValidatorSetUpdates{ValidatorUpdates: updates})
  351. }
  352. }
  353. //----------------------------------------------------------------------------------------------------
  354. // Execute block without state. TODO: eliminate
  355. // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state.
  356. // It returns the application root hash (result of abci.Commit).
  357. func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block,
  358. logger log.Logger, lastValSet *types.ValidatorSet, stateDB dbm.DB) ([]byte, error) {
  359. _, err := execBlockOnProxyApp(logger, appConnConsensus, block, lastValSet, stateDB)
  360. if err != nil {
  361. logger.Error("Error executing block on proxy app", "height", block.Height, "err", err)
  362. return nil, err
  363. }
  364. // Commit block, get hash back
  365. res, err := appConnConsensus.CommitSync()
  366. if err != nil {
  367. logger.Error("Client error during proxyAppConn.CommitSync", "err", res)
  368. return nil, err
  369. }
  370. // ResponseCommit has no error or log, just data
  371. return res.Data, nil
  372. }