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

     1  package hotstuff
     2  
     3  import (
     4  	"github.com/koko1123/flow-go-1/model/flow"
     5  	"github.com/koko1123/flow-go-1/state/protocol"
     6  )
     7  
     8  // Committee accounts for the fact that we might have multiple HotStuff instances
     9  // (collector committees and main consensus committee). Each HotStuff instance is supposed to
    10  // have a dedicated Committee state.
    11  // A Committee provides subset of the protocol.State, which is restricted to exactly those
    12  // nodes that participate in the current HotStuff instance: the state of all legitimate HotStuff
    13  // participants for the specified block. Legitimate HotStuff participants have NON-ZERO WEIGHT.
    14  //
    15  // The intended use case is to support collectors running HotStuff within Flow. Specifically,
    16  // the collectors produced their own blocks, independently of the Consensus Nodes (aka the main consensus).
    17  // Given a collector block, some logic is required to find the main consensus block
    18  // for determining the valid collector-HotStuff participants.
    19  type Committee interface {
    20  	// Identities returns a IdentityList with legitimate HotStuff participants for the specified block.
    21  	// The returned list of HotStuff participants
    22  	//   * contains nodes that are allowed to sign the specified block (legitimate participants with NON-ZERO WEIGHT)
    23  	//   * is ordered in the canonical order
    24  	//   * contains no duplicates.
    25  	// TODO: document possible error returns -> https://github.com/dapperlabs/flow-go/issues/6327
    26  	Identities(blockID flow.Identifier) (flow.IdentityList, error)
    27  
    28  	// Identity returns the full Identity for specified HotStuff participant.
    29  	// The node must be a legitimate HotStuff participant with NON-ZERO WEIGHT at the specified block.
    30  	// ERROR conditions:
    31  	//  * model.InvalidSignerError if participantID does NOT correspond to an authorized HotStuff participant at the specified block.
    32  	Identity(blockID flow.Identifier, participantID flow.Identifier) (*flow.Identity, error)
    33  
    34  	// LeaderForView returns the identity of the leader for a given view.
    35  	// CAUTION: per liveness requirement of HotStuff, the leader must be fork-independent.
    36  	//          Therefore, a node retains its proposer view slots even if it is slashed.
    37  	//          Its proposal is simply considered invalid, as it is not from a legitimate participant.
    38  	// Returns the following expected errors for invalid inputs:
    39  	//  * epoch containing the requested view has not been set up (protocol.ErrNextEpochNotSetup)
    40  	//  * epoch is too far in the past (leader.InvalidViewError)
    41  	LeaderForView(view uint64) (flow.Identifier, error)
    42  
    43  	// Self returns our own node identifier.
    44  	// TODO: ultimately, the own identity of the node is necessary for signing.
    45  	//       Ideally, we would move the method for checking whether an Identifier refers to this node to the signer.
    46  	//       This would require some refactoring of EventHandler (postponed to later)
    47  	Self() flow.Identifier
    48  
    49  	// DKG returns the DKG info for the given block.
    50  	DKG(blockID flow.Identifier) (DKG, error)
    51  }
    52  
    53  // BlockSignerDecoder defines how to convert the SignerIndices field within a particular
    54  // block header to the identifiers of the nodes which signed the block.
    55  type BlockSignerDecoder interface {
    56  	// DecodeSignerIDs decodes the signer indices from the given block header into full node IDs.
    57  	// Expected Error returns during normal operations:
    58  	//  * state.UnknownBlockError if block has not been ingested yet
    59  	//    TODO: this sentinel could be changed to `ErrViewForUnknownEpoch` once we merge the active pacemaker
    60  	//  * signature.InvalidSignerIndicesError if signer indices included in the header do
    61  	//    not encode a valid subset of the consensus committee
    62  	DecodeSignerIDs(header *flow.Header) (flow.IdentifierList, error)
    63  }
    64  
    65  type DKG interface {
    66  	protocol.DKG
    67  }
    68  
    69  // ComputeWeightThresholdForBuildingQC returns the weight that is minimally required for building a QC
    70  func ComputeWeightThresholdForBuildingQC(totalWeight uint64) uint64 {
    71  	// Given totalWeight, we need the smallest integer t such that 2 * totalWeight / 3 < t
    72  	// Formally, the minimally required weight is: 2 * Floor(totalWeight/3) + max(1, totalWeight mod 3)
    73  	floorOneThird := totalWeight / 3 // integer division, includes floor
    74  	res := 2 * floorOneThird
    75  	divRemainder := totalWeight % 3
    76  	if divRemainder <= 1 {
    77  		res = res + 1
    78  	} else {
    79  		res += divRemainder
    80  	}
    81  	return res
    82  }