Skip to content

Commit

Permalink
Merge pull request #53 from Yoii-Inc/feat/smaller-than-constraints
Browse files Browse the repository at this point in the history
Feat/smaller than constraints
  • Loading branch information
sheagrief authored Jul 15, 2024
2 parents 4cd7f5b + 8adc7fb commit 9b51215
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 4 deletions.
3 changes: 2 additions & 1 deletion examples/bin_test_marlin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ fn main() {
marlin::mpc_test_prove_and_verify_pedersen(1);
marlin::test_equality_zero(1);
marlin::test_bit_decomposition(1);
marlin::test_enforce_smaller_eq_than(5);
marlin::test_enforce_smaller_eq_than(3);
marlin::test_smaller_than(5);
}
3 changes: 3 additions & 0 deletions mpc-algebra/src/mpc_primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ pub trait UniformBitRand: Sized {
fn bit_rand<R: Rng + ?Sized>(rng: &mut R) -> Self;
// little-endian
fn rand_number_bitwise<R: Rng + ?Sized>(rng: &mut R) -> (Vec<Self>, Self::BaseField);
fn rand_number_bitwise_less_than_half_modulus<R: Rng + ?Sized>(
rng: &mut R,
) -> (Vec<Self>, Self::BaseField);
}

pub trait BitwiseLessThan {
Expand Down
43 changes: 42 additions & 1 deletion mpc-algebra/src/wire/boolean_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,48 @@ impl<F: PrimeField + SquareRootField, S: FieldShare<F>> UniformBitRand for MpcBo
}
};

// bits to field elemetn (little endian)
// bits to field element (little endian)
let num = valid_bits
.iter()
.map(|b| b.field())
.rev()
.fold(Self::BaseField::zero(), |acc, x| {
acc * Self::BaseField::from_public(F::from(2u8)) + x
});

(valid_bits, num)
}

fn rand_number_bitwise_less_than_half_modulus<R: Rng + ?Sized>(
rng: &mut R,
) -> (Vec<Self>, Self::BaseField) {
let modulus_size = F::Params::MODULUS_BITS as usize;

let mut half_modulus_bits = F::Params::MODULUS_MINUS_ONE_DIV_TWO
.to_bits_le()
.iter()
.map(|&b| Self::from(b))
.collect::<Vec<_>>();

half_modulus_bits = half_modulus_bits[..modulus_size].to_vec();

let valid_bits = loop {
let bits = (0..modulus_size)
.map(|_| Self::bit_rand(rng))
.collect::<Vec<_>>();

if bits
.clone()
.is_smaller_than_le(&half_modulus_bits)
.field()
.reveal()
.is_one()
{
break bits;
}
};

// bits to field element (little endian)
let num = valid_bits
.iter()
.map(|b| b.field())
Expand Down
1 change: 1 addition & 0 deletions src/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub use werewolf::*;
pub mod bit_decomposition;
pub mod enforce_smaller_or_eq_than;
pub mod equality_zero;
pub mod smaller_than;
48 changes: 48 additions & 0 deletions src/circuits/smaller_than.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::cmp::Ordering;

use ark_ff::One;
use ark_ff::PrimeField;
use ark_r1cs_std::alloc::AllocVar;
use ark_r1cs_std::boolean::Boolean;
use ark_r1cs_std::eq::EqGadget;
use ark_r1cs_std::fields::fp::FpVar;
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
use mpc_algebra::malicious_majority::MpcField;
use mpc_algebra::{MpcBoolean, MpcEqGadget, MpcFpVar};

type Fr = ark_bls12_377::Fr;
type MFr = MpcField<Fr>;

pub struct SmallerThanCircuit<F: PrimeField> {
pub a: F,
pub b: F,
pub res: F,
pub cmp: Ordering,
pub check_eq: bool,
}

impl ConstraintSynthesizer<MFr> for SmallerThanCircuit<MFr> {
fn generate_constraints(self, cs: ConstraintSystemRef<MFr>) -> Result<(), SynthesisError> {
let a_var = MpcFpVar::new_witness(cs.clone(), || Ok(self.a))?;
let b_var = MpcFpVar::new_witness(cs.clone(), || Ok(self.b))?;
let res_var = MpcBoolean::new_witness(cs.clone(), || Ok(self.res))?;
let res2 = MpcFpVar::is_cmp(&a_var, &b_var, self.cmp, self.check_eq).unwrap();

res_var.enforce_equal(&res2);

Ok(())
}
}

impl ConstraintSynthesizer<Fr> for SmallerThanCircuit<Fr> {
fn generate_constraints(self, cs: ConstraintSystemRef<Fr>) -> Result<(), SynthesisError> {
let a_var = FpVar::new_witness(cs.clone(), || Ok(self.a))?;
let b_var = FpVar::new_witness(cs.clone(), || Ok(self.b))?;
let res_var = Boolean::new_witness(cs.clone(), || Ok(self.res.is_one()))?;
let res2 = FpVar::is_cmp(&a_var, &b_var, self.cmp, self.check_eq).unwrap();

res_var.enforce_equal(&res2);

Ok(())
}
}
49 changes: 47 additions & 2 deletions src/marlin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cmp::Ordering;

use ark_crypto_primitives::CommitmentScheme;
use ark_ec::twisted_edwards_extended::GroupAffine;
use ark_ff::{BigInteger, PrimeField};
Expand All @@ -11,14 +13,15 @@ use blake2::Blake2s;
use itertools::Itertools;
// use mpc_algebra::honest_but_curious::*;
use mpc_algebra::{
malicious_majority::*, BooleanWire, MpcBooleanField, SpdzFieldShare, UniformBitRand,
malicious_majority::*, BooleanWire, LessThan, MpcBooleanField, SpdzFieldShare, UniformBitRand,
};
use mpc_algebra::{FromLocal, Reveal};
use mpc_net::{MpcMultiNet, MpcNet};

use ark_std::{One, Zero};

use crate::circuits::enforce_smaller_or_eq_than::SmallerEqThanCircuit;
use crate::circuits::smaller_than::{self, SmallerThanCircuit};
use crate::{
circuits::{
bit_decomposition::BitDecompositionCircuit, circuit::MyCircuit,
Expand Down Expand Up @@ -313,7 +316,6 @@ pub fn test_bit_decomposition(n_iters: usize) {
}
}

// Test
pub fn test_enforce_smaller_eq_than(n_iters: usize) {
let rng = &mut test_rng();

Expand Down Expand Up @@ -351,3 +353,46 @@ pub fn test_enforce_smaller_eq_than(n_iters: usize) {
}
}
}

pub fn test_smaller_than(n_iters: usize) {
let rng = &mut test_rng();
let (_, local_a_rand) =
MpcBooleanField::<Fr, SpdzFieldShare<Fr>>::rand_number_bitwise_less_than_half_modulus(rng);
let (_, local_b_rand) =
MpcBooleanField::<Fr, SpdzFieldShare<Fr>>::rand_number_bitwise_less_than_half_modulus(rng);
let local_res = local_a_rand.is_smaller_than(&local_b_rand);

let local_circuit = SmallerThanCircuit {
a: local_a_rand.reveal(),
b: local_b_rand.reveal(),
res: local_res.reveal(),
cmp: Ordering::Less,
check_eq: true,
};
let (mpc_index_pk, index_vk) = setup_and_index(local_circuit);
for _ in 0..n_iters {
let (_, a_rand) =
MpcBooleanField::<Fr, SpdzFieldShare<Fr>>::rand_number_bitwise_less_than_half_modulus(
rng,
);
let (_, b_rand) =
MpcBooleanField::<Fr, SpdzFieldShare<Fr>>::rand_number_bitwise_less_than_half_modulus(
rng,
);
let res = a_rand.is_smaller_than(&b_rand);
let mpc_circuit = SmallerThanCircuit {
a: a_rand,
b: b_rand,
res: res.field(),
cmp: Ordering::Less,
check_eq: true,
};
let inputs = vec![];
assert!(prove_and_verify(
&mpc_index_pk,
&index_vk,
mpc_circuit,
inputs
));
}
}

0 comments on commit 9b51215

Please sign in to comment.