use sodiumoxide::crypto::hash::sha256;
use std::fmt::Write;
use xor_name::XorName;
pub fn format_binary_array<V: AsRef<[u8]>>(input: V) -> String {
let input_ref = input.as_ref();
if input_ref.len() <= 6 {
let mut ret = String::new();
for byte in input_ref.iter() {
unwrap_result!(write!(ret, "{:02x}", byte));
}
return ret;
}
format!("{:02x}{:02x}{:02x}..{:02x}{:02x}{:02x}",
input_ref[0],
input_ref[1],
input_ref[2],
input_ref[input_ref.len() - 3],
input_ref[input_ref.len() - 2],
input_ref[input_ref.len() - 1])
}
pub fn calculate_relocated_name(mut close_nodes: Vec<XorName>,
original_name: &XorName)
-> Result<XorName, ::error::RoutingError> {
if close_nodes.is_empty() {
return Err(::error::RoutingError::RoutingTableEmpty);
}
close_nodes.sort_by(|a, b| original_name.cmp_distance(a, b));
close_nodes.truncate(2usize);
close_nodes.insert(0, *original_name);
let mut combined: Vec<u8> = Vec::new();
for node_id in close_nodes {
for i in &node_id.0 {
combined.push(*i);
}
}
Ok(XorName(sha256::hash(&combined).0))
}
#[cfg(test)]
mod test {
extern crate rand;
use core::GROUP_SIZE;
use sodiumoxide::crypto::hash::sha256;
use xor_name::XorName;
#[test]
fn calculate_relocated_name() {
let original_name: XorName = rand::random();
assert!(super::calculate_relocated_name(Vec::new(), &original_name).is_err());
let mut close_nodes_one_entry: Vec<XorName> = Vec::new();
close_nodes_one_entry.push(rand::random());
let actual_relocated_name_one_entry =
unwrap_result!(super::calculate_relocated_name(close_nodes_one_entry.clone(),
&original_name));
assert!(original_name != actual_relocated_name_one_entry);
let mut combined_one_node_vec: Vec<XorName> = Vec::new();
combined_one_node_vec.push(original_name);
combined_one_node_vec.push(close_nodes_one_entry[0]);
let mut combined_one_node: Vec<u8> = Vec::new();
for node_id in combined_one_node_vec {
for i in &node_id.0 {
combined_one_node.push(*i);
}
}
let expected_relocated_name_one_node = XorName(sha256::hash(&combined_one_node).0);
assert_eq!(actual_relocated_name_one_entry,
expected_relocated_name_one_node);
let mut close_nodes: Vec<XorName> = Vec::new();
for _ in 0..GROUP_SIZE {
close_nodes.push(rand::random());
}
let actual_relocated_name =
unwrap_result!(super::calculate_relocated_name(close_nodes.clone(), &original_name));
assert!(original_name != actual_relocated_name);
close_nodes.sort_by(|a, b| original_name.cmp_distance(a, b));
let first_closest = close_nodes[0];
let second_closest = close_nodes[1];
let mut combined: Vec<u8> = Vec::new();
for i in original_name.0.into_iter() {
combined.push(*i);
}
for i in first_closest.0.into_iter() {
combined.push(*i);
}
for i in second_closest.0.into_iter() {
combined.push(*i);
}
let expected_relocated_name = XorName(sha256::hash(&combined).0);
assert_eq!(expected_relocated_name, actual_relocated_name);
let mut invalid_combined: Vec<u8> = Vec::new();
for i in first_closest.0.into_iter() {
invalid_combined.push(*i);
}
for i in second_closest.0.into_iter() {
invalid_combined.push(*i);
}
for i in original_name.0.into_iter() {
invalid_combined.push(*i);
}
let invalid_relocated_name = XorName(sha256::hash(&invalid_combined).0);
assert!(invalid_relocated_name != actual_relocated_name);
}
}