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