ApplyBlock validates the block against the state, executes it against the app, fires the relevant events, commits the app, and saves the new state and responses. It returns the new state and the block height to retain (pruning older blocks). It's the only function that needs to be called from outsid
( state State, blockID types.BlockID, block *types.Block, )
| 129 | // from outside this package to process and commit an entire block. |
| 130 | // It takes a blockID to avoid recomputing the parts hash. |
| 131 | func (blockExec *BlockExecutor) ApplyBlock( |
| 132 | state State, blockID types.BlockID, block *types.Block, |
| 133 | ) (State, int64, error) { |
| 134 | |
| 135 | if err := validateBlock(state, block); err != nil { |
| 136 | return state, 0, ErrInvalidBlock(err) |
| 137 | } |
| 138 | |
| 139 | startTime := time.Now().UnixNano() |
| 140 | abciResponses, err := execBlockOnProxyApp( |
| 141 | blockExec.logger, blockExec.proxyApp, block, blockExec.store, state.InitialHeight, |
| 142 | ) |
| 143 | endTime := time.Now().UnixNano() |
| 144 | blockExec.metrics.BlockProcessingTime.Observe(float64(endTime-startTime) / 1000000) |
| 145 | if err != nil { |
| 146 | return state, 0, ErrProxyAppConn(err) |
| 147 | } |
| 148 | |
| 149 | fail.Fail() // XXX |
| 150 | |
| 151 | // Save the results before we commit. |
| 152 | if err := blockExec.store.SaveABCIResponses(block.Height, abciResponses); err != nil { |
| 153 | return state, 0, err |
| 154 | } |
| 155 | |
| 156 | fail.Fail() // XXX |
| 157 | |
| 158 | // validate the validator updates and convert to tendermint types |
| 159 | abciValUpdates := abciResponses.EndBlock.ValidatorUpdates |
| 160 | err = validateValidatorUpdates(abciValUpdates, state.ConsensusParams.Validator) |
| 161 | if err != nil { |
| 162 | return state, 0, fmt.Errorf("error in validator updates: %v", err) |
| 163 | } |
| 164 | |
| 165 | validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciValUpdates) |
| 166 | if err != nil { |
| 167 | return state, 0, err |
| 168 | } |
| 169 | if len(validatorUpdates) > 0 { |
| 170 | blockExec.logger.Debug("updates to validators", "updates", types.ValidatorListString(validatorUpdates)) |
| 171 | } |
| 172 | |
| 173 | // Update the state with the block and responses. |
| 174 | state, err = updateState(state, blockID, &block.Header, abciResponses, validatorUpdates) |
| 175 | if err != nil { |
| 176 | return state, 0, fmt.Errorf("commit failed for application: %v", err) |
| 177 | } |
| 178 | |
| 179 | // Lock mempool, commit app state, update mempoool. |
| 180 | appHash, retainHeight, err := blockExec.Commit(state, block, abciResponses.DeliverTxs) |
| 181 | if err != nil { |
| 182 | return state, 0, fmt.Errorf("commit failed for application: %v", err) |
| 183 | } |
| 184 | |
| 185 | // Update evpool with the latest state. |
| 186 | blockExec.evpool.Update(state, block.Evidence.Evidence) |
| 187 | |
| 188 | fail.Fail() // XXX |