arcium-primitives 0.4.2

Arcium primitives
Documentation
use std::hash::Hash;

use derive_more::derive::Display;
use elliptic_curve::{
    group::{self, GroupEncoding},
    ops::{Invert, MulByGenerator},
    scalar::{FromUintUnchecked, IsHigh},
    Curve as EllipticCurve,
    FieldBytes,
    ScalarPrimitive,
};
use ff::PrimeField;
use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption};
use wincode::{SchemaRead, SchemaWrite};

use crate::algebra::{
    field::{FieldElement, FieldExtension, SubfieldElement},
    uniform_bytes::FromUniformBytes,
};

// Defines a curve that can be encoded and decoded into bytes.
// This is a reduced version of the elliptic_curve::CurveArithmetic trait that is suitable for our
// MPC purposes. In particular, we removed the AffinePoint type.
pub trait Curve: EllipticCurve + Hash {
    /// Name of the curve, used for domain separation.
    const NAME: &'static str;
    /// Whether this curve uses big-endian for its scalar encoding natively.
    const SCALAR_BIG_ENDIAN: bool;
    /// Whether this curve uses big-endian for its point encoding natively.
    const POINT_BIG_ENDIAN: bool;

    const BASE_FIELD_BIG_ENDIAN: bool;
    /// Elliptic curve point in projective coordinates.
    ///
    /// Note: the following bounds are provided by [`group::Group`]:
    /// - `'static`
    /// - [`Copy`]
    /// - [`Clone`]
    /// - [`Debug`]
    /// - [`Eq`]
    /// - [`Sized`]
    /// - [`Send`]
    /// - [`Sync`]
    type Point: ConditionallySelectable
        + ConstantTimeEq
        + Default
        // Implemented differently for Dalek
        // + DefaultIsZeroes

        // These require Affine Repr
        // + LinearCombination<[(Self::ProjectivePoint, Self::Scalar)]>
        // + LinearCombination<[(Self::ProjectivePoint, Self::Scalar); 2]>
        + MulByGenerator
        + group::Group<Scalar = Self::Scalar>
        + GroupEncoding
        + for<'de> SchemaRead<'de, Dst = Self::Point>
        + SchemaWrite<Src = Self::Point>
        + Hash
        + FromExtendedEdwards<BaseFieldElement = BaseFieldElement<Self>>
        + ToExtendedEdwards<BaseFieldElement = BaseFieldElement<Self>>;

    /// Scalar field modulo this curve's order.
    ///
    /// Note: the following bounds are provided by [`ff::Field`]:
    /// - `'static`
    /// - [`Copy`]
    /// - [`Clone`]
    /// - [`ConditionallySelectable`]
    /// - [`ConstantTimeEq`]
    /// - [`Debug`]
    /// - [`Default`]
    /// - [`Send`]
    /// - [`Sync`]
    type Scalar: AsRef<Self::Scalar>
        // + DefaultIsZeroes
        + From<ScalarPrimitive<Self>>
        + FromUintUnchecked<Uint = Self::Uint>
        + Into<FieldBytes<Self>>
        + Into<ScalarPrimitive<Self>>
        + Into<Self::Uint>
        + Invert<Output = CtOption<Self::Scalar>>
        + FromUniformBytes
        + IsHigh
        + PartialOrd
        + PrimeField
        + FieldExtension<Subfield = Self::Scalar>
        + Hash;

    type BaseField: PrimeField + FieldExtension + FromUniformBytes + Hash;

    fn hash_to_curve(bytes: &[u8]) -> Self::Point;
}

pub trait FromExtendedEdwards {
    type BaseFieldElement;

    fn from_extended_edwards(coordinates: [Self::BaseFieldElement; 4]) -> Option<Self>
    where
        Self: Sized;
}

#[derive(Display)]
pub struct PointAtInfinityError;

pub trait ToExtendedEdwards {
    type BaseFieldElement;

    fn to_extended_edwards(self) -> Result<[Self::BaseFieldElement; 4], PointAtInfinityError>;
}

/// The scalar field of the curve.
pub type ScalarField<C> = <C as Curve>::Scalar;
/// The base field (coordinates of the points) of the curve.
pub type BaseField<C> = <C as Curve>::BaseField;

/// The scalar field of the curve as a subfield element.
pub type Scalar<C> = SubfieldElement<ScalarField<C>>;
/// The base field of the curve as a subfield element.
pub type BaseFieldElement<C> = SubfieldElement<BaseField<C>>;

/// The scalar field of the curve as a field extension element.
pub type ScalarAsExtension<C> = FieldElement<<C as Curve>::Scalar>;
/// The base field of the curve as a field extension element.
pub type BaseFieldAsExtension<C> = FieldElement<BaseField<C>>;