MCPcopy
hub / github.com/canopy-network/canopy / ApplyAndValidateBlock

Method ApplyAndValidateBlock

controller/block.go:452–501  ·  view source on GitHub ↗

INTERNAL HELPERS BELOW ApplyAndValidateBlock() plays the block against the state machine which returns a result that is compared against the candidate block header

(block *lib.Block, commit bool)

Source from the content-addressed store, hash-verified

450
451// ApplyAndValidateBlock() plays the block against the state machine which returns a result that is compared against the candidate block header
452func (c *Controller) ApplyAndValidateBlock(block *lib.Block, commit bool) (b *lib.BlockResult, err lib.ErrorI) {
453 // define convenience variables for the block header, hash, and height
454 candidate, candidateHash, candidateHeight := block.BlockHeader, lib.BytesToString(block.BlockHeader.Hash), block.BlockHeader.Height
455 // check the last qc in the candidate and set it in the ephemeral indexer to prepare for block application
456 if err = c.CheckAndSetLastCertificate(candidate); err != nil {
457 // exit with error
458 return
459 }
460 // log the start of 'apply block'
461 c.log.Debugf("Applying block %s for height %d", candidateHash[:20], candidateHeight)
462 // apply the block against the state machine
463 compare, results, err := c.FSM.ApplyBlock(context.Background(), block, false)
464 if err != nil {
465 // exit with error
466 return
467 }
468 // if any transactions failed
469 if len(results.Failed) != 0 {
470 for _, f := range results.Failed {
471 c.log.Errorf("From: %s\nType:%s\nErr:%s", f.Address, f.Transaction.MessageType, f.Error.Error())
472 }
473 return nil, lib.ErrFailedTransactions()
474 }
475 // compare the block headers for equality
476 compareHash, err := compare.SetHash()
477 if err != nil {
478 // exit with error
479 return
480 }
481 // use the hash to compare two block headers for equality
482 if !bytes.Equal(compareHash, candidate.Hash) {
483 c.debugDumpHeaderDiff(candidate, compare)
484 return nil, lib.ErrUnequalBlockHash()
485 }
486 // validate VDF if committing randomly since this randomness is pseudo-non-deterministic (among nodes)
487 if commit && compare.Height > 1 && candidate.Vdf != nil {
488 // this design has similar security guarantees but lowers the computational requirements at a per-node basis
489 if rand.Intn(100) == 0 {
490 // validate the VDF included in the block
491 if !crypto.VerifyVDF(candidate.LastBlockHash, candidate.Vdf.Output, candidate.Vdf.Proof, int(candidate.Vdf.Iterations)) {
492 // exit with vdf error
493 return nil, lib.ErrInvalidVDF()
494 }
495 }
496 }
497 // log that the proposal is valid
498 c.log.Infof("Block %s with %d txs is valid for height %d ✅ ", candidateHash[:20], len(block.Transactions), candidateHeight)
499 // exit with the valid results
500 return &lib.BlockResult{BlockHeader: candidate, Transactions: results.Results, Events: results.Events}, nil
501}
502
503// HandlePeerBlock() validates and handles an inbound certificate (with a block) from a remote peer
504func (c *Controller) HandlePeerBlock(msg *lib.BlockMessage, syncing bool) (*lib.QuorumCertificate, lib.ErrorI) {

Callers 3

ValidateProposalMethod · 0.95
CommitCertificateMethod · 0.95

Calls 14

debugDumpHeaderDiffMethod · 0.95
BytesToStringFunction · 0.92
ErrFailedTransactionsFunction · 0.92
ErrUnequalBlockHashFunction · 0.92
VerifyVDFFunction · 0.92
ErrInvalidVDFFunction · 0.92
ApplyBlockMethod · 0.80
SetHashMethod · 0.80
EqualMethod · 0.80
DebugfMethod · 0.65
ErrorfMethod · 0.65

Tested by

no test coverage detected