arcis_compiler/
traits.rs

1use crate::{
2    core::circuits::boolean::{boolean_value::Boolean, byte::Byte},
3    utils::{elliptic_curve::F25519, number::Number},
4};
5use std::ops::Not;
6
7pub trait Equal<Other>: Sized {
8    type Output: Not<Output = Self::Output>;
9
10    fn eq(self, other: Other) -> Self::Output;
11    fn ne(self, other: Other) -> Self::Output {
12        Self::eq(self, other).not()
13    }
14}
15
16pub trait IsZero {
17    type Output;
18
19    fn is_zero(&self) -> Self::Output;
20}
21
22pub trait GreaterEqual<Other>: Sized {
23    type Output: Not<Output = Self::Output>;
24
25    fn ge(self, other: Other) -> Self::Output;
26    fn lt(self, other: Other) -> Self::Output {
27        Self::ge(self, other).not()
28    }
29}
30
31pub trait GreaterThan<Other>: Sized {
32    type Output: Not<Output = Self::Output>;
33
34    fn gt(self, other: Other) -> Self::Output;
35    fn le(self, other: Other) -> Self::Output {
36        Self::gt(self, other).not()
37    }
38}
39
40/// Implement [`Equal`] for all types that implement [`Eq`].
41impl<T> Equal<T> for T
42where
43    T: Eq,
44{
45    type Output = bool;
46
47    fn eq(self, other: T) -> Self::Output {
48        self == other
49    }
50}
51
52/// Implement [`GreaterEqual`] for all types that implement [`PartialOrd`].
53impl<T> GreaterEqual<T> for T
54where
55    T: PartialOrd,
56{
57    type Output = bool;
58
59    fn ge(self, other: T) -> Self::Output {
60        self >= other
61    }
62}
63
64/// Implement [`GreaterThan`] for all types that implement [`PartialOrd`].
65impl<T> GreaterThan<T> for T
66where
67    T: PartialOrd,
68{
69    type Output = bool;
70
71    fn gt(self, other: T) -> Self::Output {
72        self > other
73    }
74}
75
76pub trait Selectable<T = Self> {
77    type Conditional;
78    type Output;
79
80    fn construct_selection(condition: Self::Conditional, a: Self, b: T) -> Self::Output;
81}
82
83pub trait Select<T, U, V> {
84    fn select(self, a: T, b: V) -> U;
85}
86
87pub trait Enc<T> {
88    fn reveal(self) -> T;
89}
90
91pub trait FromLeBits<B: Boolean> {
92    fn from_le_bits(bits: Vec<B>, signed: bool) -> Self;
93}
94
95pub trait GetBit {
96    type Output: Boolean;
97
98    fn get_bit(&self, index: usize, signed: bool) -> Self::Output;
99}
100
101pub trait FromLeBytes {
102    fn from_le_bytes(bytes: [u8; 32]) -> Self;
103}
104
105pub trait ToLeBytes {
106    type BooleanOutput: Boolean;
107
108    fn to_le_bytes(self) -> [Byte<Self::BooleanOutput>; 32];
109}
110
111pub trait Random {
112    fn random() -> Self;
113}
114
115pub trait RandomBit {
116    fn random() -> Self;
117}
118
119pub trait Reveal {
120    fn reveal(self) -> Self;
121}
122
123pub trait Invert {
124    fn invert(self, is_expected_non_zero: bool) -> Self;
125}
126
127pub trait Pow {
128    fn pow(self, e: &Number, is_expected_non_zero: bool) -> Self;
129}
130
131pub trait Keccak {
132    fn f1600(state: [Byte<Self>; 200]) -> [Byte<Self>; 200]
133    where
134        Self: Boolean;
135
136    fn sponge<const N: usize>(
137        rate: usize,
138        capacity: usize,
139        input_bytes: Vec<Byte<Self>>,
140    ) -> [Byte<Self>; N]
141    where
142        Self: Boolean,
143    {
144        if input_bytes.len() > 1 << 20 {
145            panic!(
146                "sha3 not supported on inputs of more than 2^20 bytes (found {})",
147                input_bytes.len()
148            );
149        }
150        if rate + capacity != 1600 || rate % 8 != 0 {
151            panic!("rate + capacity must equal 1600 and rate must be a multiple of 8 (found rate: {rate}, capacity: {capacity})");
152        }
153        let mut state = [Byte::from(0u8); 200];
154        let rate_in_bytes = rate / 8;
155        // absorb the input blocks
156        input_bytes.chunks(rate_in_bytes).for_each(|chunk| {
157            chunk.iter().copied().enumerate().for_each(|(i, c)| {
158                state[i] ^= c;
159            });
160            if chunk.len() == rate_in_bytes {
161                state = Keccak::f1600(state);
162            }
163        });
164        // do the padding
165        let block_size = input_bytes.len() % rate_in_bytes;
166        state[block_size] ^= Byte::from(0x06);
167        state[rate_in_bytes - 1] ^= Byte::from(0x80);
168        state = Keccak::f1600(state);
169        // squeezing phase
170        (0..N)
171            .step_by(rate_in_bytes)
172            .fold(Vec::new(), |mut acc, pos| {
173                let block_size = (N - pos).min(rate_in_bytes);
174                acc.append(&mut state[0..block_size].to_vec());
175                if acc.len() < N {
176                    state = Keccak::f1600(state);
177                }
178                acc
179            })
180            .try_into()
181            .unwrap_or_else(|v: Vec<Byte<Self>>| {
182                panic!("Expected a Vec of length {N} (found {})", v.len())
183            })
184    }
185}
186
187pub trait WithBooleanBounds {
188    fn with_boolean_bounds(&self) -> Self;
189}
190
191pub trait ToMontgomery {
192    type Output: F25519;
193
194    fn to_montgomery(self, is_expected_non_identity: bool) -> (Self::Output, Self::Output);
195}
196
197pub trait MxeX25519PrivateKey {
198    fn mxe_x25519_private_key() -> Self;
199}
200
201pub trait MxeRescueKey {
202    fn mxe_rescue_key(i: usize) -> Self;
203}
204
205/// Trait used to convert the ECDH output to the target field.
206/// The implementor must make sure that the conversion is injective!
207pub trait FromF25519<T: F25519> {
208    #[allow(non_snake_case)]
209    fn from_F25519(value: T) -> Vec<Self>
210    where
211        Self: Sized;
212}