use super::address::GraphEntryAddress;
use bls::SecretKey;
use serde::{Deserialize, Serialize};
pub use bls::{PublicKey, Signature};
pub type GraphContent = [u8; 32];
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd)]
pub struct GraphEntry {
pub owner: PublicKey,
pub parents: Vec<PublicKey>,
pub content: GraphContent,
pub descendants: Vec<(PublicKey, GraphContent)>,
pub signature: Signature,
}
impl std::fmt::Debug for GraphEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GraphEntry")
.field("owner", &self.owner.to_hex())
.field(
"parents",
&self.parents.iter().map(|p| p.to_hex()).collect::<Vec<_>>(),
)
.field("content", &hex::encode(self.content))
.field(
"descendants",
&self
.descendants
.iter()
.map(|(p, c)| format!("{}: {}", p.to_hex(), hex::encode(c)))
.collect::<Vec<_>>(),
)
.field("signature", &hex::encode(self.signature.to_bytes()))
.finish()
}
}
impl GraphEntry {
pub const MAX_SIZE: usize = 100 * 1024;
pub fn new(
owner: &SecretKey,
parents: Vec<PublicKey>,
content: GraphContent,
descendants: Vec<(PublicKey, GraphContent)>,
) -> Self {
let key = owner;
let owner = key.public_key();
let signature = key.sign(Self::bytes_to_sign(
&owner,
&parents,
&content,
&descendants,
));
Self {
owner,
parents,
content,
descendants,
signature,
}
}
pub fn new_with_signature(
owner: PublicKey,
parents: Vec<PublicKey>,
content: GraphContent,
descendants: Vec<(PublicKey, GraphContent)>,
signature: Signature,
) -> Self {
Self {
owner,
parents,
content,
descendants,
signature,
}
}
pub fn bytes_to_sign(
owner: &PublicKey,
parents: &[PublicKey],
content: &[u8],
descendants: &[(PublicKey, GraphContent)],
) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&owner.to_bytes());
bytes.extend_from_slice("parent".as_bytes());
bytes.extend_from_slice(
&parents
.iter()
.map(|p| p.to_bytes())
.collect::<Vec<_>>()
.concat(),
);
bytes.extend_from_slice("content".as_bytes());
bytes.extend_from_slice(content);
bytes.extend_from_slice("descendants".as_bytes());
bytes.extend_from_slice(
&descendants
.iter()
.flat_map(|(p, c)| [&p.to_bytes(), c.as_slice()].concat())
.collect::<Vec<_>>(),
);
bytes
}
pub fn address(&self) -> GraphEntryAddress {
GraphEntryAddress::new(self.owner)
}
pub fn bytes_for_signature(&self) -> Vec<u8> {
Self::bytes_to_sign(&self.owner, &self.parents, &self.content, &self.descendants)
}
pub fn verify_signature(&self) -> bool {
self.owner
.verify(&self.signature, self.bytes_for_signature())
}
pub fn size(&self) -> usize {
size_of::<GraphEntry>()
+ self
.descendants
.iter()
.map(|(p, c)| p.to_bytes().len() + c.len())
.sum::<usize>()
+ self
.parents
.iter()
.map(|p| p.to_bytes().len())
.sum::<usize>()
}
pub fn is_too_big(&self) -> bool {
self.size() > Self::MAX_SIZE
}
}