Skip to main content

sonobe_fs/definitions/
utils.rs

1//! Utility types shared across folding scheme definitions.
2
3use ark_ff::{Field, PrimeField};
4use ark_r1cs_std::{
5    GR1CSVar,
6    alloc::{AllocVar, AllocationMode},
7    fields::fp::FpVar,
8    prelude::Boolean,
9    select::CondSelectGadget,
10};
11use ark_relations::gr1cs::{ConstraintSystemRef, Namespace, SynthesisError};
12use ark_std::{
13    borrow::Borrow,
14    ops::{Deref, DerefMut},
15    slice::Iter,
16    vec::IntoIter,
17};
18use rayon::{
19    iter::{IntoParallelIterator, IntoParallelRefIterator},
20    slice::Iter as RayonIter,
21    vec::IntoIter as RayonIntoIter,
22};
23use sonobe_primitives::transcripts::{Absorbable, AbsorbableVar};
24
25/// [`TaggedVec`] is a wrapper around a vector that additionally carries a
26/// compile-time `char` tag.
27///
28/// This is used to create nominally distinct vector types that are structurally
29/// identical.
30#[derive(Clone, Debug, Default, PartialEq, Eq)]
31pub struct TaggedVec<V, const TAG: char>(pub Vec<V>);
32
33impl<V, const TAG: char> Deref for TaggedVec<V, TAG> {
34    type Target = Vec<V>;
35
36    fn deref(&self) -> &Self::Target {
37        &self.0
38    }
39}
40
41impl<V, const TAG: char> DerefMut for TaggedVec<V, TAG> {
42    fn deref_mut(&mut self) -> &mut Self::Target {
43        &mut self.0
44    }
45}
46
47impl<V, const TAG: char> From<Vec<V>> for TaggedVec<V, TAG> {
48    fn from(v: Vec<V>) -> Self {
49        Self(v)
50    }
51}
52
53impl<V, const TAG: char> IntoIterator for TaggedVec<V, TAG> {
54    type Item = V;
55    type IntoIter = IntoIter<V>;
56
57    fn into_iter(self) -> Self::IntoIter {
58        self.0.into_iter()
59    }
60}
61
62impl<'a, V, const TAG: char> IntoIterator for &'a TaggedVec<V, TAG> {
63    type Item = &'a V;
64    type IntoIter = Iter<'a, V>;
65
66    fn into_iter(self) -> Self::IntoIter {
67        self.0.iter()
68    }
69}
70
71impl<V: Send, const TAG: char> IntoParallelIterator for TaggedVec<V, TAG> {
72    type Item = V;
73
74    type Iter = RayonIntoIter<V>;
75
76    fn into_par_iter(self) -> Self::Iter {
77        self.0.into_par_iter()
78    }
79}
80
81impl<'a, V: Sync, const TAG: char> IntoParallelIterator for &'a TaggedVec<V, TAG> {
82    type Iter = RayonIter<'a, V>;
83
84    type Item = &'a V;
85
86    fn into_par_iter(self) -> Self::Iter {
87        self.0.par_iter()
88    }
89}
90
91impl<V, const TAG: char> From<TaggedVec<V, TAG>> for Vec<V> {
92    fn from(val: TaggedVec<V, TAG>) -> Self {
93        val.0
94    }
95}
96
97impl<V: Absorbable, const TAG: char> Absorbable for TaggedVec<V, TAG> {
98    fn absorb_into<F: PrimeField>(&self, dest: &mut Vec<F>) {
99        self.0.absorb_into(dest)
100    }
101}
102
103impl<F: PrimeField, V: AbsorbableVar<F>, const TAG: char> AbsorbableVar<F> for TaggedVec<V, TAG> {
104    fn absorb_into(&self, dest: &mut Vec<FpVar<F>>) -> Result<(), SynthesisError> {
105        self.0.absorb_into(dest)
106    }
107}
108
109impl<F: Field, X: AllocVar<Y, F>, Y, const TAG: char> AllocVar<TaggedVec<Y, TAG>, F>
110    for TaggedVec<X, TAG>
111{
112    fn new_variable<T: Borrow<TaggedVec<Y, TAG>>>(
113        cs: impl Into<Namespace<F>>,
114        f: impl FnOnce() -> Result<T, SynthesisError>,
115        mode: AllocationMode,
116    ) -> Result<Self, SynthesisError> {
117        let v = f()?;
118        Vec::new_variable(cs, || Ok(&v.borrow()[..]), mode).map(Self)
119    }
120}
121
122impl<F: PrimeField, X: CondSelectGadget<F>, const TAG: char> CondSelectGadget<F>
123    for TaggedVec<X, TAG>
124{
125    fn conditionally_select(
126        cond: &Boolean<F>,
127        true_value: &Self,
128        false_value: &Self,
129    ) -> Result<Self, SynthesisError> {
130        if true_value.len() != false_value.len() {
131            return Err(SynthesisError::Unsatisfiable);
132        }
133        true_value
134            .iter()
135            .zip(false_value.iter())
136            .map(|(t, f)| cond.select(t, f))
137            .collect::<Result<_, _>>()
138            .map(Self)
139    }
140}
141
142impl<F: Field, V: GR1CSVar<F>, const TAG: char> GR1CSVar<F> for TaggedVec<V, TAG> {
143    type Value = TaggedVec<V::Value, TAG>;
144
145    fn cs(&self) -> ConstraintSystemRef<F> {
146        self.0.cs()
147    }
148
149    fn value(&self) -> Result<Self::Value, SynthesisError> {
150        self.0.value().map(TaggedVec)
151    }
152}