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.

383 lines
12 KiB

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
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
8 years ago
8 years ago
8 years ago
8 years ago
  1. package state
  2. import (
  3. "errors"
  4. "fmt"
  5. fail "github.com/ebuchman/fail-test"
  6. abci "github.com/tendermint/abci/types"
  7. crypto "github.com/tendermint/go-crypto"
  8. "github.com/tendermint/tendermint/proxy"
  9. "github.com/tendermint/tendermint/types"
  10. dbm "github.com/tendermint/tmlibs/db"
  11. "github.com/tendermint/tmlibs/log"
  12. )
  13. //-----------------------------------------------------------------------------
  14. // BlockExecutor handles block execution and state updates.
  15. // It exposes ApplyBlock(), which validates & executes the block, updates state w/ ABCI responses,
  16. // then commits and updates the mempool atomically, then saves state.
  17. // BlockExecutor provides the context and accessories for properly executing a block.
  18. type BlockExecutor struct {
  19. db dbm.DB
  20. logger log.Logger
  21. txEventPublisher types.TxEventPublisher
  22. proxyApp proxy.AppConnConsensus
  23. mempool types.Mempool
  24. evpool types.EvidencePool
  25. }
  26. // NewBlockExecutor returns a new BlockExecutor.
  27. func NewBlockExecutor(db dbm.DB, logger log.Logger,
  28. txEventer types.TxEventPublisher, proxyApp proxy.AppConnConsensus,
  29. mempool types.Mempool, evpool types.EvidencePool) *BlockExecutor {
  30. return &BlockExecutor{
  31. db,
  32. logger,
  33. txEventer,
  34. proxyApp,
  35. mempool,
  36. evpool,
  37. }
  38. }
  39. // ApplyBlock validates the block against the state, executes it against the app,
  40. // commits it, and saves the block and state. It's the only function that needs to be called
  41. // from outside this package to process and commit an entire block.
  42. // It takes a blockID to avoid recomputing the parts hash.
  43. func (blockExec *BlockExecutor) ApplyBlock(s State, blockID types.BlockID, block *types.Block) (State, error) {
  44. if err := validateBlock(s, block); err != nil {
  45. return s, ErrInvalidBlock(err)
  46. }
  47. abciResponses, err := execBlockOnProxyApp(blockExec.logger, blockExec.proxyApp, block)
  48. if err != nil {
  49. return s, ErrProxyAppConn(err)
  50. }
  51. fireEvents(blockExec.txEventPublisher, block, abciResponses)
  52. fail.Fail() // XXX
  53. // save the results before we commit
  54. saveABCIResponses(blockExec.db, block.Height, abciResponses)
  55. fail.Fail() // XXX
  56. // update the state with the block and responses
  57. s, err = updateState(s, blockID, block.Header, abciResponses)
  58. if err != nil {
  59. return s, fmt.Errorf("Commit failed for application: %v", err)
  60. }
  61. // lock mempool, commit state, update mempoool
  62. appHash, err := blockExec.Commit(block)
  63. if err != nil {
  64. return s, fmt.Errorf("Commit failed for application: %v", err)
  65. }
  66. fail.Fail() // XXX
  67. // save the state and the validators
  68. SaveState(blockExec.db, s, appHash)
  69. return s, nil
  70. }
  71. // Commit locks the mempool, runs the ABCI Commit message, and updates the mempool.
  72. // It returns the result of calling abci.Commit (the AppHash), and an error.
  73. // The Mempool must be locked during commit and update because state is typically reset on Commit and old txs must be replayed
  74. // against committed state before new txs are run in the mempool, lest they be invalid.
  75. func (blockExec *BlockExecutor) Commit(block *types.Block) ([]byte, error) {
  76. blockExec.mempool.Lock()
  77. defer blockExec.mempool.Unlock()
  78. // Commit block, get hash back
  79. res, err := blockExec.proxyApp.CommitSync()
  80. if err != nil {
  81. blockExec.logger.Error("Client error during proxyAppConn.CommitSync", "err", err)
  82. return nil, err
  83. }
  84. if res.IsErr() {
  85. blockExec.logger.Error("Error in proxyAppConn.CommitSync", "err", res)
  86. return nil, res
  87. }
  88. if res.Log != "" {
  89. blockExec.logger.Debug("Commit.Log: " + res.Log)
  90. }
  91. blockExec.logger.Info("Committed state", "height", block.Height, "txs", block.NumTxs, "hash", res.Data)
  92. // Update evpool
  93. blockExec.evpool.MarkEvidenceAsCommitted(block.Evidence.Evidence)
  94. // Update mempool.
  95. if err := blockExec.mempool.Update(block.Height, block.Txs); err != nil {
  96. return nil, err
  97. }
  98. return res.Data, nil
  99. }
  100. //---------------------------------------------------------
  101. // Helper functions for executing blocks and updating state
  102. // Executes block's transactions on proxyAppConn.
  103. // Returns a list of transaction results and updates to the validator set
  104. func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus, block *types.Block) (*ABCIResponses, error) {
  105. var validTxs, invalidTxs = 0, 0
  106. txIndex := 0
  107. abciResponses := NewABCIResponses(block)
  108. // Execute transactions and get hash
  109. proxyCb := func(req *abci.Request, res *abci.Response) {
  110. switch r := res.Value.(type) {
  111. case *abci.Response_DeliverTx:
  112. // TODO: make use of res.Log
  113. // TODO: make use of this info
  114. // Blocks may include invalid txs.
  115. txRes := r.DeliverTx
  116. if txRes.Code == abci.CodeTypeOK {
  117. validTxs++
  118. } else {
  119. logger.Debug("Invalid tx", "code", txRes.Code, "log", txRes.Log)
  120. invalidTxs++
  121. }
  122. abciResponses.DeliverTx[txIndex] = txRes
  123. txIndex++
  124. }
  125. }
  126. proxyAppConn.SetResponseCallback(proxyCb)
  127. // determine which validators did not sign last block
  128. absentVals := make([]int32, 0)
  129. for valI, vote := range block.LastCommit.Precommits {
  130. if vote == nil {
  131. absentVals = append(absentVals, int32(valI))
  132. }
  133. }
  134. // TODO: determine which validators were byzantine
  135. // Begin block
  136. _, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
  137. Hash: block.Hash(),
  138. Header: types.TM2PB.Header(block.Header),
  139. AbsentValidators: absentVals,
  140. ByzantineValidators: nil,
  141. })
  142. if err != nil {
  143. logger.Error("Error in proxyAppConn.BeginBlock", "err", err)
  144. return nil, err
  145. }
  146. // Run txs of block
  147. for _, tx := range block.Txs {
  148. proxyAppConn.DeliverTxAsync(tx)
  149. if err := proxyAppConn.Error(); err != nil {
  150. return nil, err
  151. }
  152. }
  153. // End block
  154. abciResponses.EndBlock, err = proxyAppConn.EndBlockSync(abci.RequestEndBlock{block.Height})
  155. if err != nil {
  156. logger.Error("Error in proxyAppConn.EndBlock", "err", err)
  157. return nil, err
  158. }
  159. logger.Info("Executed block", "height", block.Height, "validTxs", validTxs, "invalidTxs", invalidTxs)
  160. valUpdates := abciResponses.EndBlock.ValidatorUpdates
  161. if len(valUpdates) > 0 {
  162. logger.Info("Updates to validators", "updates", abci.ValidatorsString(valUpdates))
  163. }
  164. return abciResponses, nil
  165. }
  166. func updateValidators(currentSet *types.ValidatorSet, updates []*abci.Validator) error {
  167. // If more or equal than 1/3 of total voting power changed in one block, then
  168. // a light client could never prove the transition externally. See
  169. // ./lite/doc.go for details on how a light client tracks validators.
  170. vp23, err := changeInVotingPowerMoreOrEqualToOneThird(currentSet, updates)
  171. if err != nil {
  172. return err
  173. }
  174. if vp23 {
  175. return errors.New("the change in voting power must be strictly less than 1/3")
  176. }
  177. for _, v := range updates {
  178. pubkey, err := crypto.PubKeyFromBytes(v.PubKey) // NOTE: expects go-wire encoded pubkey
  179. if err != nil {
  180. return err
  181. }
  182. address := pubkey.Address()
  183. power := int64(v.Power)
  184. // mind the overflow from int64
  185. if power < 0 {
  186. return fmt.Errorf("Power (%d) overflows int64", v.Power)
  187. }
  188. _, val := currentSet.GetByAddress(address)
  189. if val == nil {
  190. // add val
  191. added := currentSet.Add(types.NewValidator(pubkey, power))
  192. if !added {
  193. return fmt.Errorf("Failed to add new validator %X with voting power %d", address, power)
  194. }
  195. } else if v.Power == 0 {
  196. // remove val
  197. _, removed := currentSet.Remove(address)
  198. if !removed {
  199. return fmt.Errorf("Failed to remove validator %X", address)
  200. }
  201. } else {
  202. // update val
  203. val.VotingPower = power
  204. updated := currentSet.Update(val)
  205. if !updated {
  206. return fmt.Errorf("Failed to update validator %X with voting power %d", address, power)
  207. }
  208. }
  209. }
  210. return nil
  211. }
  212. func changeInVotingPowerMoreOrEqualToOneThird(currentSet *types.ValidatorSet, updates []*abci.Validator) (bool, error) {
  213. threshold := currentSet.TotalVotingPower() * 1 / 3
  214. acc := int64(0)
  215. for _, v := range updates {
  216. pubkey, err := crypto.PubKeyFromBytes(v.PubKey) // NOTE: expects go-wire encoded pubkey
  217. if err != nil {
  218. return false, err
  219. }
  220. address := pubkey.Address()
  221. power := int64(v.Power)
  222. // mind the overflow from int64
  223. if power < 0 {
  224. return false, fmt.Errorf("Power (%d) overflows int64", v.Power)
  225. }
  226. _, val := currentSet.GetByAddress(address)
  227. if val == nil {
  228. acc += power
  229. } else {
  230. np := val.VotingPower - power
  231. if np < 0 {
  232. np = -np
  233. }
  234. acc += np
  235. }
  236. if acc >= threshold {
  237. return true, nil
  238. }
  239. }
  240. return false, nil
  241. }
  242. // updateState returns a new State updated according to the header and responses.
  243. func updateState(s State, blockID types.BlockID, header *types.Header,
  244. abciResponses *ABCIResponses) (State, error) {
  245. // copy the valset so we can apply changes from EndBlock
  246. // and update s.LastValidators and s.Validators
  247. prevValSet := s.Validators.Copy()
  248. nextValSet := prevValSet.Copy()
  249. // update the validator set with the latest abciResponses
  250. lastHeightValsChanged := s.LastHeightValidatorsChanged
  251. if len(abciResponses.EndBlock.ValidatorUpdates) > 0 {
  252. err := updateValidators(nextValSet, abciResponses.EndBlock.ValidatorUpdates)
  253. if err != nil {
  254. return s, fmt.Errorf("Error changing validator set: %v", err)
  255. }
  256. // change results from this height but only applies to the next height
  257. lastHeightValsChanged = header.Height + 1
  258. }
  259. // Update validator accums and set state variables
  260. nextValSet.IncrementAccum(1)
  261. // update the params with the latest abciResponses
  262. nextParams := s.ConsensusParams
  263. lastHeightParamsChanged := s.LastHeightConsensusParamsChanged
  264. if abciResponses.EndBlock.ConsensusParamUpdates != nil {
  265. // NOTE: must not mutate s.ConsensusParams
  266. nextParams = s.ConsensusParams.Update(abciResponses.EndBlock.ConsensusParamUpdates)
  267. err := nextParams.Validate()
  268. if err != nil {
  269. return s, fmt.Errorf("Error updating consensus params: %v", err)
  270. }
  271. // change results from this height but only applies to the next height
  272. lastHeightParamsChanged = header.Height + 1
  273. }
  274. // NOTE: the AppHash has not been populated.
  275. // It will be filled on state.Save.
  276. return State{
  277. ChainID: s.ChainID,
  278. LastBlockHeight: header.Height,
  279. LastBlockTotalTx: s.LastBlockTotalTx + header.NumTxs,
  280. LastBlockID: blockID,
  281. LastBlockTime: header.Time,
  282. Validators: nextValSet,
  283. LastValidators: s.Validators.Copy(),
  284. LastHeightValidatorsChanged: lastHeightValsChanged,
  285. ConsensusParams: nextParams,
  286. LastHeightConsensusParamsChanged: lastHeightParamsChanged,
  287. LastResultsHash: abciResponses.ResultsHash(),
  288. AppHash: nil,
  289. }, nil
  290. }
  291. func fireEvents(txEventPublisher types.TxEventPublisher, block *types.Block, abciResponses *ABCIResponses) {
  292. // TODO: Fire events
  293. /*
  294. tx := types.Tx(req.GetDeliverTx().Tx)
  295. txEventPublisher.PublishEventTx(types.EventDataTx{types.TxResult{
  296. Height: block.Height,
  297. Index: uint32(txIndex),
  298. Tx: tx,
  299. Result: *txRes,
  300. }})
  301. */
  302. }
  303. //----------------------------------------------------------------------------------------------------
  304. // Execute block without state. TODO: eliminate
  305. // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state.
  306. // It returns the application root hash (result of abci.Commit).
  307. func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block, logger log.Logger) ([]byte, error) {
  308. _, err := execBlockOnProxyApp(logger, appConnConsensus, block)
  309. if err != nil {
  310. logger.Error("Error executing block on proxy app", "height", block.Height, "err", err)
  311. return nil, err
  312. }
  313. // Commit block, get hash back
  314. res, err := appConnConsensus.CommitSync()
  315. if err != nil {
  316. logger.Error("Client error during proxyAppConn.CommitSync", "err", res)
  317. return nil, err
  318. }
  319. if res.IsErr() {
  320. logger.Error("Error in proxyAppConn.CommitSync", "err", res)
  321. return nil, res
  322. }
  323. if res.Log != "" {
  324. logger.Info("Commit.Log: " + res.Log)
  325. }
  326. return res.Data, nil
  327. }