use crate::configuration::Configuration;
use crate::hash::{Digest, DIGEST_BYTES};
use crate::utils::i2osp_array;
use crate::{
AkdLabel, AkdValue, AzksValue, AzksValueWithEpoch, NodeLabel, VersionFreshness, EMPTY_VALUE,
};
#[cfg(feature = "nostd")]
use alloc::vec::Vec;
#[derive(Clone)]
pub struct WhatsAppV1Configuration;
unsafe impl Send for WhatsAppV1Configuration {}
unsafe impl Sync for WhatsAppV1Configuration {}
impl WhatsAppV1Configuration {
fn generate_commitment_from_nonce_client(value: &crate::AkdValue, nonce: &[u8]) -> AzksValue {
AzksValue(Self::hash(
&[i2osp_array(value), i2osp_array(nonce)].concat(),
))
}
}
impl Configuration for WhatsAppV1Configuration {
fn hash(item: &[u8]) -> crate::hash::Digest {
::blake3::hash(item).into()
}
fn empty_root_value() -> AzksValue {
AzksValue(Self::hash(&crate::EMPTY_VALUE))
}
fn empty_node_hash() -> AzksValue {
AzksValue(Self::hash(
&[
Self::hash(&EMPTY_VALUE).to_vec(),
Self::empty_label().value::<Self>(),
]
.concat(),
))
}
fn hash_leaf_with_value(
value: &crate::AkdValue,
epoch: u64,
nonce: &[u8],
) -> AzksValueWithEpoch {
let commitment = Self::generate_commitment_from_nonce_client(value, nonce);
Self::hash_leaf_with_commitment(commitment, epoch)
}
fn hash_leaf_with_commitment(commitment: AzksValue, epoch: u64) -> AzksValueWithEpoch {
let mut data = [0; DIGEST_BYTES + 8];
data[..DIGEST_BYTES].copy_from_slice(&commitment.0);
data[DIGEST_BYTES..].copy_from_slice(&epoch.to_be_bytes());
AzksValueWithEpoch(Self::hash(&data))
}
fn get_commitment_nonce(
commitment_key: &[u8],
label: &NodeLabel,
version: u64,
value: &AkdValue,
) -> Digest {
Self::hash(
&[
commitment_key,
&label.to_bytes(),
&version.to_be_bytes(),
&i2osp_array(value),
]
.concat(),
)
}
fn compute_fresh_azks_value(
commitment_key: &[u8],
label: &NodeLabel,
version: u64,
value: &AkdValue,
) -> AzksValue {
let nonce = Self::get_commitment_nonce(commitment_key, label, version, value);
AzksValue(Self::hash(
&[i2osp_array(value), i2osp_array(&nonce)].concat(),
))
}
fn get_hash_from_label_input(
label: &AkdLabel,
freshness: VersionFreshness,
version: u64,
) -> Vec<u8> {
let freshness_bytes = [freshness as u8];
let hashed_label = Self::hash(
&[
&crate::utils::i2osp_array(label)[..],
&freshness_bytes,
&version.to_be_bytes(),
]
.concat(),
);
hashed_label.to_vec()
}
fn compute_parent_hash_from_children(
left_val: &AzksValue,
left_label: &[u8],
right_val: &AzksValue,
right_label: &[u8],
) -> AzksValue {
AzksValue(Self::hash(
&[
Self::hash(&[left_val.0.to_vec(), left_label.to_vec()].concat()),
Self::hash(&[right_val.0.to_vec(), right_label.to_vec()].concat()),
]
.concat(),
))
}
fn compute_root_hash_from_val(root_val: &AzksValue) -> Digest {
Self::hash(&[&root_val.0[..], &NodeLabel::root().value::<Self>()].concat())
}
fn stale_azks_value() -> AzksValue {
AzksValue(Self::hash(&EMPTY_VALUE))
}
fn compute_node_label_value(bytes: &[u8]) -> Vec<u8> {
Self::hash(bytes).to_vec()
}
fn empty_label() -> NodeLabel {
NodeLabel {
label_val: [1u8; 32],
label_len: 0,
}
}
}
#[cfg(feature = "public_tests")]
impl super::traits::NamedConfiguration for WhatsAppV1Configuration {
fn name() -> &'static str {
"whatsapp_v1"
}
}