Nova/src/commitments.rs
src/commitments.rsRaw
1use super::{
2 errors::NovaError,
3 traits::{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
83pub trait AppendToTranscriptTrait {
84 fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript);
85}
86
87impl<G: Group> AppendToTranscriptTrait for Commitment<G> {
88 fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
89 transcript.append_message(label, self.comm.compress().as_bytes());
90 }
91}
92
93impl<C: CompressedGroup> AppendToTranscriptTrait for CompressedCommitment<C> {
94 fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
95 transcript.append_message(label, self.comm.as_bytes());
96 }
97}
98
99impl<'b, G: Group> MulAssign<&'b G::Scalar> for Commitment<G> {
100 fn mul_assign(&mut self, scalar: &'b G::Scalar) {
101 let result = (self as &Commitment<G>).comm * scalar;
102 *self = Commitment { comm: result };
103 }
104}
105
106impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment<G> {
107 type Output = Commitment<G>;
108 fn mul(self, scalar: &'b G::Scalar) -> Commitment<G> {
109 Commitment {
110 comm: self.comm * scalar,
111 }
112 }
113}
114
115impl<G: Group> Mul<G::Scalar> for Commitment<G> {
116 type Output = Commitment<G>;
117
118 fn mul(self, scalar: G::Scalar) -> Commitment<G> {
119 Commitment {
120 comm: self.comm * scalar,
121 }
122 }
123}
124
125impl<'b, G: Group> AddAssign<&'b Commitment<G>> for Commitment<G> {
126 fn add_assign(&mut self, other: &'b Commitment<G>) {
127 let result = (self as &Commitment<G>).comm + other.comm;
128 *self = Commitment { comm: result };
129 }
130}
131
132impl<'a, 'b, G: Group> Add<&'b Commitment<G>> for &'a Commitment<G> {
133 type Output = Commitment<G>;
134 fn add(self, other: &'b Commitment<G>) -> Commitment<G> {
135 Commitment {
136 comm: self.comm + other.comm,
137 }
138 }
139}
140
141macro_rules! define_add_variants {
142 (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
143 impl<'b, G: $g> Add<&'b $rhs> for $lhs {
144 type Output = $out;
145 fn add(self, rhs: &'b $rhs) -> $out {
146 &self + rhs
147 }
148 }
149
150 impl<'a, G: $g> Add<$rhs> for &'a $lhs {
151 type Output = $out;
152 fn add(self, rhs: $rhs) -> $out {
153 self + &rhs
154 }
155 }
156
157 impl<G: $g> Add<$rhs> for $lhs {
158 type Output = $out;
159 fn add(self, rhs: $rhs) -> $out {
160 &self + &rhs
161 }
162 }
163 };
164}
165
166macro_rules! define_add_assign_variants {
167 (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty) => {
168 impl<G: $g> AddAssign<$rhs> for $lhs {
169 fn add_assign(&mut self, rhs: $rhs) {
170 *self += &rhs;
171 }
172 }
173 };
174}
175
176define_add_assign_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>);
177define_add_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>, Output = Commitment<G>);