use crate::keys::PublicKey;
use serde::{Deserialize, Serialize};
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
ops::{Add, Sub},
};
use tari_utilities::{ByteArray, ByteArrayError};
#[derive(Debug, Eq, Clone, Serialize, Deserialize, Default)]
#[serde(bound(deserialize = "P: PublicKey"))]
pub struct HomomorphicCommitment<P>(pub(crate) P)
where P: PublicKey;
impl<P> HomomorphicCommitment<P>
where P: PublicKey
{
pub fn as_public_key(&self) -> &P {
&self.0
}
pub fn from_public_key(p: &P) -> HomomorphicCommitment<P> {
HomomorphicCommitment(p.clone())
}
}
impl<P> ByteArray for HomomorphicCommitment<P>
where P: PublicKey
{
fn from_bytes(bytes: &[u8]) -> Result<Self, ByteArrayError> {
let p = P::from_bytes(bytes)?;
Ok(Self(p))
}
fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl<P> PartialOrd for HomomorphicCommitment<P>
where P: PublicKey
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.0.cmp(&other.0))
}
}
impl<P> Ord for HomomorphicCommitment<P>
where P: PublicKey
{
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<'b, P> Add for &'b HomomorphicCommitment<P>
where
P: PublicKey,
&'b P: Add<&'b P, Output = P>,
{
type Output = HomomorphicCommitment<P>;
fn add(self, rhs: &'b HomomorphicCommitment<P>) -> Self::Output {
HomomorphicCommitment(&self.0 + &rhs.0)
}
}
impl<'b, P> Sub for &'b HomomorphicCommitment<P>
where
P: PublicKey,
&'b P: Sub<&'b P, Output = P>,
{
type Output = HomomorphicCommitment<P>;
fn sub(self, rhs: &'b HomomorphicCommitment<P>) -> Self::Output {
HomomorphicCommitment(&self.0 - &rhs.0)
}
}
impl<P: PublicKey> Hash for HomomorphicCommitment<P> {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(self.as_bytes())
}
}
impl<P: PublicKey> PartialEq for HomomorphicCommitment<P> {
fn eq(&self, other: &Self) -> bool {
self.as_public_key().eq(&other.as_public_key())
}
}
pub trait HomomorphicCommitmentFactory {
type P: PublicKey;
fn commit(&self, k: &<Self::P as PublicKey>::K, v: &<Self::P as PublicKey>::K) -> HomomorphicCommitment<Self::P>;
fn zero(&self) -> HomomorphicCommitment<Self::P>;
fn open(
&self,
k: &<Self::P as PublicKey>::K,
v: &<Self::P as PublicKey>::K,
commitment: &HomomorphicCommitment<Self::P>,
) -> bool;
fn commit_value(&self, k: &<Self::P as PublicKey>::K, value: u64) -> HomomorphicCommitment<Self::P>;
fn open_value(&self, k: &<Self::P as PublicKey>::K, v: u64, commitment: &HomomorphicCommitment<Self::P>) -> bool;
}