use crate::network::path::PathInfo;
use crate::types::Addressable;
use anyhow::{anyhow, bail};
use secp256k1::schnorr::Signature;
use secp256k1::{PublicKey, Secp256k1};
use serde::Serialize;
use sha2::{Digest, Sha256};
use std::hash::Hash;
#[derive(Serialize, Clone, Debug)]
pub enum NetworkNode<D: Addressable> {
Data {
label: String, parent_group_label: Option<String>,
proof: PathInfo,
object: D,
public_key: Vec<u8>,
signature: Vec<u8>,
},
Group {
label: String,
name: String,
group_hash: Option<String>, parent_group_label: Option<String>,
proof: PathInfo, child_group_hashes: Vec<String>, child_data_hashes: Vec<String>, child_labels: Vec<String>, public_key: Vec<u8>,
signature: Vec<u8>, },
Source {
label: String,
id: String,
root_hash: String,
child_group_hashes: Vec<String>,
child_data_hashes: Vec<String>,
child_labels: Vec<String>, public_key: Vec<u8>,
signature: Vec<u8>, },
}
impl<D: Addressable> NetworkNode<D> {
pub(crate) fn update_verification_path(&self, path: PathInfo) -> NetworkNode<D> {
match self {
NetworkNode::Data { label, parent_group_label, proof: verification_path, object, public_key, signature } => {
NetworkNode::Data {
label: label.clone(), parent_group_label: parent_group_label.clone(),
proof: path,
object: object.clone(),
public_key: public_key.clone(),
signature: signature.clone(),
}
}
NetworkNode::Group { label,name, group_hash, parent_group_label, proof: verification_path, child_group_hashes: group_roots, child_data_hashes: data_roots, child_labels: child_group_labels, public_key, signature } => {
NetworkNode::Group {
label: label.clone(),
name: name.clone(),
group_hash: group_hash.clone(), parent_group_label: parent_group_label.clone(),
proof: path, child_group_hashes: group_roots.clone(), child_data_hashes: data_roots.clone(), child_labels: child_group_labels.clone(), public_key: public_key.clone(),
signature: signature.clone(), }
}
NetworkNode::Source { .. } => {
self.clone()
}
}
}
pub(crate) fn get_label(&self) -> String {
match self {
NetworkNode::Data { label, .. } | NetworkNode::Group { label, .. } | NetworkNode::Source { label, .. } => {
label.clone()
}
}
}
pub(crate) fn get_tree_node_hash(&self) -> Option<String> {
match self {
NetworkNode::Data { label, .. } => { Some(label.clone()) }
NetworkNode::Group { group_hash, .. } => { group_hash.clone() }
NetworkNode::Source { root_hash, .. } => { Some(root_hash.clone()) }
}
}
pub(crate) fn is_data(&self) -> bool {
match self {
NetworkNode::Data { .. } => {true}
NetworkNode::Group { .. } | NetworkNode::Source { .. }=> {false}
}
}
pub(crate) fn get_parent_group_label(&self) -> Option<String> {
match self {
NetworkNode::Data { parent_group_label, .. } | NetworkNode::Group { parent_group_label, .. } => { parent_group_label.clone() }
NetworkNode::Source { .. } => { None }
}
}
pub(crate) fn get_group_roots(&self) -> Vec<String> {
match self {
NetworkNode::Data { .. } => { Vec::new() }
NetworkNode::Group { child_group_hashes: group_roots, .. } | NetworkNode::Source { child_group_hashes: group_roots, .. } => { group_roots.clone() }
}
}
pub(crate) fn get_data_roots(&self) -> Vec<String> {
match self {
NetworkNode::Group { child_data_hashes: data_roots, .. } | NetworkNode::Source { child_data_hashes: data_roots, .. } => { data_roots.clone() }
NetworkNode::Data { .. } => { Vec::new() }
}
}
pub(crate) fn get_child_group_labels(&self) -> Vec<String> {
match self {
NetworkNode::Group { child_labels: child_group_labels, .. } | NetworkNode::Source { child_labels: child_group_labels, .. } => { child_group_labels.clone() }
NetworkNode::Data { .. } => { Vec::new() }
}
}
pub(crate) fn get_root_hash(&self) -> Option<String> {
match self {
NetworkNode::Data { .. } | NetworkNode::Group { .. } => { None }
NetworkNode::Source { root_hash, .. } => { Some(root_hash.clone()) }
}
}
pub fn verify_origin(&self, source_public_key: &[u8]) -> anyhow::Result<()> {
match self {
NetworkNode::Data { label, signature, .. } => {
Self::check_signature(label, source_public_key, signature)?;
Ok(())
}
NetworkNode::Group { label, signature,group_hash, .. } => {
let message = format!("{}{}", label, group_hash.clone().unwrap() );
Self::check_signature(&message, source_public_key, signature)?;
Ok(())
}
NetworkNode::Source { .. } => {
bail!("Incorrect usage: verify_origin is used to verify NetworkNode::Data or NetworkNode::Group originated from the source")
}
}
}
pub fn verify_merkle_proof(&self, merkle_root: &str) -> anyhow::Result<()> {
match self {
NetworkNode::Data { label, proof: verification_path, .. } => {
Self::check_hashes(merkle_root, label, verification_path)
}
NetworkNode::Group { group_hash, proof: verification_path, .. } => {
Self::check_hashes(merkle_root, &group_hash.clone().unwrap(), verification_path)
}
NetworkNode::Source { .. } => {
bail!("Incorrect usage: verify_merkle_proof is used to verify NetworkNode::Data or NetworkNode::Group is part of the merkle root")
}
}
}
fn check_hashes(merkle_root: &str, base: &String, verification_path: &PathInfo) -> anyhow::Result<()> {
let mut current_hash = base.clone();
let nodes = verification_path.get_nodes();
for node in nodes {
let mut group_hash = String::new();
node.get_group_siblings().iter()
.for_each(|group_sibling| match group_sibling {
None => {
group_hash.push_str(current_hash.as_str());
}
Some(sibling_info) => {
group_hash.push_str(&sibling_info.tree_node_hash);
}
});
let mut data_hash = String::new();
node.get_data_siblings().iter()
.for_each(|data_sibling| {
match data_sibling {
None => {
data_hash.push_str(current_hash.as_str());
}
Some(sibling_info) => {
data_hash.push_str(&sibling_info.tree_node_hash);
}
}
});
let mut hasher = Sha256::new();
hasher.update(group_hash.as_bytes());
hasher.update(data_hash.as_bytes());
let hash_bytes: [u8; 32] = hasher.finalize().into();
current_hash = hex::encode(hash_bytes);
}
if current_hash == merkle_root {
Ok(())
} else { bail!("Incorrect hash: {}", current_hash); }
}
fn check_signature(message: &String, public_key: &[u8], signature: &Vec<u8>) -> anyhow::Result<()> {
let secp256k1 = Secp256k1::new();
let signature = Signature::from_byte_array(signature.clone().try_into().expect("Invalid signature"));
let digest: [u8; 32] = sha2::Sha256::digest(message.as_bytes()).into();
let public_key = PublicKey::from_slice(public_key)?;
let secp_verify_result = secp256k1.verify_schnorr(&signature, &digest, &public_key.x_only_public_key().0);
secp_verify_result
.map_err(|secp_err| { anyhow!("schnorr signature could not be verified: {}", secp_err) })
}
}