arcium-primitives 0.8.1

Arcium primitives
Documentation
use std::mem::MaybeUninit;

use serde::{de::DeserializeOwned, Deserialize, Serialize};

use crate::{
    algebra::{
        elliptic_curve::{BaseField, Point, ScalarField},
        field::{binary::Gf2_128, FieldElement, SubfieldElement},
    },
    errors::PrimitiveError,
    types::heap_array::{CurvePoints, FieldElements, SubfieldElements},
    utils::codec::InPlaceCodec,
};

/// Generic opening of a [`PairwiseAuthShare`]: the value and the corresponding MAC,
/// shared towards a remote peer for verification.
///
/// All four concrete opening types are type aliases of this struct:
/// - [`OpenFieldShare<F>`]     = `PairwiseAuthOpenShare<SubfieldElement<F>,   FieldElement<F>>`
/// - [`OpenFieldShares<F, M>`] = `PairwiseAuthOpenShare<SubfieldElements<F,M>,FieldElements<F,M>>`
/// - [`OpenPointShare<C>`]     = `PairwiseAuthOpenShare<Point<C>,             Point<C>>`
/// - [`OpenPointShares<C, M>`] = `PairwiseAuthOpenShare<CurvePoints<C,M>,     CurvePoints<C,M>>`
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(bound = "V: Serialize + DeserializeOwned, Mac: Serialize + DeserializeOwned")]
#[repr(C)]
pub struct PairwiseAuthOpenShare<V, Mac> {
    pub value: V,
    pub mac: Mac,
}

// SAFETY: encodes as `value` then `mac`, back to back. `write_le_bytes` initializes both halves
// (hence every byte); round-trip is unbiased since each field's is.
unsafe impl<V: InPlaceCodec, Mac: InPlaceCodec> InPlaceCodec for PairwiseAuthOpenShare<V, Mac> {
    const ENCODED_SIZE: usize = V::ENCODED_SIZE + Mac::ENCODED_SIZE;

    fn write_le_bytes(&self, out: &mut [MaybeUninit<u8>]) {
        let (value, mac) = out.split_at_mut(V::ENCODED_SIZE);
        self.value.write_le_bytes(value);
        self.mac.write_le_bytes(mac);
    }

    fn read_le_bytes(bytes: &[u8]) -> Result<Self, PrimitiveError> {
        let (value, mac) = bytes.split_at(V::ENCODED_SIZE);
        Ok(Self {
            value: V::read_le_bytes(value)?,
            mac: Mac::read_le_bytes(mac)?,
        })
    }
}

impl<V, Mac> PairwiseAuthOpenShare<V, Mac> {
    pub fn new(value: V, mac: Mac) -> Self {
        Self { value, mac }
    }

    pub fn get_value(&self) -> &V {
        &self.value
    }

    pub fn get_mac(&self) -> &Mac {
        &self.mac
    }
}

// --- Aliases --- //

// Single-element

/// Opening of a single authenticated field share.
/// Alias for [`PairwiseAuthOpenShare<SubfieldElement<F>, FieldElement<F>>`].
pub type OpenFieldShare<F> = PairwiseAuthOpenShare<SubfieldElement<F>, FieldElement<F>>;
/// Opening of a single authenticated curve-point share.
/// Alias for [`PairwiseAuthOpenShare<Point<C>, Point<C>>`].
pub type OpenPointShare<C> = PairwiseAuthOpenShare<Point<C>, Point<C>>;
/// Opening of a single authenticated share of a scalar field element (`ScalarField<C>`).
pub type OpenScalarShare<C> = OpenFieldShare<ScalarField<C>>;
/// Opening of a single authenticated share of a base field element (`BaseField<C>`).
pub type OpenBaseFieldShare<C> = OpenFieldShare<BaseField<C>>;
/// Opening of a single authenticated share of a GF(2^128) bit.
pub type OpenBitShare = OpenFieldShare<Gf2_128>;
/// Opening of a batch of `M` authenticated field shares.
/// Alias for [`PairwiseAuthOpenShare<SubfieldElements<F,M>, FieldElements<F,M>>`].
pub type OpenFieldShares<F, M> = PairwiseAuthOpenShare<SubfieldElements<F, M>, FieldElements<F, M>>;

// Batched

/// Opening of a batch of `M` authenticated curve-point shares.
/// Alias for [`PairwiseAuthOpenShare<CurvePoints<C,M>, CurvePoints<C,M>>`].
pub type OpenPointShares<C, M> = PairwiseAuthOpenShare<CurvePoints<C, M>, CurvePoints<C, M>>;
/// Opening of a batch of authenticated scalar field shares. See [`PairwiseAuthOpenShare`].
pub type OpenScalarShares<C, M> = OpenFieldShares<ScalarField<C>, M>;
/// Opening of a batch of authenticated base field shares. See [`PairwiseAuthOpenShare`].
pub type OpenBaseFieldShares<C, M> = OpenFieldShares<BaseField<C>, M>;