mod append_types;
mod immutable_data;
mod priv_appendable_data;
mod pub_appendable_data;
mod structured_data;
pub use self::append_types::{AppendWrapper, AppendedData, Filter};
pub use self::immutable_data::{ImmutableData, MAX_IMMUTABLE_DATA_SIZE_IN_BYTES};
pub use self::priv_appendable_data::{MAX_PRIV_APPENDABLE_DATA_SIZE_IN_BYTES, PrivAppendableData,
PrivAppendedData};
pub use self::pub_appendable_data::{MAX_PUB_APPENDABLE_DATA_SIZE_IN_BYTES, PubAppendableData};
pub use self::structured_data::{MAX_STRUCTURED_DATA_SIZE_IN_BYTES, StructuredData};
use error::RoutingError;
use rust_sodium::crypto::sign::{self, PublicKey, Signature};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::{self, Debug, Formatter};
use xor_name::XorName;
pub const NO_OWNER_PUB_KEY: PublicKey = PublicKey([0; sign::PUBLICKEYBYTES]);
pub fn verify_signatures(owners: &BTreeSet<PublicKey>,
data: &[u8],
signatures: &BTreeMap<PublicKey, Signature>)
-> Result<(), RoutingError> {
if signatures.len() < (owners.len() + 1) / 2 {
return Err(RoutingError::NotEnoughSignatures);
}
let verify = |(pub_key, sig)| owners.contains(pub_key) && verify_detached(sig, data, pub_key);
if !signatures.iter().all(verify) {
return Err(RoutingError::FailedSignature);
}
Ok(())
}
fn verify_detached(sig: &Signature, data: &[u8], pub_key: &PublicKey) -> bool {
*pub_key != NO_OWNER_PUB_KEY && sign::verify_detached(sig, data, pub_key)
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Clone, RustcEncodable, RustcDecodable)]
pub enum Data {
Structured(StructuredData),
Immutable(ImmutableData),
PubAppendable(PubAppendableData),
PrivAppendable(PrivAppendableData),
}
impl Data {
pub fn name(&self) -> &XorName {
match *self {
Data::Structured(ref data) => data.name(),
Data::Immutable(ref data) => data.name(),
Data::PubAppendable(ref data) => data.name(),
Data::PrivAppendable(ref data) => data.name(),
}
}
pub fn identifier(&self) -> DataIdentifier {
match *self {
Data::Structured(ref data) => data.identifier(),
Data::Immutable(ref data) => data.identifier(),
Data::PubAppendable(ref data) => data.identifier(),
Data::PrivAppendable(ref data) => data.identifier(),
}
}
pub fn validate_size(&self) -> bool {
match *self {
Data::Immutable(ref data) => data.validate_size(),
Data::PrivAppendable(ref data) => data.validate_size(),
Data::PubAppendable(ref data) => data.validate_size(),
Data::Structured(ref data) => data.validate_size(),
}
}
}
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, RustcEncodable, RustcDecodable)]
pub enum DataIdentifier {
Structured(XorName, u64),
Immutable(XorName),
PubAppendable(XorName),
PrivAppendable(XorName),
}
impl Debug for Data {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match *self {
Data::Structured(ref data) => data.fmt(formatter),
Data::Immutable(ref data) => data.fmt(formatter),
Data::PubAppendable(ref data) => data.fmt(formatter),
Data::PrivAppendable(ref data) => data.fmt(formatter),
}
}
}
impl DataIdentifier {
pub fn name(&self) -> &XorName {
match *self {
DataIdentifier::Structured(ref name, _) |
DataIdentifier::Immutable(ref name) |
DataIdentifier::PubAppendable(ref name) |
DataIdentifier::PrivAppendable(ref name) => name,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rand;
use rust_sodium::crypto::hash::sha256;
use std::collections::BTreeSet;
use xor_name::XorName;
#[test]
fn data_name() {
match StructuredData::new(0, rand::random(), 0, vec![], BTreeSet::new()) {
Ok(structured_data) => {
assert_eq!(structured_data.clone().name(),
Data::Structured(structured_data.clone()).name());
assert_eq!(DataIdentifier::Structured(*structured_data.name(),
structured_data.get_type_tag()),
structured_data.identifier());
}
Err(error) => panic!("Error: {:?}", error),
}
let value = "immutable data value".to_owned().into_bytes();
let immutable_data = ImmutableData::new(value);
assert_eq!(immutable_data.name(),
Data::Immutable(immutable_data.clone()).name());
assert_eq!(immutable_data.identifier(),
DataIdentifier::Immutable(*immutable_data.name()));
}
#[test]
fn data_request_name() {
let name = XorName(sha256::hash(&[]).0);
let tag = 0;
assert_eq!(&name, DataIdentifier::Structured(name, tag).name());
assert_eq!(&name, DataIdentifier::Immutable(name).name());
}
}