use super::errors::NovaError; use super::traits::{CompressedGroup, Group}; use core::fmt::Debug; use core::ops::{Add, AddAssign, Mul, MulAssign}; use digest::{ExtendableOutput, Input}; use merlin::Transcript; use sha3::Shake256; use std::io::Read; #[derive(Debug)] pub struct CommitGens { gens: Vec, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Commitment { comm: G, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct CompressedCommitment { comm: C, } impl CommitGens { pub fn new(label: &[u8], n: usize) -> Self { let mut shake = Shake256::default(); shake.input(label); let mut reader = shake.xof_result(); let mut gens: Vec = Vec::new(); let mut uniform_bytes = [0u8; 64]; for _ in 0..n { reader.read_exact(&mut uniform_bytes).unwrap(); gens.push(G::from_uniform_bytes(&uniform_bytes).unwrap()); } CommitGens { gens } } } impl Commitment { pub fn compress(&self) -> CompressedCommitment { CompressedCommitment { comm: self.comm.compress(), } } } impl CompressedCommitment { pub fn decompress(&self) -> Result, NovaError> { let comm = self.comm.decompress(); if comm.is_none() { return Err(NovaError::DecompressionError); } Ok(Commitment { comm: comm.unwrap(), }) } } pub trait CommitTrait { fn commit(&self, gens: &CommitGens) -> Commitment; } impl CommitTrait for [G::Scalar] { fn commit(&self, gens: &CommitGens) -> Commitment { assert_eq!(gens.gens.len(), self.len()); Commitment { comm: G::vartime_multiscalar_mul(self, &gens.gens), } } } pub trait AppendToTranscriptTrait { fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript); } impl AppendToTranscriptTrait for Commitment { fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) { transcript.append_message(label, self.comm.compress().as_bytes()); } } impl AppendToTranscriptTrait for CompressedCommitment { fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) { transcript.append_message(label, self.comm.as_bytes()); } } impl<'b, G: Group> MulAssign<&'b G::Scalar> for Commitment { fn mul_assign(&mut self, scalar: &'b G::Scalar) { let result = (self as &Commitment).comm * scalar; *self = Commitment { comm: result }; } } impl Mul for Commitment { type Output = Commitment; fn mul(self, scalar: G::Scalar) -> Commitment { Commitment { comm: self.comm * scalar, } } } impl<'b, G: Group> AddAssign<&'b Commitment> for Commitment { fn add_assign(&mut self, other: &'b Commitment) { let result = (self as &Commitment).comm + other.comm; *self = Commitment { comm: result }; } } impl<'a, 'b, G: Group> Add<&'b Commitment> for &'a Commitment { type Output = Commitment; fn add(self, other: &'b Commitment) -> Commitment { Commitment { comm: self.comm + other.comm, } } } impl AddAssign> for Commitment { fn add_assign(&mut self, rhs: Commitment) { *self += &rhs; } } impl<'b, G: Group> Add<&'b Commitment> for Commitment { type Output = Commitment; fn add(self, rhs: &'b Commitment) -> Commitment { &self + rhs } } impl<'a, G: Group> Add> for &'a Commitment { type Output = Commitment; fn add(self, rhs: Commitment) -> Commitment { self + &rhs } } impl Add> for Commitment { type Output = Commitment; fn add(self, rhs: Commitment) -> Commitment { &self + &rhs } }