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