Nova/src/traits/mod.rs
src/traits/mod.rsRaw
1//! This module defines various traits required by the users of the library to implement.
2use crate::errors::NovaError;
3use bellperson::{
4 gadgets::{boolean::AllocatedBit, num::AllocatedNum},
5 ConstraintSystem, SynthesisError,
6};
7use core::{
8 fmt::Debug,
9 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
10};
11use ff::{PrimeField, PrimeFieldBits};
12use num_bigint::BigInt;
13use serde::{Deserialize, Serialize};
14
15pub mod commitment;
16
17use commitment::CommitmentEngineTrait;
18
19/// Represents an element of a group
20/// This is currently tailored for an elliptic curve group
21pub trait Group:
22 Clone
23 + Copy
24 + Debug
25 + Eq
26 + Sized
27 + GroupOps
28 + GroupOpsOwned
29 + ScalarMul<<Self as Group>::Scalar>
30 + ScalarMulOwned<<Self as Group>::Scalar>
31 + Send
32 + Sync
33 + Serialize
34 + for<'de> Deserialize<'de>
35{
36 /// A type representing an element of the base field of the group
37 type Base: PrimeField + PrimeFieldBits + Serialize + for<'de> Deserialize<'de>;
38
39 /// A type representing an element of the scalar field of the group
40 type Scalar: PrimeField
41 + PrimeFieldBits
42 + PrimeFieldExt
43 + ChallengeTrait<Self>
44 + Send
45 + Sync
46 + Serialize
47 + for<'de> Deserialize<'de>;
48
49 /// A type representing the compressed version of the group element
50 type CompressedGroupElement: CompressedGroup<GroupElement = Self>
51 + Serialize
52 + for<'de> Deserialize<'de>;
53
54 /// A type representing preprocessed group element
55 type PreprocessedGroupElement: Clone + Debug + Send + Sync + Serialize + for<'de> Deserialize<'de>;
56
57 /// A type that represents a circuit-friendly sponge that consumes elements
58 /// from the base field and squeezes out elements of the scalar field
59 type RO: ROTrait<Self::Base, Self::Scalar> + Serialize + for<'de> Deserialize<'de>;
60
61 /// An alternate implementation of Self::RO in the circuit model
62 type ROCircuit: ROCircuitTrait<Self::Base> + Serialize + for<'de> Deserialize<'de>;
63
64 /// A type that provides a generic Fiat-Shamir transcript to be used when externalizing proofs
65 type TE: TranscriptEngineTrait<Self>;
66
67 /// A type that defines a commitment engine over scalars in the group
68 type CE: CommitmentEngineTrait<Self> + Serialize + for<'de> Deserialize<'de>;
69
70 /// A method to compute a multiexponentation
71 fn vartime_multiscalar_mul(
72 scalars: &[Self::Scalar],
73 bases: &[Self::PreprocessedGroupElement],
74 ) -> Self;
75
76 /// Compresses the group element
77 fn compress(&self) -> Self::CompressedGroupElement;
78
79 /// Produces a preprocessed element
80 fn preprocessed(&self) -> Self::PreprocessedGroupElement;
81
82 /// Produce a vector of group elements using a static label
83 fn from_label(label: &'static [u8], n: usize) -> Vec<Self::PreprocessedGroupElement>;
84
85 /// Returns the affine coordinates (x, y, infinty) for the point
86 fn to_coordinates(&self) -> (Self::Base, Self::Base, bool);
87
88 /// Returns an element that is the additive identity of the group
89 fn zero() -> Self;
90
91 /// Returns the generator of the group
92 fn get_generator() -> Self;
93
94 /// Returns A, B, and the order of the group as a big integer
95 fn get_curve_params() -> (Self::Base, Self::Base, BigInt);
96}
97
98/// Represents a compressed version of a group element
99pub trait CompressedGroup:
100 Clone + Copy + Debug + Eq + Sized + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static
101{
102 /// A type that holds the decompressed version of the compressed group element
103 type GroupElement: Group + Serialize + for<'de> Deserialize<'de>;
104
105 /// Decompresses the compressed group element
106 fn decompress(&self) -> Option<Self::GroupElement>;
107
108 /// Returns a byte array representing the compressed group element
109 fn as_bytes(&self) -> Vec<u8>;
110}
111
112/// A helper trait to absorb different objects in RO
113pub trait AbsorbInROTrait<G: Group> {
114 /// Absorbs the value in the provided RO
115 fn absorb_in_ro(&self, ro: &mut G::RO);
116}
117
118/// A helper trait that defines the behavior of a hash function that we use as an RO
119pub trait ROTrait<Base, Scalar> {
120 /// A type representing constants/parameters associated with the hash function
121 type Constants: ROConstantsTrait<Base>
122 + Clone
123 + Send
124 + Sync
125 + Serialize
126 + for<'de> Deserialize<'de>;
127
128 /// Initializes the hash function
129 fn new(constants: Self::Constants, num_absorbs: usize) -> Self;
130
131 /// Adds a scalar to the internal state
132 fn absorb(&mut self, e: Base);
133
134 /// Returns a challenge of `num_bits` by hashing the internal state
135 fn squeeze(&mut self, num_bits: usize) -> Scalar;
136}
137
138/// A helper trait that defines the behavior of a hash function that we use as an RO in the circuit model
139pub trait ROCircuitTrait<Base: PrimeField> {
140 /// A type representing constants/parameters associated with the hash function
141 type Constants: ROConstantsTrait<Base>
142 + Clone
143 + Send
144 + Sync
145 + Serialize
146 + for<'de> Deserialize<'de>;
147
148 /// Initializes the hash function
149 fn new(constants: Self::Constants, num_absorbs: usize) -> Self;
150
151 /// Adds a scalar to the internal state
152 fn absorb(&mut self, e: AllocatedNum<Base>);
153
154 /// Returns a challenge of `num_bits` by hashing the internal state
155 fn squeeze<CS>(&mut self, cs: CS, num_bits: usize) -> Result<Vec<AllocatedBit>, SynthesisError>
156 where
157 CS: ConstraintSystem<Base>;
158}
159
160/// A helper trait that defines the constants associated with a hash function
161pub trait ROConstantsTrait<Base> {
162 /// produces constants/parameters associated with the hash function
163 fn new() -> Self;
164}
165
166/// An alias for constants associated with G::RO
167pub type ROConstants<G> =
168 <<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants;
169
170/// An alias for constants associated with G::ROCircuit
171pub type ROConstantsCircuit<G> =
172 <<G as Group>::ROCircuit as ROCircuitTrait<<G as Group>::Base>>::Constants;
173
174/// A helper trait for types with a group operation.
175pub trait GroupOps<Rhs = Self, Output = Self>:
176 Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
177{
178}
179
180impl<T, Rhs, Output> GroupOps<Rhs, Output> for T where
181 T: Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
182{
183}
184
185/// A helper trait for references with a group operation.
186pub trait GroupOpsOwned<Rhs = Self, Output = Self>: for<'r> GroupOps<&'r Rhs, Output> {}
187impl<T, Rhs, Output> GroupOpsOwned<Rhs, Output> for T where T: for<'r> GroupOps<&'r Rhs, Output> {}
188
189/// A helper trait for types implementing group scalar multiplication.
190pub trait ScalarMul<Rhs, Output = Self>: Mul<Rhs, Output = Output> + MulAssign<Rhs> {}
191
192impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Output> + MulAssign<Rhs>
193{}
194
195/// A helper trait for references implementing group scalar multiplication.
196pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
197impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
198
199/// This trait defines the behavior of a transcript engine compatible with Spartan
200pub trait TranscriptEngineTrait<G: Group>: Send + Sync {
201 /// initializes the transcript
202 fn new(label: &'static [u8]) -> Self;
203
204 /// returns a scalar element of the group as a challenge
205 fn squeeze_scalar(&mut self, label: &'static [u8]) -> Result<G::Scalar, NovaError>;
206
207 /// absorbs a label and a sequence of bytes
208 fn absorb_bytes(&mut self, label: &'static [u8], bytes: &[u8]);
209}
210
211/// A helper trait to append different types to the transcript
212pub trait AppendToTranscriptTrait<G: Group> {
213 /// appends the value to the transcript under the provided label
214 fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE);
215}
216
217/// A helper trait to generate challenges using a transcript object
218pub trait ChallengeTrait<G: Group> {
219 /// Returns a challenge from the transcript
220 fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result<Self, NovaError>
221 where
222 Self: Sized;
223}
224
225/// Defines additional methods on PrimeField objects
226pub trait PrimeFieldExt: PrimeField {
227 /// Returns a scalar representing the bytes
228 fn from_uniform(bytes: &[u8]) -> Self;
229
230 /// Returns a vector of bytes representing the scalar
231 fn to_bytes(&self) -> Vec<u8>;
232}
233
234impl<G: Group<Scalar = F>, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait<G> for F {
235 fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
236 transcript.absorb_bytes(label, &<Self as PrimeFieldExt>::to_bytes(self));
237 }
238}
239
240impl<G: Group<Scalar = F>, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait<G> for [F] {
241 fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
242 let bytes = (0..self.len())
243 .map(|i| <F as PrimeFieldExt>::to_bytes(&self[i]))
244 .collect::<Vec<_>>()
245 .into_iter()
246 .flatten()
247 .collect::<Vec<u8>>();
248 transcript.absorb_bytes(label, &bytes);
249 }
250}
251
252pub mod circuit;
253pub mod evaluation;
254pub mod snark;