CommitCertificate() is executed after the quorum agrees on a block - applies block against the fsm - indexes the block and its transactions - removes block transactions from mempool - re-checks all transactions in mempool - atomically writes all to the underlying db - sets up the controller for the
(qc *lib.QuorumCertificate, block *lib.Block, blockResult *lib.BlockResult, ts uint64)
| 227 | // - atomically writes all to the underlying db |
| 228 | // - sets up the controller for the next height |
| 229 | func (c *Controller) CommitCertificate(qc *lib.QuorumCertificate, block *lib.Block, blockResult *lib.BlockResult, ts uint64) (err lib.ErrorI) { |
| 230 | start := time.Now() |
| 231 | // cancel any running mempool check |
| 232 | c.Mempool.stop() |
| 233 | // lock the mempool |
| 234 | c.Mempool.L.Lock() |
| 235 | defer c.Mempool.L.Unlock() |
| 236 | // log the beginning of the commit |
| 237 | c.log.Debugf("TryCommit block %s", lib.BytesToString(qc.ResultsHash)) |
| 238 | // cast the store to ensure the proper store type to complete this operation |
| 239 | storeI := c.FSM.Store().(lib.StoreI) |
| 240 | // reset the store once this code finishes; if code execution gets to `store.Commit()` - this will effectively be a noop |
| 241 | defer c.FSM.Reset() |
| 242 | // if the block result isn't 'pre-calculated' |
| 243 | if blockResult == nil { |
| 244 | // reset the FSM to ensure stale proposal validations don't come into play |
| 245 | c.FSM.Reset() |
| 246 | // apply the block against the state machine |
| 247 | blockResult, err = c.ApplyAndValidateBlock(block, true) |
| 248 | if err != nil { |
| 249 | // exit with error |
| 250 | return |
| 251 | } |
| 252 | } |
| 253 | // log indexing the quorum certificate |
| 254 | c.log.Debugf("Indexing certificate for height %d", qc.Header.Height) |
| 255 | // index the quorum certificate in the store |
| 256 | if err = storeI.IndexQC(qc); err != nil { |
| 257 | // exit with error |
| 258 | return |
| 259 | } |
| 260 | // log indexing the block |
| 261 | c.log.Debugf("Indexing block %d", block.BlockHeader.Height) |
| 262 | // index the block in the store |
| 263 | if err = storeI.IndexBlock(blockResult); err != nil { |
| 264 | // exit with error |
| 265 | return |
| 266 | } |
| 267 | // delete each transaction from the mempool |
| 268 | c.Mempool.DeleteTransaction(block.Transactions...) |
| 269 | // parse committed block for straw polls |
| 270 | c.FSM.ParsePollTransactions(blockResult) |
| 271 | // if self was the proposer |
| 272 | if bytes.Equal(qc.ProposerKey, c.PublicKey) && !c.isSyncing.Load() { |
| 273 | // send the certificate results transaction on behalf of the quorum |
| 274 | c.SendCertificateResultsTx(qc) |
| 275 | } |
| 276 | // log the start of the commit |
| 277 | c.log.Debug("Committing to store") |
| 278 | // atomically write all from the ephemeral database batch to the actual database |
| 279 | if _, err = storeI.Commit(); err != nil { |
| 280 | // exit with error |
| 281 | return err |
| 282 | } |
| 283 | // log to signal finishing the commit |
| 284 | c.log.Infof("Committed block %s at H:%d 🔒", lib.BytesToTruncatedString(qc.BlockHash), block.BlockHeader.Height) |
| 285 | // set up the finite state machine for the next height |
| 286 | c.FSM, err = fsm.New(c.Config, storeI, c.Plugin, c.Metrics, c.log) |
no test coverage detected