arcium-primitives 0.4.2

Arcium primitives
Documentation
use crate::{errors::PrimitiveError, random::CryptoRngCore};

pub mod hashbased;
pub mod pedersen;

pub trait CommitmentScheme<InputT> {
    type Commitment: Clone;
    type Witness: Default + Clone;

    fn commit<R: CryptoRngCore>(&self, input: &InputT, rng: R)
        -> (Self::Commitment, Self::Witness);
    fn open(
        &self,
        commitment: &Self::Commitment,
        witness: &Self::Witness,
        input: &InputT,
    ) -> Result<(), PrimitiveError>;
}

#[cfg(test)]
mod tests {
    use rand::SeedableRng;

    use super::{hashbased, pedersen};
    use crate::{
        algebra::elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension},
        commitments::CommitmentScheme,
        hashing::hash,
        random::{test_rng, BaseRng, Random, Seed},
        types::SessionId,
    };

    /// Test that a commitment can be opened successfully.
    pub fn test_happypath_commitment_opens_ok<InputT, C: CommitmentScheme<InputT>>(
        commitment_scheme: &C,
        input_generator: impl Fn(Seed) -> InputT,
    ) {
        let input = input_generator([0u8; 32]);
        let mut rng = test_rng();

        let (c, w) = commitment_scheme.commit(&input, &mut rng);
        assert!(commitment_scheme.open(&c, &w, &input).is_ok());
    }

    /// Test that a commitment cannot be opened with a different input, or with mismatched
    /// commitments and witnesses.
    pub fn test_unhappypath_wrong_or_mismatched_dont_open<InputT, C: CommitmentScheme<InputT>>(
        commitment_scheme: &C,
        input_generator: impl Fn(Seed) -> InputT,
    ) {
        let input = input_generator([1u8; 32]);
        let mut rng = test_rng();

        let (c, w) = commitment_scheme.commit(&input, &mut rng);

        // Try to open with a different input.
        let second_input = input_generator([2u8; 32]);
        assert!(commitment_scheme.open(&c, &w, &second_input).is_err());

        // Try to open mismatched commitments and witnesses.
        let (c2, w2) = commitment_scheme.commit(&input, &mut rng);
        assert!(commitment_scheme.open(&c, &w2, &input).is_err());
        assert!(commitment_scheme.open(&c2, &w, &input).is_err());
    }

    #[test]
    pub fn test_commitment_scheme_hashbased() {
        let session_id = SessionId::random(test_rng());
        let commitment_scheme = hashbased::HashBasedCommitment::new_with_session_id(session_id);
        let input_generator = |seed: Seed| hash(&[seed.as_ref()]);

        test_happypath_commitment_opens_ok(&commitment_scheme, input_generator);
        test_unhappypath_wrong_or_mismatched_dont_open(&commitment_scheme, input_generator);
    }

    #[test]
    pub fn test_commitment_scheme_pedersen() {
        let commitment_scheme =
            pedersen::PedersenCommitment::<C>::new(b"Nothing-up-my-sleeve generator h");
        let input_generator = |seed: Seed| {
            let mut rng = BaseRng::from_seed(seed);
            ScalarAsExtension::<C>::random(&mut rng)
        };

        test_happypath_commitment_opens_ok(&commitment_scheme, input_generator);
        test_unhappypath_wrong_or_mismatched_dont_open(&commitment_scheme, input_generator);
    }
}