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