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