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<Curve>;
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::Input {
100            input_type: core_utils::circuit::Input::Scalar(core_utils::circuit::ScalarPlaintext::<
101                Curve,
102            >::Fixed(
103                primitives::algebra::elliptic_curve::Scalar::<Curve>::from_le_bytes(
104                    &a.to_le_bytes(),
105                )
106                .expect("failed to convert"),
107            )),
108        }
109    }
110    fn field_type() -> core_utils::circuit::FieldType {
111        core_utils::circuit::FieldType::ScalarField
112    }
113
114    fn algebraic_type() -> core_utils::circuit::AlgebraicType {
115        core_utils::circuit::AlgebraicType::ScalarField
116    }
117    fn input(kind: InputKind) -> core_utils::circuit::Input<Curve> {
118        let algebraic_type = Self::algebraic_type();
119        kind.to_input(algebraic_type)
120    }
121}
122
123impl ActuallyUsedField for BaseField {
124    fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self> {
125        BaseField::unwrap(b)
126    }
127
128    fn field_bounds_to_bounds(field: FieldBounds<Self>) -> Bounds {
129        BaseField::wrap(field)
130    }
131
132    fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T> {
133        Expr::Base(expr)
134    }
135
136    fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T> {
137        Expr::BaseConversion(expr)
138    }
139
140    fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>> {
141        if let Expr::Base(e) = expr {
142            Some(e)
143        } else {
144            None
145        }
146    }
147
148    fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>> {
149        if let Expr::BaseConversion(e) = expr {
150            Some(e)
151        } else {
152            None
153        }
154    }
155
156    fn eval_value_to_field(eval_value: EvalValue) -> Self {
157        BaseField::unwrap(eval_value)
158    }
159    fn field_to_eval_value(a: Self) -> EvalValue {
160        EvalValue::Base(a)
161    }
162    fn field_to_constant_gate(a: Self) -> Gate {
163        Gate::Input {
164            input_type: core_utils::circuit::Input::BaseField(
165                core_utils::circuit::BaseFieldPlaintext::<Curve>::Fixed(primitives::algebra::elliptic_curve::curve::BaseFieldElement::<Curve>::from_le_bytes(&a.to_le_bytes()).expect("failed to convert")),
166            ),
167        }
168    }
169    fn field_type() -> core_utils::circuit::FieldType {
170        core_utils::circuit::FieldType::BaseField
171    }
172
173    fn algebraic_type() -> core_utils::circuit::AlgebraicType {
174        core_utils::circuit::AlgebraicType::BaseField
175    }
176    fn input(kind: InputKind) -> core_utils::circuit::Input<Curve> {
177        let algebraic_type = Self::algebraic_type();
178        let batched = core_utils::circuit::Batched::No;
179        match kind {
180            InputKind::Secret => core_utils::circuit::Input::Share {
181                algebraic_type,
182                batched,
183            },
184            InputKind::SecretFromPlayer(i) => core_utils::circuit::Input::SecretPlaintext {
185                inputer: i,
186                algebraic_type,
187                batched,
188            },
189            InputKind::Plaintext => {
190                core_utils::circuit::Input::BaseField(core_utils::circuit::BaseFieldPlaintext::<
191                    Curve,
192                >::Input(1))
193            }
194        }
195    }
196}
197
198impl<F: ActuallyUsedField> GetBit for F {
199    type Output = bool;
200
201    fn get_bit(&self, index: usize, signed: bool) -> Self::Output {
202        if signed {
203            self.signed_bit(index)
204        } else {
205            self.unsigned_bit(index)
206        }
207    }
208}
209
210impl<F: ActuallyUsedField> FromLeBits<bool> for F {
211    fn from_le_bits(bits: Vec<bool>, signed: bool) -> Self {
212        let n = bits.len();
213        bits.into_iter()
214            .enumerate()
215            .map(|(i, x)| {
216                if x {
217                    if signed && i + 1 == n {
218                        F::negative_power_of_two(i)
219                    } else {
220                        F::power_of_two(i)
221                    }
222                } else {
223                    F::ZERO
224                }
225            })
226            .sum()
227    }
228}
229
230impl FromF25519<BaseField> for BaseField {
231    fn from_F25519(value: BaseField) -> Vec<BaseField> {
232        vec![value]
233    }
234}
235
236impl FromF25519<BaseField> for ScalarField {
237    /// Injectively map a BaseField element into a Vec of ScalarField elements.
238    fn from_F25519(value: BaseField) -> Vec<ScalarField> {
239        let bytes = value.to_le_bytes();
240        // we chunk bytes by ScalarField::n_bytes - 1 and convert to ScalarField
241        let chunk_size = ScalarField::NUM_BITS.div_ceil(8) as usize - 1;
242        bytes
243            .chunks(chunk_size)
244            .map(|chunk| {
245                let mut chunk_bytes = [0u8; 32];
246                chunk_bytes[..chunk.len()].copy_from_slice(chunk);
247                ScalarField::from_le_bytes(chunk_bytes)
248            })
249            .collect::<Vec<ScalarField>>()
250    }
251}
252
253impl<F: ActuallyUsedField> Random for F {
254    fn random() -> Self {
255        let rng = &mut rand::thread_rng();
256        F::random(rng)
257    }
258}
259
260impl<F: ActuallyUsedField> Reveal for F {
261    fn reveal(self) -> Self {
262        self
263    }
264}
265
266impl<F: ActuallyUsedField> WithBooleanBounds for F {
267    fn with_boolean_bounds(&self) -> Self {
268        assert!(self.le(&F::from(1)));
269        *self
270    }
271}
272
273impl MxeX25519PrivateKey for ScalarField {
274    fn mxe_x25519_private_key() -> Self {
275        ScalarField::from_le_bytes(MXE_X25519_PRIVATE_KEY)
276    }
277}
278
279impl MxeRescueKey for BaseField {
280    fn mxe_rescue_key(i: usize) -> Self {
281        debug_assert!(i < RESCUE_KEY_COUNT);
282        BaseField::from_le_bytes(MXE_RESCUE_BASE_FIELD_KEY[i])
283    }
284}
285
286impl MxeRescueKey for ScalarField {
287    fn mxe_rescue_key(i: usize) -> Self {
288        debug_assert!(i < RESCUE_KEY_COUNT);
289        ScalarField::from_le_bytes(MXE_RESCUE_SCALAR_FIELD_KEY[i])
290    }
291}