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 }