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

     1  package votecollector
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/rs/zerolog"
     7  
     8  	"github.com/koko1123/flow-go-1/consensus/hotstuff"
     9  	"github.com/koko1123/flow-go-1/consensus/hotstuff/model"
    10  	"github.com/koko1123/flow-go-1/consensus/hotstuff/signature"
    11  )
    12  
    13  // baseFactory instantiates VerifyingVoteProcessors. Depending on the specific signing
    14  // scheme (e.g. for main consensus, or collector clusters), a different baseFactory can
    15  // be used.
    16  // CAUTION: the baseFactory creates the VerifyingVoteProcessor for the given block. It
    17  // does _not_ check the proposer's vote for its own block. The API reflects this by
    18  // expecting a `model.Block` as input (which does _not_ contain the proposer vote) as
    19  // opposed to `model.Proposal` (combines block with proposer's vote).
    20  // Therefore, baseFactory does _not_ implement `hotstuff.VoteProcessorFactory` by itself.
    21  // The VoteProcessorFactory adds the missing logic to verify the proposer's vote, by
    22  // wrapping the baseFactory (decorator pattern).
    23  type baseFactory func(log zerolog.Logger, block *model.Block) (hotstuff.VerifyingVoteProcessor, error)
    24  
    25  // VoteProcessorFactory implements `hotstuff.VoteProcessorFactory`. Its main purpose
    26  // is to construct instances of VerifyingVoteProcessors for a given block proposal.
    27  // VoteProcessorFactory
    28  // * delegates the creation of the actual instances to baseFactory
    29  // * adds the logic to verify the proposer's vote for its own block
    30  // Thereby, VoteProcessorFactory guarantees that only proposals with valid proposer
    31  // vote are accepted (as per API specification). Otherwise, an `model.InvalidBlockError`
    32  // is returned.
    33  type VoteProcessorFactory struct {
    34  	baseFactory baseFactory
    35  }
    36  
    37  var _ hotstuff.VoteProcessorFactory = (*VoteProcessorFactory)(nil)
    38  
    39  // Create instantiates a VerifyingVoteProcessor for the given block proposal.
    40  // A VerifyingVoteProcessor are only created for proposals with valid proposer votes.
    41  // Expected error returns during normal operations:
    42  // * model.InvalidBlockError - proposal has invalid proposer vote
    43  func (f *VoteProcessorFactory) Create(log zerolog.Logger, proposal *model.Proposal) (hotstuff.VerifyingVoteProcessor, error) {
    44  	processor, err := f.baseFactory(log, proposal.Block)
    45  	if err != nil {
    46  		return nil, fmt.Errorf("instantiating vote processor for block %v failed: %w", proposal.Block.BlockID, err)
    47  	}
    48  
    49  	err = processor.Process(proposal.ProposerVote())
    50  	if err != nil {
    51  		if model.IsInvalidVoteError(err) {
    52  			return nil, model.InvalidBlockError{
    53  				BlockID: proposal.Block.BlockID,
    54  				View:    proposal.Block.View,
    55  				Err:     fmt.Errorf("invalid proposer vote: %w", err),
    56  			}
    57  		}
    58  		return nil, fmt.Errorf("processing proposer's vote for block %v failed: %w", proposal.Block.BlockID, err)
    59  	}
    60  	return processor, nil
    61  }
    62  
    63  // NewStakingVoteProcessorFactory implements hotstuff.VoteProcessorFactory for
    64  // members of a collector cluster. For their cluster-local hotstuff, collectors
    65  // only sign with their staking key.
    66  func NewStakingVoteProcessorFactory(committee hotstuff.Committee, onQCCreated hotstuff.OnQCCreated) *VoteProcessorFactory {
    67  	base := &stakingVoteProcessorFactoryBase{
    68  		committee:   committee,
    69  		onQCCreated: onQCCreated,
    70  	}
    71  	return &VoteProcessorFactory{
    72  		baseFactory: base.Create,
    73  	}
    74  }
    75  
    76  // NewCombinedVoteProcessorFactory implements hotstuff.VoteProcessorFactory fo
    77  // participants of the Main Consensus Committee.
    78  //
    79  // With their vote, members of the main consensus committee can contribute to hotstuff and
    80  // the random beacon. When a consensus participant signs with its random beacon key, it
    81  // contributes to HotStuff consensus _and_ the Random Beacon. As a fallback, a consensus
    82  // participant can sign with its staking key; thereby it contributes only to consensus but
    83  // not the random beacon. There should be an economic incentive for the nodes to preferably
    84  // sign with their random beacon key.
    85  func NewCombinedVoteProcessorFactory(committee hotstuff.Committee, onQCCreated hotstuff.OnQCCreated) *VoteProcessorFactory {
    86  	base := &combinedVoteProcessorFactoryBaseV2{
    87  		committee:   committee,
    88  		onQCCreated: onQCCreated,
    89  		packer:      signature.NewConsensusSigDataPacker(committee),
    90  	}
    91  	return &VoteProcessorFactory{
    92  		baseFactory: base.Create,
    93  	}
    94  }
    95  
    96  /* ***************************** VerifyingVoteProcessor constructors for bootstrapping ***************************** */
    97  
    98  // NewBootstrapCombinedVoteProcessor directly creates a CombinedVoteProcessorV2,
    99  // suitable for the collector's local cluster consensus.
   100  // Intended use: only for bootstrapping.
   101  // UNSAFE: the proposer vote for `block` is _not_ validated or included
   102  func NewBootstrapCombinedVoteProcessor(log zerolog.Logger, committee hotstuff.Committee, block *model.Block, onQCCreated hotstuff.OnQCCreated) (hotstuff.VerifyingVoteProcessor, error) {
   103  	factory := &combinedVoteProcessorFactoryBaseV2{
   104  		committee:   committee,
   105  		onQCCreated: onQCCreated,
   106  		packer:      signature.NewConsensusSigDataPacker(committee),
   107  	}
   108  	return factory.Create(log, block)
   109  }
   110  
   111  // NewBootstrapStakingVoteProcessor directly creates a `StakingVoteProcessor`,
   112  // suitable for the collector's local cluster consensus.
   113  // Intended use: only for bootstrapping.
   114  // UNSAFE: the proposer vote for `block` is _not_ validated or included
   115  func NewBootstrapStakingVoteProcessor(log zerolog.Logger, committee hotstuff.Committee, block *model.Block, onQCCreated hotstuff.OnQCCreated) (hotstuff.VerifyingVoteProcessor, error) {
   116  	factory := &stakingVoteProcessorFactoryBase{
   117  		committee:   committee,
   118  		onQCCreated: onQCCreated,
   119  	}
   120  	return factory.Create(log, block)
   121  }