github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/flow/identity_order.go (about) 1 package flow 2 3 // Canonical is a function that defines a weak strict ordering "<" for identities. 4 // It returns: 5 // - a strict negative number if id1 < id2 6 // - a strict positive number if id2 < id1 7 // - zero if id1 and id2 are equal 8 // 9 // By definition, two identities (id1, id2) are in canonical order if id1's NodeID is lexicographically 10 // _strictly_ smaller than id2's NodeID. The strictness is important, meaning that identities 11 // with equal NodeIDs do not satisfy canonical ordering (order is irreflexive). 12 // Hence, only a returned strictly negative value means the pair is in canonical order. 13 // Use `IsCanonical` for canonical order checks. 14 // 15 // The current function is based on the identifiers bytes lexicographic comparison. 16 func Canonical[T GenericIdentity](identity1 *T, identity2 *T) int { 17 return IdentifierCanonical((*identity1).GetNodeID(), (*identity2).GetNodeID()) 18 } 19 20 // IsCanonical returns true if and only if the given Identities are in canonical order. 21 // 22 // By convention, two Identities (i1, i2) are in canonical order if i1's NodeID bytes 23 // are lexicographically _strictly_ smaller than i2's NodeID bytes. 24 // 25 // The strictness is important, meaning that two identities with the same 26 // NodeID do not satisfy the canonical order. 27 // This also implies that the canonical order is irreflexive ((i,i) isn't in canonical order). 28 func IsCanonical[T GenericIdentity](i1, i2 *T) bool { 29 return Canonical(i1, i2) < 0 30 } 31 32 // ByReferenceOrder return a function for sorting identities based on the order 33 // of the given nodeIDs 34 func ByReferenceOrder(nodeIDs []Identifier) func(*Identity, *Identity) int { 35 indices := make(map[Identifier]int) 36 for index, nodeID := range nodeIDs { 37 _, ok := indices[nodeID] 38 if ok { 39 panic("should never order by reference order with duplicate node IDs") 40 } 41 indices[nodeID] = index 42 } 43 return func(identity1 *Identity, identity2 *Identity) int { 44 return indices[identity1.NodeID] - indices[identity2.NodeID] 45 } 46 } 47 48 // IsIdentityListCanonical returns true if and only if the given IdentityList is 49 // _strictly_ sorted with regards to the canonical order. 50 // 51 // The strictness is important here, meaning that a list with 2 successive entities 52 // with equal NodeID isn't considered well sorted. 53 func IsIdentityListCanonical[T GenericIdentity](il GenericIdentityList[T]) bool { 54 for i := 0; i < len(il)-1; i++ { 55 if !IsCanonical(il[i], il[i+1]) { 56 return false 57 } 58 } 59 return true 60 }