arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/src/commitments.rs
src/commitments.rsRaw
  1use super::{
  2  errors::NovaError,
  3  traits::{CompressedGroup, Group},
  4};
  5use core::{
  6  fmt::Debug,
  7  marker::PhantomData,
  8  ops::{Add, AddAssign, Mul, MulAssign},
  9};
 10use digest::{ExtendableOutput, Input};
 11use merlin::Transcript;
 12use sha3::Shake256;
 13use std::io::Read;
 14
 15#[derive(Debug)]
 16pub struct CommitGens<G: Group> {
 17  gens: Vec<G::PreprocessedGroupElement>,
 18  _p: PhantomData<G>,
 19}
 20
 21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 22pub struct Commitment<G: Group> {
 23  pub(crate) comm: G,
 24}
 25
 26#[derive(Clone, Debug, PartialEq, Eq)]
 27pub struct CompressedCommitment<C: CompressedGroup> {
 28  comm: C,
 29}
 30
 31impl<G: Group> CommitGens<G> {
 32  pub fn new(label: &[u8], n: usize) -> Self {
 33    let mut shake = Shake256::default();
 34    shake.input(label);
 35    let mut reader = shake.xof_result();
 36    let mut gens: Vec<G::PreprocessedGroupElement> = Vec::new();
 37    let mut uniform_bytes = [0u8; 64];
 38    for _ in 0..n {
 39      reader.read_exact(&mut uniform_bytes).unwrap();
 40      gens.push(G::from_uniform_bytes(&uniform_bytes).unwrap());
 41    }
 42
 43    CommitGens {
 44      gens,
 45      _p: PhantomData::default(),
 46    }
 47  }
 48}
 49
 50impl<G: Group> Commitment<G> {
 51  pub fn compress(&self) -> CompressedCommitment<G::CompressedGroupElement> {
 52    CompressedCommitment {
 53      comm: self.comm.compress(),
 54    }
 55  }
 56}
 57
 58impl<C: CompressedGroup> CompressedCommitment<C> {
 59  pub fn decompress(&self) -> Result<Commitment<C::GroupElement>, NovaError> {
 60    let comm = self.comm.decompress();
 61    if comm.is_none() {
 62      return Err(NovaError::DecompressionError);
 63    }
 64    Ok(Commitment {
 65      comm: comm.unwrap(),
 66    })
 67  }
 68}
 69
 70pub trait CommitTrait<G: Group> {
 71  fn commit(&self, gens: &CommitGens<G>) -> Commitment<G>;
 72}
 73
 74impl<G: Group> CommitTrait<G> for [G::Scalar] {
 75  fn commit(&self, gens: &CommitGens<G>) -> Commitment<G> {
 76    assert!(gens.gens.len() >= self.len());
 77    Commitment {
 78      comm: G::vartime_multiscalar_mul(self, &gens.gens[..self.len()]),
 79    }
 80  }
 81}
 82
 83pub trait AppendToTranscriptTrait {
 84  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript);
 85}
 86
 87impl<G: Group> AppendToTranscriptTrait for Commitment<G> {
 88  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
 89    transcript.append_message(label, self.comm.compress().as_bytes());
 90  }
 91}
 92
 93impl<C: CompressedGroup> AppendToTranscriptTrait for CompressedCommitment<C> {
 94  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
 95    transcript.append_message(label, self.comm.as_bytes());
 96  }
 97}
 98
 99impl<'b, G: Group> MulAssign<&'b G::Scalar> for Commitment<G> {
100  fn mul_assign(&mut self, scalar: &'b G::Scalar) {
101    let result = (self as &Commitment<G>).comm * scalar;
102    *self = Commitment { comm: result };
103  }
104}
105
106impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment<G> {
107  type Output = Commitment<G>;
108  fn mul(self, scalar: &'b G::Scalar) -> Commitment<G> {
109    Commitment {
110      comm: self.comm * scalar,
111    }
112  }
113}
114
115impl<G: Group> Mul<G::Scalar> for Commitment<G> {
116  type Output = Commitment<G>;
117
118  fn mul(self, scalar: G::Scalar) -> Commitment<G> {
119    Commitment {
120      comm: self.comm * scalar,
121    }
122  }
123}
124
125impl<'b, G: Group> AddAssign<&'b Commitment<G>> for Commitment<G> {
126  fn add_assign(&mut self, other: &'b Commitment<G>) {
127    let result = (self as &Commitment<G>).comm + other.comm;
128    *self = Commitment { comm: result };
129  }
130}
131
132impl<'a, 'b, G: Group> Add<&'b Commitment<G>> for &'a Commitment<G> {
133  type Output = Commitment<G>;
134  fn add(self, other: &'b Commitment<G>) -> Commitment<G> {
135    Commitment {
136      comm: self.comm + other.comm,
137    }
138  }
139}
140
141macro_rules! define_add_variants {
142  (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
143    impl<'b, G: $g> Add<&'b $rhs> for $lhs {
144      type Output = $out;
145      fn add(self, rhs: &'b $rhs) -> $out {
146        &self + rhs
147      }
148    }
149
150    impl<'a, G: $g> Add<$rhs> for &'a $lhs {
151      type Output = $out;
152      fn add(self, rhs: $rhs) -> $out {
153        self + &rhs
154      }
155    }
156
157    impl<G: $g> Add<$rhs> for $lhs {
158      type Output = $out;
159      fn add(self, rhs: $rhs) -> $out {
160        &self + &rhs
161      }
162    }
163  };
164}
165
166macro_rules! define_add_assign_variants {
167  (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty) => {
168    impl<G: $g> AddAssign<$rhs> for $lhs {
169      fn add_assign(&mut self, rhs: $rhs) {
170        *self += &rhs;
171      }
172    }
173  };
174}
175
176define_add_assign_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>);
177define_add_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>, Output = Commitment<G>);