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);