Skip to main content

nova_snark/traits/
commitment.rs

1//! This module defines a collection of traits that define the behavior of a commitment engine
2//! We require the commitment engine to provide a commitment to vectors with a single group element
3use crate::errors::NovaError;
4#[cfg(feature = "io")]
5use crate::provider::ptau::PtauFileError;
6use crate::traits::{AbsorbInRO2Trait, AbsorbInROTrait, Engine, TranscriptReprTrait};
7use core::{
8  fmt::Debug,
9  ops::{Add, Mul, MulAssign, Range},
10};
11use num_integer::Integer;
12use num_traits::ToPrimitive;
13use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
14use serde::{Deserialize, Serialize};
15
16/// A helper trait for types implementing scalar multiplication.
17pub trait ScalarMul<Rhs, Output = Self>: Mul<Rhs, Output = Output> + MulAssign<Rhs> {}
18
19impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Output> + MulAssign<Rhs>
20{}
21
22/// This trait defines the behavior of the commitment
23pub trait CommitmentTrait<E: Engine>:
24  Clone
25  + Copy
26  + Debug
27  + Default
28  + PartialEq
29  + Eq
30  + Send
31  + Sync
32  + TranscriptReprTrait<E::GE>
33  + Serialize
34  + for<'de> Deserialize<'de>
35  + AbsorbInROTrait<E>
36  + AbsorbInRO2Trait<E>
37  + Add<Self, Output = Self>
38  + ScalarMul<E::Scalar>
39{
40  /// Returns the coordinate representation of the commitment
41  fn to_coordinates(&self) -> (E::Base, E::Base, bool);
42}
43
44/// A trait that helps determine the length of a structure.
45/// Note this does not impose any memory representation constraints on the structure.
46pub trait Len {
47  /// Returns the length of the structure.
48  fn length(&self) -> usize;
49}
50
51/// A trait that ties different pieces of the commitment generation together
52pub trait CommitmentEngineTrait<E: Engine>: Clone + Send + Sync {
53  /// Holds the type of the commitment key
54  /// The key should quantify its length in terms of group generators.
55  type CommitmentKey: Len + Clone + Debug + Send + Sync + Serialize + for<'de> Deserialize<'de>;
56
57  /// Holds the type of the derandomization key
58  type DerandKey: Clone + Debug + Send + Sync + Serialize + for<'de> Deserialize<'de>;
59
60  /// Holds the type of the commitment
61  type Commitment: CommitmentTrait<E>;
62
63  /// Load keys
64  #[cfg(feature = "io")]
65  fn load_setup(
66    reader: &mut (impl std::io::Read + std::io::Seek),
67    label: &'static [u8],
68    n: usize,
69  ) -> Result<Self::CommitmentKey, PtauFileError>;
70
71  /// Saves the key to the provided writer.
72  #[cfg(feature = "io")]
73  fn save_setup(
74    ck: &Self::CommitmentKey,
75    writer: &mut (impl std::io::Write + std::io::Seek),
76  ) -> Result<(), PtauFileError>;
77
78  /// Samples a new commitment key of a specified size.
79  ///
80  /// # Errors
81  ///
82  /// Returns an error if the setup cannot be performed (e.g., HyperKZG in production
83  /// builds without the `test-utils` feature).
84  fn setup(label: &'static [u8], n: usize)
85    -> Result<Self::CommitmentKey, crate::errors::NovaError>;
86
87  /// Extracts the blinding generator
88  fn derand_key(ck: &Self::CommitmentKey) -> Self::DerandKey;
89
90  /// Commits to the provided vector using the provided generators and random blind
91  fn commit(ck: &Self::CommitmentKey, v: &[E::Scalar], r: &E::Scalar) -> Self::Commitment;
92
93  /// Batch commits to the provided vectors using the provided generators and random blind
94  fn batch_commit(
95    ck: &Self::CommitmentKey,
96    v: &[Vec<E::Scalar>],
97    r: &[E::Scalar],
98  ) -> Vec<Self::Commitment> {
99    assert!(v.len() == r.len());
100    v.par_iter()
101      .zip(r.par_iter())
102      .map(|(v_i, r_i)| Self::commit(ck, v_i, r_i))
103      .collect()
104  }
105
106  /// Commits to the provided vector of sparse binary scalars using the provided generators and random blind
107  fn commit_sparse_binary(
108    ck: &Self::CommitmentKey,
109    non_zero_indices: &[usize],
110    r: &E::Scalar,
111  ) -> Self::Commitment;
112
113  /// Commits to the provided vector of "small" scalars (at most 64 bits) using the provided generators and random blind
114  fn commit_small<T: Integer + Into<u64> + Copy + Sync + ToPrimitive>(
115    ck: &Self::CommitmentKey,
116    v: &[T],
117    r: &E::Scalar,
118  ) -> Self::Commitment;
119
120  /// Commits to the provided vector of "small" scalars (at most 64 bits) using the provided generators and random blind (range)
121  fn commit_small_range<T: Integer + Into<u64> + Copy + Sync + ToPrimitive>(
122    ck: &Self::CommitmentKey,
123    v: &[T],
124    r: &E::Scalar,
125    range: Range<usize>,
126    max_num_bits: usize,
127  ) -> Self::Commitment;
128
129  /// Batch commits to the provided vectors of "small" scalars (at most 64 bits) using the provided generators and random blind
130  fn batch_commit_small<T: Integer + Into<u64> + Copy + Sync + ToPrimitive>(
131    ck: &Self::CommitmentKey,
132    v: &[Vec<T>],
133    r: &[E::Scalar],
134  ) -> Vec<Self::Commitment> {
135    assert!(v.len() == r.len());
136    v.par_iter()
137      .zip(r.par_iter())
138      .map(|(v_i, r_i)| Self::commit_small(ck, v_i, r_i))
139      .collect()
140  }
141
142  /// Remove given blind from commitment
143  fn derandomize(
144    dk: &Self::DerandKey,
145    commit: &Self::Commitment,
146    r: &E::Scalar,
147  ) -> Self::Commitment;
148
149  /// Returns the coordinates of each generator in the commitment key.
150  ///
151  /// This method extracts the (x, y) coordinates of each generator point
152  /// in the commitment key. This is useful for operations that need direct
153  /// access to the underlying elliptic curve points, such as in-circuit
154  /// verification of polynomial evaluations.
155  ///
156  /// # Panics
157  ///
158  /// Panics if any generator point is the point at infinity.
159  fn ck_to_coordinates(ck: &Self::CommitmentKey) -> Vec<(E::Base, E::Base)>;
160
161  /// Returns the generators as projective group elements.
162  ///
163  /// This provides full group-operation access (add, double, scalar mul)
164  /// on the commitment key generators, useful for precomputing correction
165  /// points in circuit optimizations.
166  fn ck_to_group_elements(ck: &Self::CommitmentKey) -> Vec<E::GE>;
167
168  /// Derive a commitment key of length `table_size` whose j-th generator is
169  /// `sum_{i : addresses[i] == j} ck[i]`.
170  ///
171  /// For a lookup polynomial `L[i] = T[addresses[i]]`:
172  ///   `Comm(L, ck) = Comm(T, ck_derived)`
173  ///
174  /// Table indices with no matching address get the identity generator.
175  /// The returned key must only be used with `commit()` (not with
176  /// `ck_to_coordinates`/`ck_to_group_elements`, which reject identity).
177  ///
178  /// # Errors
179  /// Returns `InvalidCommitmentKeyLength` if `addresses.len() != ck.len()`,
180  /// or `InvalidIndex` if any address is `>= table_size`.
181  fn ck_derive_by_address(
182    ck: &Self::CommitmentKey,
183    addresses: &[usize],
184    table_size: usize,
185  ) -> Result<Self::CommitmentKey, NovaError>;
186}