github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/flow/filter/identity.go (about) 1 package filter 2 3 import ( 4 "github.com/onflow/crypto" 5 6 "github.com/onflow/flow-go/model/flow" 7 ) 8 9 // Adapt takes an IdentityFilter on the domain of IdentitySkeletons 10 // and adapts the filter to the domain of full Identities. In other words, it converts 11 // flow.IdentityFilter[flow.IdentitySkeleton] to flow.IdentityFilter[flow.Identity]. 12 func Adapt(f flow.IdentityFilter[flow.IdentitySkeleton]) flow.IdentityFilter[flow.Identity] { 13 return func(i *flow.Identity) bool { 14 return f(&i.IdentitySkeleton) 15 } 16 } 17 18 // Any will always be true. 19 func Any(*flow.Identity) bool { 20 return true 21 } 22 23 // And combines two or more filters that all need to be true. 24 func And[T flow.GenericIdentity](filters ...flow.IdentityFilter[T]) flow.IdentityFilter[T] { 25 return func(identity *T) bool { 26 for _, filter := range filters { 27 if !filter(identity) { 28 return false 29 } 30 } 31 return true 32 } 33 } 34 35 // Or combines two or more filters and only needs one of them to be true. 36 func Or[T flow.GenericIdentity](filters ...flow.IdentityFilter[T]) flow.IdentityFilter[T] { 37 return func(identity *T) bool { 38 for _, filter := range filters { 39 if filter(identity) { 40 return true 41 } 42 } 43 return false 44 } 45 } 46 47 // Not returns a filter equivalent to the inverse of the input filter. 48 func Not[T flow.GenericIdentity](filter flow.IdentityFilter[T]) flow.IdentityFilter[T] { 49 return func(identity *T) bool { 50 return !filter(identity) 51 } 52 } 53 54 // In returns a filter for identities within the input list. For an input identity i, 55 // the filter returns true if and only if i ∈ list. 56 // Caution: The filter solely operates on NodeIDs. Other identity fields are not compared. 57 // This function is just a compact representation of `HasNodeID[T](list.NodeIDs()...)` 58 // which behaves algorithmically the same way. 59 func In[T flow.GenericIdentity](list flow.GenericIdentityList[T]) flow.IdentityFilter[T] { 60 return HasNodeID[T](list.NodeIDs()...) 61 } 62 63 // HasNodeID returns a filter that returns true for any identity with an ID 64 // matching any of the inputs. 65 func HasNodeID[T flow.GenericIdentity](nodeIDs ...flow.Identifier) flow.IdentityFilter[T] { 66 lookup := make(map[flow.Identifier]struct{}) 67 for _, nodeID := range nodeIDs { 68 lookup[nodeID] = struct{}{} 69 } 70 return func(identity *T) bool { 71 _, ok := lookup[(*identity).GetNodeID()] 72 return ok 73 } 74 } 75 76 // HasNetworkingKey returns a filter that returns true for any identity with a 77 // networking public key matching any of the inputs. 78 func HasNetworkingKey(keys ...crypto.PublicKey) flow.IdentityFilter[flow.Identity] { 79 return func(identity *flow.Identity) bool { 80 for _, key := range keys { 81 if key.Equals(identity.NetworkPubKey) { 82 return true 83 } 84 } 85 return false 86 } 87 } 88 89 // HasInitialWeight returns a filter for nodes with non-zero initial weight. 90 func HasInitialWeight[T flow.GenericIdentity](hasWeight bool) flow.IdentityFilter[T] { 91 return func(identity *T) bool { 92 return ((*identity).GetInitialWeight() > 0) == hasWeight 93 } 94 } 95 96 // HasParticipationStatus is a filter that returns true if the node epoch participation status matches the input. 97 func HasParticipationStatus(status flow.EpochParticipationStatus) flow.IdentityFilter[flow.Identity] { 98 return func(identity *flow.Identity) bool { 99 return identity.EpochParticipationStatus == status 100 } 101 } 102 103 // HasRole returns a filter for nodes with one of the input roles. 104 func HasRole[T flow.GenericIdentity](roles ...flow.Role) flow.IdentityFilter[T] { 105 lookup := make(map[flow.Role]struct{}) 106 for _, role := range roles { 107 lookup[role] = struct{}{} 108 } 109 return func(identity *T) bool { 110 _, ok := lookup[(*identity).GetRole()] 111 return ok 112 } 113 } 114 115 // IsValidCurrentEpochParticipant is an identity filter for members of the 116 // current epoch in good standing. 117 // Effective it means that node is an active identity in current epoch and has not been ejected. 118 var IsValidCurrentEpochParticipant = HasParticipationStatus(flow.EpochParticipationStatusActive) 119 120 // IsValidCurrentEpochParticipantOrJoining is an identity filter for members of the current epoch or that are going to join in next epoch. 121 var IsValidCurrentEpochParticipantOrJoining = Or(IsValidCurrentEpochParticipant, HasParticipationStatus(flow.EpochParticipationStatusJoining)) 122 123 // IsConsensusCommitteeMember is an identity filter for all members of the consensus committee. 124 // Formally, a Node X is a Consensus Committee Member if and only if X is a consensus node with 125 // positive initial weight. This is specified by the EpochSetup Event and remains static 126 // throughout the epoch. 127 var IsConsensusCommitteeMember = And( 128 HasRole[flow.IdentitySkeleton](flow.RoleConsensus), 129 HasInitialWeight[flow.IdentitySkeleton](true), 130 ) 131 132 // IsVotingConsensusCommitteeMember is an identity filter for all members of 133 // the consensus committee allowed to vote. 134 // Formally, a Node X has authority to vote in the consensus process, if and only if 135 // 1. Node X is an active member of the current epoch AND 136 // 2. X is a consensus node with positive initial weight in the current Epoch. This 137 // is specified by the EpochSetup Event for the current epoch and remains static 138 // throughout the epoch. 139 var IsVotingConsensusCommitteeMember = And[flow.Identity]( 140 IsValidCurrentEpochParticipant, // enforces 1. 141 Adapt(IsConsensusCommitteeMember), // enforces 2. 142 ) 143 144 // IsValidDKGParticipant is an identity filter for all DKG participants. It is 145 // equivalent to the filter for consensus committee members, as these are 146 // the same group for now. 147 var IsValidDKGParticipant = IsConsensusCommitteeMember 148 149 // NotEjectedFilter is an identity filter for peers that are not ejected. 150 var NotEjectedFilter = Not(HasParticipationStatus(flow.EpochParticipationStatusEjected)) 151 152 // HasWeightGreaterThanZero returns a filter for nodes with a weight greater than zero. 153 func HasWeightGreaterThanZero[T flow.GenericIdentity](identity *T) bool { 154 return (*identity).GetInitialWeight() > 0 155 } 156 157 // IsValidProtocolParticipant is an identity filter for all valid protocol participants. 158 // A protocol participant is considered valid if and only if the following are both true. 159 // 1. The node is not ejected. 160 // 2. The node has a weight greater than 0. 161 var IsValidProtocolParticipant = And[flow.Identity]( 162 NotEjectedFilter, // enforces 1 163 HasWeightGreaterThanZero[flow.Identity], // enforces 2 164 )