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