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 }