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