Skip to content

Commit

Permalink
116 AuxInfo Tests (#472)
Browse files Browse the repository at this point in the history
  • Loading branch information
hridambasu authored Sep 25, 2023
1 parent 95ed53a commit 0b4bdb9
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 43 deletions.
31 changes: 14 additions & 17 deletions src/auxinfo/participant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
auxinfo::{
auxinfo_commit::{Commitment, CommitmentScheme},
info::{AuxInfoPrivate, AuxInfoPublic, AuxInfoWitnesses},
proof::AuxInfoProof,
proof::{AuxInfoProof, CommonInput},
Output,
},
broadcast::participant::{BroadcastOutput, BroadcastParticipant, BroadcastTag},
Expand Down Expand Up @@ -493,23 +493,18 @@ impl AuxInfoParticipant {

let witness = self.local_storage.retrieve::<storage::Witnesses>(self.id)?;
let product = &witness.p * &witness.q;

self.other_participant_ids
.iter()
.map(|&pid| {
// Grab the other participant's decommitment record from storage...
let verifier_decommit = self.local_storage.retrieve::<storage::Decommit>(pid)?;
let setup_params = verifier_decommit.clone().into_public();
let params = setup_params.params();
let shared_context = &self.retrieve_context();
// ... and use its setup parameters in the proof.
let proof = AuxInfoProof::prove(
rng,
&self.retrieve_context(),
sid,
global_rid,
verifier_decommit.clone().into_public().params(),
&product,
&witness.p,
&witness.q,
)?;
let common_input =
CommonInput::new(shared_context, sid, global_rid, params, &product);
let proof = AuxInfoProof::prove(rng, &common_input, &witness.p, &witness.q)?;
Message::new(
MessageType::Auxinfo(AuxinfoMessageType::R3Proof),
sid,
Expand Down Expand Up @@ -552,15 +547,17 @@ impl AuxInfoParticipant {
let my_public = self.local_storage.retrieve::<storage::Public>(self.id)?;

let proof = AuxInfoProof::from_message(message)?;
// Verify the public parameters for the given participant. Note that
// this verification verifies _both_ the `𝚷[mod]` and `𝚷[fac]` proofs.
proof.verify(
&self.retrieve_context(),
let shared_context = &self.retrieve_context();
let common_input = CommonInput::new(
shared_context,
message.id(),
*global_rid,
my_public.params(),
auxinfo_pub.pk().modulus(),
)?;
);
// Verify the public parameters for the given participant. Note that
// this verification verifies _both_ the `𝚷[mod]` and `𝚷[fac]` proofs.
proof.verify(&common_input)?;

self.local_storage
.store::<storage::Public>(message.from(), auxinfo_pub);
Expand Down
202 changes: 177 additions & 25 deletions src/auxinfo/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,35 @@ pub(crate) struct AuxInfoProof {
pifac: pifac::PiFacProof,
}

/// Common input and setup parameters known to both the prover and the verifier.
#[derive(Clone)]
pub(crate) struct CommonInput<'a> {
shared_context: &'a <AuxInfoParticipant as InnerProtocolParticipant>::Context,
sid: Identifier,
rho: [u8; 32],
setup_parameters: &'a VerifiedRingPedersen,
modulus: &'a BigNumber,
}

impl<'a> CommonInput<'a> {
/// Collect common parameters for proving or verifying a [`AuxInfoProof`]
pub(crate) fn new(
shared_context: &'a <AuxInfoParticipant as InnerProtocolParticipant>::Context,
sid: Identifier,
rho: [u8; 32],
verifier_setup_parameters: &'a VerifiedRingPedersen,
modulus: &'a BigNumber,
) -> CommonInput<'a> {
Self {
shared_context,
sid,
rho,
setup_parameters: verifier_setup_parameters,
modulus,
}
}
}

impl AuxInfoProof {
/// Generate a fresh transcript to be used in [`AuxInfoProof`].
fn new_transcript() -> Transcript {
Expand All @@ -56,28 +85,34 @@ impl AuxInfoProof {
#[allow(clippy::too_many_arguments)]
pub(crate) fn prove<R: RngCore + CryptoRng>(
rng: &mut R,
context: &<AuxInfoParticipant as InnerProtocolParticipant>::Context,
sid: Identifier,
rho: [u8; 32],
verifier_params: &VerifiedRingPedersen,
N: &BigNumber,
common_input: &CommonInput,
p: &BigNumber,
q: &BigNumber,
) -> Result<Self> {
let mut transcript = Self::new_transcript();
Self::append_pimod_transcript(&mut transcript, context, sid, rho)?;
Self::append_pimod_transcript(
&mut transcript,
common_input.shared_context,
common_input.sid,
common_input.rho,
)?;
let pimod = pimod::PiModProof::prove(
pimod::CommonInput::new(N),
pimod::CommonInput::new(common_input.modulus),
pimod::ProverSecret::new(p, q),
context,
common_input.shared_context,
&mut transcript,
rng,
)?;
Self::append_pifac_transcript(&mut transcript, context, sid, rho)?;
Self::append_pifac_transcript(
&mut transcript,
common_input.shared_context,
common_input.sid,
common_input.rho,
)?;
let pifac = pifac::PiFacProof::prove(
pifac::CommonInput::new(verifier_params, N),
pifac::CommonInput::new(common_input.setup_parameters, common_input.modulus),
pifac::ProverSecret::new(p, q),
context,
common_input.shared_context,
&mut transcript,
rng,
)?;
Expand All @@ -91,22 +126,28 @@ impl AuxInfoProof {
///
/// Note: The [`VerifiedRingPedersen`] argument **must be** provided by the
/// verifier!
pub(crate) fn verify(
self,
context: &<AuxInfoParticipant as InnerProtocolParticipant>::Context,
sid: Identifier,
rho: [u8; 32],
verifier_params: &VerifiedRingPedersen,
N: &BigNumber,
) -> Result<()> {
pub(crate) fn verify(self, common_input: &CommonInput) -> Result<()> {
let mut transcript = Self::new_transcript();
Self::append_pimod_transcript(&mut transcript, context, sid, rho)?;
self.pimod
.verify(pimod::CommonInput::new(N), context, &mut transcript)?;
Self::append_pifac_transcript(&mut transcript, context, sid, rho)?;
Self::append_pimod_transcript(
&mut transcript,
common_input.shared_context,
common_input.sid,
common_input.rho,
)?;
self.pimod.verify(
pimod::CommonInput::new(common_input.modulus),
common_input.shared_context,
&mut transcript,
)?;
Self::append_pifac_transcript(
&mut transcript,
common_input.shared_context,
common_input.sid,
common_input.rho,
)?;
self.pifac.verify(
pifac::CommonInput::new(verifier_params, N),
context,
pifac::CommonInput::new(common_input.setup_parameters, common_input.modulus),
common_input.shared_context,
&mut transcript,
)?;
Ok(())
Expand Down Expand Up @@ -142,3 +183,114 @@ impl AuxInfoProof {
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{paillier::prime_gen, protocol::SharedContext, utils::testing::init_testing};
use rand::{rngs::StdRng, Rng, SeedableRng};

fn random_auxinfo_proof<R: RngCore + CryptoRng>(
rng: &mut R,
test_code: impl FnOnce(CommonInput, AuxInfoProof) -> Result<()>,
) -> Result<()> {
let sid = Identifier::random(rng);
let rho = rng.gen();
let setup_params = VerifiedRingPedersen::gen(rng, &()).unwrap();
let (p, q) = prime_gen::get_prime_pair_from_pool_insecure(rng).unwrap();
let modulus = &p * &q;
let shared_context = SharedContext::random(rng);
let common_input = CommonInput::new(&shared_context, sid, rho, &setup_params, &modulus);
let proof = AuxInfoProof::prove(rng, &common_input, &p, &q).unwrap();
test_code(common_input, proof)
}

#[test]
fn auxinfo_proof_verifies() -> Result<()> {
let mut rng = init_testing();
let sid = Identifier::random(&mut rng);
let rho = rng.gen();
let setup_params = VerifiedRingPedersen::gen(&mut rng, &())?;
let (p, q) = prime_gen::get_prime_pair_from_pool_insecure(&mut rng).unwrap();
let modulus = &p * &q;
let shared_context = SharedContext::random(&mut rng);
let common_input = CommonInput::new(&shared_context, sid, rho, &setup_params, &modulus);
let proof = AuxInfoProof::prove(&mut rng, &common_input, &p, &q)?;
assert!(proof.verify(&common_input).is_ok());
Ok(())
}

#[test]
fn each_constituent_proof_must_be_valid() -> Result<()> {
let mut rng = init_testing();
let mut rng2 = StdRng::from_rng(&mut rng).unwrap();
let f = |input: CommonInput, proof: AuxInfoProof| {
let f1 = |input1: CommonInput, proof1: AuxInfoProof| {
let mix_one = AuxInfoProof {
pifac: proof.pifac,
pimod: proof1.pimod,
};
let mix_two = AuxInfoProof {
pifac: proof1.pifac,
pimod: proof.pimod,
};
assert!(mix_one.verify(&input).is_err());
assert!(mix_two.verify(&input1).is_err());
Ok(())
};
random_auxinfo_proof(&mut rng2, f1)?;
Ok(())
};
random_auxinfo_proof(&mut rng, f)?;
Ok(())
}

#[test]
fn modulus_factors_must_be_correct() -> Result<()> {
let mut rng = init_testing();
let sid = Identifier::random(&mut rng);
let rho = rng.gen();
let setup_params = VerifiedRingPedersen::gen(&mut rng, &())?;
let (p, q) = prime_gen::get_prime_pair_from_pool_insecure(&mut rng).unwrap();
let (p1, q1) = prime_gen::get_prime_pair_from_pool_insecure(&mut rng).unwrap();
let modulus = &p * &q;
let shared_context = &SharedContext::random(&mut rng);
let common_input = CommonInput::new(shared_context, sid, rho, &setup_params, &modulus);
match AuxInfoProof::prove(&mut rng, &common_input, &p1, &q1) {
Ok(proof) => assert!(proof.verify(&common_input).is_err()),
Err(_) => return Ok(()),
}
Ok(())
}

#[test]
fn context_must_be_correct() -> Result<()> {
let mut rng = init_testing();
let sid = Identifier::random(&mut rng);
let rho = rng.gen();
let setup_params = VerifiedRingPedersen::gen(&mut rng, &())?;
let (p, q) = prime_gen::get_prime_pair_from_pool_insecure(&mut rng).unwrap();
let modulus = &p * &q;
let shared_context = &SharedContext::random(&mut rng);
let bad_shared_context = &SharedContext::random(&mut rng);
let common_input = CommonInput {
shared_context,
sid,
rho,
setup_parameters: &setup_params,
modulus: &modulus,
};
let bad_common_input = CommonInput {
shared_context: bad_shared_context,
sid,
rho,
setup_parameters: &setup_params,
modulus: &modulus,
};
match AuxInfoProof::prove(&mut rng, &common_input, &p, &q) {
Ok(proof) => assert!(proof.verify(&bad_common_input).is_err()),
Err(_) => return Ok(()),
}
Ok(())
}
}
19 changes: 18 additions & 1 deletion src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ impl ParticipantIdentifier {

/// The `SharedContext` contains fixed known parameters across the entire
/// protocol. It does not however contain the entire protocol context.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub(crate) struct SharedContext {
sid: Identifier,
participants: Vec<ParticipantIdentifier>,
Expand All @@ -517,6 +517,23 @@ impl ProofContext for SharedContext {
}

impl SharedContext {
/// This function should not be used outside of the tests.
#[cfg(test)]
pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let sid = Identifier::random(rng);
let participant = ParticipantIdentifier::random(rng);
let participant2 = ParticipantIdentifier::random(rng);
let participants = vec![participant, participant2];
let generator = CurvePoint::GENERATOR;
let order = k256_order();
SharedContext {
sid,
participants,
generator,
order,
}
}

pub(crate) fn collect<P: InnerProtocolParticipant>(p: &P) -> Self {
let mut participants = p.all_participants();
participants.sort();
Expand Down

0 comments on commit 0b4bdb9

Please sign in to comment.