github.com/onflow/flow-go@v0.33.17/model/flow/factory/cluster_list.go (about) 1 package factory 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/flow-go/model/flow" 7 ) 8 9 // NewClusterList creates a new cluster list based on the given cluster assignment 10 // and the provided list of identities. 11 // 12 // The caller must ensure the following prerequisites: 13 // - each assignment contains identities ordered in canonical order 14 // - every collector has a unique NodeID, i.e. there are no two elements in `collectors` with the same NodeID 15 // 16 // These prerequisites ensures that each cluster in the returned cluster list is ordered in canonical order as well. 17 // This function checks that the prerequisites are satisfied and errors otherwise. 18 func NewClusterList(assignments flow.AssignmentList, collectors flow.IdentityList) (flow.ClusterList, error) { 19 20 // build a lookup for all the identities by node identifier 21 lookup := make(map[flow.Identifier]*flow.Identity) 22 for _, collector := range collectors { 23 lookup[collector.NodeID] = collector 24 } 25 if len(lookup) != len(collectors) { 26 return nil, fmt.Errorf("duplicate collector in list") 27 } 28 29 // replicate the identifier list but use identities instead 30 clusters := make(flow.ClusterList, 0, len(assignments)) 31 for i, participants := range assignments { 32 cluster := make(flow.IdentityList, 0, len(participants)) 33 if len(participants) == 0 { 34 return nil, fmt.Errorf("participants in assignment list is empty, cluster index %v", i) 35 } 36 37 // Check assignments is sorted in canonical order 38 prev := participants[0] 39 40 for i, participantID := range participants { 41 participant, found := lookup[participantID] 42 if !found { 43 return nil, fmt.Errorf("could not find collector identity (%x)", participantID) 44 } 45 cluster = append(cluster, participant) 46 delete(lookup, participantID) 47 48 if i > 0 { 49 if !flow.IsIdentifierCanonical(prev, participantID) { 50 return nil, fmt.Errorf("the assignments is not sorted in canonical order or there are duplicates in cluster index %v, prev %v, next %v", 51 i, prev, participantID) 52 } 53 } 54 prev = participantID 55 } 56 57 clusters = append(clusters, cluster) 58 } 59 60 // check that every collector was assigned 61 if len(lookup) != 0 { 62 return nil, fmt.Errorf("missing collector assignments (%s)", lookup) 63 } 64 65 return clusters, nil 66 }