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