use secp256k1::XOnlyPublicKey;
use secp256k1::schnorr::Signature;
use std::fmt;
use super::TreeError;
use crate::{Identity, NodeAddr};
#[derive(Clone)]
pub struct ParentDeclaration {
node_addr: NodeAddr,
parent_id: NodeAddr,
sequence: u64,
timestamp: u64,
signature: Option<Signature>,
}
impl ParentDeclaration {
pub fn new(node_addr: NodeAddr, parent_id: NodeAddr, sequence: u64, timestamp: u64) -> Self {
Self {
node_addr,
parent_id,
sequence,
timestamp,
signature: None,
}
}
pub fn self_root(node_addr: NodeAddr, sequence: u64, timestamp: u64) -> Self {
Self::new(node_addr, node_addr, sequence, timestamp)
}
pub fn with_signature(
node_addr: NodeAddr,
parent_id: NodeAddr,
sequence: u64,
timestamp: u64,
signature: Signature,
) -> Self {
Self {
node_addr,
parent_id,
sequence,
timestamp,
signature: Some(signature),
}
}
pub fn node_addr(&self) -> &NodeAddr {
&self.node_addr
}
pub fn parent_id(&self) -> &NodeAddr {
&self.parent_id
}
pub fn sequence(&self) -> u64 {
self.sequence
}
pub fn timestamp(&self) -> u64 {
self.timestamp
}
pub fn signature(&self) -> Option<&Signature> {
self.signature.as_ref()
}
pub fn set_signature(&mut self, signature: Signature) {
self.signature = Some(signature);
}
pub fn sign(&mut self, identity: &Identity) -> Result<(), TreeError> {
if identity.node_addr() != &self.node_addr {
return Err(TreeError::InvalidSignature(self.node_addr));
}
let signature = identity.sign(&self.signing_bytes());
self.signature = Some(signature);
Ok(())
}
pub fn is_root(&self) -> bool {
self.node_addr == self.parent_id
}
pub fn is_signed(&self) -> bool {
self.signature.is_some()
}
pub fn signing_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(48);
bytes.extend_from_slice(self.node_addr.as_bytes());
bytes.extend_from_slice(self.parent_id.as_bytes());
bytes.extend_from_slice(&self.sequence.to_le_bytes());
bytes.extend_from_slice(&self.timestamp.to_le_bytes());
bytes
}
pub fn verify(&self, pubkey: &XOnlyPublicKey) -> Result<(), TreeError> {
let signature = self
.signature
.as_ref()
.ok_or(TreeError::InvalidSignature(self.node_addr))?;
let secp = secp256k1::Secp256k1::verification_only();
let hash = self.signing_hash();
secp.verify_schnorr(signature, &hash, pubkey)
.map_err(|_| TreeError::InvalidSignature(self.node_addr))
}
fn signing_hash(&self) -> [u8; 32] {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(self.signing_bytes());
hasher.finalize().into()
}
pub fn is_fresher_than(&self, other: &ParentDeclaration) -> bool {
self.sequence > other.sequence
}
}
impl fmt::Debug for ParentDeclaration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ParentDeclaration")
.field("node_addr", &self.node_addr)
.field("parent_id", &self.parent_id)
.field("sequence", &self.sequence)
.field("is_root", &self.is_root())
.field("signed", &self.is_signed())
.finish()
}
}
impl PartialEq for ParentDeclaration {
fn eq(&self, other: &Self) -> bool {
self.node_addr == other.node_addr
&& self.parent_id == other.parent_id
&& self.sequence == other.sequence
&& self.timestamp == other.timestamp
}
}
impl Eq for ParentDeclaration {}