github.com/PikeEcosystem/tendermint@v0.0.4/state/execution.go (about)

     1  package state
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"time"
     7  
     8  	abci "github.com/tendermint/tendermint/abci/types"
     9  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    10  
    11  	tmabci "github.com/PikeEcosystem/tendermint/abci/types"
    12  	"github.com/PikeEcosystem/tendermint/crypto"
    13  	cryptoenc "github.com/PikeEcosystem/tendermint/crypto/encoding"
    14  	"github.com/PikeEcosystem/tendermint/crypto/vrf"
    15  	"github.com/PikeEcosystem/tendermint/libs/fail"
    16  	"github.com/PikeEcosystem/tendermint/libs/log"
    17  	mempl "github.com/PikeEcosystem/tendermint/mempool"
    18  	tmstate "github.com/PikeEcosystem/tendermint/proto/tendermint/state"
    19  	"github.com/PikeEcosystem/tendermint/proxy"
    20  	"github.com/PikeEcosystem/tendermint/types"
    21  	canonictime "github.com/PikeEcosystem/tendermint/types/time"
    22  )
    23  
    24  //-----------------------------------------------------------------------------
    25  // BlockExecutor handles block execution and state updates.
    26  // It exposes ApplyBlock(), which validates & executes the block, updates state w/ ABCI responses,
    27  // then commits and updates the mempool atomically, then saves state.
    28  
    29  // BlockExecutor provides the context and accessories for properly executing a block.
    30  type BlockExecutor struct {
    31  	// save state, validators, consensus params, abci responses here
    32  	store Store
    33  
    34  	// execute the app against this
    35  	proxyApp proxy.AppConnConsensus
    36  
    37  	// events
    38  	eventBus types.BlockEventPublisher
    39  
    40  	// manage the mempool lock during commit
    41  	// and update both with block results after commit.
    42  	mempool mempl.Mempool
    43  	evpool  EvidencePool
    44  
    45  	logger log.Logger
    46  
    47  	metrics *Metrics
    48  }
    49  
    50  type CommitStepTimes struct {
    51  	CommitExecuting  types.StepDuration
    52  	CommitCommitting types.StepDuration
    53  	CommitRechecking types.StepDuration
    54  	Current          *types.StepDuration
    55  }
    56  
    57  func (st *CommitStepTimes) ToNextStep(from, next *types.StepDuration) time.Time {
    58  	now := canonictime.Now()
    59  	if st.Current == from {
    60  		from.End, next.Start = now, now
    61  		st.Current = next
    62  	}
    63  	return now
    64  }
    65  
    66  func (st *CommitStepTimes) ToCommitCommitting() time.Time {
    67  	return st.ToNextStep(&st.CommitExecuting, &st.CommitCommitting)
    68  }
    69  
    70  func (st *CommitStepTimes) ToCommitRechecking() time.Time {
    71  	return st.ToNextStep(&st.CommitCommitting, &st.CommitRechecking)
    72  }
    73  
    74  type BlockExecutorOption func(executor *BlockExecutor)
    75  
    76  func BlockExecutorWithMetrics(metrics *Metrics) BlockExecutorOption {
    77  	return func(blockExec *BlockExecutor) {
    78  		blockExec.metrics = metrics
    79  	}
    80  }
    81  
    82  // NewBlockExecutor returns a new BlockExecutor with a NopEventBus.
    83  // Call SetEventBus to provide one.
    84  func NewBlockExecutor(
    85  	stateStore Store,
    86  	logger log.Logger,
    87  	proxyApp proxy.AppConnConsensus,
    88  	mempool mempl.Mempool,
    89  	evpool EvidencePool,
    90  	options ...BlockExecutorOption,
    91  ) *BlockExecutor {
    92  	res := &BlockExecutor{
    93  		store:    stateStore,
    94  		proxyApp: proxyApp,
    95  		eventBus: types.NopEventBus{},
    96  		mempool:  mempool,
    97  		evpool:   evpool,
    98  		logger:   logger,
    99  		metrics:  NopMetrics(),
   100  	}
   101  
   102  	for _, option := range options {
   103  		option(res)
   104  	}
   105  
   106  	return res
   107  }
   108  
   109  func (blockExec *BlockExecutor) Store() Store {
   110  	return blockExec.store
   111  }
   112  
   113  // SetEventBus - sets the event bus for publishing block related events.
   114  // If not called, it defaults to types.NopEventBus.
   115  func (blockExec *BlockExecutor) SetEventBus(eventBus types.BlockEventPublisher) {
   116  	blockExec.eventBus = eventBus
   117  }
   118  
   119  // CreateProposalBlock calls state.MakeBlock with evidence from the evpool
   120  // and txs from the mempool. The max bytes must be big enough to fit the commit.
   121  // Up to 1/10th of the block space is allcoated for maximum sized evidence.
   122  // The rest is given to txs, up to the max gas.
   123  func (blockExec *BlockExecutor) CreateProposalBlock(
   124  	height int64,
   125  	state State, commit *types.Commit,
   126  	proposerAddr []byte,
   127  	round int32,
   128  	proof crypto.Proof,
   129  	maxTxs int64,
   130  ) (*types.Block, *types.PartSet) {
   131  
   132  	maxBytes := state.ConsensusParams.Block.MaxBytes
   133  	maxGas := state.ConsensusParams.Block.MaxGas
   134  
   135  	evidence, evSize := blockExec.evpool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
   136  
   137  	// Fetch a limited amount of valid txs
   138  	maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Validators.Size())
   139  
   140  	txs := blockExec.mempool.ReapMaxBytesMaxGasMaxTxs(maxDataBytes, maxGas, maxTxs)
   141  
   142  	return state.MakeBlock(height, txs, commit, evidence, proposerAddr, round, proof)
   143  }
   144  
   145  // ValidateBlock validates the given block against the given state.
   146  // If the block is invalid, it returns an error.
   147  // Validation does not mutate state, but does require historical information from the stateDB,
   148  // ie. to verify evidence from a validator at an old height.
   149  func (blockExec *BlockExecutor) ValidateBlock(state State, round int32, block *types.Block) error {
   150  	err := validateBlock(state, round, block)
   151  	if err != nil {
   152  		return err
   153  	}
   154  	return blockExec.evpool.CheckEvidence(block.Evidence.Evidence)
   155  }
   156  
   157  // ApplyBlock validates the block against the state, executes it against the app,
   158  // fires the relevant events, commits the app, and saves the new state and responses.
   159  // It returns the new state and the block height to retain (pruning older blocks).
   160  // It's the only function that needs to be called
   161  // from outside this package to process and commit an entire block.
   162  // It takes a blockID to avoid recomputing the parts hash.
   163  func (blockExec *BlockExecutor) ApplyBlock(
   164  	state State, blockID types.BlockID, block *types.Block, stepTimes *CommitStepTimes,
   165  ) (State, int64, error) {
   166  
   167  	// When doing ApplyBlock, we don't need to check whether the block.Round is same to current round,
   168  	// so we just put block.Round for the current round parameter
   169  	if err := blockExec.ValidateBlock(state, block.Round, block); err != nil {
   170  		return state, 0, ErrInvalidBlock(err)
   171  	}
   172  
   173  	execStartTime := time.Now().UnixNano()
   174  	abciResponses, err := execBlockOnProxyApp(
   175  		blockExec.logger, blockExec.proxyApp, block, blockExec.store, state.InitialHeight,
   176  	)
   177  	execEndTime := time.Now().UnixNano()
   178  
   179  	execTimeMs := float64(execEndTime-execStartTime) / 1000000
   180  	blockExec.metrics.BlockProcessingTime.Observe(execTimeMs)
   181  	blockExec.metrics.BlockExecutionTime.Set(execTimeMs)
   182  
   183  	if err != nil {
   184  		return state, 0, ErrProxyAppConn(err)
   185  	}
   186  
   187  	fail.Fail() // XXX
   188  
   189  	// Save the results before we commit.
   190  	if err := blockExec.store.SaveABCIResponses(block.Height, abciResponses); err != nil {
   191  		return state, 0, err
   192  	}
   193  
   194  	fail.Fail() // XXX
   195  
   196  	// validate the validator updates and convert to tendermint types
   197  	abciValUpdates := abciResponses.EndBlock.ValidatorUpdates
   198  	err = validateValidatorUpdates(abciValUpdates, state.ConsensusParams.Validator)
   199  	if err != nil {
   200  		return state, 0, fmt.Errorf("error in validator updates: %v", err)
   201  	}
   202  
   203  	validatorUpdates, err := types.PB2OC.ValidatorUpdates(abciValUpdates)
   204  	if err != nil {
   205  		return state, 0, err
   206  	}
   207  	if len(validatorUpdates) > 0 {
   208  		blockExec.logger.Debug("updates to validators", "updates", types.ValidatorListString(validatorUpdates))
   209  	}
   210  
   211  	// Update the state with the block and responses.
   212  	state, err = updateState(state, blockID, &block.Header, &block.Entropy, abciResponses, validatorUpdates)
   213  	if err != nil {
   214  		return state, 0, fmt.Errorf("commit failed for application: %v", err)
   215  	}
   216  
   217  	if stepTimes != nil {
   218  		stepTimes.ToCommitCommitting()
   219  	}
   220  
   221  	// Lock mempool, commit app state, update mempoool.
   222  	commitStartTime := time.Now().UnixNano()
   223  	appHash, retainHeight, err := blockExec.Commit(state, block, abciResponses.DeliverTxs, stepTimes)
   224  	commitEndTime := time.Now().UnixNano()
   225  
   226  	commitTimeMs := float64(commitEndTime-commitStartTime) / 1000000
   227  	blockExec.metrics.BlockCommitTime.Set(commitTimeMs)
   228  
   229  	if err != nil {
   230  		return state, 0, fmt.Errorf("commit failed for application: %v", err)
   231  	}
   232  
   233  	// Update evpool with the latest state.
   234  	blockExec.evpool.Update(state, block.Evidence.Evidence)
   235  
   236  	fail.Fail() // XXX
   237  
   238  	// Update the app hash and save the state.
   239  	state.AppHash = appHash
   240  	if err := blockExec.store.Save(state); err != nil {
   241  		return state, 0, err
   242  	}
   243  
   244  	fail.Fail() // XXX
   245  
   246  	// Can't use stepTimes at this point as it gets wrapped up by the caller of this function
   247  	blockGenerationTimeMs := float64((time.Now().UnixNano() - execStartTime) / 1000000.0)
   248  	numTxs := len(block.Txs)
   249  	tps := 0
   250  	if blockGenerationTimeMs > 0 {
   251  		tps = int(float64(numTxs) / blockGenerationTimeMs * 1000.0)
   252  	}
   253  	blockExec.logger.Info(
   254  		"block generated",
   255  		"height", block.Height,
   256  		"num_txs", numTxs,
   257  		"generation_time", blockGenerationTimeMs/1000.0,
   258  		"tps", tps,
   259  	)
   260  
   261  	// Events are fired after everything else.
   262  	// NOTE: if we crash between Commit and Save, events wont be fired during replay
   263  	fireEvents(blockExec.logger, blockExec.eventBus, block, abciResponses, validatorUpdates)
   264  
   265  	return state, retainHeight, nil
   266  }
   267  
   268  // Commit locks the mempool, runs the ABCI Commit message, and updates the
   269  // mempool.
   270  // It returns the result of calling abci.Commit (the AppHash) and the height to retain (if any).
   271  // The Mempool must be locked during commit and update because state is
   272  // typically reset on Commit and old txs must be replayed against committed
   273  // state before new txs are run in the mempool, lest they be invalid.
   274  func (blockExec *BlockExecutor) Commit(
   275  	state State,
   276  	block *types.Block,
   277  	deliverTxResponses []*abci.ResponseDeliverTx,
   278  	stepTimes *CommitStepTimes,
   279  ) ([]byte, int64, error) {
   280  	blockExec.mempool.Lock()
   281  	defer blockExec.mempool.Unlock()
   282  
   283  	// while mempool is Locked, flush to ensure all async requests have completed
   284  	// in the ABCI app before Commit.
   285  	err := blockExec.mempool.FlushAppConn()
   286  	if err != nil {
   287  		blockExec.logger.Error("client error during mempool.FlushAppConn", "err", err)
   288  		return nil, 0, err
   289  	}
   290  
   291  	// Commit block, get hash back
   292  	appCommitStartTime := time.Now().UnixNano()
   293  	res, err := blockExec.proxyApp.CommitSync()
   294  	appCommitEndTime := time.Now().UnixNano()
   295  
   296  	appCommitTimeMs := float64(appCommitEndTime-appCommitStartTime) / 1000000
   297  	blockExec.metrics.BlockAppCommitTime.Set(appCommitTimeMs)
   298  
   299  	if err != nil {
   300  		blockExec.logger.Error("client error during proxyAppConn.CommitSync", "err", err)
   301  		return nil, 0, err
   302  	}
   303  
   304  	// ResponseCommit has no error code - just data
   305  
   306  	if stepTimes != nil {
   307  		stepTimes.ToCommitRechecking()
   308  	}
   309  
   310  	// Update mempool.
   311  	updateMempoolStartTime := time.Now().UnixNano()
   312  	err = blockExec.mempool.Update(
   313  		block,
   314  		deliverTxResponses,
   315  		TxPreCheck(state),
   316  		TxPostCheck(state),
   317  	)
   318  	updateMempoolEndTime := time.Now().UnixNano()
   319  
   320  	updateMempoolTimeMs := float64(updateMempoolEndTime-updateMempoolStartTime) / 1000000
   321  	blockExec.metrics.BlockUpdateMempoolTime.Set(updateMempoolTimeMs)
   322  
   323  	blockExec.logger.Info(
   324  		"committed state",
   325  		"height", block.Height,
   326  		"num_txs", len(block.Txs),
   327  		"app_hash", fmt.Sprintf("%X", res.Data),
   328  		"commit_time", float64(int(appCommitTimeMs))/1000.0,
   329  		"update_mempool_time", float64(int(updateMempoolTimeMs))/1000.0,
   330  	)
   331  
   332  	return res.Data, res.RetainHeight, err
   333  }
   334  
   335  //---------------------------------------------------------
   336  // Helper functions for executing blocks and updating state
   337  
   338  // Executes block's transactions on proxyAppConn.
   339  // Returns a list of transaction results and updates to the validator set
   340  func execBlockOnProxyApp(
   341  	logger log.Logger,
   342  	proxyAppConn proxy.AppConnConsensus,
   343  	block *types.Block,
   344  	store Store,
   345  	initialHeight int64,
   346  ) (*tmstate.ABCIResponses, error) {
   347  	var validTxs, invalidTxs = 0, 0
   348  
   349  	txIndex := 0
   350  	abciResponses := new(tmstate.ABCIResponses)
   351  	dtxs := make([]*abci.ResponseDeliverTx, len(block.Txs))
   352  	abciResponses.DeliverTxs = dtxs
   353  
   354  	// Execute transactions and get hash.
   355  	proxyCb := func(req *tmabci.Request, res *tmabci.Response) {
   356  		if r, ok := res.Value.(*tmabci.Response_DeliverTx); ok {
   357  			// TODO: make use of res.Log
   358  			// TODO: make use of this info
   359  			// Blocks may include invalid txs.
   360  			txRes := r.DeliverTx
   361  			if txRes.Code == tmabci.CodeTypeOK {
   362  				validTxs++
   363  			} else {
   364  				logger.Debug("invalid tx", "code", txRes.Code, "log", txRes.Log)
   365  				invalidTxs++
   366  			}
   367  
   368  			abciResponses.DeliverTxs[txIndex] = txRes
   369  			txIndex++
   370  		}
   371  	}
   372  	proxyAppConn.SetGlobalCallback(proxyCb)
   373  
   374  	commitInfo := getBeginBlockValidatorInfo(block, store, initialHeight)
   375  
   376  	byzVals := make([]abci.Evidence, 0)
   377  	for _, evidence := range block.Evidence.Evidence {
   378  		byzVals = append(byzVals, evidence.ABCI()...)
   379  	}
   380  
   381  	// Begin block
   382  	var err error
   383  	pbh := block.Header.ToProto()
   384  	if pbh == nil {
   385  		return nil, errors.New("nil header")
   386  	}
   387  
   388  	pbe := block.Entropy.ToProto()
   389  	if pbe == nil {
   390  		return nil, errors.New("nil entropy")
   391  	}
   392  
   393  	abciResponses.BeginBlock, err = proxyAppConn.BeginBlockSync(tmabci.RequestBeginBlock{
   394  		Hash:                block.Hash(),
   395  		Header:              *pbh,
   396  		LastCommitInfo:      commitInfo,
   397  		ByzantineValidators: byzVals,
   398  		Entropy:             *pbe,
   399  	})
   400  	if err != nil {
   401  		logger.Error("error in proxyAppConn.BeginBlock", "err", err)
   402  		return nil, err
   403  	}
   404  
   405  	startTime := time.Now()
   406  	// run txs of block
   407  	for _, tx := range block.Txs {
   408  		proxyAppConn.DeliverTxAsync(abci.RequestDeliverTx{Tx: tx}, nil)
   409  		if err := proxyAppConn.Error(); err != nil {
   410  			return nil, err
   411  		}
   412  	}
   413  	endTime := time.Now()
   414  	execTime := endTime.Sub(startTime)
   415  
   416  	// End block.
   417  	abciResponses.EndBlock, err = proxyAppConn.EndBlockSync(abci.RequestEndBlock{Height: block.Height})
   418  	if err != nil {
   419  		logger.Error("error in proxyAppConn.EndBlock", "err", err)
   420  		return nil, err
   421  	}
   422  
   423  	tps := 0
   424  	if execTime.Milliseconds() > 0 {
   425  		tps = int(float64(validTxs+invalidTxs) / float64(execTime.Milliseconds()) * 1000.0)
   426  	}
   427  	logger.Info("executed block", "height", block.Height, "num_valid_txs", validTxs,
   428  		"num_invalid_txs", invalidTxs, "exec_time", float64(execTime.Milliseconds())/1000.0, "tps", tps)
   429  	return abciResponses, nil
   430  }
   431  
   432  func getBeginBlockValidatorInfo(block *types.Block, store Store,
   433  	initialHeight int64) abci.LastCommitInfo {
   434  	voteInfos := make([]abci.VoteInfo, block.LastCommit.Size())
   435  	// Initial block -> LastCommitInfo.Votes are empty.
   436  	// Remember that the first LastCommit is intentionally empty, so it makes
   437  	// sense for LastCommitInfo.Votes to also be empty.
   438  	if block.Height > initialHeight {
   439  		lastValSet, err := store.LoadValidators(block.Height - 1)
   440  		if err != nil {
   441  			panic(err)
   442  		}
   443  
   444  		// Sanity check that commit size matches validator set size - only applies
   445  		// after first block.
   446  		var (
   447  			commitSize = block.LastCommit.Size()
   448  			valSetLen  = len(lastValSet.Validators)
   449  		)
   450  		if commitSize != valSetLen {
   451  			panic(fmt.Sprintf(
   452  				"commit size (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v",
   453  				commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators,
   454  			))
   455  		}
   456  
   457  		for i, val := range lastValSet.Validators {
   458  			commitSig := block.LastCommit.Signatures[i]
   459  			voteInfos[i] = abci.VoteInfo{
   460  				Validator:       types.OC2PB.Validator(val),
   461  				SignedLastBlock: !commitSig.Absent(),
   462  			}
   463  		}
   464  	}
   465  
   466  	return abci.LastCommitInfo{
   467  		Round: block.LastCommit.Round,
   468  		Votes: voteInfos,
   469  	}
   470  }
   471  
   472  func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate,
   473  	params tmproto.ValidatorParams) error {
   474  	for _, valUpdate := range abciUpdates {
   475  		if valUpdate.GetPower() < 0 {
   476  			return fmt.Errorf("voting power can't be negative %v", valUpdate)
   477  		} else if valUpdate.GetPower() == 0 {
   478  			// continue, since this is deleting the validator, and thus there is no
   479  			// pubkey to check
   480  			continue
   481  		}
   482  
   483  		// Check if validator's pubkey matches an ABCI type in the consensus params
   484  		pk, err := cryptoenc.PubKeyFromProto(&valUpdate.PubKey)
   485  		if err != nil {
   486  			return err
   487  		}
   488  
   489  		if !types.IsValidPubkeyType(params, pk.Type()) {
   490  			return fmt.Errorf("validator %v is using pubkey %s, which is unsupported for consensus",
   491  				valUpdate, pk.Type())
   492  		}
   493  	}
   494  	return nil
   495  }
   496  
   497  // updateState returns a new State updated according to the header and responses.
   498  func updateState(
   499  	state State,
   500  	blockID types.BlockID,
   501  	header *types.Header,
   502  	entropy *types.Entropy,
   503  	abciResponses *tmstate.ABCIResponses,
   504  	validatorUpdates []*types.Validator,
   505  ) (State, error) {
   506  
   507  	// Copy the valset so we can apply changes from EndBlock
   508  	// and update s.LastValidators and s.Validators.
   509  	nValSet := state.NextValidators.Copy()
   510  
   511  	// Update the validator set with the latest abciResponses.
   512  	lastHeightValsChanged := state.LastHeightValidatorsChanged
   513  	if len(validatorUpdates) > 0 {
   514  		err := nValSet.UpdateWithChangeSet(validatorUpdates)
   515  		if err != nil {
   516  			return state, fmt.Errorf("error changing validator set: %v", err)
   517  		}
   518  		// Change results from this height but only applies to the next next height.
   519  		lastHeightValsChanged = header.Height + 1 + 1
   520  	}
   521  
   522  	// Update validator proposer priority and set state variables.
   523  	nValSet.IncrementProposerPriority(1)
   524  
   525  	// Update the params with the latest abciResponses.
   526  	nextParams := state.ConsensusParams
   527  	lastHeightParamsChanged := state.LastHeightConsensusParamsChanged
   528  	if abciResponses.EndBlock.ConsensusParamUpdates != nil {
   529  		// NOTE: must not mutate s.ConsensusParams
   530  		nextParams = types.UpdateConsensusParams(state.ConsensusParams, abciResponses.EndBlock.ConsensusParamUpdates)
   531  		err := types.ValidateConsensusParams(nextParams)
   532  		if err != nil {
   533  			return state, fmt.Errorf("error updating consensus params: %v", err)
   534  		}
   535  
   536  		state.Version.Consensus.App = nextParams.Version.AppVersion
   537  
   538  		// Change results from this height but only applies to the next height.
   539  		lastHeightParamsChanged = header.Height + 1
   540  	}
   541  
   542  	nextVersion := state.Version
   543  
   544  	// get proof hash from vrf proof
   545  	proofHash, err := vrf.ProofToHash(entropy.Proof.Bytes())
   546  	if err != nil {
   547  		return state, fmt.Errorf("error get proof of hash: %v", err)
   548  	}
   549  
   550  	// NOTE: the AppHash has not been populated.
   551  	// It will be filled on state.Save.
   552  	return State{
   553  		Version:                          nextVersion,
   554  		ChainID:                          state.ChainID,
   555  		InitialHeight:                    state.InitialHeight,
   556  		LastBlockHeight:                  header.Height,
   557  		LastBlockID:                      blockID,
   558  		LastBlockTime:                    header.Time,
   559  		LastProofHash:                    proofHash,
   560  		NextValidators:                   nValSet,
   561  		Validators:                       state.NextValidators.Copy(),
   562  		LastValidators:                   state.Validators.Copy(),
   563  		LastHeightValidatorsChanged:      lastHeightValsChanged,
   564  		ConsensusParams:                  nextParams,
   565  		LastHeightConsensusParamsChanged: lastHeightParamsChanged,
   566  		LastResultsHash:                  ABCIResponsesResultsHash(abciResponses),
   567  		AppHash:                          nil,
   568  	}, nil
   569  }
   570  
   571  // Fire NewBlock, NewBlockHeader.
   572  // Fire TxEvent for every tx.
   573  // NOTE: if tendermint crashes before commit, some or all of these events may be published again.
   574  func fireEvents(
   575  	logger log.Logger,
   576  	eventBus types.BlockEventPublisher,
   577  	block *types.Block,
   578  	abciResponses *tmstate.ABCIResponses,
   579  	validatorUpdates []*types.Validator,
   580  ) {
   581  	if err := eventBus.PublishEventNewBlock(types.EventDataNewBlock{
   582  		Block:            block,
   583  		ResultBeginBlock: *abciResponses.BeginBlock,
   584  		ResultEndBlock:   *abciResponses.EndBlock,
   585  	}); err != nil {
   586  		logger.Error("failed publishing new block", "err", err)
   587  	}
   588  
   589  	if err := eventBus.PublishEventNewBlockHeader(types.EventDataNewBlockHeader{
   590  		Header:           block.Header,
   591  		NumTxs:           int64(len(block.Txs)),
   592  		ResultBeginBlock: *abciResponses.BeginBlock,
   593  		ResultEndBlock:   *abciResponses.EndBlock,
   594  	}); err != nil {
   595  		logger.Error("failed publishing new block header", "err", err)
   596  	}
   597  
   598  	if len(block.Evidence.Evidence) != 0 {
   599  		for _, ev := range block.Evidence.Evidence {
   600  			if err := eventBus.PublishEventNewEvidence(types.EventDataNewEvidence{
   601  				Evidence: ev,
   602  				Height:   block.Height,
   603  			}); err != nil {
   604  				logger.Error("failed publishing new evidence", "err", err)
   605  			}
   606  		}
   607  	}
   608  
   609  	for i, tx := range block.Data.Txs {
   610  		if err := eventBus.PublishEventTx(types.EventDataTx{TxResult: abci.TxResult{
   611  			Height: block.Height,
   612  			Index:  uint32(i),
   613  			Tx:     tx,
   614  			Result: *(abciResponses.DeliverTxs[i]),
   615  		}}); err != nil {
   616  			logger.Error("failed publishing event TX", "err", err)
   617  		}
   618  	}
   619  
   620  	if len(validatorUpdates) > 0 {
   621  		if err := eventBus.PublishEventValidatorSetUpdates(
   622  			types.EventDataValidatorSetUpdates{ValidatorUpdates: validatorUpdates}); err != nil {
   623  			logger.Error("failed publishing event", "err", err)
   624  		}
   625  	}
   626  }
   627  
   628  //----------------------------------------------------------------------------------------------------
   629  // Execute block without state. TODO: eliminate
   630  
   631  // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state.
   632  // It returns the application root hash (result of abci.Commit).
   633  func ExecCommitBlock(
   634  	appConnConsensus proxy.AppConnConsensus,
   635  	block *types.Block,
   636  	logger log.Logger,
   637  	store Store,
   638  	initialHeight int64,
   639  ) ([]byte, error) {
   640  	_, err := execBlockOnProxyApp(logger, appConnConsensus, block, store, initialHeight)
   641  	if err != nil {
   642  		logger.Error("failed executing block on proxy app", "height", block.Height, "err", err)
   643  		return nil, err
   644  	}
   645  
   646  	// Commit block, get hash back
   647  	res, err := appConnConsensus.CommitSync()
   648  	if err != nil {
   649  		logger.Error("client error during proxyAppConn.CommitSync", "err", res)
   650  		return nil, err
   651  	}
   652  
   653  	// ResponseCommit has no error or log, just data
   654  	return res.Data, nil
   655  }