github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/forks/forks.go (about)

     1  package forks
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/koko1123/flow-go-1/consensus/hotstuff"
     7  	"github.com/koko1123/flow-go-1/consensus/hotstuff/model"
     8  	"github.com/koko1123/flow-go-1/model/flow"
     9  )
    10  
    11  // Forks implements the hotstuff.Reactor API
    12  type Forks struct {
    13  	finalizer  Finalizer
    14  	forkchoice ForkChoice
    15  }
    16  
    17  var _ hotstuff.Forks = (*Forks)(nil)
    18  
    19  // New creates a Forks instance
    20  func New(finalizer Finalizer, forkchoice ForkChoice) *Forks {
    21  	return &Forks{
    22  		finalizer:  finalizer,
    23  		forkchoice: forkchoice,
    24  	}
    25  }
    26  
    27  // GetBlocksForView returns all the blocks for a certain view.
    28  func (f *Forks) GetBlocksForView(view uint64) []*model.Block {
    29  	return f.finalizer.GetBlocksForView(view)
    30  }
    31  
    32  // GetBlock returns the block for the given block ID
    33  func (f *Forks) GetBlock(id flow.Identifier) (*model.Block, bool) {
    34  	return f.finalizer.GetBlock(id)
    35  }
    36  
    37  // FinalizedBlock returns the latest finalized block
    38  func (f *Forks) FinalizedBlock() *model.Block {
    39  	return f.finalizer.FinalizedBlock()
    40  }
    41  
    42  // FinalizedView returns the view of the latest finalized block
    43  func (f *Forks) FinalizedView() uint64 {
    44  	return f.finalizer.FinalizedBlock().View
    45  }
    46  
    47  // IsSafeBlock returns whether a block is safe to vote for.
    48  func (f *Forks) IsSafeBlock(block *model.Block) bool {
    49  	if err := f.finalizer.VerifyBlock(block); err != nil {
    50  		return false
    51  	}
    52  	return f.finalizer.IsSafeBlock(block)
    53  }
    54  
    55  // AddBlock passes the block to the finalizer for finalization and
    56  // gives the QC to forkchoice for updating the preferred parent block
    57  func (f *Forks) AddBlock(block *model.Block) error {
    58  	if err := f.finalizer.VerifyBlock(block); err != nil {
    59  		// technically, this not strictly required. However, we leave this as a sanity check for now
    60  		return fmt.Errorf("cannot add invalid block to Forks: %w", err)
    61  	}
    62  	err := f.finalizer.AddBlock(block)
    63  	if err != nil {
    64  		return fmt.Errorf("error storing block in Forks: %w", err)
    65  	}
    66  
    67  	// We only process the block's QC if the block's view is larger than the last finalized block.
    68  	// By ignoring hte qc's of block's at or below the finalized view, we allow the genesis block
    69  	// to have a nil QC.
    70  	if block.View <= f.finalizer.FinalizedBlock().View {
    71  		return nil
    72  	}
    73  	return f.AddQC(block.QC)
    74  }
    75  
    76  // MakeForkChoice returns the block to build new block proposal from for the current view.
    77  // the QC is the QC that points to that block.
    78  func (f *Forks) MakeForkChoice(curView uint64) (*flow.QuorumCertificate, *model.Block, error) {
    79  	return f.forkchoice.MakeForkChoice(curView)
    80  }
    81  
    82  // AddQC gives the QC to the forkchoice for updating the preferred parent block
    83  func (f *Forks) AddQC(qc *flow.QuorumCertificate) error {
    84  	return f.forkchoice.AddQC(qc) // forkchoice ensures that block referenced by qc is known
    85  }