Skip to main content

arcis_compiler/core/
mxe_input.rs

1use crate::{
2    core::{
3        actually_used_field::ActuallyUsedField,
4        bounds::{BoolBounds, Bounds, CurveBounds, FieldBounds},
5        circuits::boolean::byte::Byte,
6        expressions::expr::EvalValue,
7    },
8    traits::FromLeBytes,
9    utils::{
10        crypto::key::{
11            AES_128_KEY_COUNT,
12            AES_192_KEY_COUNT,
13            AES_256_KEY_COUNT,
14            ED25519_SECRET_KEY_COUNT,
15            ED25519_SIGNING_KEY_HASH_PREFIX_COUNT,
16            ED25519_VERIFYING_KEY_COUNT,
17            MXE_AES128_KEY,
18            MXE_AES192_KEY,
19            MXE_AES256_KEY,
20            MXE_ED25519_SECRET_KEY,
21            MXE_ED25519_SIGNING_KEY_HASH_PREFIX,
22            MXE_ED25519_SIGNING_KEY_S,
23            MXE_ED25519_VERIFYING_KEY,
24            MXE_ELGAMAL_PUBKEY,
25            MXE_ELGAMAL_SECRET_KEY,
26            MXE_RESCUE_BASE_FIELD_KEY,
27            MXE_X25519_PRIVATE_KEY,
28            RESCUE_KEY_COUNT,
29        },
30        curve_point::CurvePoint,
31        field::{BaseField, ScalarField},
32    },
33};
34use curve25519_dalek_arcium_fork::ristretto::CompressedRistretto;
35use serde::{Deserialize, Serialize};
36use std::marker::PhantomData;
37
38/// `pub trait` but meant to be closed.
39pub trait ArxInput {
40    type Output;
41    /// Whether this `MxeInput` is plaintext.
42    fn is_plaintext(&self) -> bool;
43    /// The mock value of this `MxeInput`.
44    fn mock_eval(&self) -> Self::Output;
45}
46
47/// An input given by the MXE, not by the user.
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub enum MxeInput {
50    Bit(MxeBitInput),
51    ScalarOnly(MxeScalarInput),
52    Scalar(MxeFieldInput<ScalarField>),
53    Base(MxeFieldInput<BaseField>),
54    Curve(MxeCurveInput),
55}
56
57impl MxeInput {
58    /// The bounds of this `MxeInput`.
59    pub fn bounds(&self) -> Bounds {
60        match self {
61            MxeInput::Bit(_) => Bounds::Bit(BoolBounds::new(true, true)),
62            MxeInput::ScalarOnly(_) => Bounds::Scalar(FieldBounds::All),
63            MxeInput::Scalar(i) => Bounds::Scalar(i.bounds()),
64            MxeInput::Base(i) => Bounds::Base(i.bounds()),
65            MxeInput::Curve(_) => Bounds::Curve(CurveBounds::All),
66        }
67    }
68}
69
70impl ArxInput for MxeInput {
71    type Output = EvalValue;
72    fn is_plaintext(&self) -> bool {
73        match self {
74            MxeInput::Bit(i) => i.is_plaintext(),
75            MxeInput::ScalarOnly(i) => i.is_plaintext(),
76            MxeInput::Scalar(i) => i.is_plaintext(),
77            MxeInput::Base(i) => i.is_plaintext(),
78            MxeInput::Curve(i) => i.is_plaintext(),
79        }
80    }
81    fn mock_eval(&self) -> Self::Output {
82        match self {
83            MxeInput::Bit(i) => EvalValue::Bit(i.mock_eval()),
84            MxeInput::ScalarOnly(i) => EvalValue::Scalar(i.mock_eval()),
85            MxeInput::Scalar(i) => EvalValue::Scalar(i.mock_eval()),
86            MxeInput::Base(i) => EvalValue::Base(i.mock_eval()),
87            MxeInput::Curve(i) => EvalValue::Curve(i.mock_eval()),
88        }
89    }
90}
91
92/// A `bool` MXE input.
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
94pub enum MxeBitInput {
95    /// The MXE aes-128 key.
96    AES128Key(usize),
97    /// The MXE aes-192 key.
98    AES192Key(usize),
99    /// The MXE aes-256 key.
100    AES256Key(usize),
101    /// The MXE ed25519 secret key.
102    Ed25519SecretKey(usize),
103    /// The MXE ed25519 signing key hash-prefix.
104    Ed25519SigningKeyHashPrefix(usize),
105}
106
107impl ArxInput for MxeBitInput {
108    type Output = bool;
109
110    fn is_plaintext(&self) -> bool {
111        false
112    }
113
114    fn mock_eval(&self) -> Self::Output {
115        match *self {
116            MxeBitInput::AES128Key(i) => {
117                if i < AES_128_KEY_COUNT {
118                    Byte::from(MXE_AES128_KEY[i / 8]).get_bits()[i % 8]
119                } else {
120                    false
121                }
122            }
123            MxeBitInput::AES192Key(i) => {
124                if i < AES_192_KEY_COUNT {
125                    Byte::from(MXE_AES192_KEY[i / 8]).get_bits()[i % 8]
126                } else {
127                    false
128                }
129            }
130            MxeBitInput::AES256Key(i) => {
131                if i < AES_256_KEY_COUNT {
132                    Byte::from(MXE_AES256_KEY[i / 8]).get_bits()[i % 8]
133                } else {
134                    false
135                }
136            }
137            MxeBitInput::Ed25519SecretKey(i) => {
138                if i < ED25519_SECRET_KEY_COUNT {
139                    Byte::from(MXE_ED25519_SECRET_KEY[i / 8]).get_bits()[i % 8]
140                } else {
141                    false
142                }
143            }
144            MxeBitInput::Ed25519SigningKeyHashPrefix(i) => {
145                if i < ED25519_SIGNING_KEY_HASH_PREFIX_COUNT {
146                    Byte::from(MXE_ED25519_SIGNING_KEY_HASH_PREFIX[i / 8]).get_bits()[i % 8]
147                } else {
148                    false
149                }
150            }
151        }
152    }
153}
154
155/// A `ScalarField` MXE input.
156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
157pub enum MxeScalarInput {
158    /// The MXE x25519 private key.
159    X25519PrivateKey(),
160    /// The MXE ed25519 signing key s.
161    Ed25519SigningKeyS(),
162    /// The ElGamal secret key, used for c-spl.
163    ElGamalSecretKey(),
164}
165
166impl ArxInput for MxeScalarInput {
167    type Output = ScalarField;
168
169    fn is_plaintext(&self) -> bool {
170        false
171    }
172
173    fn mock_eval(&self) -> Self::Output {
174        match self {
175            MxeScalarInput::X25519PrivateKey() => {
176                ScalarField::from_le_bytes(MXE_X25519_PRIVATE_KEY)
177            }
178            MxeScalarInput::Ed25519SigningKeyS() => {
179                ScalarField::from_le_bytes(MXE_ED25519_SIGNING_KEY_S)
180            }
181            MxeScalarInput::ElGamalSecretKey() => {
182                ScalarField::from_le_bytes(MXE_ELGAMAL_SECRET_KEY)
183            }
184        }
185    }
186}
187
188/// An MXE input that could exist on any field.
189#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
190pub enum MxeFieldInput<F: ActuallyUsedField> {
191    /// The MXE ed25519 verifying key.
192    Ed25519VerifyingKey(usize),
193    /// Rescue Key.
194    RescueKey(usize),
195    /// Do not use.
196    Phantom(PhantomData<F>),
197}
198
199impl<F: ActuallyUsedField> MxeFieldInput<F> {
200    pub fn bounds(&self) -> FieldBounds<F> {
201        match self {
202            MxeFieldInput::Ed25519VerifyingKey(_) => FieldBounds::new(F::ZERO, F::from(255)),
203            MxeFieldInput::RescueKey(_) => FieldBounds::All,
204            MxeFieldInput::Phantom(_) => {
205                panic!("Phantom type cannot be created.")
206            }
207        }
208    }
209}
210
211impl<F: ActuallyUsedField> ArxInput for MxeFieldInput<F> {
212    type Output = F;
213    fn is_plaintext(&self) -> bool {
214        match self {
215            MxeFieldInput::Ed25519VerifyingKey(_) => true,
216            MxeFieldInput::RescueKey(_) => false,
217            MxeFieldInput::Phantom(_) => {
218                panic!("Phantom type is not supported")
219            }
220        }
221    }
222    fn mock_eval(&self) -> F {
223        match *self {
224            MxeFieldInput::Ed25519VerifyingKey(i) => {
225                if i < ED25519_VERIFYING_KEY_COUNT {
226                    F::from(MXE_ED25519_VERIFYING_KEY[i] as u64)
227                } else {
228                    F::ZERO
229                }
230            }
231            MxeFieldInput::RescueKey(i) => {
232                if i < RESCUE_KEY_COUNT {
233                    F::from_le_bytes(MXE_RESCUE_BASE_FIELD_KEY[i])
234                } else {
235                    F::ZERO
236                }
237            }
238            MxeFieldInput::Phantom(_) => {
239                panic!("Phantom type is not supported")
240            }
241        }
242    }
243}
244
245/// An MXE input that is a curve point.
246#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
247pub enum MxeCurveInput {
248    /// The ElGamal pubkey, used for c-spl.
249    ElGamalPubkey(),
250}
251
252impl ArxInput for MxeCurveInput {
253    type Output = CurvePoint;
254
255    fn is_plaintext(&self) -> bool {
256        true
257    }
258    fn mock_eval(&self) -> CurvePoint {
259        match self {
260            MxeCurveInput::ElGamalPubkey() => {
261                let point = CompressedRistretto::from_slice(&MXE_ELGAMAL_PUBKEY)
262                    .unwrap()
263                    .decompress()
264                    .unwrap();
265                CurvePoint::new(point)
266            }
267        }
268    }
269}