Skip to main content

core_utils/
config.rs

1//! Compile-time protocol suite selection.
2//!
3//! An [`MpcConfig`] bundles the elliptic curve and the standalone MPC field that circuits and the
4//! online phase are instantiated with. The curve fixes the point/scalar/base-field backends; the
5//! MPC field is the additional prime-field-like backend historically hardcoded to `Mersenne107`.
6
7use std::{fmt::Debug, hash::Hash};
8
9use primitives::{
10    algebra::{
11        elliptic_curve::{Curve, Curve25519Ristretto},
12        field::{mersenne::Mersenne107, PrimeFieldExtension, SubfieldElement},
13    },
14    sharing::FieldShare,
15    types::identifiers::Named,
16};
17
18/// Compile-time protocol suite: the elliptic curve and the standalone MPC field.
19///
20/// Adding a new MPC field backend means providing a `PrimeFieldExtension` (a `FieldExtension`
21/// with `Subfield = Self`, so `FieldShare` secrets are full field elements) with a unique
22/// [`Named`](primitives::types::identifiers::Named) name, plus a config type selecting it. Only
23/// dealer-generated (`dev`) preprocessing is available for fields without a production
24/// preprocessing backend.
25pub trait MpcConfig:
26    'static + Sized + Send + Sync + Unpin + Copy + Default + Debug + Eq + Hash
27{
28    type Curve: Curve + Named;
29    type Field: PrimeFieldExtension;
30}
31
32/// Production suite: Ristretto25519 + Mersenne107.
33#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash)]
34pub struct DefaultConfig;
35
36impl MpcConfig for DefaultConfig {
37    type Curve = Curve25519Ristretto;
38    type Field = Mersenne107;
39}
40
41/// Test/dev suite: Ristretto25519 + `Gf2_128Field` (full 128-bit binary secrets). Only
42/// dealer-generated preprocessing exists for this field.
43#[cfg(any(test, feature = "dev"))]
44#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash)]
45pub struct Gf2_128Config;
46
47#[cfg(any(test, feature = "dev"))]
48impl MpcConfig for Gf2_128Config {
49    type Curve = Curve25519Ristretto;
50    type Field = primitives::algebra::field::binary::Gf2_128Field;
51}
52
53pub type CurveOf<Cfg> = <Cfg as MpcConfig>::Curve;
54pub type MpcFieldOf<Cfg> = <Cfg as MpcConfig>::Field;
55pub type ScalarFieldOf<Cfg> = <CurveOf<Cfg> as Curve>::Scalar;
56pub type BaseFieldOf<Cfg> = <CurveOf<Cfg> as Curve>::BaseField;
57pub type MpcFieldElement<Cfg> = SubfieldElement<MpcFieldOf<Cfg>>;
58pub type MpcFieldShare<Cfg> = FieldShare<MpcFieldOf<Cfg>>;
59
60/// Fixed-width identifier of a [`Named`] type (curve or MPC field), embedded in the serialized
61/// circuit format: the name as UTF-8, zero-padded to 32 bytes.
62pub fn name_tag<T: Named>() -> [u8; 32] {
63    let name = T::get_name();
64    let bytes = name.as_bytes();
65    assert!(
66        bytes.len() <= 32,
67        "name {name:?} exceeds the 32-byte circuit tag"
68    );
69    let mut tag = [0u8; 32];
70    tag[..bytes.len()].copy_from_slice(bytes);
71    tag
72}
73
74/// Best-effort inverse of [`name_tag`] for error messages.
75pub fn tag_name(tag: &[u8; 32]) -> String {
76    let end = tag.iter().position(|b| *b == 0).unwrap_or(32);
77    String::from_utf8_lossy(&tag[..end]).into_owned()
78}