redgold_schema/util/
xor_distance.rs

1use crate::proto_serde::ProtoSerde;
2use crate::structs::{Hash, NodeMetadata, PartitionInfo, PublicKey};
3use itertools::Itertools;
4
5pub fn xor_distance(v1: &Vec<u8>, v2: &Vec<u8>) -> i64 {
6    let xor_value: Vec<u8> = v1
7        .iter()
8        .zip(v2.iter())
9        .map(|(&x1, &x2)| x1 ^ x2)
10        .collect();
11    let distance: i64 = xor_value.iter().map(|&byte| i64::from(byte)).sum();
12    distance
13}
14
15pub fn xorf_conv_distance(query_hash: &Vec<u8>, peer_marker: &Vec<u8>) -> i64 {
16
17    // Helps prevent pre-generating TX hash to be near specific peer markers
18    let mut concat = query_hash.clone();
19    concat.extend(peer_marker.clone());
20    // 32 bytes
21    let merged = Hash::digest(concat).vec();
22
23    // Helps prevent pre-generating peer markers to be near one another.
24    let mut concat2 = peer_marker.clone();
25    concat2.extend(query_hash.clone());
26
27    let merged2 = Hash::digest(concat2).vec();
28
29    let xor_value: Vec<u8> = merged
30        .iter()
31        .zip(merged2.iter())
32        .map(|(&x1, &x2)| x1 ^ x2)
33        .collect();
34    let distance: i64 = xor_value.iter().map(|&byte| i64::from(byte)).sum();
35    distance
36}
37
38pub fn xorfc_hash(query_hash: &Hash, pk: &PublicKey) -> i64 {
39    let query_hash = query_hash.vec();
40    let pk_bytes = pk.vec();
41    xorf_conv_distance(&query_hash, &pk_bytes)
42}
43
44pub trait XorDistancePartitionInfo {
45    fn tx_hash_distance(&self, hash: &Hash, pk: &PublicKey) -> bool;
46}
47
48impl XorDistancePartitionInfo for Option<PartitionInfo> {
49     fn tx_hash_distance(&self, hash: &Hash, pk: &PublicKey) -> bool {
50        let d = xorfc_hash(hash, &pk);
51        self.as_ref().and_then(|pi| pi.transaction_hash.as_ref())
52            .map(|d_max| &d < d_max).unwrap_or(true)
53    }
54}
55
56pub trait XorfConvDistanceSubset<T> {
57    fn xorf_conv_distance_subset<F>(
58        &self, other: &Vec<u8>, partition_func: F
59    ) -> Vec<&T>
60        where F: FnOnce(&PartitionInfo) -> Option<i64> + Copy;
61}
62
63impl XorfConvDistanceSubset<NodeMetadata> for Vec<NodeMetadata> {
64    fn xorf_conv_distance_subset<F>(
65        &self, other: &Vec<u8>, partition_func: F
66    ) -> Vec<&NodeMetadata>
67    where F: FnOnce(&PartitionInfo) -> Option<i64> + Copy {
68        let res = self.iter()
69            .filter_map(|n| n.public_key.as_ref().map(|p| (p, n)))
70            .filter_map(|(p, n)| p.bytes.as_ref().map(|b| (b.value.clone(), n)))
71            .map(|(p, n)| (xorf_conv_distance(other, &p), n))
72            .filter(|(p, n)|
73                n.partition_info.as_ref().and_then(|i| partition_func(i)).map(|d| d < *p).unwrap_or(true))
74            .sorted_by(|(p1, _), (p2, _)| p1.cmp(p2))
75            .map(|(_p, n)| n)
76            .collect_vec();
77        res
78    }
79}
80
81#[test]
82pub fn xor_test() {
83}