use sodiumoxide::crypto::sign::{PublicKey, Signature};
use sodiumoxide::crypto;
use maidsafe_utilities::serialisation;
use block_identifier::BlockIdentifier;
use node_block::{NodeBlock, NodeBlockProof};
use error::Error;
#[allow(missing_docs)]
#[derive(Debug, RustcEncodable, RustcDecodable, PartialEq, Clone)]
pub struct Block {
identifier: BlockIdentifier,
proof: Vec<(PublicKey, Signature)>,
pub valid: bool,
}
impl Block {
pub fn new(node_block: NodeBlock) -> Result<Block, Error> {
if !node_block.validate() {
return Err(Error::Signature);
}
let mut vec = Vec::new();
vec.push((*node_block.proof().key(), *node_block.proof().sig()));
Ok(Block {
identifier: node_block.identifier().clone(),
proof: vec,
valid: false,
})
}
pub fn add_proof(&mut self, proof: NodeBlockProof) -> Result<(), Error> {
if !self.validate_proof(&proof) {
return Err(Error::Signature);
}
self.proof.push((*proof.key(), *proof.sig()));
self.proof.sort();
self.proof.dedup();
Ok(())
}
pub fn validate_proof(&self, proof: &NodeBlockProof) -> bool {
let data = if let Ok(data) = serialisation::serialise(&self.identifier) {
data
} else {
return false;
};
crypto::sign::verify_detached(proof.sig(), &data[..], proof.key())
}
pub fn validate_block_signatures(&self) -> bool {
let data = if let Ok(data) = serialisation::serialise(&self.identifier) {
data
} else {
return false;
};
self.proof().iter().all(|x| crypto::sign::verify_detached(&x.1, &data[..], &x.0))
}
pub fn remove_invalid_signatures(&mut self) {
let data = if let Ok(data) = serialisation::serialise(&self.identifier) {
data
} else {
self.proof.clear();
return;
};
self.proof.retain(|x| crypto::sign::verify_detached(&x.1, &data[..], &x.0));
}
pub fn proof(&self) -> &Vec<(PublicKey, Signature)> {
&self.proof
}
pub fn proof_mut(&mut self) -> &Vec<(PublicKey, Signature)> {
&self.proof
}
pub fn identifier(&self) -> &BlockIdentifier {
&self.identifier
}
}