arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/src/commitments.rs
src/commitments.rsRaw
  1use super::errors::NovaError;
  2use core::ops::{Add, AddAssign, Mul, MulAssign};
  3use curve25519_dalek::traits::VartimeMultiscalarMul;
  4use digest::{ExtendableOutput, Input};
  5use merlin::Transcript;
  6use sha3::Shake256;
  7use std::io::Read;
  8
  9pub type Scalar = curve25519_dalek::scalar::Scalar;
 10type GroupElement = curve25519_dalek::ristretto::RistrettoPoint;
 11type CompressedGroup = curve25519_dalek::ristretto::CompressedRistretto;
 12
 13#[derive(Debug)]
 14pub struct CommitGens {
 15  gens: Vec<GroupElement>,
 16}
 17
 18#[derive(Clone, Debug, PartialEq, Eq)]
 19pub struct Commitment {
 20  comm: GroupElement,
 21}
 22
 23#[derive(Clone, Debug, PartialEq, Eq)]
 24pub struct CompressedCommitment {
 25  comm: CompressedGroup,
 26}
 27
 28impl CommitGens {
 29  pub fn new(label: &[u8], n: usize) -> Self {
 30    let mut shake = Shake256::default();
 31    shake.input(label);
 32    let mut reader = shake.xof_result();
 33    let mut gens: Vec<GroupElement> = Vec::new();
 34    let mut uniform_bytes = [0u8; 64];
 35    for _ in 0..n {
 36      reader.read_exact(&mut uniform_bytes).unwrap();
 37      gens.push(GroupElement::from_uniform_bytes(&uniform_bytes));
 38    }
 39
 40    CommitGens { gens }
 41  }
 42}
 43
 44impl Commitment {
 45  pub fn compress(&self) -> CompressedCommitment {
 46    CompressedCommitment {
 47      comm: self.comm.compress(),
 48    }
 49  }
 50}
 51
 52impl CompressedCommitment {
 53  pub fn decompress(&self) -> Result<Commitment, NovaError> {
 54    let comm = self.comm.decompress();
 55    if comm.is_none() {
 56      return Err(NovaError::DecompressionError);
 57    }
 58    Ok(Commitment {
 59      comm: comm.unwrap(),
 60    })
 61  }
 62}
 63
 64pub trait CommitTrait {
 65  fn commit(&self, gens: &CommitGens) -> Commitment;
 66}
 67
 68impl CommitTrait for [Scalar] {
 69  fn commit(&self, gens: &CommitGens) -> Commitment {
 70    assert_eq!(gens.gens.len(), self.len());
 71    Commitment {
 72      comm: GroupElement::vartime_multiscalar_mul(self, &gens.gens),
 73    }
 74  }
 75}
 76
 77pub trait ProofTranscriptTrait {
 78  fn append_protocol_name(&mut self, protocol_name: &'static [u8]);
 79  fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar;
 80}
 81
 82impl ProofTranscriptTrait for Transcript {
 83  fn append_protocol_name(&mut self, protocol_name: &'static [u8]) {
 84    self.append_message(b"protocol-name", protocol_name);
 85  }
 86
 87  fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
 88    let mut buf = [0u8; 64];
 89    self.challenge_bytes(label, &mut buf);
 90    Scalar::from_bytes_mod_order_wide(&buf)
 91  }
 92}
 93
 94pub trait AppendToTranscriptTrait {
 95  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript);
 96}
 97
 98impl AppendToTranscriptTrait for CompressedCommitment {
 99  fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
100    transcript.append_message(label, self.comm.as_bytes());
101  }
102}
103
104impl<'b> MulAssign<&'b Scalar> for Commitment {
105  fn mul_assign(&mut self, scalar: &'b Scalar) {
106    let result = (self as &Commitment).comm * scalar;
107    *self = Commitment { comm: result };
108  }
109}
110
111impl<'a, 'b> Mul<&'b Scalar> for &'a Commitment {
112  type Output = Commitment;
113  fn mul(self, scalar: &'b Scalar) -> Commitment {
114    Commitment {
115      comm: self.comm * scalar,
116    }
117  }
118}
119
120impl<'a, 'b> Mul<&'b Commitment> for &'a Scalar {
121  type Output = Commitment;
122
123  fn mul(self, comm: &'b Commitment) -> Commitment {
124    Commitment {
125      comm: self * comm.comm,
126    }
127  }
128}
129
130macro_rules! define_mul_variants {
131  (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
132    impl<'b> Mul<&'b $rhs> for $lhs {
133      type Output = $out;
134      fn mul(self, rhs: &'b $rhs) -> $out {
135        &self * rhs
136      }
137    }
138
139    impl<'a> Mul<$rhs> for &'a $lhs {
140      type Output = $out;
141      fn mul(self, rhs: $rhs) -> $out {
142        self * &rhs
143      }
144    }
145
146    impl Mul<$rhs> for $lhs {
147      type Output = $out;
148      fn mul(self, rhs: $rhs) -> $out {
149        &self * &rhs
150      }
151    }
152  };
153}
154
155macro_rules! define_mul_assign_variants {
156  (LHS = $lhs:ty, RHS = $rhs:ty) => {
157    impl MulAssign<$rhs> for $lhs {
158      fn mul_assign(&mut self, rhs: $rhs) {
159        *self *= &rhs;
160      }
161    }
162  };
163}
164
165define_mul_assign_variants!(LHS = Commitment, RHS = Scalar);
166define_mul_variants!(LHS = Commitment, RHS = Scalar, Output = Commitment);
167define_mul_variants!(LHS = Scalar, RHS = Commitment, Output = Commitment);
168
169impl<'b> AddAssign<&'b Commitment> for Commitment {
170  fn add_assign(&mut self, other: &'b Commitment) {
171    let result = (self as &Commitment).comm + other.comm;
172    *self = Commitment { comm: result };
173  }
174}
175
176impl<'a, 'b> Add<&'b Commitment> for &'a Commitment {
177  type Output = Commitment;
178  fn add(self, other: &'b Commitment) -> Commitment {
179    Commitment {
180      comm: self.comm + other.comm,
181    }
182  }
183}
184
185macro_rules! define_add_variants {
186  (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
187    impl<'b> Add<&'b $rhs> for $lhs {
188      type Output = $out;
189      fn add(self, rhs: &'b $rhs) -> $out {
190        &self + rhs
191      }
192    }
193
194    impl<'a> Add<$rhs> for &'a $lhs {
195      type Output = $out;
196      fn add(self, rhs: $rhs) -> $out {
197        self + &rhs
198      }
199    }
200
201    impl Add<$rhs> for $lhs {
202      type Output = $out;
203      fn add(self, rhs: $rhs) -> $out {
204        &self + &rhs
205      }
206    }
207  };
208}
209
210macro_rules! define_add_assign_variants {
211  (LHS = $lhs:ty, RHS = $rhs:ty) => {
212    impl AddAssign<$rhs> for $lhs {
213      fn add_assign(&mut self, rhs: $rhs) {
214        *self += &rhs;
215      }
216    }
217  };
218}
219
220define_add_assign_variants!(LHS = Commitment, RHS = Commitment);
221define_add_variants!(LHS = Commitment, RHS = Commitment, Output = Commitment);