use core::{
cmp::Ordering,
convert::TryFrom,
hash::{Hash, Hasher},
ops::{Add, Mul, Sub},
};
use tari_utilities::{ByteArray, ByteArrayError};
use crate::{
alloc::string::ToString,
errors::CommitmentError,
keys::{PublicKey, SecretKey},
};
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HomomorphicCommitment<P>(pub(crate) P);
#[cfg(feature = "borsh")]
impl<P: borsh::BorshDeserialize> borsh::BorshDeserialize for HomomorphicCommitment<P> {
fn deserialize_reader<R>(reader: &mut R) -> Result<Self, borsh::io::Error>
where R: borsh::io::Read {
Ok(Self(P::deserialize_reader(reader)?))
}
}
#[cfg(feature = "borsh")]
impl<P: borsh::BorshSerialize> borsh::BorshSerialize for HomomorphicCommitment<P> {
fn serialize<W: borsh::io::Write>(&self, writer: &mut W) -> borsh::io::Result<()> {
self.0.serialize(writer)
}
}
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_canonical_bytes(bytes: &[u8]) -> Result<Self, ByteArrayError> {
let p = P::from_canonical_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.cmp(other))
}
}
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> Add<&'b P> for &'b HomomorphicCommitment<P>
where
P: PublicKey,
&'b P: Add<&'b P, Output = P>,
{
type Output = HomomorphicCommitment<P>;
fn add(self, rhs: &'b P) -> Self::Output {
HomomorphicCommitment(&self.0 + rhs)
}
}
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<'a, 'b, P, K> Mul<&'b K> for &'a HomomorphicCommitment<P>
where
P: PublicKey<K = K>,
K: SecretKey,
&'b K: Mul<&'a P, Output = P>,
{
type Output = HomomorphicCommitment<P>;
fn mul(self, rhs: &'b K) -> HomomorphicCommitment<P> {
let p = rhs * &self.0;
HomomorphicCommitment::<P>::from_public_key(&p)
}
}
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() == other.as_public_key()
}
}
impl<P: PublicKey> Eq for HomomorphicCommitment<P> {}
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;
}
pub trait ExtendedHomomorphicCommitmentFactory {
type P: PublicKey;
fn commit_extended(
&self,
k_vec: &[<Self::P as PublicKey>::K],
v: &<Self::P as PublicKey>::K,
) -> Result<HomomorphicCommitment<Self::P>, CommitmentError>;
fn zero_extended(&self) -> HomomorphicCommitment<Self::P>;
fn open_extended(
&self,
k_vec: &[<Self::P as PublicKey>::K],
v: &<Self::P as PublicKey>::K,
commitment: &HomomorphicCommitment<Self::P>,
) -> Result<bool, CommitmentError>;
fn commit_value_extended(
&self,
k_vec: &[<Self::P as PublicKey>::K],
value: u64,
) -> Result<HomomorphicCommitment<Self::P>, CommitmentError>;
fn open_value_extended(
&self,
k_vec: &[<Self::P as PublicKey>::K],
v: u64,
commitment: &HomomorphicCommitment<Self::P>,
) -> Result<bool, CommitmentError>;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ExtensionDegree {
DefaultPedersen = 1,
AddOneBasePoint = 2,
AddTwoBasePoints = 3,
AddThreeBasePoints = 4,
AddFourBasePoints = 5,
AddFiveBasePoints = 6,
}
impl ExtensionDegree {
pub fn try_from_size(size: usize) -> Result<ExtensionDegree, CommitmentError> {
match size {
1 => Ok(ExtensionDegree::DefaultPedersen),
2 => Ok(ExtensionDegree::AddOneBasePoint),
3 => Ok(ExtensionDegree::AddTwoBasePoints),
4 => Ok(ExtensionDegree::AddThreeBasePoints),
5 => Ok(ExtensionDegree::AddFourBasePoints),
6 => Ok(ExtensionDegree::AddFiveBasePoints),
_ => Err(CommitmentError::CommitmentExtensionDegree {
reason: "Extension degree not valid".to_string(),
}),
}
}
}
impl TryFrom<usize> for ExtensionDegree {
type Error = CommitmentError;
fn try_from(value: usize) -> Result<Self, Self::Error> {
Self::try_from_size(value)
}
}