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