github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/vote_collector.go (about)

     1  package hotstuff
     2  
     3  import (
     4  	"github.com/rs/zerolog"
     5  
     6  	"github.com/onflow/flow-go/consensus/hotstuff/model"
     7  	"github.com/onflow/flow-go/model/flow"
     8  )
     9  
    10  // VoteConsumer consumes all votes for one specific view. It is registered with
    11  // the `VoteCollector` for the respective view. Upon registration, the
    12  // `VoteCollector` feeds votes into the consumer in the order they are received
    13  // (already cached votes as well as votes received in the future). Only votes
    14  // that pass de-duplication and equivocation detection are passed on. CAUTION,
    15  // VoteConsumer implementations must be
    16  //   - NON-BLOCKING and consume the votes without noteworthy delay, and
    17  //   - CONCURRENCY SAFE
    18  type VoteConsumer func(vote *model.Vote)
    19  
    20  // OnQCCreated is a callback which will be used by VoteCollector to submit a QC when it's able to create it
    21  type OnQCCreated func(*flow.QuorumCertificate)
    22  
    23  // VoteCollectorStatus indicates the VoteCollector's status
    24  // It has three different status.
    25  type VoteCollectorStatus int
    26  
    27  const (
    28  	// VoteCollectorStatusCaching is for the status when the block has not been received.
    29  	// The vote collector in this status will cache all the votes without verifying them
    30  	VoteCollectorStatusCaching VoteCollectorStatus = iota
    31  
    32  	// VoteCollectorStatusVerifying is for the status when the block has been received,
    33  	// and is able to process all votes for it.
    34  	VoteCollectorStatusVerifying
    35  
    36  	// VoteCollectorStatusInvalid is for the status when the block has been verified and
    37  	// is invalid. All votes to this block will be collected to slash the voter.
    38  	VoteCollectorStatusInvalid
    39  )
    40  
    41  // VoteCollector collects votes for the same block, produces QC when enough votes are collected
    42  // VoteCollector takes a callback function to report the event that a QC has been produced.
    43  var collectorStatusNames = [...]string{"VoteCollectorStatusCaching",
    44  	"VoteCollectorStatusVerifying",
    45  	"VoteCollectorStatusInvalid"}
    46  
    47  func (ps VoteCollectorStatus) String() string {
    48  	if ps < 0 || int(ps) > len(collectorStatusNames) {
    49  		return "UNKNOWN"
    50  	}
    51  	return collectorStatusNames[ps]
    52  }
    53  
    54  // VoteCollector collects all votes for a specified view. On the happy path, it
    55  // generates a QC when enough votes have been collected.
    56  // The VoteCollector internally delegates the vote-format specific processing
    57  // to the VoteProcessor.
    58  type VoteCollector interface {
    59  	// ProcessBlock performs validation of block signature and processes block with respected collector.
    60  	// Calling this function will mark conflicting collector as stale and change state of valid collectors
    61  	// It returns nil if the block is valid.
    62  	// It returns model.InvalidProposalError if block is invalid.
    63  	// It returns other error if there is exception processing the block.
    64  	ProcessBlock(block *model.Proposal) error
    65  
    66  	// AddVote adds a vote to the collector
    67  	// When enough votes have been added to produce a QC, the QC will be created asynchronously, and
    68  	// passed to EventLoop through a callback.
    69  	// No errors are expected during normal operations.
    70  	AddVote(vote *model.Vote) error
    71  
    72  	// RegisterVoteConsumer registers a VoteConsumer. Upon registration, the collector
    73  	// feeds all cached votes into the consumer in the order they arrived.
    74  	// CAUTION, VoteConsumer implementations must be
    75  	//  * NON-BLOCKING and consume the votes without noteworthy delay, and
    76  	//  * CONCURRENCY SAFE
    77  	RegisterVoteConsumer(consumer VoteConsumer)
    78  
    79  	// View returns the view that this instance is collecting votes for.
    80  	// This method is useful when adding the newly created vote collector to vote collectors map.
    81  	View() uint64
    82  
    83  	// Status returns the status of the vote collector
    84  	Status() VoteCollectorStatus
    85  }
    86  
    87  // VoteProcessor processes votes. It implements the vote-format specific processing logic.
    88  // Depending on their implementation, a VoteProcessor might drop votes or attempt to construct a QC.
    89  type VoteProcessor interface {
    90  	// Process performs processing of single vote. This function is safe to call from multiple goroutines.
    91  	// Expected error returns during normal operations:
    92  	// * VoteForIncompatibleBlockError - submitted vote for incompatible block
    93  	// * VoteForIncompatibleViewError - submitted vote for incompatible view
    94  	// * model.InvalidVoteError - submitted vote with invalid signature
    95  	// * model.DuplicatedSignerError - vote from a signer whose vote was previously already processed
    96  	// All other errors should be treated as exceptions.
    97  	Process(vote *model.Vote) error
    98  
    99  	// Status returns the status of the vote processor
   100  	Status() VoteCollectorStatus
   101  }
   102  
   103  // VerifyingVoteProcessor is a VoteProcessor that attempts to construct a QC for the given block.
   104  type VerifyingVoteProcessor interface {
   105  	VoteProcessor
   106  
   107  	// Block returns which block that will be used to collector votes for. Transition to VerifyingVoteCollector can occur only
   108  	// when we have received block proposal so this information has to be available.
   109  	Block() *model.Block
   110  }
   111  
   112  // VoteProcessorFactory is a factory that can be used to create a verifying vote processors for a specific proposal.
   113  // Depending on factory implementation it will return processors for consensus or collection clusters
   114  type VoteProcessorFactory interface {
   115  	// Create instantiates a VerifyingVoteProcessor for processing votes for a specific proposal.
   116  	// Caller can be sure that proposal vote was successfully verified and processed.
   117  	// Expected error returns during normal operations:
   118  	// * model.InvalidProposalError - proposal has invalid proposer vote
   119  	Create(log zerolog.Logger, proposal *model.Proposal) (VerifyingVoteProcessor, error)
   120  }