Skip to main content

nova_snark/traits/
mod.rs

1//! This module defines various traits required by the users of the library to implement.
2use crate::{
3  errors::NovaError,
4  frontend::{num::AllocatedNum, AllocatedBit, ConstraintSystem, SynthesisError},
5};
6use core::fmt::Debug;
7use ff::{PrimeField, PrimeFieldBits};
8use num_bigint::BigInt;
9use serde::{Deserialize, Serialize};
10
11pub mod commitment;
12pub mod evm_serde;
13pub use evm_serde::CustomSerdeTrait;
14
15use commitment::CommitmentEngineTrait;
16
17/// Represents an element of a group
18/// This is currently tailored for an elliptic curve group
19pub trait Group: Clone + Copy + Debug + Send + Sync + Sized + Eq + PartialEq {
20  /// A type representing an element of the base field of the group
21  type Base: PrimeFieldBits + Serialize + for<'de> Deserialize<'de>;
22
23  /// A type representing an element of the scalar field of the group
24  type Scalar: PrimeFieldBits + PrimeFieldExt + Send + Sync + Serialize + for<'de> Deserialize<'de>;
25
26  /// Returns A, B, the order of the group, the size of the base field as big integers
27  fn group_params() -> (Self::Base, Self::Base, BigInt, BigInt);
28}
29
30/// A collection of engines that are required by the library
31pub trait Engine: Clone + Copy + Debug + Send + Sync + Sized + Eq + PartialEq {
32  /// A type representing an element of the base field of the group
33  type Base: PrimeFieldBits
34    + TranscriptReprTrait<Self::GE>
35    + Serialize
36    + for<'de> Deserialize<'de>
37    + CustomSerdeTrait;
38
39  /// A type representing an element of the scalar field of the group
40  type Scalar: PrimeFieldBits
41    + PrimeFieldExt
42    + Send
43    + Sync
44    + TranscriptReprTrait<Self::GE>
45    + Serialize
46    + for<'de> Deserialize<'de>
47    + CustomSerdeTrait;
48
49  /// A type that represents an element of the group
50  type GE: Group<Base = Self::Base, Scalar = Self::Scalar>
51    + Serialize
52    + for<'de> Deserialize<'de>
53    + CustomSerdeTrait;
54
55  /// A type that represents a circuit-friendly sponge that consumes
56  /// elements from the base field
57  type RO: ROTrait<Self::Base>;
58
59  /// An alternate implementation of `Self::RO` in the circuit model
60  type ROCircuit: ROCircuitTrait<Self::Base>;
61
62  /// A type that represents a circuit-friendly sponge that consumes
63  /// elements from the scalar field
64  type RO2: ROTrait<Self::Scalar>;
65
66  /// An alternate implementation of `Self::RO2` in the circuit model
67  type RO2Circuit: ROCircuitTrait<Self::Scalar>;
68
69  /// A type that provides a generic Fiat-Shamir transcript to be used when externalizing proofs
70  type TE: TranscriptEngineTrait<Self>;
71
72  /// A type that defines a commitment engine over scalars in the group
73  type CE: CommitmentEngineTrait<Self>;
74}
75
76/// A helper trait to absorb different objects in RO
77pub trait AbsorbInROTrait<E: Engine> {
78  /// Absorbs the value in the provided RO
79  fn absorb_in_ro(&self, ro: &mut E::RO);
80}
81
82/// A helper trait to absorb different objects in RO2
83pub trait AbsorbInRO2Trait<E: Engine> {
84  /// Absorbs the value in the provided RO2
85  fn absorb_in_ro2(&self, ro: &mut E::RO2);
86}
87
88/// A helper trait that defines the behavior of a hash function that we use as an RO
89pub trait ROTrait<Base: PrimeField> {
90  /// The circuit alter ego of this trait impl - this constrains it to use the same constants
91  type CircuitRO: ROCircuitTrait<Base, Constants = Self::Constants>;
92
93  /// A type representing constants/parameters associated with the hash function
94  type Constants: Default + Clone + Send + Sync + Serialize + for<'de> Deserialize<'de>;
95
96  /// Initializes the hash function
97  fn new(constants: Self::Constants) -> Self;
98
99  /// Adds a scalar to the internal state
100  fn absorb(&mut self, e: Base);
101
102  /// Returns a challenge of `num_bits` by hashing the internal state
103  /// If `start_with_one` is true, force bit (num_bits-1) (the MSB) to 1.
104  fn squeeze(&mut self, num_bits: usize, start_with_one: bool) -> Base;
105}
106
107/// A helper trait that defines the behavior of a hash function that we use as an RO in the circuit model
108pub trait ROCircuitTrait<Base: PrimeField> {
109  /// the vanilla alter ego of this trait - this constrains it to use the same constants
110  type NativeRO: ROTrait<Base, Constants = Self::Constants>;
111
112  /// A type representing constants/parameters associated with the hash function on this Base field
113  type Constants: Default + Clone + Send + Sync + Serialize + for<'de> Deserialize<'de>;
114
115  /// Initializes the hash function
116  fn new(constants: Self::Constants) -> Self;
117
118  /// Adds a scalar to the internal state
119  fn absorb(&mut self, e: &AllocatedNum<Base>);
120
121  /// Returns a challenge of `num_bits` by hashing the internal state
122  /// The `squeeze` method can be called only once
123  /// If `start_with_one` is true, force bit (num_bits-1) (the MSB) to 1.
124  fn squeeze<CS: ConstraintSystem<Base>>(
125    &mut self,
126    cs: CS,
127    num_bits: usize,
128    start_with_one: bool,
129  ) -> Result<Vec<AllocatedBit>, SynthesisError>;
130
131  /// Returns the hash as a scalar element by hashing the internal state
132  /// This is more efficient than squeeze when the scalar is needed directly
133  fn squeeze_scalar<CS: ConstraintSystem<Base>>(
134    &mut self,
135    cs: CS,
136  ) -> Result<AllocatedNum<Base>, SynthesisError>;
137}
138
139/// An alias for constants associated with E::RO
140pub type ROConstants<E> = <<E as Engine>::RO as ROTrait<<E as Engine>::Base>>::Constants;
141
142/// An alias for constants associated with `E::ROCircuit`
143pub type ROConstantsCircuit<E> =
144  <<E as Engine>::ROCircuit as ROCircuitTrait<<E as Engine>::Base>>::Constants;
145
146/// An alias for constants associated with E::RO2
147pub type RO2Constants<E> = <<E as Engine>::RO2 as ROTrait<<E as Engine>::Scalar>>::Constants;
148
149/// An alias for constants associated with `E::RO2Circuit`
150pub type RO2ConstantsCircuit<E> =
151  <<E as Engine>::RO2Circuit as ROCircuitTrait<<E as Engine>::Scalar>>::Constants;
152
153/// This trait allows types to implement how they want to be added to `TranscriptEngine`
154pub trait TranscriptReprTrait<G: Group>: Send + Sync {
155  /// returns a byte representation of self to be added to the transcript
156  fn to_transcript_bytes(&self) -> Vec<u8>;
157}
158
159/// This trait defines the behavior of a transcript engine compatible with Spartan
160pub trait TranscriptEngineTrait<E: Engine>: Send + Sync {
161  /// initializes the transcript
162  fn new(label: &'static [u8]) -> Self;
163
164  /// returns a scalar element of the group as a challenge
165  fn squeeze(&mut self, label: &'static [u8]) -> Result<E::Scalar, NovaError>;
166
167  /// Returns a challenge truncated to `num_bits` bits.
168  ///
169  /// If `start_with_one` is true, bit `num_bits - 1` (the MSB of the
170  /// truncated value) is forced to 1, so the result lies in
171  /// `[2^{num_bits-1}, 2^{num_bits} - 1]`.
172  ///
173  /// `num_bits` must be at most `E::Scalar::NUM_BITS - 1` to ensure the
174  /// result is always a valid field element even after setting the MSB.
175  fn squeeze_bits(
176    &mut self,
177    label: &'static [u8],
178    num_bits: usize,
179    start_with_one: bool,
180  ) -> Result<E::Scalar, NovaError>;
181
182  /// absorbs any type that implements `TranscriptReprTrait` under a label
183  fn absorb<T: TranscriptReprTrait<E::GE>>(&mut self, label: &'static [u8], o: &T);
184
185  /// adds a domain separator
186  fn dom_sep(&mut self, bytes: &'static [u8]);
187}
188
189/// Defines additional methods on `PrimeField` objects
190pub trait PrimeFieldExt: PrimeField {
191  /// Returns a scalar representing the bytes
192  fn from_uniform(bytes: &[u8]) -> Self;
193}
194
195impl<G: Group, T: TranscriptReprTrait<G>> TranscriptReprTrait<G> for &[T] {
196  fn to_transcript_bytes(&self) -> Vec<u8> {
197    self
198      .iter()
199      .flat_map(|t| t.to_transcript_bytes())
200      .collect::<Vec<u8>>()
201  }
202}
203
204pub mod circuit;
205pub mod evaluation;
206pub mod snark;