Skip to main content

arcis_compiler/core/
actually_used_field.rs

1use crate::{
2    core::{
3        bounds::{Bounds, FieldBounds},
4        expressions::{
5            conversion_expr::ConversionExpr,
6            domain::Domain,
7            expr::{EvalValue, Expr},
8            field_expr::FieldExpr,
9            InputKind,
10        },
11    },
12    traits::{
13        FromF25519,
14        FromLeBits,
15        FromLeBytes,
16        GetBit,
17        MxeRescueKey,
18        MxeX25519PrivateKey,
19        Random,
20        Reveal,
21        WithBooleanBounds,
22    },
23    utils::{
24        crypto::key::{
25            MXE_RESCUE_BASE_FIELD_KEY,
26            MXE_RESCUE_SCALAR_FIELD_KEY,
27            MXE_X25519_PRIVATE_KEY,
28            RESCUE_KEY_COUNT,
29        },
30        field::{BaseField, ScalarField},
31        used_field::UsedField,
32    },
33};
34use ff::PrimeField;
35
36type Curve = primitives::algebra::elliptic_curve::Curve25519Ristretto;
37type Gate = core_utils::circuit::Gate<Curve>;
38
39/// A trait for actually used fields: fields which have Exprs.
40pub trait ActuallyUsedField: UsedField {
41    fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self>;
42    fn field_bounds_to_bounds(field: FieldBounds<Self>) -> Bounds;
43    fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T>;
44    fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T>;
45    fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>>;
46    fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>>;
47    fn eval_value_to_field(eval_value: EvalValue) -> Self;
48    fn field_to_eval_value(a: Self) -> EvalValue;
49    fn field_to_constant_gate(a: Self) -> Gate;
50    fn field_type() -> core_utils::circuit::FieldType;
51    fn algebraic_type() -> core_utils::circuit::AlgebraicType;
52    fn input(kind: InputKind) -> core_utils::circuit::Input;
53}
54
55impl ActuallyUsedField for ScalarField {
56    fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self> {
57        if let Bounds::Scalar(s) = b {
58            s
59        } else {
60            panic!("invalid bounds");
61        }
62    }
63    fn field_bounds_to_bounds(b: FieldBounds<Self>) -> Bounds {
64        Bounds::Scalar(b)
65    }
66    fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T> {
67        Expr::Scalar(expr)
68    }
69    fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T> {
70        Expr::ScalarConversion(expr)
71    }
72
73    fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>> {
74        if let Expr::Scalar(e) = expr {
75            Some(e)
76        } else {
77            None
78        }
79    }
80
81    fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>> {
82        if let Expr::ScalarConversion(e) = expr {
83            Some(e)
84        } else {
85            None
86        }
87    }
88    fn eval_value_to_field(eval_value: EvalValue) -> Self {
89        let EvalValue::Scalar(x) = eval_value else {
90            panic!("wrong inner type for eval_value")
91        };
92        x
93    }
94    fn field_to_eval_value(a: Self) -> EvalValue {
95        EvalValue::Scalar(a)
96    }
97
98    fn field_to_constant_gate(a: Self) -> Gate {
99        Gate::Constant(core_utils::circuit::Constant::Scalar(
100            primitives::algebra::elliptic_curve::Scalar::<Curve>::from_le_bytes(&a.to_le_bytes())
101                .expect("failed to convert"),
102        ))
103    }
104    fn field_type() -> core_utils::circuit::FieldType {
105        core_utils::circuit::FieldType::ScalarField
106    }
107
108    fn algebraic_type() -> core_utils::circuit::AlgebraicType {
109        core_utils::circuit::AlgebraicType::ScalarField
110    }
111    fn input(kind: InputKind) -> core_utils::circuit::Input {
112        let algebraic_type = Self::algebraic_type();
113        kind.to_input(algebraic_type)
114    }
115}
116
117impl ActuallyUsedField for BaseField {
118    fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self> {
119        BaseField::unwrap(b)
120    }
121
122    fn field_bounds_to_bounds(field: FieldBounds<Self>) -> Bounds {
123        BaseField::wrap(field)
124    }
125
126    fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T> {
127        Expr::Base(expr)
128    }
129
130    fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T> {
131        Expr::BaseConversion(expr)
132    }
133
134    fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>> {
135        if let Expr::Base(e) = expr {
136            Some(e)
137        } else {
138            None
139        }
140    }
141
142    fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>> {
143        if let Expr::BaseConversion(e) = expr {
144            Some(e)
145        } else {
146            None
147        }
148    }
149
150    fn eval_value_to_field(eval_value: EvalValue) -> Self {
151        BaseField::unwrap(eval_value)
152    }
153    fn field_to_eval_value(a: Self) -> EvalValue {
154        EvalValue::Base(a)
155    }
156    fn field_to_constant_gate(a: Self) -> Gate {
157        Gate::Constant(core_utils::circuit::Constant::BaseField(
158            primitives::algebra::elliptic_curve::curve::BaseFieldElement::<Curve>::from_le_bytes(
159                &a.to_le_bytes(),
160            )
161            .expect("failed to convert"),
162        ))
163    }
164    fn field_type() -> core_utils::circuit::FieldType {
165        core_utils::circuit::FieldType::BaseField
166    }
167
168    fn algebraic_type() -> core_utils::circuit::AlgebraicType {
169        core_utils::circuit::AlgebraicType::BaseField
170    }
171    fn input(kind: InputKind) -> core_utils::circuit::Input {
172        let algebraic_type = Self::algebraic_type();
173        match kind {
174            InputKind::Secret => core_utils::circuit::Input::Share {
175                algebraic_type,
176                batch_size: 1,
177            },
178            InputKind::SecretFromPlayer(i) => core_utils::circuit::Input::SecretPlaintext {
179                inputer: i,
180                algebraic_type,
181                batch_size: 1,
182            },
183            InputKind::Plaintext => core_utils::circuit::Input::Plaintext {
184                algebraic_type,
185                batch_size: 1,
186            },
187        }
188    }
189}
190
191impl<F: ActuallyUsedField> GetBit for F {
192    type Output = bool;
193
194    fn get_bit(&self, index: usize, signed: bool) -> Self::Output {
195        if signed {
196            self.signed_bit(index)
197        } else {
198            self.unsigned_bit(index)
199        }
200    }
201}
202
203impl<F: ActuallyUsedField> FromLeBits<bool> for F {
204    fn from_le_bits(bits: Vec<bool>, signed: bool) -> Self {
205        let n = bits.len();
206        bits.into_iter()
207            .enumerate()
208            .map(|(i, x)| {
209                if x {
210                    if signed && i + 1 == n {
211                        F::negative_power_of_two(i)
212                    } else {
213                        F::power_of_two(i)
214                    }
215                } else {
216                    F::ZERO
217                }
218            })
219            .sum()
220    }
221}
222
223impl FromF25519<BaseField> for BaseField {
224    fn from_F25519(value: BaseField) -> Vec<BaseField> {
225        vec![value]
226    }
227}
228
229impl FromF25519<BaseField> for ScalarField {
230    /// Injectively map a BaseField element into a Vec of ScalarField elements.
231    fn from_F25519(value: BaseField) -> Vec<ScalarField> {
232        let bytes = value.to_le_bytes();
233        // we chunk bytes by ScalarField::n_bytes - 1 and convert to ScalarField
234        let chunk_size = ScalarField::NUM_BITS.div_ceil(8) as usize - 1;
235        bytes
236            .chunks(chunk_size)
237            .map(|chunk| {
238                let mut chunk_bytes = [0u8; 32];
239                chunk_bytes[..chunk.len()].copy_from_slice(chunk);
240                ScalarField::from_le_bytes(chunk_bytes)
241            })
242            .collect::<Vec<ScalarField>>()
243    }
244}
245
246impl<F: ActuallyUsedField> Random for F {
247    fn random() -> Self {
248        let rng = &mut rand::thread_rng();
249        F::random(rng)
250    }
251}
252
253impl<F: ActuallyUsedField> Reveal for F {
254    fn reveal(self) -> Self {
255        self
256    }
257}
258
259impl<F: ActuallyUsedField> WithBooleanBounds for F {
260    fn with_boolean_bounds(&self) -> Self {
261        assert!(self.le(&F::from(1)));
262        *self
263    }
264}
265
266impl MxeX25519PrivateKey for ScalarField {
267    fn mxe_x25519_private_key() -> Self {
268        ScalarField::from_le_bytes(MXE_X25519_PRIVATE_KEY)
269    }
270}
271
272impl MxeRescueKey for BaseField {
273    fn mxe_rescue_key(i: usize) -> Self {
274        debug_assert!(i < RESCUE_KEY_COUNT);
275        BaseField::from_le_bytes(MXE_RESCUE_BASE_FIELD_KEY[i])
276    }
277}
278
279impl MxeRescueKey for ScalarField {
280    fn mxe_rescue_key(i: usize) -> Self {
281        debug_assert!(i < RESCUE_KEY_COUNT);
282        ScalarField::from_le_bytes(MXE_RESCUE_SCALAR_FIELD_KEY[i])
283    }
284}