github.com/okex/exchain@v1.8.0/libs/tendermint/state/execution.go (about)

     1  package state
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"time"
     7  
     8  	"github.com/okex/exchain/libs/system/trace"
     9  	abci "github.com/okex/exchain/libs/tendermint/abci/types"
    10  	cfg "github.com/okex/exchain/libs/tendermint/config"
    11  	"github.com/okex/exchain/libs/tendermint/global"
    12  	"github.com/okex/exchain/libs/tendermint/libs/automation"
    13  	"github.com/okex/exchain/libs/tendermint/libs/fail"
    14  	"github.com/okex/exchain/libs/tendermint/libs/log"
    15  	mempl "github.com/okex/exchain/libs/tendermint/mempool"
    16  	"github.com/okex/exchain/libs/tendermint/proxy"
    17  	"github.com/okex/exchain/libs/tendermint/types"
    18  	tmtime "github.com/okex/exchain/libs/tendermint/types/time"
    19  	dbm "github.com/okex/exchain/libs/tm-db"
    20  	"github.com/tendermint/go-amino"
    21  )
    22  
    23  // -----------------------------------------------------------------------------
    24  type (
    25  	// Enum mode for executing [deliverTx, ...]
    26  	DeliverTxsExecMode int
    27  )
    28  
    29  const (
    30  	DeliverTxsExecModeSerial   DeliverTxsExecMode = iota // execute [deliverTx,...] sequentially
    31  	DeliverTxsExecModeParallel                    = 2    // execute [deliverTx,...] parallel
    32  
    33  	// There are two modes.
    34  	// 0: execute [deliverTx,...] sequentially (default)
    35  	// 1: execute [deliverTx,...] deprecated
    36  	// 2: execute [deliverTx,...] parallel
    37  	FlagDeliverTxsExecMode = "deliver-txs-mode"
    38  	FlagEnableConcurrency  = "enable-concurrency"
    39  )
    40  
    41  // BlockExecutor handles block execution and state updates.
    42  // It exposes ApplyBlock(), which validates & executes the block, updates state w/ ABCI responses,
    43  // then commits and updates the mempool atomically, then saves state.
    44  
    45  // BlockExecutor provides the context and accessories for properly executing a block.
    46  type BlockExecutor struct {
    47  	// save state, validators, consensus params, abci responses here
    48  	db dbm.DB
    49  
    50  	// execute the app against this
    51  	proxyApp proxy.AppConnConsensus
    52  
    53  	// events
    54  	eventBus types.BlockEventPublisher
    55  
    56  	// manage the mempool lock during commit
    57  	// and update both with block results after commit.
    58  	mempool mempl.Mempool
    59  	evpool  EvidencePool
    60  
    61  	logger  log.Logger
    62  	metrics *Metrics
    63  
    64  	// download or upload data to dds
    65  	deltaContext *DeltaContext
    66  
    67  	prerunCtx *prerunContext
    68  
    69  	isFastSync bool
    70  
    71  	// async save state, validators, consensus params, abci responses here
    72  	asyncDBContext
    73  
    74  	// the owner is validator
    75  	isNullIndexer bool
    76  	eventsChan    chan event
    77  }
    78  
    79  type event struct {
    80  	block   *types.Block
    81  	abciRsp *ABCIResponses
    82  	vals    []*types.Validator
    83  }
    84  
    85  type BlockExecutorOption func(executor *BlockExecutor)
    86  
    87  func BlockExecutorWithMetrics(metrics *Metrics) BlockExecutorOption {
    88  	return func(blockExec *BlockExecutor) {
    89  		blockExec.metrics = metrics
    90  	}
    91  }
    92  
    93  // NewBlockExecutor returns a new BlockExecutor with a NopEventBus.
    94  // Call SetEventBus to provide one.
    95  func NewBlockExecutor(
    96  	db dbm.DB,
    97  	logger log.Logger,
    98  	proxyApp proxy.AppConnConsensus,
    99  	mempool mempl.Mempool,
   100  	evpool EvidencePool,
   101  	options ...BlockExecutorOption,
   102  ) *BlockExecutor {
   103  	res := &BlockExecutor{
   104  		db:           db,
   105  		proxyApp:     proxyApp,
   106  		eventBus:     types.NopEventBus{},
   107  		mempool:      mempool,
   108  		evpool:       evpool,
   109  		logger:       logger,
   110  		metrics:      NopMetrics(),
   111  		prerunCtx:    newPrerunContex(logger),
   112  		deltaContext: newDeltaContext(logger),
   113  		eventsChan:   make(chan event, 5),
   114  	}
   115  
   116  	for _, option := range options {
   117  		option(res)
   118  	}
   119  	automation.LoadTestCase(logger)
   120  	res.deltaContext.init()
   121  
   122  	res.initAsyncDBContext()
   123  
   124  	return res
   125  }
   126  
   127  func (blockExec *BlockExecutor) fireEventsRountine() {
   128  	for et := range blockExec.eventsChan {
   129  		if et.block == nil {
   130  			break
   131  		}
   132  		fireEvents(blockExec.logger, blockExec.eventBus, et.block, et.abciRsp, et.vals)
   133  	}
   134  	blockExec.wg.Done()
   135  }
   136  
   137  func (blockExec *BlockExecutor) DB() dbm.DB {
   138  	return blockExec.db
   139  }
   140  
   141  func (blockExec *BlockExecutor) SetIsFastSyncing(isSyncing bool) {
   142  	blockExec.isFastSync = isSyncing
   143  }
   144  
   145  func (blockExec *BlockExecutor) SetIsNullIndexer(isNullIndexer bool) {
   146  	blockExec.isNullIndexer = isNullIndexer
   147  }
   148  
   149  func (blockExec *BlockExecutor) Stop() {
   150  	blockExec.stopAsyncDBContext()
   151  }
   152  
   153  // SetEventBus - sets the event bus for publishing block related events.
   154  // If not called, it defaults to types.NopEventBus.
   155  func (blockExec *BlockExecutor) SetEventBus(eventBus types.BlockEventPublisher) {
   156  	blockExec.eventBus = eventBus
   157  	blockExec.mempool.SetEventBus(eventBus)
   158  }
   159  
   160  // CreateProposalBlock calls state.MakeBlock with evidence from the evpool
   161  // and txs from the mempool. The max bytes must be big enough to fit the commit.
   162  // Up to 1/10th of the block space is allcoated for maximum sized evidence.
   163  // The rest is given to txs, up to the max gas.
   164  func (blockExec *BlockExecutor) CreateProposalBlock(
   165  	height int64,
   166  	state State, commit *types.Commit,
   167  	proposerAddr []byte,
   168  ) (*types.Block, *types.PartSet) {
   169  
   170  	maxBytes := state.ConsensusParams.Block.MaxBytes
   171  	maxGas := state.ConsensusParams.Block.MaxGas
   172  
   173  	// Fetch a limited amount of valid evidence
   174  	maxNumEvidence, _ := types.MaxEvidencePerBlock(maxBytes)
   175  	evidence := blockExec.evpool.PendingEvidence(maxNumEvidence)
   176  
   177  	// Fetch a limited amount of valid txs
   178  	maxDataBytes := types.MaxDataBytes(maxBytes, state.Validators.Size(), len(evidence))
   179  	if cfg.DynamicConfig.GetMaxGasUsedPerBlock() > -1 {
   180  		maxGas = cfg.DynamicConfig.GetMaxGasUsedPerBlock()
   181  	}
   182  	txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas)
   183  
   184  	return state.MakeBlock(height, txs, commit, evidence, proposerAddr)
   185  }
   186  
   187  // ValidateBlock validates the given block against the given state.
   188  // If the block is invalid, it returns an error.
   189  // Validation does not mutate state, but does require historical information from the stateDB,
   190  // ie. to verify evidence from a validator at an old height.
   191  func (blockExec *BlockExecutor) ValidateBlock(state State, block *types.Block) error {
   192  	if IgnoreSmbCheck {
   193  		// debug only
   194  		return nil
   195  	}
   196  	return validateBlock(blockExec.evpool, blockExec.db, state, block)
   197  }
   198  
   199  // ApplyBlock validates the block against the state, executes it against the app,
   200  // fires the relevant events, commits the app, and saves the new state and responses.
   201  // It returns the new state and the block height to retain (pruning older blocks).
   202  // It's the only function that needs to be called
   203  // from outside this package to process and commit an entire block.
   204  // It takes a blockID to avoid recomputing the parts hash.
   205  func (blockExec *BlockExecutor) ApplyBlock(
   206  	state State, blockID types.BlockID, block *types.Block) (State, int64, error) {
   207  	if ApplyBlockPprofTime >= 0 {
   208  		f, t := PprofStart()
   209  		defer PprofEnd(int(block.Height), f, t)
   210  	}
   211  
   212  	trc := trace.NewTracer(trace.ApplyBlock)
   213  	trc.EnableSummary()
   214  	trc.SetWorkloadStatistic(trace.GetApplyBlockWorkloadSttistic())
   215  	dc := blockExec.deltaContext
   216  
   217  	defer func() {
   218  		trace.GetElapsedInfo().AddInfo(trace.Height, strconv.FormatInt(block.Height, 10))
   219  		trace.GetElapsedInfo().AddInfo(trace.Tx, strconv.Itoa(len(block.Data.Txs)))
   220  		trace.GetElapsedInfo().AddInfo(trace.BlockSize, strconv.Itoa(block.FastSize()))
   221  		trace.GetElapsedInfo().AddInfo(trace.ApplyBlock, trc.Format())
   222  		trace.GetElapsedInfo().AddInfo(trace.Workload, trace.GetApplyBlockWorkloadSttistic().Format())
   223  		trace.GetElapsedInfo().SetElapsedTime(trc.GetElapsedTime())
   224  
   225  		now := time.Now().UnixNano()
   226  		blockExec.metrics.IntervalTime.Set(float64(now-blockExec.metrics.lastBlockTime) / 1e6)
   227  		blockExec.metrics.lastBlockTime = now
   228  		blockExec.metrics.CommittedHeight.Set(float64(block.Height))
   229  	}()
   230  
   231  	if err := blockExec.ValidateBlock(state, block); err != nil {
   232  		return state, 0, ErrInvalidBlock(err)
   233  	}
   234  
   235  	deltaInfo := dc.prepareStateDelta(block.Height)
   236  
   237  	trc.Pin(trace.Abci)
   238  	if cfg.DynamicConfig.GetEnablePGU() {
   239  		global.CommitLock()
   240  		defer global.CommitUnlock()
   241  	}
   242  
   243  	startTime := time.Now().UnixNano()
   244  
   245  	//wait till the last block async write be saved
   246  	blockExec.tryWaitLastBlockSave(block.Height - 1)
   247  
   248  	abciResponses, duration, err := blockExec.runAbci(block, deltaInfo)
   249  
   250  	// publish event
   251  	if types.EnableEventBlockTime {
   252  		blockExec.FireBlockTimeEvents(block.Height, len(block.Txs), true)
   253  		if !blockExec.isNullIndexer {
   254  			blockExec.eventsChan <- event{
   255  				block:   block,
   256  				abciRsp: abciResponses,
   257  			}
   258  		}
   259  	}
   260  
   261  	trace.GetElapsedInfo().AddInfo(trace.LastRun, fmt.Sprintf("%dms", duration.Milliseconds()))
   262  	trace.GetApplyBlockWorkloadSttistic().Add(trace.LastRun, time.Now(), duration)
   263  
   264  	if err != nil {
   265  		return state, 0, ErrProxyAppConn(err)
   266  	}
   267  
   268  	fail.Fail() // XXX
   269  
   270  	// Save the results before we commit.
   271  	blockExec.trySaveABCIResponsesAsync(block.Height, abciResponses)
   272  
   273  	fail.Fail() // XXX
   274  	endTime := time.Now().UnixNano()
   275  	blockExec.metrics.BlockProcessingTime.Observe(float64(endTime-startTime) / 1e6)
   276  	blockExec.metrics.AbciTime.Set(float64(endTime-startTime) / 1e6)
   277  
   278  	// validate the validator updates and convert to tendermint types
   279  	abciValUpdates := abciResponses.EndBlock.ValidatorUpdates
   280  	err = validateValidatorUpdates(abciValUpdates, state.ConsensusParams.Validator)
   281  	if err != nil {
   282  		return state, 0, fmt.Errorf("error in validator updates: %v", err)
   283  	}
   284  	validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciValUpdates)
   285  	if err != nil {
   286  		return state, 0, err
   287  	}
   288  	if len(validatorUpdates) > 0 {
   289  		blockExec.logger.Info("Updates to validators", "updates", types.ValidatorListString(validatorUpdates))
   290  	}
   291  
   292  	// Update the state with the block and responses.
   293  	state, err = updateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
   294  	if err != nil {
   295  		return state, 0, fmt.Errorf("commit failed for application: %v", err)
   296  	}
   297  
   298  	trc.Pin(trace.Persist)
   299  	startTime = time.Now().UnixNano()
   300  
   301  	// Lock mempool, commit app state, update mempoool.
   302  	commitResp, retainHeight, err := blockExec.commit(state, block, deltaInfo, abciResponses.DeliverTxs, trc)
   303  	endTime = time.Now().UnixNano()
   304  	blockExec.metrics.CommitTime.Set(float64(endTime-startTime) / 1e6)
   305  	if err != nil {
   306  		return state, 0, fmt.Errorf("commit failed for application: %v", err)
   307  	}
   308  	global.SetGlobalHeight(block.Height)
   309  
   310  	// Update evpool with the block and state.
   311  	blockExec.evpool.Update(block, state)
   312  
   313  	fail.Fail() // XXX
   314  
   315  	trc.Pin("SaveState")
   316  	// Update the app hash and save the state.
   317  	state.AppHash = commitResp.Data
   318  	blockExec.trySaveStateAsync(state)
   319  
   320  	blockExec.logger.Debug("SaveState", "state", &state)
   321  	fail.Fail() // XXX
   322  
   323  	dc.postApplyBlock(block.Height, deltaInfo, abciResponses, commitResp.DeltaMap, blockExec.isFastSync)
   324  
   325  	// Events are fired after everything else.
   326  	// NOTE: if we crash between Commit and Save, events wont be fired during replay
   327  	if !types.EnableEventBlockTime {
   328  		if !blockExec.isNullIndexer {
   329  			blockExec.eventsChan <- event{
   330  				block:   block,
   331  				abciRsp: abciResponses,
   332  			}
   333  		}
   334  	}
   335  
   336  	return state, retainHeight, nil
   337  }
   338  
   339  func (blockExec *BlockExecutor) ApplyBlockWithTrace(
   340  	state State, blockID types.BlockID, block *types.Block) (State, int64, error) {
   341  	s, id, err := blockExec.ApplyBlock(state, blockID, block)
   342  	trace.GetElapsedInfo().Dump(blockExec.logger.With("module", "main"))
   343  	return s, id, err
   344  }
   345  
   346  func (blockExec *BlockExecutor) runAbci(block *types.Block, deltaInfo *DeltaInfo) (*ABCIResponses, time.Duration, error) {
   347  	var abciResponses *ABCIResponses
   348  	var err error
   349  	var duration time.Duration
   350  
   351  	if deltaInfo != nil {
   352  		blockExec.logger.Info("Apply delta", "height", block.Height, "deltas-length", deltaInfo.deltaLen)
   353  		t0 := time.Now()
   354  		execBlockOnProxyAppWithDeltas(blockExec.proxyApp, block, blockExec.db)
   355  		abciResponses = deltaInfo.abciResponses
   356  		duration = time.Now().Sub(t0)
   357  	} else {
   358  		pc := blockExec.prerunCtx
   359  		if pc.prerunTx {
   360  			abciResponses, duration, err = pc.getPrerunResult(block)
   361  		}
   362  
   363  		if abciResponses == nil {
   364  			t0 := time.Now()
   365  			ctx := &executionTask{
   366  				logger:   blockExec.logger,
   367  				block:    block,
   368  				db:       blockExec.db,
   369  				proxyApp: blockExec.proxyApp,
   370  			}
   371  			mode := DeliverTxsExecMode(cfg.DynamicConfig.GetDeliverTxsExecuteMode())
   372  			switch mode {
   373  			case DeliverTxsExecModeSerial:
   374  				abciResponses, err = execBlockOnProxyApp(ctx)
   375  			case DeliverTxsExecModeParallel:
   376  				abciResponses, err = execBlockOnProxyAppAsync(blockExec.logger, blockExec.proxyApp, block, blockExec.db)
   377  			default:
   378  				abciResponses, err = execBlockOnProxyApp(ctx)
   379  			}
   380  			duration = time.Now().Sub(t0)
   381  		}
   382  	}
   383  
   384  	return abciResponses, duration, err
   385  }
   386  
   387  // Commit locks the mempool, runs the ABCI Commit message, and updates the
   388  // mempool.
   389  // It returns the result of calling abci.Commit (the AppHash) and the height to retain (if any).
   390  // The Mempool must be locked during commit and update because state is
   391  // typically reset on Commit and old txs must be replayed against committed
   392  // state before new txs are run in the mempool, lest they be invalid.
   393  func (blockExec *BlockExecutor) commit(
   394  	state State,
   395  	block *types.Block,
   396  	deltaInfo *DeltaInfo,
   397  	deliverTxResponses []*abci.ResponseDeliverTx,
   398  	trc *trace.Tracer,
   399  ) (*abci.ResponseCommit, int64, error) {
   400  	blockExec.mempool.Lock()
   401  	defer func() {
   402  		blockExec.mempool.Unlock()
   403  		// Forced flushing mempool
   404  		if cfg.DynamicConfig.GetMempoolFlush() {
   405  			blockExec.mempool.Flush()
   406  		}
   407  	}()
   408  
   409  	// while mempool is Locked, flush to ensure all async requests have completed
   410  	// in the ABCI app before Commit.
   411  	err := blockExec.mempool.FlushAppConn()
   412  	if err != nil {
   413  		blockExec.logger.Error("Client error during mempool.FlushAppConn", "err", err)
   414  		return nil, 0, err
   415  	}
   416  
   417  	// Commit block, get hash back
   418  	var treeDeltaMap interface{}
   419  	if deltaInfo != nil {
   420  		treeDeltaMap = deltaInfo.treeDeltaMap
   421  	}
   422  	res, err := blockExec.proxyApp.CommitSync(abci.RequestCommit{DeltaMap: treeDeltaMap})
   423  	if err != nil {
   424  		blockExec.logger.Error(
   425  			"Client error during proxyAppConn.CommitSync",
   426  			"err", err,
   427  		)
   428  		return nil, 0, err
   429  	}
   430  
   431  	// ResponseCommit has no error code - just data
   432  	blockExec.logger.Debug(
   433  		"Committed state",
   434  		"height", block.Height,
   435  		"txs", len(block.Txs),
   436  		"appHash", amino.BytesHexStringer(res.Data),
   437  		"blockLen", amino.FuncStringer(func() string { return strconv.Itoa(block.FastSize()) }),
   438  	)
   439  
   440  	trc.Pin("mpUpdate")
   441  	// Update mempool.
   442  	err = blockExec.mempool.Update(
   443  		block.Height,
   444  		block.Txs,
   445  		deliverTxResponses,
   446  		TxPreCheck(state),
   447  		TxPostCheck(state),
   448  	)
   449  
   450  	if !cfg.DynamicConfig.GetMempoolRecheck() && block.Height%cfg.DynamicConfig.GetMempoolForceRecheckGap() == 0 {
   451  		proxyCb := func(req *abci.Request, res *abci.Response) {
   452  
   453  		}
   454  		blockExec.proxyApp.SetResponseCallback(proxyCb)
   455  		// reset checkState
   456  		blockExec.proxyApp.SetOptionAsync(abci.RequestSetOption{
   457  			Key: "ResetCheckState",
   458  		})
   459  	}
   460  
   461  	return res, res.RetainHeight, err
   462  }
   463  
   464  func transTxsToBytes(txs types.Txs) [][]byte {
   465  	ret := make([][]byte, 0)
   466  	for _, v := range txs {
   467  		ret = append(ret, v)
   468  	}
   469  	return ret
   470  }
   471  
   472  //---------------------------------------------------------
   473  // Helper functions for executing blocks and updating state
   474  
   475  // Executes block's transactions on proxyAppConn.
   476  // Returns a list of transaction results and updates to the validator set
   477  func execBlockOnProxyApp(context *executionTask) (*ABCIResponses, error) {
   478  	block := context.block
   479  	proxyAppConn := context.proxyApp
   480  	stateDB := context.db
   481  	logger := context.logger
   482  
   483  	var validTxs, invalidTxs = 0, 0
   484  
   485  	txIndex := 0
   486  	abciResponses := NewABCIResponses(block)
   487  
   488  	// Execute transactions and get hash.
   489  	proxyCb := func(req *abci.Request, res *abci.Response) {
   490  		if r, ok := res.Value.(*abci.Response_DeliverTx); ok {
   491  			// TODO: make use of res.Log
   492  			// TODO: make use of this info
   493  			// Blocks may include invalid txs.
   494  			txRes := r.DeliverTx
   495  			if txRes.Code == abci.CodeTypeOK {
   496  				validTxs++
   497  			} else {
   498  				logger.Debug("Invalid tx", "code", txRes.Code, "log", txRes.Log, "index", txIndex)
   499  				invalidTxs++
   500  			}
   501  			abciResponses.DeliverTxs[txIndex] = txRes
   502  			txIndex++
   503  		}
   504  	}
   505  	proxyAppConn.SetResponseCallback(proxyCb)
   506  
   507  	// proxyAppConn.ParallelTxs(transTxsToBytes(block.Txs), true)
   508  	commitInfo, byzVals := getBeginBlockValidatorInfo(block, stateDB)
   509  
   510  	// Begin block
   511  	var err error
   512  	abciResponses.BeginBlock, err = proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
   513  		Hash:                block.Hash(),
   514  		Header:              types.TM2PB.Header(&block.Header),
   515  		LastCommitInfo:      commitInfo,
   516  		ByzantineValidators: byzVals,
   517  	})
   518  	if err != nil {
   519  		logger.Error("Error in proxyAppConn.BeginBlock", "err", err)
   520  		return nil, err
   521  	}
   522  
   523  	realTxCh := make(chan abci.TxEssentials, len(block.Txs))
   524  	stopedCh := make(chan struct{}, 1)
   525  
   526  	go preDeliverRoutine(proxyAppConn, block.Txs, realTxCh, stopedCh)
   527  
   528  	count := 0
   529  	for realTx := range realTxCh {
   530  		if realTx != nil {
   531  			proxyAppConn.DeliverRealTxAsync(realTx)
   532  		} else {
   533  			proxyAppConn.DeliverTxAsync(abci.RequestDeliverTx{Tx: block.Txs[count]})
   534  		}
   535  
   536  		if err = proxyAppConn.Error(); err != nil {
   537  			return nil, err
   538  		}
   539  		if context != nil && context.stopped {
   540  			stopedCh <- struct{}{}
   541  			close(stopedCh)
   542  			context.dump(fmt.Sprintf("Prerun stopped, %d/%d tx executed", count+1, len(block.Txs)))
   543  			return nil, fmt.Errorf("Prerun stopped")
   544  		}
   545  		count += 1
   546  	}
   547  	close(stopedCh)
   548  
   549  	// End block.
   550  	abciResponses.EndBlock, err = proxyAppConn.EndBlockSync(abci.RequestEndBlock{Height: block.Height})
   551  	if err != nil {
   552  		logger.Error("Error in proxyAppConn.EndBlock", "err", err)
   553  		return nil, err
   554  	}
   555  
   556  	trace.GetElapsedInfo().AddInfo(trace.InvalidTxs, fmt.Sprintf("%d", invalidTxs))
   557  
   558  	return abciResponses, nil
   559  }
   560  
   561  func preDeliverRoutine(proxyAppConn proxy.AppConnConsensus, txs types.Txs, realTxCh chan<- abci.TxEssentials, stopedCh <-chan struct{}) {
   562  	for _, tx := range txs {
   563  		realTx := proxyAppConn.PreDeliverRealTxAsync(tx)
   564  		select {
   565  		case realTxCh <- realTx:
   566  		case <-stopedCh:
   567  			close(realTxCh)
   568  			return
   569  		}
   570  	}
   571  	close(realTxCh)
   572  }
   573  
   574  func execBlockOnProxyAppWithDeltas(
   575  	proxyAppConn proxy.AppConnConsensus,
   576  	block *types.Block,
   577  	stateDB dbm.DB,
   578  ) {
   579  	proxyCb := func(req *abci.Request, res *abci.Response) {
   580  	}
   581  	proxyAppConn.SetResponseCallback(proxyCb)
   582  
   583  	commitInfo, byzVals := getBeginBlockValidatorInfo(block, stateDB)
   584  	_, _ = proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
   585  		Hash:                block.Hash(),
   586  		Header:              types.TM2PB.Header(&block.Header),
   587  		LastCommitInfo:      commitInfo,
   588  		ByzantineValidators: byzVals,
   589  	})
   590  }
   591  
   592  func getBeginBlockValidatorInfo(block *types.Block, stateDB dbm.DB) (abci.LastCommitInfo, []abci.Evidence) {
   593  	voteInfos := make([]abci.VoteInfo, block.LastCommit.Size())
   594  	// block.Height=1 -> LastCommitInfo.Votes are empty.
   595  	// Remember that the first LastCommit is intentionally empty, so it makes
   596  	// sense for LastCommitInfo.Votes to also be empty.
   597  	if block.Height > types.GetStartBlockHeight()+1 {
   598  		lastValSet, err := LoadValidators(stateDB, block.Height-1)
   599  		if err != nil {
   600  			panic(err)
   601  		}
   602  
   603  		// Sanity check that commit size matches validator set size - only applies
   604  		// after first block.
   605  		var (
   606  			commitSize = block.LastCommit.Size()
   607  			valSetLen  = len(lastValSet.Validators)
   608  		)
   609  		if commitSize != valSetLen {
   610  			panic(fmt.Sprintf("commit size (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v",
   611  				commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators))
   612  		}
   613  
   614  		for i, val := range lastValSet.Validators {
   615  			commitSig := block.LastCommit.Signatures[i]
   616  			voteInfos[i] = abci.VoteInfo{
   617  				Validator:       types.TM2PB.Validator(val),
   618  				SignedLastBlock: !commitSig.Absent(),
   619  			}
   620  		}
   621  	}
   622  
   623  	byzVals := make([]abci.Evidence, len(block.Evidence.Evidence))
   624  	for i, ev := range block.Evidence.Evidence {
   625  		// We need the validator set. We already did this in validateBlock.
   626  		// TODO: Should we instead cache the valset in the evidence itself and add
   627  		// `SetValidatorSet()` and `ToABCI` methods ?
   628  		valset, err := LoadValidators(stateDB, ev.Height())
   629  		if err != nil {
   630  			panic(err)
   631  		}
   632  		byzVals[i] = types.TM2PB.Evidence(ev, valset, block.Time)
   633  	}
   634  
   635  	return abci.LastCommitInfo{
   636  		Round: int32(block.LastCommit.Round),
   637  		Votes: voteInfos,
   638  	}, byzVals
   639  }
   640  
   641  func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate,
   642  	params types.ValidatorParams) error {
   643  	for _, valUpdate := range abciUpdates {
   644  		if valUpdate.GetPower() < 0 {
   645  			return fmt.Errorf("voting power can't be negative %v", valUpdate)
   646  		} else if valUpdate.GetPower() == 0 {
   647  			// continue, since this is deleting the validator, and thus there is no
   648  			// pubkey to check
   649  			continue
   650  		}
   651  
   652  		// Check if validator's pubkey matches an ABCI type in the consensus params
   653  		thisKeyType := valUpdate.PubKey.Type
   654  		if !params.IsValidPubkeyType(thisKeyType) {
   655  			return fmt.Errorf("validator %v is using pubkey %s, which is unsupported for consensus",
   656  				valUpdate, thisKeyType)
   657  		}
   658  	}
   659  	return nil
   660  }
   661  
   662  // updateState returns a new State updated according to the header and responses.
   663  func updateState(
   664  	state State,
   665  	blockID types.BlockID,
   666  	header *types.Header,
   667  	abciResponses *ABCIResponses,
   668  	validatorUpdates []*types.Validator,
   669  ) (State, error) {
   670  
   671  	// Copy the valset so we can apply changes from EndBlock
   672  	// and update s.LastValidators and s.Validators.
   673  	nValSet := state.NextValidators.Copy()
   674  
   675  	// Update the validator set with the latest abciResponses.
   676  	lastHeightValsChanged := state.LastHeightValidatorsChanged
   677  	if len(validatorUpdates) > 0 {
   678  		err := nValSet.UpdateWithChangeSet(validatorUpdates)
   679  		if err != nil {
   680  			return state, fmt.Errorf("error changing validator set: %v", err)
   681  		}
   682  		// Change results from this height but only applies to the next next height.
   683  		lastHeightValsChanged = header.Height + 1 + 1
   684  	}
   685  
   686  	// Update validator proposer priority and set state variables.
   687  	nValSet.IncrementProposerPriority(1)
   688  
   689  	// Update the params with the latest abciResponses.
   690  	nextParams := state.ConsensusParams
   691  	lastHeightParamsChanged := state.LastHeightConsensusParamsChanged
   692  	if abciResponses.EndBlock.ConsensusParamUpdates != nil {
   693  		// NOTE: must not mutate s.ConsensusParams
   694  		nextParams = state.ConsensusParams.Update(abciResponses.EndBlock.ConsensusParamUpdates)
   695  		err := nextParams.Validate()
   696  		if err != nil {
   697  			return state, fmt.Errorf("error updating consensus params: %v", err)
   698  		}
   699  		// Change results from this height but only applies to the next height.
   700  		lastHeightParamsChanged = header.Height + 1
   701  	}
   702  
   703  	// TODO: allow app to upgrade version
   704  	nextVersion := state.Version
   705  	if types.HigherThanVenus1(header.Height) && !state.Version.IsUpgraded() {
   706  		nextVersion = state.Version.UpgradeToIBCVersion()
   707  	}
   708  
   709  	// NOTE: the AppHash has not been populated.
   710  	// It will be filled on state.Save.
   711  	return State{
   712  		Version:                          nextVersion,
   713  		ChainID:                          state.ChainID,
   714  		LastBlockHeight:                  header.Height,
   715  		LastBlockID:                      blockID,
   716  		LastBlockTime:                    header.Time,
   717  		NextValidators:                   nValSet,
   718  		Validators:                       state.NextValidators.Copy(),
   719  		LastValidators:                   state.Validators.Copy(),
   720  		LastHeightValidatorsChanged:      lastHeightValsChanged,
   721  		ConsensusParams:                  nextParams,
   722  		LastHeightConsensusParamsChanged: lastHeightParamsChanged,
   723  		LastResultsHash:                  abciResponses.ResultsHash(),
   724  		AppHash:                          nil,
   725  	}, nil
   726  }
   727  
   728  // Fire NewBlock, NewBlockHeader.
   729  // Fire TxEvent for every tx.
   730  // NOTE: if Tendermint crashes before commit, some or all of these events may be published again.
   731  func fireEvents(
   732  	logger log.Logger,
   733  	eventBus types.BlockEventPublisher,
   734  	block *types.Block,
   735  	abciResponses *ABCIResponses,
   736  	validatorUpdates []*types.Validator,
   737  ) {
   738  	eventBus.PublishEventNewBlock(types.EventDataNewBlock{
   739  		Block:            block,
   740  		ResultBeginBlock: *abciResponses.BeginBlock,
   741  		ResultEndBlock:   *abciResponses.EndBlock,
   742  	})
   743  	eventBus.PublishEventNewBlockHeader(types.EventDataNewBlockHeader{
   744  		Header:           block.Header,
   745  		NumTxs:           int64(len(block.Txs)),
   746  		ResultBeginBlock: *abciResponses.BeginBlock,
   747  		ResultEndBlock:   *abciResponses.EndBlock,
   748  	})
   749  
   750  	//publish tx event 1by1
   751  	for i, tx := range block.Data.Txs {
   752  		eventBus.PublishEventTx(types.EventDataTx{TxResult: types.TxResult{
   753  			Height: block.Height,
   754  			Index:  uint32(i),
   755  			Tx:     tx,
   756  			Result: *(abciResponses.DeliverTxs[i]),
   757  		}})
   758  	}
   759  
   760  	//publish batch txs event
   761  	if len(block.Data.Txs) > 0 {
   762  		eventBus.PublishEventTxs(types.EventDataTxs{
   763  			Height:  block.Height,
   764  			Results: abciResponses.DeliverTxs,
   765  		})
   766  	}
   767  
   768  	//if len(validatorUpdates) > 0 {
   769  	//	eventBus.PublishEventValidatorSetUpdates(
   770  	//		types.EventDataValidatorSetUpdates{ValidatorUpdates: validatorUpdates})
   771  	//}
   772  }
   773  
   774  func (blockExec *BlockExecutor) FireBlockTimeEvents(height int64, txNum int, available bool) {
   775  	blockExec.eventBus.PublishEventLatestBlockTime(
   776  		types.EventDataBlockTime{Height: height, TimeNow: tmtime.Now().UnixMilli(), TxNum: txNum, Available: available})
   777  }