// Copyright (C) 2019 Storj Labs, Inc. // See LICENSE for copying information. package kademlia import ( "math/bits" "sort" "storj.io/storj/pkg/storj" "storj.io/storj/storage" ) // compareByXor compares left, right xorred by reference func compareByXor(left, right, reference storj.NodeID) int { for i, r := range reference { a, b := left[i]^r, right[i]^r if a != b { if a < b { return -1 } return 1 } } return 0 } func sortByXOR(nodeIDs storj.NodeIDList, ref storj.NodeID) { sort.Slice(nodeIDs, func(i, k int) bool { return compareByXor(nodeIDs[i], nodeIDs[k], ref) < 0 }) } func keyToBucketID(key storage.Key) (bID bucketID) { copy(bID[:], key) return bID } // xorNodeID returns the xor of each byte in NodeID func xorNodeID(a, b storj.NodeID) storj.NodeID { r := storj.NodeID{} for i, av := range a { r[i] = av ^ b[i] } return r } // xorBucketID returns the xor of each byte in bucketID func xorBucketID(a, b bucketID) bucketID { r := bucketID{} for i, av := range a { r[i] = av ^ b[i] } return r } // determineDifferingBitIndex: helper, returns the last bit differs starting from prefix to suffix func determineDifferingBitIndex(bID, comparisonID bucketID) (int, error) { if bID == comparisonID { return -2, RoutingErr.New("compared two equivalent k bucket ids") } if comparisonID == emptyBucketID { comparisonID = firstBucketID } xorID := xorBucketID(bID, comparisonID) if xorID == firstBucketID { return -1, nil } for i, v := range xorID { if v != 0 { return i*8 + 7 - bits.TrailingZeros8(v), nil } } return -1, nil }