arcis_compiler/core/
actually_used_field.rs1use 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
66pub 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 fn from_F25519(value: BaseField) -> Vec<ScalarField> {
259 let bytes = value.to_le_bytes();
260 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}