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