Skip to content

Commit 5a5df66

Browse files
authored
Add Neg and Sub imples for ScalarVar, GroupVar, and Term (#50)
1 parent 01c1a79 commit 5a5df66

File tree

3 files changed

+619
-110
lines changed

3 files changed

+619
-110
lines changed

src/errors.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
//! - Mismatched parameters during batch verification.
99
//! - Uninitialized group variables.
1010
11-
use crate::linear_relation::GroupVar;
12-
1311
/// An error during proving or verification, such as a verification failure.
1412
#[non_exhaustive]
1513
#[derive(Debug, thiserror::Error)]
@@ -21,6 +19,6 @@ pub enum Error {
2119
#[error("Mismatched parameter sizes for batch verification.")]
2220
ProofSizeMismatch,
2321
/// Uninitialized group element variable.
24-
#[error("Uninitialized group element variable {var:?}")]
25-
UnassignedGroupVar { var: GroupVar },
22+
#[error("Uninitialized group element variable: {var_debug}")]
23+
UnassignedGroupVar { var_debug: String },
2624
}

src/linear_relation/mod.rs

Lines changed: 52 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
1111
use std::collections::BTreeMap;
1212
use std::iter;
13+
use std::marker::PhantomData;
1314

1415
use ff::Field;
1516
use group::{Group, GroupEncoding};
@@ -27,9 +28,9 @@ mod ops;
2728
///
2829
/// Used to reference scalars in sparse linear combinations.
2930
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
30-
pub struct ScalarVar(usize);
31+
pub struct ScalarVar<G>(usize, PhantomData<G>);
3132

32-
impl ScalarVar {
33+
impl<G> ScalarVar<G> {
3334
pub fn index(&self) -> usize {
3435
self.0
3536
}
@@ -39,34 +40,33 @@ impl ScalarVar {
3940
///
4041
/// Used to reference group elements in sparse linear combinations.
4142
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
42-
pub struct GroupVar(usize);
43+
pub struct GroupVar<G>(usize, PhantomData<G>);
4344

44-
impl GroupVar {
45+
impl<G> GroupVar<G> {
4546
pub fn index(&self) -> usize {
4647
self.0
4748
}
4849
}
4950

5051
/// A term in a linear combination, representing `scalar * elem`.
51-
#[derive(Copy, Clone, Debug)]
52-
pub struct Term {
53-
scalar: ScalarVar,
54-
elem: GroupVar,
52+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
53+
pub struct Term<G> {
54+
scalar: ScalarVar<G>,
55+
elem: GroupVar<G>,
5556
}
5657

57-
impl From<(ScalarVar, GroupVar)> for Term {
58-
fn from((scalar, elem): (ScalarVar, GroupVar)) -> Self {
58+
impl<G> From<(ScalarVar<G>, GroupVar<G>)> for Term<G> {
59+
fn from((scalar, elem): (ScalarVar<G>, GroupVar<G>)) -> Self {
5960
Self { scalar, elem }
6061
}
6162
}
6263

63-
impl<F: Field> From<(ScalarVar, GroupVar)> for Weighted<Term, F> {
64-
fn from(pair: (ScalarVar, GroupVar)) -> Self {
64+
impl<G: Group> From<(ScalarVar<G>, GroupVar<G>)> for Weighted<Term<G>, G::Scalar> {
65+
fn from(pair: (ScalarVar<G>, GroupVar<G>)) -> Self {
6566
Term::from(pair).into()
6667
}
6768
}
6869

69-
// TODO: Should this be generic over the field instead of the group?
7070
#[derive(Copy, Clone, Debug)]
7171
pub struct Weighted<T, F> {
7272
pub term: T,
@@ -97,49 +97,25 @@ impl<T> Sum<T> {
9797
macro_rules! impl_from_for_sum {
9898
($($type:ty),+) => {
9999
$(
100-
impl<T: Into<$type>> From<T> for Sum<$type> {
101-
fn from(value: T) -> Self {
102-
Sum(vec![value.into()])
103-
}
104-
}
105-
106-
impl<T: Into<$type>> From<Vec<T>> for Sum<$type> {
107-
fn from(terms: Vec<T>) -> Self {
108-
Self::from_iter(terms)
109-
}
110-
}
111-
112-
impl<T: Into<$type>, const N: usize> From<[T; N]> for Sum<$type> {
113-
fn from(terms: [T; N]) -> Self {
114-
Self::from_iter(terms)
115-
}
116-
}
117-
118-
impl<T: Into<$type>> FromIterator<T> for Sum<$type> {
119-
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
120-
Self(iter.into_iter().map(|x| x.into()).collect())
121-
}
122-
}
123-
124-
impl<F, T: Into<Weighted<$type, F>>> From<T> for Sum<Weighted<$type, F>> {
100+
impl<G: Group, T: Into<$type>> From<T> for Sum<$type> {
125101
fn from(value: T) -> Self {
126102
Sum(vec![value.into()])
127103
}
128104
}
129105

130-
impl<F, T: Into<Weighted<$type, F>>> From<Vec<T>> for Sum<Weighted<$type, F>> {
106+
impl<G: Group, T: Into<$type>> From<Vec<T>> for Sum<$type> {
131107
fn from(terms: Vec<T>) -> Self {
132108
Self::from_iter(terms)
133109
}
134110
}
135111

136-
impl<F, T: Into<Weighted<$type, F>>, const N: usize> From<[T; N]> for Sum<Weighted<$type, F>> {
112+
impl<G: Group, T: Into<$type>, const N: usize> From<[T; N]> for Sum<$type> {
137113
fn from(terms: [T; N]) -> Self {
138114
Self::from_iter(terms)
139115
}
140116
}
141117

142-
impl<F, T: Into<Weighted<$type, F>>> FromIterator<T> for Sum<Weighted<$type, F>> {
118+
impl<G: Group, T: Into<$type>> FromIterator<T> for Sum<$type> {
143119
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
144120
Self(iter.into_iter().map(|x| x.into()).collect())
145121
}
@@ -148,7 +124,14 @@ macro_rules! impl_from_for_sum {
148124
};
149125
}
150126

151-
impl_from_for_sum!(ScalarVar, GroupVar, Term);
127+
impl_from_for_sum!(
128+
ScalarVar<G>,
129+
GroupVar<G>,
130+
Term<G>,
131+
Weighted<ScalarVar<G>, G::Scalar>,
132+
Weighted<GroupVar<G>, G::Scalar>,
133+
Weighted<Term<G>, G::Scalar>
134+
);
152135

153136
impl<T, F: Field> From<Sum<T>> for Sum<Weighted<T, F>> {
154137
fn from(sum: Sum<T>) -> Self {
@@ -164,7 +147,7 @@ impl<T, F: Field> From<Sum<T>> for Sum<Weighted<T, F>> {
164147
/// where `s_i` are scalars (referenced by `scalar_vars`) and `P_i` are group elements (referenced by `element_vars`).
165148
///
166149
/// The indices refer to external lists managed by the containing LinearMap.
167-
pub type LinearCombination<G> = Sum<Weighted<Term, <G as Group>::Scalar>>;
150+
pub type LinearCombination<G> = Sum<Weighted<Term<G>, <G as Group>::Scalar>>;
168151

169152
/// Ordered mapping of [GroupVar] to group elements assignments.
170153
#[derive(Clone, Debug)]
@@ -181,7 +164,7 @@ impl<G: Group> GroupMap<G> {
181164
/// # Panics
182165
///
183166
/// Panics if the given assignment conflicts with the existing assignment.
184-
pub fn assign_element(&mut self, var: GroupVar, element: G) {
167+
pub fn assign_element(&mut self, var: GroupVar<G>, element: G) {
185168
if self.0.len() <= var.0 {
186169
self.0.resize(var.0 + 1, None);
187170
} else if let Some(assignment) = self.0[var.0] {
@@ -202,7 +185,7 @@ impl<G: Group> GroupMap<G> {
202185
/// # Panics
203186
///
204187
/// Panics if the collection contains two conflicting assignments for the same variable.
205-
pub fn assign_elements(&mut self, assignments: impl IntoIterator<Item = (GroupVar, G)>) {
188+
pub fn assign_elements(&mut self, assignments: impl IntoIterator<Item = (GroupVar<G>, G)>) {
206189
for (var, elem) in assignments.into_iter() {
207190
self.assign_element(var, elem);
208191
}
@@ -211,26 +194,28 @@ impl<G: Group> GroupMap<G> {
211194
/// Get the element value assigned to the given point var.
212195
///
213196
/// Returns [`Error::UnassignedGroupVar`] if a value is not assigned.
214-
pub fn get(&self, var: GroupVar) -> Result<G, Error> {
215-
self.0[var.0].ok_or(Error::UnassignedGroupVar { var })
197+
pub fn get(&self, var: GroupVar<G>) -> Result<G, Error> {
198+
self.0[var.0].ok_or(Error::UnassignedGroupVar {
199+
var_debug: format!("{var:?}"),
200+
})
216201
}
217202

218203
/// Iterate over the assigned variable and group element pairs in this mapping.
219204
// NOTE: Not implemented as `IntoIterator` for now because doing so requires explicitly
220205
// defining an iterator type, See https://github.com/rust-lang/rust/issues/63063
221206
#[allow(clippy::should_implement_trait)]
222-
pub fn into_iter(self) -> impl Iterator<Item = (GroupVar, Option<G>)> {
207+
pub fn into_iter(self) -> impl Iterator<Item = (GroupVar<G>, Option<G>)> {
223208
self.0
224209
.into_iter()
225210
.enumerate()
226-
.map(|(i, x)| (GroupVar(i), x))
211+
.map(|(i, x)| (GroupVar(i, PhantomData), x))
227212
}
228213

229-
pub fn iter(&self) -> impl Iterator<Item = (GroupVar, Option<&G>)> {
214+
pub fn iter(&self) -> impl Iterator<Item = (GroupVar<G>, Option<&G>)> {
230215
self.0
231216
.iter()
232217
.enumerate()
233-
.map(|(i, opt)| (GroupVar(i), opt.as_ref()))
218+
.map(|(i, opt)| (GroupVar(i, PhantomData), opt.as_ref()))
234219
}
235220
}
236221

@@ -240,8 +225,8 @@ impl<G> Default for GroupMap<G> {
240225
}
241226
}
242227

243-
impl<G: Group> FromIterator<(GroupVar, G)> for GroupMap<G> {
244-
fn from_iter<T: IntoIterator<Item = (GroupVar, G)>>(iter: T) -> Self {
228+
impl<G: Group> FromIterator<(GroupVar<G>, G)> for GroupMap<G> {
229+
fn from_iter<T: IntoIterator<Item = (GroupVar<G>, G)>>(iter: T) -> Self {
245230
iter.into_iter()
246231
.fold(Self::default(), |mut instance, (var, val)| {
247232
instance.assign_element(var, val);
@@ -361,7 +346,7 @@ where
361346
/// The underlying linear map describing the structure of the statement.
362347
pub linear_map: LinearMap<G>,
363348
/// Indices pointing to elements representing the "target" images for each constraint.
364-
pub image: Vec<GroupVar>,
349+
pub image: Vec<GroupVar<G>>,
365350
}
366351

367352
impl<G> LinearRelation<G>
@@ -388,7 +373,7 @@ where
388373
/// # Parameters
389374
/// - `lhs`: The image group element variable (left-hand side of the equation).
390375
/// - `rhs`: A slice of `(ScalarVar, GroupVar)` pairs representing the linear combination on the right-hand side.
391-
pub fn append_equation(&mut self, lhs: GroupVar, rhs: impl Into<LinearCombination<G>>) {
376+
pub fn append_equation(&mut self, lhs: GroupVar<G>, rhs: impl Into<LinearCombination<G>>) {
392377
self.linear_map.append(rhs.into());
393378
self.image.push(lhs);
394379
}
@@ -399,16 +384,16 @@ where
399384
/// # Parameters
400385
/// - `lhs`: The image group element variable (left-hand side of the equation).
401386
/// - `rhs`: A slice of `(ScalarVar, GroupVar)` pairs representing the linear combination on the right-hand side.
402-
pub fn allocate_eq(&mut self, rhs: impl Into<LinearCombination<G>>) -> GroupVar {
387+
pub fn allocate_eq(&mut self, rhs: impl Into<LinearCombination<G>>) -> GroupVar<G> {
403388
let var = self.allocate_element();
404389
self.append_equation(var, rhs);
405390
var
406391
}
407392

408393
/// Allocates a scalar variable for use in the morphism.
409-
pub fn allocate_scalar(&mut self) -> ScalarVar {
394+
pub fn allocate_scalar(&mut self) -> ScalarVar<G> {
410395
self.linear_map.num_scalars += 1;
411-
ScalarVar(self.linear_map.num_scalars - 1)
396+
ScalarVar(self.linear_map.num_scalars - 1, PhantomData)
412397
}
413398

414399
/// Allocates space for `N` new scalar variables.
@@ -425,18 +410,18 @@ where
425410
/// let [var_x, var_y] = morphism.allocate_scalars();
426411
/// let vars = morphism.allocate_scalars::<10>();
427412
/// ```
428-
pub fn allocate_scalars<const N: usize>(&mut self) -> [ScalarVar; N] {
429-
let mut vars = [ScalarVar(usize::MAX); N];
413+
pub fn allocate_scalars<const N: usize>(&mut self) -> [ScalarVar<G>; N] {
414+
let mut vars = [ScalarVar(usize::MAX, PhantomData); N];
430415
for var in vars.iter_mut() {
431416
*var = self.allocate_scalar();
432417
}
433418
vars
434419
}
435420

436421
/// Allocates a point variable (group element) for use in the morphism.
437-
pub fn allocate_element(&mut self) -> GroupVar {
422+
pub fn allocate_element(&mut self) -> GroupVar<G> {
438423
self.linear_map.num_elements += 1;
439-
GroupVar(self.linear_map.num_elements - 1)
424+
GroupVar(self.linear_map.num_elements - 1, PhantomData)
440425
}
441426

442427
/// Allocates `N` point variables (group elements) for use in the morphism.
@@ -453,8 +438,8 @@ where
453438
/// let [var_g, var_h] = morphism.allocate_elements();
454439
/// let vars = morphism.allocate_elements::<10>();
455440
/// ```
456-
pub fn allocate_elements<const N: usize>(&mut self) -> [GroupVar; N] {
457-
let mut vars = [GroupVar(usize::MAX); N];
441+
pub fn allocate_elements<const N: usize>(&mut self) -> [GroupVar<G>; N] {
442+
let mut vars = [GroupVar(usize::MAX, PhantomData); N];
458443
for var in vars.iter_mut() {
459444
*var = self.allocate_element();
460445
}
@@ -471,7 +456,7 @@ where
471456
/// # Panics
472457
///
473458
/// Panics if the given assignment conflicts with the existing assignment.
474-
pub fn set_element(&mut self, var: GroupVar, element: G) {
459+
pub fn set_element(&mut self, var: GroupVar<G>, element: G) {
475460
self.linear_map.group_elements.assign_element(var, element)
476461
}
477462

@@ -484,7 +469,7 @@ where
484469
/// # Panics
485470
///
486471
/// Panics if the collection contains two conflicting assignments for the same variable.
487-
pub fn set_elements(&mut self, assignments: impl IntoIterator<Item = (GroupVar, G)>) {
472+
pub fn set_elements(&mut self, assignments: impl IntoIterator<Item = (GroupVar<G>, G)>) {
488473
self.linear_map.group_elements.assign_elements(assignments)
489474
}
490475

@@ -606,7 +591,7 @@ where
606591
// implement Hash or Ord.
607592
let mut remapping = BTreeMap::<usize, Vec<(G::Scalar, u32)>>::new();
608593
let mut group_var_remap_index = 0u32;
609-
let mut remap_var = |var: GroupVar, weight: G::Scalar| -> u32 {
594+
let mut remap_var = |var: GroupVar<G>, weight: G::Scalar| -> u32 {
610595
let entry = remapping.entry(var.0).or_default();
611596

612597
// If the (weight, group_var) pair has already been assigned an index, use it.

0 commit comments

Comments
 (0)