arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/src/commitments.rs
src/commitments.rsRaw
  1use super::{
  2  errors::NovaError,
  3  traits::{AbsorbInROTrait, AppendToTranscriptTrait, CompressedGroup, Group, ROTrait},
  4};
  5use core::{
  6  fmt::Debug,
  7  marker::PhantomData,
  8  ops::{Add, AddAssign, Mul, MulAssign},
  9};
 10use ff::Field;
 11use merlin::Transcript;
 12use rayon::prelude::*;
 13
 14#[derive(Clone, Debug)]
 15pub struct CommitGens<G: Group> {
 16  gens: Vec<G::PreprocessedGroupElement>,
 17  _p: PhantomData<G>,
 18}
 19
 20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 21pub struct Commitment<G: Group> {
 22  pub(crate) comm: G,
 23}
 24
 25#[derive(Clone, Debug, PartialEq, Eq)]
 26pub struct CompressedCommitment<C: CompressedGroup> {
 27  comm: C,
 28}
 29
 30impl<G: Group> CommitGens<G> {
 31  pub fn new(label: &'static [u8], n: usize) -> Self {
 32    CommitGens {
 33      gens: G::from_label(label, n.next_power_of_two()),
 34      _p: Default::default(),
 35    }
 36  }
 37
 38  fn len(&self) -> usize {
 39    self.gens.len()
 40  }
 41
 42  pub fn split_at(&self, n: usize) -> (CommitGens<G>, CommitGens<G>) {
 43    (
 44      CommitGens {
 45        gens: self.gens[0..n].to_vec(),
 46        _p: Default::default(),
 47      },
 48      CommitGens {
 49        gens: self.gens[n..].to_vec(),
 50        _p: Default::default(),
 51      },
 52    )
 53  }
 54
 55  pub fn combine(&self, other: &CommitGens<G>) -> CommitGens<G> {
 56    let gens = {
 57      let mut c = self.gens.clone();
 58      c.extend(other.gens.clone());
 59      c
 60    };
 61    CommitGens {
 62      gens,
 63      _p: Default::default(),
 64    }
 65  }
 66
 67  // combines the left and right halves of `self` using `w1` and `w2` as the weights
 68  pub fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> CommitGens<G> {
 69    let w = vec![*w1, *w2];
 70    let (L, R) = self.split_at(self.len() / 2);
 71
 72    let gens = (0..self.len() / 2)
 73      .into_par_iter()
 74      .map(|i| {
 75        let gens = CommitGens::<G> {
 76          gens: [L.gens[i].clone(), R.gens[i].clone()].to_vec(),
 77          _p: Default::default(),
 78        };
 79        w.commit(&gens).comm.preprocessed()
 80      })
 81      .collect();
 82
 83    CommitGens {
 84      gens,
 85      _p: Default::default(),
 86    }
 87  }
 88
 89  /// Scales each element in `self` by `r`
 90  pub fn scale(&self, r: &G::Scalar) -> Self {
 91    let gens_scaled = self
 92      .gens
 93      .clone()
 94      .into_par_iter()
 95      .map(|g| {
 96        let gens = CommitGens::<G> {
 97          gens: vec![g],
 98          _p: Default::default(),
 99        };
100        [*r].commit(&gens).comm.preprocessed()
101      })
102      .collect();
103
104    CommitGens {
105      gens: gens_scaled,
106      _p: Default::default(),
107    }
108  }
109
110  /// reinterprets a vector of commitments as a set of generators
111  pub fn reinterpret_commitments_as_gens(
112    c: &[CompressedCommitment<G::CompressedGroupElement>],
113  ) -> Result<Self, NovaError> {
114    let d = (0..c.len())
115      .into_par_iter()
116      .map(|i| c[i].decompress())
117      .collect::<Result<Vec<Commitment<G>>, NovaError>>()?;
118    let gens = (0..d.len())
119      .into_par_iter()
120      .map(|i| d[i].comm.preprocessed())
121      .collect();
122    Ok(CommitGens {
123      gens,
124      _p: Default::default(),
125    })
126  }
127}
128
129impl<G: Group> Commitment<G> {
130  pub fn compress(&self) -> CompressedCommitment<G::CompressedGroupElement> {
131    CompressedCommitment {
132      comm: self.comm.compress(),
133    }
134  }
135}
136
137impl<G: Group> Default for Commitment<G> {
138  fn default() -> Self {
139    Commitment { comm: G::zero() }
140  }
141}
142
143impl<C: CompressedGroup> CompressedCommitment<C> {
144  pub fn decompress(&self) -> Result<Commitment<C::GroupElement>, NovaError> {
145    let comm = self.comm.decompress();
146    if comm.is_none() {
147      return Err(NovaError::DecompressionError);
148    }
149    Ok(Commitment {
150      comm: comm.unwrap(),
151    })
152  }
153}
154
155pub trait CommitTrait<G: Group> {
156  fn commit(&self, gens: &CommitGens<G>) -> Commitment<G>;
157}
158
159impl<G: Group> CommitTrait<G> for [G::Scalar] {
160  fn commit(&self, gens: &CommitGens<G>) -> Commitment<G> {
161    assert!(gens.gens.len() >= self.len());
162    Commitment {
163      comm: G::vartime_multiscalar_mul(self, &gens.gens[..self.len()]),
164    }
165  }
166}
167
168impl<G: Group> AppendToTranscriptTrait for Commitment<G> {
169  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
170    transcript.append_message(label, self.comm.compress().as_bytes());
171  }
172}
173
174impl<G: Group> AbsorbInROTrait<G> for Commitment<G> {
175  fn absorb_in_ro(&self, ro: &mut G::RO) {
176    let (x, y, is_infinity) = self.comm.to_coordinates();
177    ro.absorb(x);
178    ro.absorb(y);
179    ro.absorb(if is_infinity {
180      G::Base::one()
181    } else {
182      G::Base::zero()
183    });
184  }
185}
186
187impl<C: CompressedGroup> AppendToTranscriptTrait for CompressedCommitment<C> {
188  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
189    transcript.append_message(label, self.comm.as_bytes());
190  }
191}
192
193impl<'b, G: Group> MulAssign<&'b G::Scalar> for Commitment<G> {
194  fn mul_assign(&mut self, scalar: &'b G::Scalar) {
195    let result = (self as &Commitment<G>).comm * scalar;
196    *self = Commitment { comm: result };
197  }
198}
199
200impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment<G> {
201  type Output = Commitment<G>;
202  fn mul(self, scalar: &'b G::Scalar) -> Commitment<G> {
203    Commitment {
204      comm: self.comm * scalar,
205    }
206  }
207}
208
209impl<G: Group> Mul<G::Scalar> for Commitment<G> {
210  type Output = Commitment<G>;
211
212  fn mul(self, scalar: G::Scalar) -> Commitment<G> {
213    Commitment {
214      comm: self.comm * scalar,
215    }
216  }
217}
218
219impl<'b, G: Group> AddAssign<&'b Commitment<G>> for Commitment<G> {
220  fn add_assign(&mut self, other: &'b Commitment<G>) {
221    let result = (self as &Commitment<G>).comm + other.comm;
222    *self = Commitment { comm: result };
223  }
224}
225
226impl<'a, 'b, G: Group> Add<&'b Commitment<G>> for &'a Commitment<G> {
227  type Output = Commitment<G>;
228  fn add(self, other: &'b Commitment<G>) -> Commitment<G> {
229    Commitment {
230      comm: self.comm + other.comm,
231    }
232  }
233}
234
235macro_rules! define_add_variants {
236  (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
237    impl<'b, G: $g> Add<&'b $rhs> for $lhs {
238      type Output = $out;
239      fn add(self, rhs: &'b $rhs) -> $out {
240        &self + rhs
241      }
242    }
243
244    impl<'a, G: $g> Add<$rhs> for &'a $lhs {
245      type Output = $out;
246      fn add(self, rhs: $rhs) -> $out {
247        self + &rhs
248      }
249    }
250
251    impl<G: $g> Add<$rhs> for $lhs {
252      type Output = $out;
253      fn add(self, rhs: $rhs) -> $out {
254        &self + &rhs
255      }
256    }
257  };
258}
259
260macro_rules! define_add_assign_variants {
261  (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty) => {
262    impl<G: $g> AddAssign<$rhs> for $lhs {
263      fn add_assign(&mut self, rhs: $rhs) {
264        *self += &rhs;
265      }
266    }
267  };
268}
269
270define_add_assign_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>);
271define_add_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>, Output = Commitment<G>);