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