use xor_name::XorName;
pub fn get_debug_id<V: AsRef<[u8]>>(input: V) -> ::std::string::String {
use std::fmt::Write;
let input_ref = input.as_ref();
if input_ref.len() <= 6 {
let mut ret = String::from("BYTES:");
for byte in input_ref.iter() {
unwrap_result!(write!(ret, "{:02x}", byte));
}
return ret;
}
format!("BYTES:{: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| {
if ::xor_name::closer_to_target(&a, &b, original_name) {
::std::cmp::Ordering::Less
} else {
::std::cmp::Ordering::Greater
}
});
close_nodes.truncate(2usize);
close_nodes.insert(0, original_name.clone());
let mut combined: Vec<u8> = Vec::new();
for node_id in close_nodes {
for i in node_id.get_id().iter() {
combined.push(*i);
}
}
Ok(XorName(::sodiumoxide::crypto::hash::sha512::hash(&combined).0))
}
#[cfg(test)]
mod test {
use rand;
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.clone());
combined_one_node_vec.push(close_nodes_one_entry[0].clone());
let mut combined_one_node: Vec<u8> = Vec::new();
for node_id in combined_one_node_vec {
for i in node_id.get_id().iter() {
combined_one_node.push(*i);
}
}
let expected_relocated_name_one_node =
XorName(::sodiumoxide::crypto::hash::sha512::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..::kademlia_routing_table::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| {
if ::xor_name::closer_to_target(&a, &b, &original_name) {
::std::cmp::Ordering::Less
} else {
::std::cmp::Ordering::Greater
}
});
let first_closest = close_nodes[0].clone();
let second_closest = close_nodes[1].clone();
let mut combined: Vec<u8> = Vec::new();
for i in original_name.get_id().into_iter() {
combined.push(*i);
}
for i in first_closest.get_id().into_iter() {
combined.push(*i);
}
for i in second_closest.get_id().into_iter() {
combined.push(*i);
}
let expected_relocated_name = XorName(::sodiumoxide::crypto::hash::sha512::hash(&combined)
.0);
assert_eq!(expected_relocated_name, actual_relocated_name);
let mut invalid_combined: Vec<u8> = Vec::new();
for i in first_closest.get_id().into_iter() {
invalid_combined.push(*i);
}
for i in second_closest.get_id().into_iter() {
invalid_combined.push(*i);
}
for i in original_name.get_id().into_iter() {
invalid_combined.push(*i);
}
let invalid_relocated_name =
XorName(::sodiumoxide::crypto::hash::sha512::hash(&invalid_combined).0);
assert!(invalid_relocated_name != actual_relocated_name);
}
}