use crate::{
core::{
bounds::{Bounds, FieldBounds},
expressions::{
conversion_expr::ConversionExpr,
domain::Domain,
expr::{EvalValue, Expr},
field_expr::FieldExpr,
InputKind,
},
},
traits::{
FromF25519,
FromLeBits,
FromLeBytes,
GetBit,
MxeRescueKey,
MxeX25519PrivateKey,
Random,
Reveal,
WithBooleanBounds,
},
utils::{
crypto::key::{
MXE_RESCUE_BASE_FIELD_KEY,
MXE_RESCUE_SCALAR_FIELD_KEY,
MXE_X25519_PRIVATE_KEY,
RESCUE_KEY_COUNT,
},
field::{BaseField, ScalarField},
used_field::UsedField,
},
};
use ff::PrimeField;
type Curve = primitives::algebra::elliptic_curve::Curve25519Ristretto;
type Gate = core_utils::circuit::Gate<Curve>;
pub trait ActuallyUsedField: UsedField {
fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self>;
fn field_bounds_to_bounds(field: FieldBounds<Self>) -> Bounds;
fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T>;
fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T>;
fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>>;
fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>>;
fn eval_value_to_field(eval_value: EvalValue) -> Self;
fn field_to_eval_value(a: Self) -> EvalValue;
fn field_to_constant_gate(a: Self) -> Gate;
fn field_type() -> core_utils::circuit::FieldType;
fn algebraic_type() -> core_utils::circuit::AlgebraicType;
fn input(kind: InputKind) -> core_utils::circuit::Input<Curve>;
}
impl ActuallyUsedField for ScalarField {
fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self> {
if let Bounds::Scalar(s) = b {
s
} else {
panic!("invalid bounds");
}
}
fn field_bounds_to_bounds(b: FieldBounds<Self>) -> Bounds {
Bounds::Scalar(b)
}
fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T> {
Expr::Scalar(expr)
}
fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T> {
Expr::ScalarConversion(expr)
}
fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>> {
if let Expr::Scalar(e) = expr {
Some(e)
} else {
None
}
}
fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>> {
if let Expr::ScalarConversion(e) = expr {
Some(e)
} else {
None
}
}
fn eval_value_to_field(eval_value: EvalValue) -> Self {
let EvalValue::Scalar(x) = eval_value else {
panic!("wrong inner type for eval_value")
};
x
}
fn field_to_eval_value(a: Self) -> EvalValue {
EvalValue::Scalar(a)
}
fn field_to_constant_gate(a: Self) -> Gate {
Gate::Input {
input_type: core_utils::circuit::Input::Scalar(core_utils::circuit::ScalarPlaintext::<
Curve,
>::Fixed(
primitives::algebra::elliptic_curve::Scalar::<Curve>::from_le_bytes(
&a.to_le_bytes(),
)
.expect("failed to convert"),
)),
}
}
fn field_type() -> core_utils::circuit::FieldType {
core_utils::circuit::FieldType::ScalarField
}
fn algebraic_type() -> core_utils::circuit::AlgebraicType {
core_utils::circuit::AlgebraicType::ScalarField
}
fn input(kind: InputKind) -> core_utils::circuit::Input<Curve> {
let algebraic_type = Self::algebraic_type();
kind.to_input(algebraic_type)
}
}
impl ActuallyUsedField for BaseField {
fn bounds_to_field_bounds(b: Bounds) -> FieldBounds<Self> {
BaseField::unwrap(b)
}
fn field_bounds_to_bounds(field: FieldBounds<Self>) -> Bounds {
BaseField::wrap(field)
}
fn field_expr_to_expr<T: Clone>(expr: FieldExpr<Self, T>) -> Expr<T> {
Expr::Base(expr)
}
fn conversion_expr_to_expr<T: Clone>(expr: ConversionExpr<Self, T>) -> Expr<T> {
Expr::BaseConversion(expr)
}
fn expr_to_field_expr<T: Clone>(expr: Expr<T>) -> Option<FieldExpr<Self, T>> {
if let Expr::Base(e) = expr {
Some(e)
} else {
None
}
}
fn expr_to_conversion_expr<T: Clone>(expr: Expr<T>) -> Option<ConversionExpr<Self, T>> {
if let Expr::BaseConversion(e) = expr {
Some(e)
} else {
None
}
}
fn eval_value_to_field(eval_value: EvalValue) -> Self {
BaseField::unwrap(eval_value)
}
fn field_to_eval_value(a: Self) -> EvalValue {
EvalValue::Base(a)
}
fn field_to_constant_gate(a: Self) -> Gate {
Gate::Input {
input_type: core_utils::circuit::Input::BaseField(
core_utils::circuit::BaseFieldPlaintext::<Curve>::Fixed(primitives::algebra::elliptic_curve::curve::BaseFieldElement::<Curve>::from_le_bytes(&a.to_le_bytes()).expect("failed to convert")),
),
}
}
fn field_type() -> core_utils::circuit::FieldType {
core_utils::circuit::FieldType::BaseField
}
fn algebraic_type() -> core_utils::circuit::AlgebraicType {
core_utils::circuit::AlgebraicType::BaseField
}
fn input(kind: InputKind) -> core_utils::circuit::Input<Curve> {
let algebraic_type = Self::algebraic_type();
let batched = core_utils::circuit::Batched::No;
match kind {
InputKind::Secret => core_utils::circuit::Input::Share {
algebraic_type,
batched,
},
InputKind::SecretFromPlayer(i) => core_utils::circuit::Input::SecretPlaintext {
inputer: i,
algebraic_type,
batched,
},
InputKind::Plaintext => {
core_utils::circuit::Input::BaseField(core_utils::circuit::BaseFieldPlaintext::<
Curve,
>::Input(1))
}
}
}
}
impl<F: ActuallyUsedField> GetBit for F {
type Output = bool;
fn get_bit(&self, index: usize, signed: bool) -> Self::Output {
if signed {
self.signed_bit(index)
} else {
self.unsigned_bit(index)
}
}
}
impl<F: ActuallyUsedField> FromLeBits<bool> for F {
fn from_le_bits(bits: Vec<bool>, signed: bool) -> Self {
let n = bits.len();
bits.into_iter()
.enumerate()
.map(|(i, x)| {
if x {
if signed && i + 1 == n {
F::negative_power_of_two(i)
} else {
F::power_of_two(i)
}
} else {
F::ZERO
}
})
.sum()
}
}
impl FromF25519<BaseField> for BaseField {
fn from_F25519(value: BaseField) -> Vec<BaseField> {
vec![value]
}
}
impl FromF25519<BaseField> for ScalarField {
fn from_F25519(value: BaseField) -> Vec<ScalarField> {
let bytes = value.to_le_bytes();
let chunk_size = ScalarField::NUM_BITS.div_ceil(8) as usize - 1;
bytes
.chunks(chunk_size)
.map(|chunk| {
let mut chunk_bytes = [0u8; 32];
chunk_bytes[..chunk.len()].copy_from_slice(chunk);
ScalarField::from_le_bytes(chunk_bytes)
})
.collect::<Vec<ScalarField>>()
}
}
impl<F: ActuallyUsedField> Random for F {
fn random() -> Self {
let rng = &mut rand::thread_rng();
F::random(rng)
}
}
impl<F: ActuallyUsedField> Reveal for F {
fn reveal(self) -> Self {
self
}
}
impl<F: ActuallyUsedField> WithBooleanBounds for F {
fn with_boolean_bounds(&self) -> Self {
assert!(self.le(&F::from(1)));
*self
}
}
impl MxeX25519PrivateKey for ScalarField {
fn mxe_x25519_private_key() -> Self {
ScalarField::from_le_bytes(MXE_X25519_PRIVATE_KEY)
}
}
impl MxeRescueKey for BaseField {
fn mxe_rescue_key(i: usize) -> Self {
debug_assert!(i < RESCUE_KEY_COUNT);
BaseField::from_le_bytes(MXE_RESCUE_BASE_FIELD_KEY[i])
}
}
impl MxeRescueKey for ScalarField {
fn mxe_rescue_key(i: usize) -> Self {
debug_assert!(i < RESCUE_KEY_COUNT);
ScalarField::from_le_bytes(MXE_RESCUE_SCALAR_FIELD_KEY[i])
}
}