use core::{
cmp::Ordering,
hash::{Hash, Hasher},
};
use tari_utilities::{ByteArray, ByteArrayError};
use crate::{commitment::HomomorphicCommitment, compressed_key::CompressedKey, keys::PublicKey};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CompressedCommitment<P>(pub(crate) CompressedKey<P>);
impl<P: Default + ByteArray + PublicKey> Default for CompressedCommitment<P> {
fn default() -> Self {
Self(CompressedKey::default())
}
}
#[cfg(feature = "borsh")]
impl<P: borsh::BorshDeserialize> borsh::BorshDeserialize for CompressedCommitment<P> {
fn deserialize_reader<R>(reader: &mut R) -> Result<Self, borsh::io::Error>
where R: borsh::io::Read {
Ok(Self(CompressedKey::deserialize_reader(reader)?))
}
}
#[cfg(feature = "borsh")]
impl<P: borsh::BorshSerialize> borsh::BorshSerialize for CompressedCommitment<P> {
fn serialize<W: borsh::io::Write>(&self, writer: &mut W) -> borsh::io::Result<()> {
self.0.serialize(writer)
}
}
impl<P> CompressedCommitment<P>
where P: PublicKey
{
pub fn to_public_key(&self) -> Result<P, ByteArrayError> {
self.0.to_public_key()
}
pub fn to_commitment(&self) -> Result<HomomorphicCommitment<P>, ByteArrayError> {
Ok(HomomorphicCommitment(self.to_public_key()?))
}
pub fn to_compressed_key(&self) -> CompressedKey<P> {
self.0.clone()
}
pub fn from_public_key(p: P) -> CompressedCommitment<P> {
let compressed_key = CompressedKey::new_from_pk(p);
CompressedCommitment(compressed_key)
}
pub fn from_compressed_key(compressed_key: CompressedKey<P>) -> Self {
Self(compressed_key)
}
pub fn from_commitment(commitment: HomomorphicCommitment<P>) -> Self {
Self(CompressedKey::new_from_pk(commitment.0))
}
}
impl<P> ByteArray for CompressedCommitment<P>
where P: PublicKey
{
fn from_canonical_bytes(bytes: &[u8]) -> Result<Self, ByteArrayError> {
let key = CompressedKey::from_canonical_bytes(bytes)?;
Ok(Self(key))
}
fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl<P> PartialOrd for CompressedCommitment<P>
where P: PublicKey
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<P> Ord for CompressedCommitment<P>
where P: PublicKey
{
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<P: PublicKey> Hash for CompressedCommitment<P> {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(self.as_bytes())
}
}
impl<P: PublicKey> PartialEq for CompressedCommitment<P> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<P: PublicKey> Eq for CompressedCommitment<P> {}