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