lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

relay_set.rs (1431B)


      1 #![forbid(unsafe_code)]
      2 
      3 use std::collections::BTreeSet;
      4 
      5 const FNV_1A_64_OFFSET_BASIS: u64 = 0xcbf29ce484222325;
      6 const FNV_1A_64_PRIME: u64 = 0x100000001b3;
      7 
      8 pub const CANONICAL_RELAY_SET_FINGERPRINT_VERSION: &str = "radroots-local-events-relay-set-v1";
      9 
     10 /// Returns the canonical shared local-event relay-set fingerprint.
     11 ///
     12 /// Relay URLs are trimmed, blank entries are discarded, duplicates are removed,
     13 /// and the remaining set is sorted before hashing.
     14 pub fn canonical_relay_set_fingerprint<I, S>(relay_urls: I) -> Option<String>
     15 where
     16     I: IntoIterator<Item = S>,
     17     S: AsRef<str>,
     18 {
     19     let relays = relay_urls
     20         .into_iter()
     21         .filter_map(|relay_url| {
     22             let relay_url = relay_url.as_ref().trim();
     23             (!relay_url.is_empty()).then(|| relay_url.to_owned())
     24         })
     25         .collect::<BTreeSet<_>>();
     26 
     27     if relays.is_empty() {
     28         return None;
     29     }
     30 
     31     let mut hash = FNV_1A_64_OFFSET_BASIS;
     32     for relay in relays {
     33         update_hash(&mut hash, relay.len().to_string().as_bytes());
     34         update_hash(&mut hash, &[0]);
     35         update_hash(&mut hash, relay.as_bytes());
     36         update_hash(&mut hash, &[0]);
     37     }
     38 
     39     Some(format!(
     40         "{CANONICAL_RELAY_SET_FINGERPRINT_VERSION}:{hash:016x}"
     41     ))
     42 }
     43 
     44 fn update_hash(hash: &mut u64, bytes: &[u8]) {
     45     for byte in bytes {
     46         *hash ^= u64::from(*byte);
     47         *hash = hash.wrapping_mul(FNV_1A_64_PRIME);
     48     }
     49 }