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

     1  package committees
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/crypto"
     7  
     8  	"github.com/onflow/flow-go/consensus/hotstuff"
     9  	"github.com/onflow/flow-go/consensus/hotstuff/model"
    10  	"github.com/onflow/flow-go/model/flow"
    11  	"github.com/onflow/flow-go/state/protocol"
    12  )
    13  
    14  func NewStaticReplicas(participants flow.IdentitySkeletonList, myID flow.Identifier, dkgParticipants map[flow.Identifier]flow.DKGParticipant, dkgGroupKey crypto.PublicKey) (*StaticReplicas, error) {
    15  	return NewStaticReplicasWithDKG(participants, myID, staticDKG{
    16  		dkgParticipants: dkgParticipants,
    17  		dkgGroupKey:     dkgGroupKey,
    18  	})
    19  }
    20  
    21  func NewStaticReplicasWithDKG(participants flow.IdentitySkeletonList, myID flow.Identifier, dkg protocol.DKG) (*StaticReplicas, error) {
    22  	valid := flow.IsIdentityListCanonical(participants)
    23  	if !valid {
    24  		return nil, fmt.Errorf("participants %v is not in Canonical order", participants)
    25  	}
    26  
    27  	static := &StaticReplicas{
    28  		participants: participants,
    29  		myID:         myID,
    30  		dkg:          dkg,
    31  	}
    32  	return static, nil
    33  }
    34  
    35  // NewStaticCommittee returns a new committee with a static participant set.
    36  func NewStaticCommittee(participants flow.IdentityList, myID flow.Identifier, dkgParticipants map[flow.Identifier]flow.DKGParticipant, dkgGroupKey crypto.PublicKey) (*Static, error) {
    37  	return NewStaticCommitteeWithDKG(participants, myID, staticDKG{
    38  		dkgParticipants: dkgParticipants,
    39  		dkgGroupKey:     dkgGroupKey,
    40  	})
    41  }
    42  
    43  // NewStaticCommitteeWithDKG returns a new committee with a static participant set.
    44  func NewStaticCommitteeWithDKG(participants flow.IdentityList, myID flow.Identifier, dkg protocol.DKG) (*Static, error) {
    45  	replicas, err := NewStaticReplicasWithDKG(participants.ToSkeleton(), myID, dkg)
    46  	if err != nil {
    47  		return nil, fmt.Errorf("could not create static replicas: %w", err)
    48  	}
    49  
    50  	static := &Static{
    51  		StaticReplicas: *replicas,
    52  		fullIdentities: participants,
    53  	}
    54  	return static, nil
    55  }
    56  
    57  type StaticReplicas struct {
    58  	participants flow.IdentitySkeletonList
    59  	myID         flow.Identifier
    60  	dkg          protocol.DKG
    61  }
    62  
    63  var _ hotstuff.Replicas = (*StaticReplicas)(nil)
    64  
    65  func (s StaticReplicas) IdentitiesByEpoch(view uint64) (flow.IdentitySkeletonList, error) {
    66  	return s.participants.ToSkeleton(), nil
    67  }
    68  
    69  func (s StaticReplicas) IdentityByEpoch(view uint64, participantID flow.Identifier) (*flow.IdentitySkeleton, error) {
    70  	identity, ok := s.participants.ByNodeID(participantID)
    71  	if !ok {
    72  		return nil, model.NewInvalidSignerErrorf("unknown participant %x", participantID)
    73  	}
    74  	return identity, nil
    75  }
    76  
    77  func (s StaticReplicas) LeaderForView(_ uint64) (flow.Identifier, error) {
    78  	return flow.ZeroID, fmt.Errorf("invalid for static committee")
    79  }
    80  
    81  func (s StaticReplicas) QuorumThresholdForView(_ uint64) (uint64, error) {
    82  	return WeightThresholdToBuildQC(s.participants.ToSkeleton().TotalWeight()), nil
    83  }
    84  
    85  func (s StaticReplicas) TimeoutThresholdForView(_ uint64) (uint64, error) {
    86  	return WeightThresholdToTimeout(s.participants.ToSkeleton().TotalWeight()), nil
    87  }
    88  
    89  func (s StaticReplicas) Self() flow.Identifier {
    90  	return s.myID
    91  }
    92  
    93  func (s StaticReplicas) DKG(_ uint64) (hotstuff.DKG, error) {
    94  	return s.dkg, nil
    95  }
    96  
    97  // Static represents a committee with a static participant set. It is used for
    98  // bootstrapping purposes.
    99  type Static struct {
   100  	StaticReplicas
   101  	fullIdentities flow.IdentityList
   102  }
   103  
   104  var _ hotstuff.DynamicCommittee = (*Static)(nil)
   105  
   106  func (s Static) IdentitiesByBlock(_ flow.Identifier) (flow.IdentityList, error) {
   107  	return s.fullIdentities, nil
   108  }
   109  
   110  func (s Static) IdentityByBlock(_ flow.Identifier, participantID flow.Identifier) (*flow.Identity, error) {
   111  	identity, ok := s.fullIdentities.ByNodeID(participantID)
   112  	if !ok {
   113  		return nil, model.NewInvalidSignerErrorf("unknown participant %x", participantID)
   114  	}
   115  	return identity, nil
   116  }
   117  
   118  type staticDKG struct {
   119  	dkgParticipants map[flow.Identifier]flow.DKGParticipant
   120  	dkgGroupKey     crypto.PublicKey
   121  }
   122  
   123  func (s staticDKG) Size() uint {
   124  	return uint(len(s.dkgParticipants))
   125  }
   126  
   127  func (s staticDKG) GroupKey() crypto.PublicKey {
   128  	return s.dkgGroupKey
   129  }
   130  
   131  // Index returns the index for the given node. Error Returns:
   132  // protocol.IdentityNotFoundError if nodeID is not a valid DKG participant.
   133  func (s staticDKG) Index(nodeID flow.Identifier) (uint, error) {
   134  	participant, ok := s.dkgParticipants[nodeID]
   135  	if !ok {
   136  		return 0, protocol.IdentityNotFoundError{NodeID: nodeID}
   137  	}
   138  	return participant.Index, nil
   139  }
   140  
   141  // KeyShare returns the public key share for the given node. Error Returns:
   142  // protocol.IdentityNotFoundError if nodeID is not a valid DKG participant.
   143  func (s staticDKG) KeyShare(nodeID flow.Identifier) (crypto.PublicKey, error) {
   144  	participant, ok := s.dkgParticipants[nodeID]
   145  	if !ok {
   146  		return nil, protocol.IdentityNotFoundError{NodeID: nodeID}
   147  	}
   148  	return participant.KeyShare, nil
   149  }