diff --git a/proof_system/Cargo.toml b/proof_system/Cargo.toml index 08a4431d..84627343 100644 --- a/proof_system/Cargo.toml +++ b/proof_system/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "proof_system" -version = "0.25.0" +version = "0.26.0" edition.workspace = true authors.workspace = true license.workspace = true @@ -29,7 +29,7 @@ aead = {version = "0.5.2", default-features = false, features = [ "alloc" ]} chacha20poly1305 = {version = "0.10.1", default-features = false} bbs_plus = { version = "0.19.0", default-features = false, path = "../bbs_plus" } schnorr_pok = { version = "0.17.0", default-features = false, path = "../schnorr_pok" } -vb_accumulator = { version = "0.20.0", default-features = false, path = "../vb_accumulator" } +vb_accumulator = { version = "0.21.0", default-features = false, path = "../vb_accumulator" } dock_crypto_utils = { version = "0.17.0", default-features = false, path = "../utils" } saver = { version = "0.15.0", default-features = false, path = "../saver" } coconut-crypto = { version = "0.8.0", default-features = false, path = "../coconut" } diff --git a/proof_system/src/prover.rs b/proof_system/src/prover.rs index 644c2d8e..a3dfa269 100644 --- a/proof_system/src/prover.rs +++ b/proof_system/src/prover.rs @@ -38,7 +38,11 @@ use crate::{ DetachedAccumulatorMembershipSubProtocol, DetachedAccumulatorNonMembershipSubProtocol, }, - keyed_verification::VBAccumulatorMembershipKVSubProtocol, + keyed_verification::{ + KBUniversalAccumulatorMembershipKVSubProtocol, + KBUniversalAccumulatorNonMembershipKVSubProtocol, + VBAccumulatorMembershipKVSubProtocol, + }, KBPositiveAccumulatorMembershipSubProtocol, KBUniversalAccumulatorMembershipSubProtocol, KBUniversalAccumulatorNonMembershipSubProtocol, VBAccumulatorMembershipSubProtocol, @@ -227,6 +231,17 @@ impl Proof { }}; } + macro_rules! accum_kv_protocol_init { + ($s: ident, $s_idx: ident, $w: ident, $protocol: ident, $protocol_variant: ident, $label: ident) => {{ + let blinding = blindings.remove(&($s_idx, 0)); + let mut sp = $protocol::new($s_idx, $s.accumulator_value); + sp.init(rng, blinding, $w)?; + transcript.set_label($label); + sp.challenge_contribution(&mut transcript)?; + sub_protocols.push(SubProtocol::$protocol_variant(sp)); + }}; + } + fn build_blindings_map( blindings: &mut BTreeMap, s_idx: usize, @@ -694,13 +709,40 @@ impl Proof { }, Statement::VBAccumulatorMembershipKV(s) => match witness { Witness::VBAccumulatorMembership(w) => { - let blinding = blindings.remove(&(s_idx, 0)); - let mut sp = - VBAccumulatorMembershipKVSubProtocol::new(s_idx, s.accumulator_value); - sp.init(rng, blinding, w)?; - transcript.set_label(VB_ACCUM_MEM_LABEL); - sp.challenge_contribution(&mut transcript)?; - sub_protocols.push(SubProtocol::VBAccumulatorMembershipKV(sp)); + accum_kv_protocol_init!( + s, + s_idx, + w, + VBAccumulatorMembershipKVSubProtocol, + VBAccumulatorMembershipKV, + VB_ACCUM_MEM_LABEL + ); + } + _ => err_incompat_witness!(s_idx, s, witness), + }, + Statement::KBUniversalAccumulatorMembershipKV(s) => match witness { + Witness::KBUniAccumulatorMembership(w) => { + accum_kv_protocol_init!( + s, + s_idx, + w, + KBUniversalAccumulatorMembershipKVSubProtocol, + KBUniversalAccumulatorMembershipKV, + KB_UNI_ACCUM_MEM_LABEL + ); + } + _ => err_incompat_witness!(s_idx, s, witness), + }, + Statement::KBUniversalAccumulatorNonMembershipKV(s) => match witness { + Witness::KBUniAccumulatorNonMembership(w) => { + accum_kv_protocol_init!( + s, + s_idx, + w, + KBUniversalAccumulatorNonMembershipKVSubProtocol, + KBUniversalAccumulatorNonMembershipKV, + KB_UNI_ACCUM_NON_MEM_LABEL + ); } _ => err_incompat_witness!(s_idx, s, witness), }, @@ -787,6 +829,12 @@ impl Proof { SubProtocol::VBAccumulatorMembershipKV(mut sp) => { sp.gen_proof_contribution(&challenge)? } + SubProtocol::KBUniversalAccumulatorMembershipKV(mut sp) => { + sp.gen_proof_contribution(&challenge)? + } + SubProtocol::KBUniversalAccumulatorNonMembershipKV(mut sp) => { + sp.gen_proof_contribution(&challenge)? + } }); } @@ -888,7 +936,7 @@ impl Proof { &self.statement_proofs } - /// Hash bytes to a field element. This is vulnerable to timing attack and is only used input + /// Hash bytes to a field element. This is vulnerable to timing attack and is only used when input /// is public anyway like when generating setup parameters or challenge pub fn generate_challenge_from_bytes(bytes: &[u8]) -> E::ScalarField { field_elem_from_try_and_incr::(bytes) diff --git a/proof_system/src/statement/accumulator/keyed_verification.rs b/proof_system/src/statement/accumulator/keyed_verification.rs index 20a0b0a8..22bfb9c9 100644 --- a/proof_system/src/statement/accumulator/keyed_verification.rs +++ b/proof_system/src/statement/accumulator/keyed_verification.rs @@ -7,41 +7,81 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use vb_accumulator::setup::SecretKey; -#[serde_as] -#[derive( - Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize, -)] -#[serde(bound = "")] -pub struct VBAccumulatorMembershipKV { - #[serde_as(as = "ArkObjectBytes")] - pub accumulator_value: G, -} +macro_rules! impl_struct_and_funcs { + ($(#[$doc:meta])* + $name:ident, $name_full_verifier: ident, $stmt_variant: ident, $stmt_full_verifier_variant: ident) => { + #[serde_as] + #[derive( + Clone, + Debug, + PartialEq, + Eq, + CanonicalSerialize, + CanonicalDeserialize, + Serialize, + Deserialize, + )] + #[serde(bound = "")] + pub struct $name { + #[serde_as(as = "ArkObjectBytes")] + pub accumulator_value: G, + } -#[serde_as] -#[derive( - Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize, -)] -#[serde(bound = "")] -pub struct VBAccumulatorMembershipKVFullVerifier { - #[serde_as(as = "ArkObjectBytes")] - pub accumulator_value: G, - pub secret_key: SecretKey, -} + #[serde_as] + #[derive( + Clone, + Debug, + PartialEq, + Eq, + CanonicalSerialize, + CanonicalDeserialize, + Serialize, + Deserialize, + )] + #[serde(bound = "")] + pub struct $name_full_verifier { + #[serde_as(as = "ArkObjectBytes")] + pub accumulator_value: G, + pub secret_key: SecretKey, + } -impl VBAccumulatorMembershipKV { - pub fn new>(accumulator_value: G) -> Statement { - Statement::VBAccumulatorMembershipKV(Self { accumulator_value }) - } -} + impl $name { + pub fn new>(accumulator_value: G) -> Statement { + Statement::$stmt_variant(Self { accumulator_value }) + } + } -impl VBAccumulatorMembershipKVFullVerifier { - pub fn new>( - accumulator_value: G, - secret_key: SecretKey, - ) -> Statement { - Statement::VBAccumulatorMembershipKVFullVerifier(Self { - accumulator_value, - secret_key, - }) - } + impl $name_full_verifier { + pub fn new>( + accumulator_value: G, + secret_key: SecretKey, + ) -> Statement { + Statement::$stmt_full_verifier_variant(Self { + accumulator_value, + secret_key, + }) + } + } + }; } + +impl_struct_and_funcs!( + VBAccumulatorMembershipKV, + VBAccumulatorMembershipKVFullVerifier, + VBAccumulatorMembershipKV, + VBAccumulatorMembershipKVFullVerifier +); + +impl_struct_and_funcs!( + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKVFullVerifier +); + +impl_struct_and_funcs!( + KBUniversalAccumulatorNonMembershipKV, + KBUniversalAccumulatorNonMembershipKVFullVerifier, + KBUniversalAccumulatorNonMembershipKV, + KBUniversalAccumulatorNonMembershipKVFullVerifier +); diff --git a/proof_system/src/statement/mod.rs b/proof_system/src/statement/mod.rs index 633b1ce7..a4391ff3 100644 --- a/proof_system/src/statement/mod.rs +++ b/proof_system/src/statement/mod.rs @@ -105,6 +105,26 @@ pub enum Statement { VBAccumulatorMembershipKVFullVerifier( accumulator::keyed_verification::VBAccumulatorMembershipKVFullVerifier, ), + /// For proof of membership in KB universal accumulator in keyed verification model. + KBUniversalAccumulatorMembershipKV( + accumulator::keyed_verification::KBUniversalAccumulatorMembershipKV, + ), + /// Statement used by verifier for proof of membership in KB universal when it knows the secret key + KBUniversalAccumulatorMembershipKVFullVerifier( + accumulator::keyed_verification::KBUniversalAccumulatorMembershipKVFullVerifier< + E::G1Affine, + >, + ), + /// For proof of non-membership in KB universal accumulator in keyed verification model. + KBUniversalAccumulatorNonMembershipKV( + accumulator::keyed_verification::KBUniversalAccumulatorNonMembershipKV, + ), + /// Statement used by verifier for proof of non-membership in KB universal when it knows the secret key + KBUniversalAccumulatorNonMembershipKVFullVerifier( + accumulator::keyed_verification::KBUniversalAccumulatorNonMembershipKVFullVerifier< + E::G1Affine, + >, + ), } /// A collection of statements @@ -176,7 +196,11 @@ macro_rules! delegate { PoKBDDT16MACFullVerifier, PedersenCommitmentG2, VBAccumulatorMembershipKV, - VBAccumulatorMembershipKVFullVerifier + VBAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorNonMembershipKV, + KBUniversalAccumulatorNonMembershipKVFullVerifier : $($tt)+ } }} @@ -225,7 +249,11 @@ macro_rules! delegate_reverse { PoKBDDT16MACFullVerifier, PedersenCommitmentG2, VBAccumulatorMembershipKV, - VBAccumulatorMembershipKVFullVerifier + VBAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorNonMembershipKV, + KBUniversalAccumulatorNonMembershipKVFullVerifier : $($tt)+ } diff --git a/proof_system/src/statement_proof.rs b/proof_system/src/statement_proof.rs index 58c658ef..b552ab90 100644 --- a/proof_system/src/statement_proof.rs +++ b/proof_system/src/statement_proof.rs @@ -59,7 +59,9 @@ pub enum StatementProof { KBPositiveAccumulatorMembershipCDH(#[serde_as(as = "ArkObjectBytes")] KBPositiveAccumulatorMembershipProofCDH), PoKOfBDDT16MAC(PoKOfMAC), PedersenCommitmentG2(PedersenCommitmentProof), - VBAccumulatorMembershipKV(vb_accumulator::proofs_keyed_verification::MembershipProof) + VBAccumulatorMembershipKV(vb_accumulator::proofs_keyed_verification::MembershipProof), + KBUniversalAccumulatorMembershipKV(vb_accumulator::kb_universal_accumulator::proofs_keyed_verification::KBUniversalAccumulatorMembershipProof), + KBUniversalAccumulatorNonMembershipKV(vb_accumulator::kb_universal_accumulator::proofs_keyed_verification::KBUniversalAccumulatorNonMembershipProof), } @@ -95,7 +97,9 @@ macro_rules! delegate { KBPositiveAccumulatorMembershipCDH, PoKOfBDDT16MAC, PedersenCommitmentG2, - VBAccumulatorMembershipKV + VBAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorNonMembershipKV : $($tt)+ } }}; @@ -133,7 +137,9 @@ macro_rules! delegate_reverse { KBPositiveAccumulatorMembershipCDH, PoKOfBDDT16MAC, PedersenCommitmentG2, - VBAccumulatorMembershipKV + VBAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorNonMembershipKV : $($tt)+ } diff --git a/proof_system/src/sub_protocols/accumulator/keyed_verification.rs b/proof_system/src/sub_protocols/accumulator/keyed_verification.rs index c8c30667..26a65076 100644 --- a/proof_system/src/sub_protocols/accumulator/keyed_verification.rs +++ b/proof_system/src/sub_protocols/accumulator/keyed_verification.rs @@ -1,93 +1,130 @@ -//! Membership proof in VB accumulator with keyed-verification +//! Membership proof in VB positive accumulator and KB universal accumulator with keyed-verification use crate::{error::ProofSystemError, statement_proof::StatementProof}; use ark_ec::{pairing::Pairing, AffineRepr}; use ark_std::{io::Write, rand::RngCore}; use vb_accumulator::{ + kb_universal_accumulator::proofs_keyed_verification::{ + KBUniversalAccumulatorMembershipProof, KBUniversalAccumulatorMembershipProofProtocol, + KBUniversalAccumulatorNonMembershipProof, KBUniversalAccumulatorNonMembershipProofProtocol, + }, proofs_keyed_verification::{MembershipProof, MembershipProofProtocol}, setup::SecretKey, }; -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct VBAccumulatorMembershipKVSubProtocol { - pub id: usize, - pub accumulator_value: G, - pub protocol: Option>, -} - -impl VBAccumulatorMembershipKVSubProtocol { - pub fn new(id: usize, accumulator_value: G) -> Self { - Self { - id, - accumulator_value, - protocol: None, +macro_rules! impl_struct_and_funcs { + ($(#[$doc:meta])* + $sub_protocol:ident, $protocol: ident, $proof: ident, $witness: ident, $sp_variant: ident, $error_variant: ident) => { + #[derive(Clone, Debug, PartialEq, Eq)] + pub struct $sub_protocol { + pub id: usize, + pub accumulator_value: G, + pub protocol: Option<$protocol>, } - } - pub fn init( - &mut self, - rng: &mut R, - blinding: Option, - witness: crate::witness::Membership, - ) -> Result<(), ProofSystemError> { - if self.protocol.is_some() { - return Err(ProofSystemError::SubProtocolAlreadyInitialized(self.id)); - } - self.protocol = Some(MembershipProofProtocol::init( - rng, - witness.element, - blinding, - &witness.witness, - &self.accumulator_value, - )); - Ok(()) - } + impl $sub_protocol { + pub fn new(id: usize, accumulator_value: G) -> Self { + Self { + id, + accumulator_value, + protocol: None, + } + } - pub fn challenge_contribution(&self, writer: W) -> Result<(), ProofSystemError> { - if self.protocol.is_none() { - return Err(ProofSystemError::SubProtocolNotReadyToGenerateChallenge( - self.id, - )); - } - self.protocol - .as_ref() - .unwrap() - .challenge_contribution(&self.accumulator_value, writer)?; - Ok(()) - } + pub fn init( + &mut self, + rng: &mut R, + blinding: Option, + witness: crate::witness::$witness, + ) -> Result<(), ProofSystemError> { + if self.protocol.is_some() { + return Err(ProofSystemError::SubProtocolAlreadyInitialized(self.id)); + } + self.protocol = Some($protocol::init( + rng, + witness.element, + blinding, + &witness.witness, + &self.accumulator_value, + )); + Ok(()) + } - pub fn gen_proof_contribution>( - &mut self, - challenge: &G::ScalarField, - ) -> Result, ProofSystemError> { - if self.protocol.is_none() { - return Err(ProofSystemError::SubProtocolNotReadyToGenerateProof( - self.id, - )); - } - let protocol = self.protocol.take().unwrap(); - let proof = protocol.gen_proof(challenge)?; - Ok(StatementProof::VBAccumulatorMembershipKV(proof)) - } + pub fn challenge_contribution( + &self, + writer: W, + ) -> Result<(), ProofSystemError> { + if self.protocol.is_none() { + return Err(ProofSystemError::SubProtocolNotReadyToGenerateChallenge( + self.id, + )); + } + self.protocol + .as_ref() + .unwrap() + .challenge_contribution(&self.accumulator_value, writer)?; + Ok(()) + } + + pub fn gen_proof_contribution>( + &mut self, + challenge: &G::ScalarField, + ) -> Result, ProofSystemError> { + if self.protocol.is_none() { + return Err(ProofSystemError::SubProtocolNotReadyToGenerateProof( + self.id, + )); + } + let protocol = self.protocol.take().unwrap(); + let proof = protocol.gen_proof(challenge)?; + Ok(StatementProof::$sp_variant(proof)) + } - pub fn verify_proof_contribution( - &self, - challenge: &G::ScalarField, - proof: &MembershipProof, - ) -> Result<(), ProofSystemError> { - proof - .verify_schnorr_proof(&self.accumulator_value, challenge) - .map_err(|e| ProofSystemError::VBAccumProofContributionFailed(self.id as u32, e)) - } + pub fn verify_proof_contribution( + &self, + challenge: &G::ScalarField, + proof: &$proof, + ) -> Result<(), ProofSystemError> { + proof + .verify_schnorr_proof(&self.accumulator_value, challenge) + .map_err(|e| ProofSystemError::$error_variant(self.id as u32, e)) + } - pub fn verify_full_proof_contribution( - &self, - challenge: &G::ScalarField, - proof: &MembershipProof, - secret_key: &SecretKey, - ) -> Result<(), ProofSystemError> { - proof - .verify(&self.accumulator_value, secret_key, challenge) - .map_err(|e| ProofSystemError::VBAccumProofContributionFailed(self.id as u32, e)) - } + pub fn verify_full_proof_contribution( + &self, + challenge: &G::ScalarField, + proof: &$proof, + secret_key: &SecretKey, + ) -> Result<(), ProofSystemError> { + proof + .verify(&self.accumulator_value, secret_key, challenge) + .map_err(|e| ProofSystemError::$error_variant(self.id as u32, e)) + } + } + }; } + +impl_struct_and_funcs!( + VBAccumulatorMembershipKVSubProtocol, + MembershipProofProtocol, + MembershipProof, + Membership, + VBAccumulatorMembershipKV, + VBAccumProofContributionFailed +); +impl_struct_and_funcs!( + KBUniversalAccumulatorMembershipKVSubProtocol, + KBUniversalAccumulatorMembershipProofProtocol, + KBUniversalAccumulatorMembershipProof, + KBUniMembership, + KBUniversalAccumulatorMembershipKV, + KBAccumProofContributionFailed +); +impl_struct_and_funcs!( + KBUniversalAccumulatorNonMembershipKVSubProtocol, + KBUniversalAccumulatorNonMembershipProofProtocol, + KBUniversalAccumulatorNonMembershipProof, + KBUniNonMembership, + KBUniversalAccumulatorNonMembershipKV, + KBAccumProofContributionFailed +); diff --git a/proof_system/src/sub_protocols/mod.rs b/proof_system/src/sub_protocols/mod.rs index e01def05..549a0492 100644 --- a/proof_system/src/sub_protocols/mod.rs +++ b/proof_system/src/sub_protocols/mod.rs @@ -29,7 +29,10 @@ use crate::sub_protocols::{ KBUniversalAccumulatorNonMembershipCDHSubProtocol, VBAccumulatorMembershipCDHSubProtocol, VBAccumulatorNonMembershipCDHSubProtocol, }, - keyed_verification::VBAccumulatorMembershipKVSubProtocol, + keyed_verification::{ + KBUniversalAccumulatorMembershipKVSubProtocol, + KBUniversalAccumulatorNonMembershipKVSubProtocol, VBAccumulatorMembershipKVSubProtocol, + }, KBPositiveAccumulatorMembershipSubProtocol, KBUniversalAccumulatorMembershipSubProtocol, KBUniversalAccumulatorNonMembershipSubProtocol, }, @@ -88,6 +91,10 @@ pub enum SubProtocol<'a, E: Pairing> { PoKOfBDDT16MAC(PoKOfMACSubProtocol<'a, E::G1Affine>), PoKDiscreteLogsG2(schnorr::SchnorrProtocol<'a, E::G2Affine>), VBAccumulatorMembershipKV(VBAccumulatorMembershipKVSubProtocol), + KBUniversalAccumulatorMembershipKV(KBUniversalAccumulatorMembershipKVSubProtocol), + KBUniversalAccumulatorNonMembershipKV( + KBUniversalAccumulatorNonMembershipKVSubProtocol, + ), } macro_rules! delegate { @@ -119,7 +126,9 @@ macro_rules! delegate { KBPositiveAccumulatorMembershipCDH, PoKOfBDDT16MAC, PoKDiscreteLogsG2, - VBAccumulatorMembershipKV + VBAccumulatorMembershipKV, + KBUniversalAccumulatorMembershipKV, + KBUniversalAccumulatorNonMembershipKV : $($tt)+ } }}; diff --git a/proof_system/src/verifier.rs b/proof_system/src/verifier.rs index e09e2c16..49806719 100644 --- a/proof_system/src/verifier.rs +++ b/proof_system/src/verifier.rs @@ -19,7 +19,11 @@ use crate::{ KBUniversalAccumulatorNonMembershipCDHSubProtocol, VBAccumulatorMembershipCDHSubProtocol, VBAccumulatorNonMembershipCDHSubProtocol, }, - keyed_verification::VBAccumulatorMembershipKVSubProtocol, + keyed_verification::{ + KBUniversalAccumulatorMembershipKVSubProtocol, + KBUniversalAccumulatorNonMembershipKVSubProtocol, + VBAccumulatorMembershipKVSubProtocol, + }, KBPositiveAccumulatorMembershipSubProtocol, KBUniversalAccumulatorMembershipSubProtocol, KBUniversalAccumulatorNonMembershipSubProtocol, VBAccumulatorMembershipSubProtocol, @@ -280,6 +284,21 @@ impl Proof { }}; } + macro_rules! accum_cdh_protocol_chal_gen { + ($s: ident, $s_idx: ident, $p: ident, $label: ident) => {{ + check_resp_for_equalities!( + witness_equalities, + $s_idx, + $p, + get_schnorr_response_for_element, + Self, + responses_for_equalities + ); + transcript.set_label($label); + $p.challenge_contribution(&$s.accumulator_value, &mut transcript)?; + }}; + } + // Get challenge contribution for each statement and check if response is equal for all witnesses. for (s_idx, (statement, proof)) in proof_spec .statements @@ -399,16 +418,17 @@ impl Proof { }, Statement::VBAccumulatorMembershipCDHVerifier(s) => match proof { StatementProof::VBAccumulatorMembershipCDH(p) => { - check_resp_for_equalities!( - witness_equalities, - s_idx, - p, - get_schnorr_response_for_element, - Self, - responses_for_equalities - ); - transcript.set_label(VB_ACCUM_CDH_MEM_LABEL); - p.challenge_contribution(&s.accumulator_value, &mut transcript)?; + // check_resp_for_equalities!( + // witness_equalities, + // s_idx, + // p, + // get_schnorr_response_for_element, + // Self, + // responses_for_equalities + // ); + // transcript.set_label(VB_ACCUM_CDH_MEM_LABEL); + // p.challenge_contribution(&s.accumulator_value, &mut transcript)?; + accum_cdh_protocol_chal_gen!(s, s_idx, p, VB_ACCUM_CDH_MEM_LABEL); } _ => err_incompat_proof!(s_idx, s, proof), }, @@ -435,31 +455,13 @@ impl Proof { }, Statement::KBUniversalAccumulatorMembershipCDHVerifier(s) => match proof { StatementProof::KBUniversalAccumulatorMembershipCDH(p) => { - check_resp_for_equalities!( - witness_equalities, - s_idx, - p, - get_schnorr_response_for_element, - Self, - responses_for_equalities - ); - transcript.set_label(KB_UNI_ACCUM_CDH_MEM_LABEL); - p.challenge_contribution(&s.accumulator_value, &mut transcript)?; + accum_cdh_protocol_chal_gen!(s, s_idx, p, KB_UNI_ACCUM_CDH_MEM_LABEL); } _ => err_incompat_proof!(s_idx, s, proof), }, Statement::KBUniversalAccumulatorNonMembershipCDHVerifier(s) => match proof { StatementProof::KBUniversalAccumulatorNonMembershipCDH(p) => { - check_resp_for_equalities!( - witness_equalities, - s_idx, - p, - get_schnorr_response_for_element, - Self, - responses_for_equalities - ); - transcript.set_label(KB_UNI_ACCUM_CDH_NON_MEM_LABEL); - p.challenge_contribution(&s.accumulator_value, &mut transcript)?; + accum_cdh_protocol_chal_gen!(s, s_idx, p, KB_UNI_ACCUM_CDH_NON_MEM_LABEL); } _ => err_incompat_proof!(s_idx, s, proof), }, @@ -830,31 +832,37 @@ impl Proof { }, Statement::VBAccumulatorMembershipKV(s) => match proof { StatementProof::VBAccumulatorMembershipKV(p) => { - check_resp_for_equalities!( - witness_equalities, - s_idx, - p, - get_schnorr_response_for_element, - Self, - responses_for_equalities - ); - transcript.set_label(VB_ACCUM_MEM_LABEL); - p.challenge_contribution(&s.accumulator_value, &mut transcript)?; + accum_cdh_protocol_chal_gen!(s, s_idx, p, VB_ACCUM_MEM_LABEL); } _ => err_incompat_proof!(s_idx, s, proof), }, Statement::VBAccumulatorMembershipKVFullVerifier(s) => match proof { StatementProof::VBAccumulatorMembershipKV(p) => { - check_resp_for_equalities!( - witness_equalities, - s_idx, - p, - get_schnorr_response_for_element, - Self, - responses_for_equalities - ); - transcript.set_label(VB_ACCUM_MEM_LABEL); - p.challenge_contribution(&s.accumulator_value, &mut transcript)?; + accum_cdh_protocol_chal_gen!(s, s_idx, p, VB_ACCUM_MEM_LABEL); + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorMembershipKV(s) => match proof { + StatementProof::KBUniversalAccumulatorMembershipKV(p) => { + accum_cdh_protocol_chal_gen!(s, s_idx, p, KB_UNI_ACCUM_MEM_LABEL); + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorMembershipKVFullVerifier(s) => match proof { + StatementProof::KBUniversalAccumulatorMembershipKV(p) => { + accum_cdh_protocol_chal_gen!(s, s_idx, p, KB_UNI_ACCUM_MEM_LABEL); + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorNonMembershipKV(s) => match proof { + StatementProof::KBUniversalAccumulatorNonMembershipKV(p) => { + accum_cdh_protocol_chal_gen!(s, s_idx, p, KB_UNI_ACCUM_NON_MEM_LABEL); + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorNonMembershipKVFullVerifier(s) => match proof { + StatementProof::KBUniversalAccumulatorNonMembershipKV(p) => { + accum_cdh_protocol_chal_gen!(s, s_idx, p, KB_UNI_ACCUM_NON_MEM_LABEL); } _ => err_incompat_proof!(s_idx, s, proof), }, @@ -1415,6 +1423,46 @@ impl Proof { } _ => err_incompat_proof!(s_idx, s, proof), }, + Statement::KBUniversalAccumulatorMembershipKV(s) => match proof { + StatementProof::KBUniversalAccumulatorMembershipKV(ref p) => { + let sp = KBUniversalAccumulatorMembershipKVSubProtocol::new( + s_idx, + s.accumulator_value, + ); + sp.verify_proof_contribution(&challenge, p)? + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorMembershipKVFullVerifier(s) => match proof { + StatementProof::KBUniversalAccumulatorMembershipKV(ref p) => { + let sp = KBUniversalAccumulatorMembershipKVSubProtocol::new( + s_idx, + s.accumulator_value, + ); + sp.verify_full_proof_contribution(&challenge, p, &s.secret_key)? + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorNonMembershipKV(s) => match proof { + StatementProof::KBUniversalAccumulatorNonMembershipKV(ref p) => { + let sp = KBUniversalAccumulatorNonMembershipKVSubProtocol::new( + s_idx, + s.accumulator_value, + ); + sp.verify_proof_contribution(&challenge, p)? + } + _ => err_incompat_proof!(s_idx, s, proof), + }, + Statement::KBUniversalAccumulatorNonMembershipKVFullVerifier(s) => match proof { + StatementProof::KBUniversalAccumulatorNonMembershipKV(ref p) => { + let sp = KBUniversalAccumulatorNonMembershipKVSubProtocol::new( + s_idx, + s.accumulator_value, + ); + sp.verify_full_proof_contribution(&challenge, p, &s.secret_key)? + } + _ => err_incompat_proof!(s_idx, s, proof), + }, _ => return Err(ProofSystemError::InvalidStatement), } } diff --git a/proof_system/tests/kvac.rs b/proof_system/tests/kvac.rs index ca73fa0f..53006eab 100644 --- a/proof_system/tests/kvac.rs +++ b/proof_system/tests/kvac.rs @@ -14,19 +14,28 @@ use proof_system::{ setup_params::SetupParams, statement::{ accumulator::keyed_verification::{ - VBAccumulatorMembershipKV, VBAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorMembershipKV, KBUniversalAccumulatorMembershipKVFullVerifier, + KBUniversalAccumulatorNonMembershipKV, + KBUniversalAccumulatorNonMembershipKVFullVerifier, VBAccumulatorMembershipKV, + VBAccumulatorMembershipKVFullVerifier, }, bddt16_kvac::{PoKOfMAC, PoKOfMACFullVerifier}, ped_comm::PedersenCommitment as PedersenCommitmentStmt, Statements, }, - witness::{Membership as MembershipWit, PoKOfBDDT16MAC, Witnesses}, + witness::{ + KBUniMembership, KBUniNonMembership, Membership as MembershipWit, PoKOfBDDT16MAC, Witnesses, + }, }; use std::{ collections::{BTreeMap, BTreeSet}, time::Instant, }; -use test_utils::{accumulators::setup_positive_accum, kvac::bddt16_mac_setup, test_serialization}; +use test_utils::{ + accumulators::{setup_kb_universal_accum_given_domain, setup_positive_accum}, + kvac::bddt16_mac_setup, + test_serialization, +}; use vb_accumulator::positive::Accumulator; #[test] @@ -61,6 +70,14 @@ fn proof_of_knowledge_of_macs_and_equality_of_messages_and_kv_accumulator() { let (_, pos_accum_keypair, mut pos_accumulator, mut pos_state) = setup_positive_accum(&mut rng); + let max = 100; + let mut domain = msgs_1.clone(); + while domain.len() < max as usize { + domain.push(Fr::rand(&mut rng)); + } + let (_, uni_accum_keypair, mut uni_accumulator, mut uni_mem_state, mut uni_non_mem_state) = + setup_kb_universal_accum_given_domain(&mut rng, domain); + // Message with index `accum_member_1_idx` is added in the positive VB accumulator let accum_member_1_idx = 1; let accum_member_1 = msgs_1[accum_member_1_idx]; @@ -75,6 +92,36 @@ fn proof_of_knowledge_of_macs_and_equality_of_messages_and_kv_accumulator() { .get_membership_witness(&accum_member_1, &pos_accum_keypair.secret_key, &pos_state) .unwrap(); + // Message with index `accum_member_2_idx` is added in the KB universal accumulator + let accum_member_2_idx = 3; + let accum_member_2 = msgs_1[accum_member_2_idx]; + uni_accumulator = uni_accumulator + .add( + accum_member_2, + &uni_accum_keypair.secret_key, + &mut uni_mem_state, + &mut uni_non_mem_state, + ) + .unwrap(); + let mem_2_wit = uni_accumulator + .get_membership_witness( + &accum_member_2, + &uni_accum_keypair.secret_key, + &uni_mem_state, + ) + .unwrap(); + + // Message with index `accum_non_member_idx` is not added in the KB universal accumulator + let accum_non_member_idx = 4; + let accum_non_member = msgs_1[accum_non_member_idx]; + let non_mem_wit = uni_accumulator + .get_non_membership_witness( + &accum_non_member, + &uni_accum_keypair.secret_key, + &uni_non_mem_state, + ) + .unwrap(); + // Prepare revealed messages for the proof of knowledge of 1st MAC let mut revealed_indices_1 = BTreeSet::new(); revealed_indices_1.insert(0); @@ -127,6 +174,12 @@ fn proof_of_knowledge_of_macs_and_equality_of_messages_and_kv_accumulator() { BTreeMap::new(), )); statements.add(VBAccumulatorMembershipKV::new(*pos_accumulator.value())); + statements.add(KBUniversalAccumulatorMembershipKV::new( + *uni_accumulator.mem_value(), + )); + statements.add(KBUniversalAccumulatorNonMembershipKV::new( + *uni_accumulator.non_mem_value(), + )); // Since 3 of the messages are being proven equal, add a `MetaStatement` describing that let mut meta_statements = MetaStatements::new(); @@ -156,6 +209,16 @@ fn proof_of_knowledge_of_macs_and_equality_of_messages_and_kv_accumulator() { .into_iter() .collect::>(), )); + meta_statements.add_witness_equality(EqualWitnesses( + vec![(0, accum_member_2_idx), (4, 0)] + .into_iter() + .collect::>(), + )); + meta_statements.add_witness_equality(EqualWitnesses( + vec![(0, accum_non_member_idx), (5, 0)] + .into_iter() + .collect::>(), + )); test_serialization!(Statements, statements); test_serialization!(MetaStatements, meta_statements); @@ -183,6 +246,14 @@ fn proof_of_knowledge_of_macs_and_equality_of_messages_and_kv_accumulator() { accum_member_1, mem_1_wit.clone(), )); + witnesses.add(KBUniMembership::new_as_witness( + accum_member_2, + mem_2_wit.clone(), + )); + witnesses.add(KBUniNonMembership::new_as_witness( + accum_non_member, + non_mem_wit.clone(), + )); test_serialization!(Witnesses, witnesses); @@ -233,6 +304,14 @@ fn proof_of_knowledge_of_macs_and_equality_of_messages_and_kv_accumulator() { *pos_accumulator.value(), pos_accum_keypair.secret_key.clone(), )); + statements.add(KBUniversalAccumulatorMembershipKVFullVerifier::new( + *uni_accumulator.mem_value(), + uni_accum_keypair.secret_key.clone(), + )); + statements.add(KBUniversalAccumulatorNonMembershipKVFullVerifier::new( + *uni_accumulator.non_mem_value(), + uni_accum_keypair.secret_key.clone(), + )); let proof_spec = ProofSpec::new(statements, meta_statements, vec![], context); proof_spec.validate().unwrap(); diff --git a/vb_accumulator/Cargo.toml b/vb_accumulator/Cargo.toml index 60643942..74d77d2c 100644 --- a/vb_accumulator/Cargo.toml +++ b/vb_accumulator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vb_accumulator" -version = "0.20.0" +version = "0.21.0" edition.workspace = true authors.workspace = true license.workspace = true diff --git a/vb_accumulator/src/batch_utils.rs b/vb_accumulator/src/batch_utils.rs index 12e304c8..66ea33b0 100644 --- a/vb_accumulator/src/batch_utils.rs +++ b/vb_accumulator/src/batch_utils.rs @@ -31,6 +31,7 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use dock_crypto_utils::ff::{inner_product, powers}; + #[cfg(feature = "parallel")] use rayon::prelude::*; @@ -618,7 +619,13 @@ where // mem_poly_v_AD = mem_poly_v_A - mem_poly_v_AD*(additions[0] + alpha)*(additions[1] + alpha)*...(additions[m-1] + alpha) let mut mem_poly_v_AD = mem_poly_v_A; if !removals.is_empty() { - mem_poly_v_AD = &mem_poly_v_AD - &(&mem_poly_v_D * factors_add[m - 1]); + mem_poly_v_AD = &mem_poly_v_AD + - &(&mem_poly_v_D + * if additions.is_empty() { + G::ScalarField::one() + } else { + factors_add[m - 1] + }); } let omega_mem = Self(G::Group::normalize_batch( &multiply_field_elems_with_same_group_elem( @@ -630,7 +637,13 @@ where // non_mem_poly_v_AD = non_mem_poly_v_AD - non_mem_poly_v_AD*(removals[0] + alpha)*(removals[1] + alpha)*...(removals[n-1] + alpha) let mut non_mem_poly_v_AD = non_mem_poly_v_A; if !additions.is_empty() { - non_mem_poly_v_AD = &non_mem_poly_v_AD - &(&non_mem_poly_v_D * factors_rem[n - 1]); + non_mem_poly_v_AD = &non_mem_poly_v_AD + - &(&non_mem_poly_v_D + * if removals.is_empty() { + G::ScalarField::one() + } else { + factors_rem[n - 1] + }); } let omega_non_mem = Self(G::Group::normalize_batch( &multiply_field_elems_with_same_group_elem( diff --git a/vb_accumulator/src/kb_positive_accumulator/adaptive_accumulator.rs b/vb_accumulator/src/kb_positive_accumulator/adaptive_accumulator.rs index 5bc92376..765da612 100644 --- a/vb_accumulator/src/kb_positive_accumulator/adaptive_accumulator.rs +++ b/vb_accumulator/src/kb_positive_accumulator/adaptive_accumulator.rs @@ -84,7 +84,7 @@ impl KBPositiveAccumulator { let members = cfg_iter!(sigs).map(|s| s.1).collect::>(); let w = self .0 - .compute_membership_witness_for_batch(&members, &sk.accum); + .compute_membership_witnesses_for_batch(&members, &sk.accum); self.0.add_batch(members, state)?; let wits = cfg_into_iter!(sigs) .zip(cfg_into_iter!(w)) @@ -129,7 +129,7 @@ impl KBPositiveAccumulator { let new = KBPositiveAccumulator(self.0.remove_batch(&removals, &sk.accum, state)?); let w = new .0 - .compute_membership_witness_for_batch(&additions, &sk.accum); + .compute_membership_witnesses_for_batch(&additions, &sk.accum); self.0.add_batch(additions, state)?; let wits = cfg_into_iter!(sigs) .zip(cfg_into_iter!(w)) diff --git a/vb_accumulator/src/kb_universal_accumulator/accumulator.rs b/vb_accumulator/src/kb_universal_accumulator/accumulator.rs index 5238938f..1868a7b0 100644 --- a/vb_accumulator/src/kb_universal_accumulator/accumulator.rs +++ b/vb_accumulator/src/kb_universal_accumulator/accumulator.rs @@ -1,5 +1,5 @@ //! A universal accumulator contructed from 2 positive accumulators where one accumulator accumulates all the members, say *Acc_M*, -//! and the other accumulates all the non-members, say *Acc_N*. Thus in an empty universal accumulator, all possible elements, called +//! and the other accumulates all the non-members, say *Acc_N*. Thus, in an empty universal accumulator, all possible elements, called //! the *domain* are present in the accumulator *Acc_N*. Adding an element to the universal accumulator results in adding the element to *Acc_M* and //! removing it from *Acc_N* and removing an element from the universal accumulator results in adding it to *Acc_N* and removing from *Acc_M*. //! A membership witness in the universal accumulator is a membership witness in *Acc_M* and a non-membership witness is a membership witness in *Acc_N* @@ -14,12 +14,16 @@ use crate::{ positive::{Accumulator, PositiveAccumulator}, setup::{PublicKey, SecretKey, SetupParams}, }; -use ark_ec::pairing::Pairing; -use ark_ff::{Field, One}; +use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; +use ark_ff::{Field, One, PrimeField}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::vec::Vec; +use serde::{Deserialize, Serialize}; -#[derive(Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize)] +#[derive( + Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize, +)] +#[serde(bound = "")] pub struct KBUniversalAccumulator { /// The accumulator accumulating all the members pub mem: PositiveAccumulator, @@ -50,6 +54,12 @@ impl KBUniversalAccumulator { Self { mem, non_mem } } + pub fn initialize_empty(params_gen: impl AsRef) -> Self { + let mem = PositiveAccumulator::initialize(params_gen); + let non_mem = mem.clone(); + Self { mem, non_mem } + } + /// Add new elements to an already initialized accumulator that were not part of its `domain`. pub fn extend_domain( &self, @@ -104,8 +114,7 @@ impl KBUniversalAccumulator { self.mem.check_before_add(element, mem_state)?; } let mut new = self.clone(); - let update = Poly_d::::eval_direct(&elements, &-sk.0); - let update_inv = update.inverse().unwrap(); + let (update, update_inv) = Self::compute_update_for_batch(&elements, sk); for element in elements { non_mem_state.remove(&element); mem_state.add(element); @@ -127,8 +136,7 @@ impl KBUniversalAccumulator { self.non_mem.check_before_add(element, non_mem_state)?; } let mut new = self.clone(); - let update = Poly_d::::eval_direct(&elements, &-sk.0); - let update_inv = update.inverse().unwrap(); + let (update, update_inv) = Self::compute_update_for_batch(&elements, sk); for element in elements { mem_state.remove(&element); non_mem_state.add(element); @@ -156,17 +164,8 @@ impl KBUniversalAccumulator { } let mut new = self.clone(); - let update_add = if !additions.is_empty() { - Poly_d::::eval_direct(&additions, &-sk.0) - } else { - E::ScalarField::one() - }; - let update_rem = if !removals.is_empty() { - Poly_d::::eval_direct(&removals, &-sk.0) - } else { - E::ScalarField::one() - }; - let update_mem = update_add * update_rem.inverse().unwrap(); + let (update_mem, update_non_mem) = + Self::compute_update_for_batches(&additions, &removals, sk); for element in additions { non_mem_state.remove(&element); @@ -177,8 +176,7 @@ impl KBUniversalAccumulator { non_mem_state.add(element); } new.mem = PositiveAccumulator((*new.mem.value() * update_mem).into()); - new.non_mem = - PositiveAccumulator((*new.non_mem.value() * update_mem.inverse().unwrap()).into()); + new.non_mem = PositiveAccumulator((*new.non_mem.value() * update_non_mem).into()); Ok(new) } @@ -269,6 +267,188 @@ impl KBUniversalAccumulator { non_mem: PositiveAccumulator::from_accumulated(non_mem_accumulated), } } + + pub fn compute_extended( + &self, + new_elements: &[E::ScalarField], + sk: &SecretKey, + ) -> (E::G1Affine, E::G1Affine) { + let mem = self.mem.value().clone(); + let non_mem = self.mem.compute_new_post_add_batch(new_elements, sk); + (mem, non_mem) + } + + pub fn compute_new_post_add( + &self, + element: &E::ScalarField, + sk: &SecretKey, + ) -> (E::G1Affine, E::G1Affine) { + // element + sk + let y_plus_alpha = *element + sk.0; + // 1/(element + sk) + let y_plus_alpha_inv = y_plus_alpha.inverse().unwrap(); // Unwrap is fine as element has to equal secret key for it to panic + let mem = self + .mem + .value() + .mul_bigint(y_plus_alpha.into_bigint()) + .into_affine(); + let non_mem = self + .non_mem + .value() + .mul_bigint(y_plus_alpha_inv.into_bigint()) + .into_affine(); + (mem, non_mem) + } + + pub fn compute_new_post_remove( + &self, + element: &E::ScalarField, + sk: &SecretKey, + ) -> (E::G1Affine, E::G1Affine) { + // element + sk + let y_plus_alpha = *element + sk.0; + // 1/(element + sk) + let y_plus_alpha_inv = y_plus_alpha.inverse().unwrap(); // Unwrap is fine as element has to equal secret key for it to panic + let mem = self + .mem + .value() + .mul_bigint(y_plus_alpha_inv.into_bigint()) + .into_affine(); + let non_mem = self + .non_mem + .value() + .mul_bigint(y_plus_alpha.into_bigint()) + .into_affine(); + (mem, non_mem) + } + + pub fn compute_new_post_add_batch( + &self, + elements: &[E::ScalarField], + sk: &SecretKey, + ) -> (E::G1Affine, E::G1Affine) { + let (update, update_inv) = Self::compute_update_for_batch(elements, sk); + let mem = self + .mem + .value() + .mul_bigint(update.into_bigint()) + .into_affine(); + let non_mem = self + .non_mem + .value() + .mul_bigint(update_inv.into_bigint()) + .into_affine(); + (mem, non_mem) + } + + pub fn compute_new_post_remove_batch( + &self, + elements: &[E::ScalarField], + sk: &SecretKey, + ) -> (E::G1Affine, E::G1Affine) { + let (update, update_inv) = Self::compute_update_for_batch(elements, sk); + let mem = self + .mem + .value() + .mul_bigint(update_inv.into_bigint()) + .into_affine(); + let non_mem = self + .non_mem + .value() + .mul_bigint(update.into_bigint()) + .into_affine(); + (mem, non_mem) + } + + pub fn compute_new_post_batch_updates( + &self, + additions: &[E::ScalarField], + removals: &[E::ScalarField], + sk: &SecretKey, + ) -> (E::G1Affine, E::G1Affine) { + let (update_mem, update_non_mem) = + Self::compute_update_for_batches(additions, removals, sk); + let mem = self + .mem + .value() + .mul_bigint(update_mem.into_bigint()) + .into_affine(); + let non_mem = self + .non_mem + .value() + .mul_bigint(update_non_mem.into_bigint()) + .into_affine(); + (mem, non_mem) + } + + pub fn compute_membership_witness( + &self, + member: &E::ScalarField, + sk: &SecretKey, + ) -> KBUniversalAccumulatorMembershipWitness { + self.mem.compute_membership_witness(member, sk).into() + } + + pub fn compute_non_membership_witness( + &self, + member: &E::ScalarField, + sk: &SecretKey, + ) -> KBUniversalAccumulatorNonMembershipWitness { + self.non_mem.compute_membership_witness(member, sk).into() + } + + pub fn compute_membership_witnesses_for_batch( + &self, + members: &[E::ScalarField], + sk: &SecretKey, + ) -> Vec> { + self.mem + .compute_membership_witnesses_for_batch(members, sk) + .into_iter() + .map(|w| w.into()) + .collect() + } + + pub fn compute_non_membership_witnesses_for_batch( + &self, + members: &[E::ScalarField], + sk: &SecretKey, + ) -> Vec> { + self.non_mem + .compute_membership_witnesses_for_batch(members, sk) + .into_iter() + .map(|w| w.into()) + .collect() + } + + fn compute_update_for_batch( + elements: &[E::ScalarField], + sk: &SecretKey, + ) -> (E::ScalarField, E::ScalarField) { + let update = Poly_d::::eval_direct(&elements, &-sk.0); + let update_inv = update.inverse().unwrap(); + (update, update_inv) + } + + fn compute_update_for_batches( + additions: &[E::ScalarField], + removals: &[E::ScalarField], + sk: &SecretKey, + ) -> (E::ScalarField, E::ScalarField) { + let update_add = if !additions.is_empty() { + Poly_d::::eval_direct(&additions, &-sk.0) + } else { + E::ScalarField::one() + }; + let update_rem = if !removals.is_empty() { + Poly_d::::eval_direct(&removals, &-sk.0) + } else { + E::ScalarField::one() + }; + let update_mem = update_add * update_rem.inverse().unwrap(); + let update_non_mem = update_mem.inverse().unwrap(); + (update_mem, update_non_mem) + } } #[cfg(test)] @@ -327,6 +507,11 @@ pub mod tests { let (params, keypair, mut accumulator, domain, mut mem_state, mut non_mem_state) = setup_kb_universal_accum(&mut rng, max); + let accumulator_ = KBUniversalAccumulator::::initialize_empty(¶ms); + let (mem, non_mem) = accumulator_.compute_extended(&domain, &keypair.secret_key); + assert_eq!(*accumulator.mem_value(), mem); + assert_eq!(*accumulator.non_mem_value(), non_mem); + let mut total_mem_check_time = Duration::default(); let mut total_non_mem_check_time = Duration::default(); let count = max; @@ -348,9 +533,13 @@ pub mod tests { )); total_non_mem_check_time += start.elapsed(); + let nm_wit_ = accumulator.compute_non_membership_witness(&elem, &keypair.secret_key); + assert_eq!(nm_wit, nm_wit_); + assert!(!mem_state.has(&elem)); assert!(non_mem_state.has(&elem)); + let accumulator_ = accumulator.compute_new_post_add(&elem, &keypair.secret_key); accumulator = accumulator .add( elem, @@ -363,13 +552,41 @@ pub mod tests { assert!(mem_state.has(&elem)); assert!(!non_mem_state.has(&elem)); + assert_eq!(*accumulator.mem_value(), accumulator_.0); + assert_eq!(*accumulator.non_mem_value(), accumulator_.1); + + start = Instant::now(); let m_wit = accumulator .get_membership_witness(&elem, &keypair.secret_key, &mem_state) .unwrap(); - - start = Instant::now(); assert!(accumulator.verify_membership(&elem, &m_wit, &keypair.public_key, ¶ms)); total_mem_check_time += start.elapsed(); + + let m_wit_ = accumulator.compute_membership_witness(&elem, &keypair.secret_key); + assert_eq!(m_wit, m_wit_); + } + + for i in 0..count { + let elem = domain[i].clone(); + + assert!(mem_state.has(&elem)); + assert!(!non_mem_state.has(&elem)); + + let accumulator_ = accumulator.compute_new_post_remove(&elem, &keypair.secret_key); + accumulator = accumulator + .remove( + elem, + &keypair.secret_key, + &mut mem_state, + &mut non_mem_state, + ) + .unwrap(); + + assert!(!mem_state.has(&elem)); + assert!(non_mem_state.has(&elem)); + + assert_eq!(*accumulator.mem_value(), accumulator_.0); + assert_eq!(*accumulator.non_mem_value(), accumulator_.1); } println!( @@ -417,6 +634,8 @@ pub mod tests { } // Add as a batch + let accumulator_ = + accumulator_2.compute_new_post_add_batch(&additions, &keypair.secret_key); accumulator_2 = accumulator_2 .add_batch( additions.clone(), @@ -428,6 +647,8 @@ pub mod tests { assert_eq!(accumulator_1.value(), accumulator_2.value()); assert_eq!(mem_state.db, state_2_mem.db); assert_eq!(non_mem_state.db, state_2_non_mem.db); + assert_eq!(*accumulator_2.mem_value(), accumulator_.0); + assert_eq!(*accumulator_2.non_mem_value(), accumulator_.1); // Remove one by one for i in 0..removals.len() { @@ -442,6 +663,8 @@ pub mod tests { } // Remove as a batch + let accumulator_ = + accumulator_2.compute_new_post_remove_batch(&removals, &keypair.secret_key); accumulator_2 = accumulator_2 .remove_batch( removals.clone(), @@ -453,6 +676,8 @@ pub mod tests { assert_eq!(accumulator_1.value(), accumulator_2.value()); assert_eq!(mem_state.db, state_2_mem.db); assert_eq!(non_mem_state.db, state_2_non_mem.db); + assert_eq!(*accumulator_2.mem_value(), accumulator_.0); + assert_eq!(*accumulator_2.non_mem_value(), accumulator_.1); // Need to make `accumulator_3` same as `accumulator_1` and `accumulator_2` by doing batch addition and removal simultaneously. // To do the removals, first they need to be added to the accumulator and the additions elements need to be adjusted. @@ -473,6 +698,11 @@ pub mod tests { assert_ne!(accumulator_2.value(), accumulator_3.value()); // Add and remove as a batch + let accumulator_ = accumulator_3.compute_new_post_batch_updates( + &new_additions, + &removals, + &keypair.secret_key, + ); accumulator_3 = accumulator_3 .batch_updates( new_additions.clone(), @@ -490,6 +720,9 @@ pub mod tests { assert_eq!(mem_state.db, state_3_mem.db); assert_eq!(non_mem_state.db, state_3_non_mem.db); + assert_eq!(*accumulator_3.mem_value(), accumulator_.0); + assert_eq!(*accumulator_3.non_mem_value(), accumulator_.1); + let mem_witnesses = accumulator_3 .get_membership_witnesses_for_batch(&new_additions, &keypair.secret_key, &state_3_mem) .unwrap(); @@ -501,7 +734,11 @@ pub mod tests { ¶ms )); } - let npn_mem_witnesses = accumulator_3 + let mem_witnesses_ = accumulator_3 + .compute_membership_witnesses_for_batch(&new_additions, &keypair.secret_key); + assert_eq!(mem_witnesses, mem_witnesses_); + + let non_mem_witnesses = accumulator_3 .get_non_membership_witnesses_for_batch( &removals, &keypair.secret_key, @@ -511,10 +748,13 @@ pub mod tests { for i in 0..removals.len() { assert!(accumulator_3.verify_non_membership( &removals[i], - &npn_mem_witnesses[i], + &non_mem_witnesses[i], &keypair.public_key, ¶ms )); } + let non_mem_witnesses_ = accumulator_3 + .compute_non_membership_witnesses_for_batch(&removals, &keypair.secret_key); + assert_eq!(non_mem_witnesses, non_mem_witnesses_); } } diff --git a/vb_accumulator/src/kb_universal_accumulator/proofs_keyed_verification.rs b/vb_accumulator/src/kb_universal_accumulator/proofs_keyed_verification.rs index 84afdd35..194db203 100644 --- a/vb_accumulator/src/kb_universal_accumulator/proofs_keyed_verification.rs +++ b/vb_accumulator/src/kb_universal_accumulator/proofs_keyed_verification.rs @@ -28,6 +28,7 @@ pub struct KBUniversalAccumulatorMembershipProofProtocol( #[derive( Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize, )] +#[serde(bound = "")] pub struct KBUniversalAccumulatorMembershipProof(pub MembershipProof); #[serde_as] @@ -47,6 +48,7 @@ pub struct KBUniversalAccumulatorNonMembershipProofProtocol( #[derive( Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize, )] +#[serde(bound = "")] pub struct KBUniversalAccumulatorNonMembershipProof(pub MembershipProof); #[serde_as] diff --git a/vb_accumulator/src/kb_universal_accumulator/witness.rs b/vb_accumulator/src/kb_universal_accumulator/witness.rs index 23c80198..124138c4 100644 --- a/vb_accumulator/src/kb_universal_accumulator/witness.rs +++ b/vb_accumulator/src/kb_universal_accumulator/witness.rs @@ -357,16 +357,32 @@ impl KBUniversalAccumulator { let (mem_d_A, mut mem_d_D): (Vec<_>, Vec<_>) = cfg_into_iter!(0..p) .map(|i| { ( - mem_add_poly[i][0] * (additions[0] - members[i]), - mem_rem_poly[i][n - 1] * (removals[n - 1] - members[i]), + if additions.is_empty() { + E::ScalarField::one() + } else { + mem_add_poly[i][0] * (additions[0] - members[i]) + }, + if removals.is_empty() { + E::ScalarField::one() + } else { + mem_rem_poly[i][n - 1] * (removals[n - 1] - members[i]) + }, ) }) .unzip(); let (non_mem_d_A, mut non_mem_d_D): (Vec<_>, Vec<_>) = cfg_into_iter!(0..q) .map(|i| { ( - non_mem_add_poly[i][0] * (removals[0] - non_members[i]), - non_mem_rem_poly[i][m - 1] * (additions[m - 1] - non_members[i]), + if removals.is_empty() { + E::ScalarField::one() + } else { + non_mem_add_poly[i][0] * (removals[0] - non_members[i]) + }, + if additions.is_empty() { + E::ScalarField::one() + } else { + non_mem_rem_poly[i][m - 1] * (additions[m - 1] - non_members[i]) + }, ) }) .unzip(); @@ -388,7 +404,13 @@ impl KBUniversalAccumulator { let mem_poly_v_D = inner_product(&factors_rem_inv, &mem_rem_poly[j]); - mem_poly_v_A - (mem_poly_v_D * factors_add[m - 1]) + mem_poly_v_A + - (mem_poly_v_D + * if additions.is_empty() { + E::ScalarField::one() + } else { + factors_add[m - 1] + }) }) .collect::>(); @@ -403,7 +425,13 @@ impl KBUniversalAccumulator { let non_mem_poly_v_D = inner_product(&factors_add_inv, &non_mem_rem_poly[j]); - non_mem_poly_v_A - (non_mem_poly_v_D * factors_rem[n - 1]) + non_mem_poly_v_A + - (non_mem_poly_v_D + * if removals.is_empty() { + E::ScalarField::one() + } else { + factors_rem[n - 1] + }) }) .collect::>(); @@ -936,6 +964,20 @@ mod tests { )); } + let (membership_witnesses_2_, non_membership_witnesses_2_) = accumulator_3 + .update_both_wit_using_secret_key_on_batch_updates( + &[], + &[], + &additions_1, + &membership_witnesses_2, + &non_members, + &non_membership_witnesses_2, + &keypair.secret_key, + ) + .unwrap(); + assert_eq!(membership_witnesses_2_, membership_witnesses_2); + assert_eq!(non_membership_witnesses_2_, non_membership_witnesses_2); + let start = Instant::now(); let (membership_witnesses_4, non_membership_witnesses_4) = accumulator_3 .update_both_wit_using_secret_key_on_batch_updates( @@ -1028,5 +1070,11 @@ mod tests { "Time to generate Omega for witnesses in single calls {:?}", omega_time_1 ); + + let (_, __) = + accumulator_3.generate_omega_for_both_witnesses(&[], &remaining, &keypair.secret_key); + + let (_, __) = + accumulator_3.generate_omega_for_both_witnesses(&additions_3, &[], &keypair.secret_key); } } diff --git a/vb_accumulator/src/positive.rs b/vb_accumulator/src/positive.rs index cbef8930..6cb4fd49 100644 --- a/vb_accumulator/src/positive.rs +++ b/vb_accumulator/src/positive.rs @@ -362,7 +362,7 @@ pub trait Accumulator { } /// Compute membership witness for batch - fn compute_membership_witness_for_batch( + fn compute_membership_witnesses_for_batch( &self, members: &[E::ScalarField], sk: &SecretKey, @@ -390,7 +390,7 @@ pub trait Accumulator { return Err(VBAccumulatorError::ElementAbsent); } } - Ok(self.compute_membership_witness_for_batch(members, sk)) + Ok(self.compute_membership_witnesses_for_batch(members, sk)) } /// Check if element present in accumulator given the accumulated value. Described in section 2 of the paper @@ -814,7 +814,8 @@ pub mod tests { )); } assert_eq!( - accumulator_3.compute_membership_witness_for_batch(&new_additions, &keypair.secret_key), + accumulator_3 + .compute_membership_witnesses_for_batch(&new_additions, &keypair.secret_key), witnesses ); diff --git a/vb_accumulator/src/universal.rs b/vb_accumulator/src/universal.rs index 035b4dc8..24a09008 100644 --- a/vb_accumulator/src/universal.rs +++ b/vb_accumulator/src/universal.rs @@ -494,7 +494,7 @@ impl UniversalAccumulator { /// Compute non-membership witnesses for a batch {`y_i`} given their `d`s, where `d = f_V(-y_i)` /// for each member `y_i` - pub fn compute_non_membership_witness_for_batch_given_d( + pub fn compute_non_membership_witnesses_for_batch_given_d( &self, d: Vec, non_members: &[E::ScalarField], @@ -572,7 +572,7 @@ impl UniversalAccumulator { } } - self.compute_non_membership_witness_for_batch_given_d( + self.compute_non_membership_witnesses_for_batch_given_d( d_for_witnesses, non_members, sk, @@ -1038,7 +1038,8 @@ pub mod tests { )); } assert_eq!( - accumulator_3.compute_membership_witness_for_batch(&new_additions, &keypair.secret_key), + accumulator_3 + .compute_membership_witnesses_for_batch(&new_additions, &keypair.secret_key), mem_witnesses ); @@ -1067,7 +1068,7 @@ pub mod tests { ); assert_eq!( accumulator_3 - .compute_non_membership_witness_for_batch_given_d( + .compute_non_membership_witnesses_for_batch_given_d( d, &removals, &keypair.secret_key,