arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/src/provider/pedersen.rs
src/provider/pedersen.rsRaw
  1//! This module provides an implementation of a commitment engine
  2use crate::{
  3  errors::NovaError,
  4  traits::{
  5    commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait},
  6    AbsorbInROTrait, CompressedGroup, Group, ROTrait, TranscriptReprTrait,
  7  },
  8};
  9use core::{
 10  fmt::Debug,
 11  marker::PhantomData,
 12  ops::{Add, AddAssign, Mul, MulAssign},
 13};
 14use ff::Field;
 15use rayon::prelude::*;
 16use serde::{Deserialize, Serialize};
 17
 18/// A type that holds commitment generators
 19#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
 20pub struct CommitmentKey<G: Group> {
 21  ck: Vec<G::PreprocessedGroupElement>,
 22  _p: PhantomData<G>,
 23}
 24
 25/// A type that holds a commitment
 26#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
 27#[serde(bound = "")]
 28pub struct Commitment<G: Group> {
 29  pub(crate) comm: G,
 30}
 31
 32/// A type that holds a compressed commitment
 33#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
 34#[serde(bound = "")]
 35pub struct CompressedCommitment<G: Group> {
 36  comm: G::CompressedGroupElement,
 37}
 38
 39impl<G: Group> CommitmentKeyTrait<G> for CommitmentKey<G> {
 40  type Commitment = Commitment<G>;
 41
 42  fn new(label: &'static [u8], n: usize) -> Self {
 43    CommitmentKey {
 44      ck: G::from_label(label, n.next_power_of_two()),
 45      _p: Default::default(),
 46    }
 47  }
 48
 49  fn len(&self) -> usize {
 50    self.ck.len()
 51  }
 52
 53  fn commit(&self, v: &[G::Scalar]) -> Self::Commitment {
 54    assert!(self.ck.len() >= v.len());
 55    Commitment {
 56      comm: G::vartime_multiscalar_mul(v, &self.ck[..v.len()]),
 57    }
 58  }
 59}
 60
 61impl<G: Group> CommitmentTrait<G> for Commitment<G> {
 62  type CompressedCommitment = CompressedCommitment<G>;
 63
 64  fn compress(&self) -> Self::CompressedCommitment {
 65    CompressedCommitment {
 66      comm: self.comm.compress(),
 67    }
 68  }
 69
 70  fn to_coordinates(&self) -> (G::Base, G::Base, bool) {
 71    self.comm.to_coordinates()
 72  }
 73
 74  fn decompress(c: &Self::CompressedCommitment) -> Result<Self, NovaError> {
 75    let comm = c.comm.decompress();
 76    if comm.is_none() {
 77      return Err(NovaError::DecompressionError);
 78    }
 79    Ok(Commitment {
 80      comm: comm.unwrap(),
 81    })
 82  }
 83}
 84
 85impl<G: Group> Default for Commitment<G> {
 86  fn default() -> Self {
 87    Commitment { comm: G::zero() }
 88  }
 89}
 90
 91impl<G: Group> TranscriptReprTrait<G> for Commitment<G> {
 92  fn to_transcript_bytes(&self) -> Vec<u8> {
 93    let (x, y, is_infinity) = self.comm.to_coordinates();
 94    let is_infinity_byte = if is_infinity { 0u8 } else { 1u8 };
 95    [
 96      x.to_transcript_bytes(),
 97      y.to_transcript_bytes(),
 98      [is_infinity_byte].to_vec(),
 99    ]
100    .concat()
101  }
102}
103
104impl<G: Group> AbsorbInROTrait<G> for Commitment<G> {
105  fn absorb_in_ro(&self, ro: &mut G::RO) {
106    let (x, y, is_infinity) = self.comm.to_coordinates();
107    ro.absorb(x);
108    ro.absorb(y);
109    ro.absorb(if is_infinity {
110      G::Base::one()
111    } else {
112      G::Base::zero()
113    });
114  }
115}
116
117impl<G: Group> TranscriptReprTrait<G> for CompressedCommitment<G> {
118  fn to_transcript_bytes(&self) -> Vec<u8> {
119    self.comm.to_transcript_bytes()
120  }
121}
122
123impl<G: Group> MulAssign<G::Scalar> for Commitment<G> {
124  fn mul_assign(&mut self, scalar: G::Scalar) {
125    let result = (self as &Commitment<G>).comm * scalar;
126    *self = Commitment { comm: result };
127  }
128}
129
130impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment<G> {
131  type Output = Commitment<G>;
132  fn mul(self, scalar: &'b G::Scalar) -> Commitment<G> {
133    Commitment {
134      comm: self.comm * scalar,
135    }
136  }
137}
138
139impl<G: Group> Mul<G::Scalar> for Commitment<G> {
140  type Output = Commitment<G>;
141
142  fn mul(self, scalar: G::Scalar) -> Commitment<G> {
143    Commitment {
144      comm: self.comm * scalar,
145    }
146  }
147}
148
149impl<'b, G: Group> AddAssign<&'b Commitment<G>> for Commitment<G> {
150  fn add_assign(&mut self, other: &'b Commitment<G>) {
151    let result = (self as &Commitment<G>).comm + other.comm;
152    *self = Commitment { comm: result };
153  }
154}
155
156impl<'a, 'b, G: Group> Add<&'b Commitment<G>> for &'a Commitment<G> {
157  type Output = Commitment<G>;
158  fn add(self, other: &'b Commitment<G>) -> Commitment<G> {
159    Commitment {
160      comm: self.comm + other.comm,
161    }
162  }
163}
164
165macro_rules! define_add_variants {
166  (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
167    impl<'b, G: $g> Add<&'b $rhs> for $lhs {
168      type Output = $out;
169      fn add(self, rhs: &'b $rhs) -> $out {
170        &self + rhs
171      }
172    }
173
174    impl<'a, G: $g> Add<$rhs> for &'a $lhs {
175      type Output = $out;
176      fn add(self, rhs: $rhs) -> $out {
177        self + &rhs
178      }
179    }
180
181    impl<G: $g> Add<$rhs> for $lhs {
182      type Output = $out;
183      fn add(self, rhs: $rhs) -> $out {
184        &self + &rhs
185      }
186    }
187  };
188}
189
190macro_rules! define_add_assign_variants {
191  (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty) => {
192    impl<G: $g> AddAssign<$rhs> for $lhs {
193      fn add_assign(&mut self, rhs: $rhs) {
194        *self += &rhs;
195      }
196    }
197  };
198}
199
200define_add_assign_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>);
201define_add_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>, Output = Commitment<G>);
202
203/// Provides a commitment engine
204#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
205pub struct CommitmentEngine<G: Group> {
206  _p: PhantomData<G>,
207}
208
209impl<G: Group> CommitmentEngineTrait<G> for CommitmentEngine<G> {
210  type CommitmentKey = CommitmentKey<G>;
211  type Commitment = Commitment<G>;
212
213  fn commit(ck: &Self::CommitmentKey, v: &[G::Scalar]) -> Self::Commitment {
214    ck.commit(v)
215  }
216}
217
218pub(crate) trait CommitmentKeyExtTrait<G: Group>: CommitmentKeyTrait<G> {
219  type CE: CommitmentEngineTrait<G>;
220
221  /// Splits the commitment key into two pieces at a specified point
222  fn split_at(&self, n: usize) -> (Self, Self)
223  where
224    Self: Sized;
225
226  /// Combines two commitment keys into one
227  fn combine(&self, other: &Self) -> Self;
228
229  /// Folds the two commitment keys into one using the provided weights
230  fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> Self;
231
232  /// Scales the commitment key using the provided scalar
233  fn scale(&self, r: &G::Scalar) -> Self;
234
235  /// Reinterprets commitments as commitment keys
236  fn reinterpret_commitments_as_ck(
237    c: &[<<<Self as CommitmentKeyExtTrait<G>>::CE as CommitmentEngineTrait<G>>::Commitment as CommitmentTrait<G>>::CompressedCommitment],
238  ) -> Result<Self, NovaError>
239  where
240    Self: Sized;
241}
242
243impl<G: Group> CommitmentKeyExtTrait<G> for CommitmentKey<G> {
244  type CE = CommitmentEngine<G>;
245
246  fn split_at(&self, n: usize) -> (CommitmentKey<G>, CommitmentKey<G>) {
247    (
248      CommitmentKey {
249        ck: self.ck[0..n].to_vec(),
250        _p: Default::default(),
251      },
252      CommitmentKey {
253        ck: self.ck[n..].to_vec(),
254        _p: Default::default(),
255      },
256    )
257  }
258
259  fn combine(&self, other: &CommitmentKey<G>) -> CommitmentKey<G> {
260    let ck = {
261      let mut c = self.ck.clone();
262      c.extend(other.ck.clone());
263      c
264    };
265    CommitmentKey {
266      ck,
267      _p: Default::default(),
268    }
269  }
270
271  // combines the left and right halves of `self` using `w1` and `w2` as the weights
272  fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> CommitmentKey<G> {
273    let w = vec![*w1, *w2];
274    let (L, R) = self.split_at(self.len() / 2);
275
276    let ck = (0..self.len() / 2)
277      .into_par_iter()
278      .map(|i| {
279        let bases = [L.ck[i].clone(), R.ck[i].clone()].to_vec();
280        G::vartime_multiscalar_mul(&w, &bases).preprocessed()
281      })
282      .collect();
283
284    CommitmentKey {
285      ck,
286      _p: Default::default(),
287    }
288  }
289
290  /// Scales each element in `self` by `r`
291  fn scale(&self, r: &G::Scalar) -> Self {
292    let ck_scaled = self
293      .ck
294      .clone()
295      .into_par_iter()
296      .map(|g| G::vartime_multiscalar_mul(&[*r], &[g]).preprocessed())
297      .collect();
298
299    CommitmentKey {
300      ck: ck_scaled,
301      _p: Default::default(),
302    }
303  }
304
305  /// reinterprets a vector of commitments as a set of generators
306  fn reinterpret_commitments_as_ck(c: &[CompressedCommitment<G>]) -> Result<Self, NovaError> {
307    let d = (0..c.len())
308      .into_par_iter()
309      .map(|i| Commitment::<G>::decompress(&c[i]))
310      .collect::<Result<Vec<Commitment<G>>, NovaError>>()?;
311    let ck = (0..d.len())
312      .into_par_iter()
313      .map(|i| d[i].comm.preprocessed())
314      .collect();
315    Ok(CommitmentKey {
316      ck,
317      _p: Default::default(),
318    })
319  }
320}