use std::{borrow::Borrow, collections::BTreeMap};
use super::{types::*, utils};
use crate::bulletproofs::{
range_proof::{verify_in_range, RangeProof, VerificationError},
set_membership_proof::verify as verify_set_membership,
set_non_membership_proof::verify as verify_set_non_membership,
utils::Generators,
};
use super::id_proof_types::*;
use crate::bulletproofs::set_membership_proof::SetMembershipProof;
use crate::bulletproofs::set_non_membership_proof::SetNonMembershipProof;
use crate::random_oracle::{RandomOracle, TranscriptProtocol};
use crate::sigma_protocols::common::SigmaProof;
use crate::sigma_protocols::dlog;
use crate::{
curve_arithmetic::{Curve, Field},
pedersen_commitment::{
Commitment, CommitmentKey as PedersenKey, Randomness as PedersenRandomness, Value,
},
sigma_protocols::{common::verify as sigma_verify, dlog::Dlog},
};
use sha2::{Digest, Sha256};
pub fn verify_attribute<C: Curve, AttributeType: Attribute<C::Scalar>>(
keys: &PedersenKey<C>,
attribute: &AttributeType,
r: &PedersenRandomness<C>,
c: &Commitment<C>,
) -> bool {
let s = Value::new(attribute.to_field_element());
keys.open(&s, r, c)
}
#[allow(clippy::too_many_arguments)]
pub fn verify_attribute_range<C: Curve, AttributeType: Attribute<C::Scalar>>(
version: ProofVersion,
transcript: &mut impl TranscriptProtocol,
keys: &PedersenKey<C>,
gens: &Generators<C>,
lower: &AttributeType,
upper: &AttributeType,
c: &Commitment<C>,
proof: &RangeProof<C>,
) -> Result<(), VerificationError> {
let a = lower.to_field_element();
let b = upper.to_field_element();
match version {
ProofVersion::Version1 => {
#[allow(deprecated)]
let mut transcript_v1 = RandomOracle::domain("attribute_range_proof");
verify_in_range(
ProofVersion::Version1,
&mut transcript_v1,
keys,
gens,
a,
b,
c,
proof,
)
}
ProofVersion::Version2 => {
transcript.append_label(b"AttributeRangeProof");
transcript.append_message(b"a", &a);
transcript.append_message(b"b", &b);
verify_in_range(
ProofVersion::Version2,
transcript,
keys,
gens,
a,
b,
c,
proof,
)
}
}
}
pub fn verify_account_ownership(
public_data: &CredentialPublicKeys,
account: AccountAddress,
challenge: &[u8],
proof: &AccountOwnershipProof,
) -> bool {
let mut hasher = Sha256::new();
hasher.update(account.0);
hasher.update([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]);
hasher.update(b"account_ownership_proof");
hasher.update(challenge);
let to_sign = &hasher.finalize();
utils::verify_account_ownership_proof(&public_data.keys, public_data.threshold, proof, to_sign)
}
impl<C: Curve, AttributeType: Attribute<C::Scalar>> StatementWithContext<C, AttributeType> {
pub fn verify(
&self,
version: ProofVersion,
challenge: &[u8],
global: &GlobalContext<C>,
commitments: &CredentialDeploymentCommitments<C>,
proofs: &Proof<C, AttributeType>,
) -> bool {
self.statement.verify(
version,
challenge,
global,
&self.credential,
commitments,
proofs,
)
}
}
impl<
C: Curve,
TagType: std::cmp::Ord + crate::common::Serialize,
AttributeType: Attribute<C::Scalar>,
> AtomicStatement<C, TagType, AttributeType>
{
pub(crate) fn verify<Q: std::cmp::Ord + Borrow<TagType>>(
&self,
version: ProofVersion,
global: &GlobalContext<C>,
transcript: &mut impl TranscriptProtocol,
cmm_attributes: &BTreeMap<Q, Commitment<C>>,
proof: &AtomicProof<C, AttributeType>,
) -> bool {
match (self, proof) {
(
AtomicStatement::RevealAttribute {
statement: RevealAttributeStatement { attribute_tag },
},
AtomicProof::RevealAttribute { attribute, proof },
) => {
let maybe_com = cmm_attributes.get(attribute_tag);
if let Some(com) = maybe_com {
verify_value_equal_to_commitment(
attribute, com, version, global, transcript, proof,
)
} else {
false
}
}
(
AtomicStatement::AttributeInRange { statement },
AtomicProof::AttributeInRange { proof },
) => statement.verify(version, global, transcript, cmm_attributes, proof),
(
AtomicStatement::AttributeInSet { statement },
AtomicProof::AttributeInSet { proof },
) => statement.verify(version, global, transcript, cmm_attributes, proof),
(
AtomicStatement::AttributeNotInSet { statement },
AtomicProof::AttributeNotInSet { proof },
) => statement.verify(version, global, transcript, cmm_attributes, proof),
_ => false,
}
}
}
impl<
C: Curve,
TagType: std::cmp::Ord + crate::common::Serialize,
AttributeType: Attribute<C::Scalar>,
> AttributeInRangeStatement<C, TagType, AttributeType>
{
pub(crate) fn verify<Q: std::cmp::Ord + Borrow<TagType>>(
&self,
version: ProofVersion,
global: &GlobalContext<C>,
transcript: &mut impl TranscriptProtocol,
cmm_attributes: &BTreeMap<Q, Commitment<C>>,
proof: &RangeProof<C>,
) -> bool {
let maybe_com = cmm_attributes.get(&self.attribute_tag);
if let Some(com) = maybe_com {
super::id_verifier::verify_attribute_range(
version,
transcript,
&global.on_chain_commitment_key,
global.bulletproof_generators(),
&self.lower,
&self.upper,
com,
proof,
)
.is_ok()
} else {
false
}
}
}
impl<
C: Curve,
TagType: std::cmp::Ord + crate::common::Serialize,
AttributeType: Attribute<C::Scalar>,
> AttributeInSetStatement<C, TagType, AttributeType>
{
pub(crate) fn verify<Q: std::cmp::Ord + Borrow<TagType>>(
&self,
version: ProofVersion,
global: &GlobalContext<C>,
transcript: &mut impl TranscriptProtocol,
cmm_attributes: &BTreeMap<Q, Commitment<C>>,
proof: &SetMembershipProof<C>,
) -> bool {
let maybe_com = cmm_attributes.get(&self.attribute_tag);
if let Some(com) = maybe_com {
let attribute_vec: Vec<_> = self.set.iter().map(|x| x.to_field_element()).collect();
verify_set_membership(
version,
transcript,
&attribute_vec,
com,
proof,
global.bulletproof_generators(),
&global.on_chain_commitment_key,
)
.is_ok()
} else {
false
}
}
}
impl<
C: Curve,
TagType: std::cmp::Ord + crate::common::Serialize,
AttributeType: Attribute<C::Scalar>,
> AttributeNotInSetStatement<C, TagType, AttributeType>
{
pub(crate) fn verify<Q: std::cmp::Ord + Borrow<TagType>>(
&self,
version: ProofVersion,
global: &GlobalContext<C>,
transcript: &mut impl TranscriptProtocol,
cmm_attributes: &BTreeMap<Q, Commitment<C>>,
proof: &SetNonMembershipProof<C>,
) -> bool {
let maybe_com = cmm_attributes.get(&self.attribute_tag);
if let Some(com) = maybe_com {
let attribute_vec: Vec<_> = self.set.iter().map(|x| x.to_field_element()).collect();
verify_set_non_membership(
version,
transcript,
&attribute_vec,
com,
proof,
global.bulletproof_generators(),
&global.on_chain_commitment_key,
)
.is_ok()
} else {
false
}
}
}
fn verify_value_equal_to_commitment<C: Curve, AttributeType: Attribute<C::Scalar>>(
attribute_value: &AttributeType,
attribute_cmm: &Commitment<C>,
version: ProofVersion,
global: &GlobalContext<C>,
transcript: &mut impl TranscriptProtocol,
proof: &SigmaProof<dlog::Response<C>>,
) -> bool {
let x = attribute_value.to_field_element();
transcript.append_label(b"RevealAttributeDlogProof");
transcript.append_message(b"x", &x);
if version >= ProofVersion::Version2 {
transcript.append_message(b"keys", &global.on_chain_commitment_key);
transcript.append_message(b"C", &attribute_cmm);
}
let mut minus_x = x;
minus_x.negate();
let g_minus_x = global.on_chain_commitment_key.g.mul_by_scalar(&minus_x);
let public = attribute_cmm.plus_point(&g_minus_x);
let verifier = Dlog {
public, coeff: global.on_chain_commitment_key.h, };
sigma_verify(transcript, &verifier, proof)
}
impl<
C: Curve,
TagType: std::cmp::Ord + crate::common::Serialize,
AttributeType: Attribute<C::Scalar>,
> AttributeValueStatement<C, TagType, AttributeType>
{
pub(crate) fn verify<Q: std::cmp::Ord + Borrow<TagType>>(
&self,
version: ProofVersion,
global: &GlobalContext<C>,
transcript: &mut impl TranscriptProtocol,
cmm_attributes: &BTreeMap<Q, Commitment<C>>,
proof: &AttributeValueProof<C>,
) -> bool {
let Some(attribute_cmm) = cmm_attributes.get(&self.attribute_tag) else {
return false;
};
verify_value_equal_to_commitment(
&self.attribute_value,
attribute_cmm,
version,
global,
transcript,
&proof.proof,
)
}
pub(crate) fn verify_for_already_revealed(
&self,
transcript: &mut impl TranscriptProtocol,
revealed_attributes: &BTreeMap<TagType, &AttributeType>,
) -> bool {
let Some(revealed_attribute) = revealed_attributes.get(&self.attribute_tag) else {
return false;
};
transcript.append_message("RevealedAttribute", &self.attribute_value);
self.attribute_value == **revealed_attribute
}
}
impl<C: Curve, AttributeType: Attribute<C::Scalar>> Statement<C, AttributeType> {
pub fn verify(
&self,
version: ProofVersion,
challenge: &[u8],
global: &GlobalContext<C>,
credential: &CredId<C>,
commitments: &CredentialDeploymentCommitments<C>,
proofs: &Proof<C, AttributeType>,
) -> bool {
#[allow(deprecated)]
let mut transcript = RandomOracle::domain("Concordium ID2.0 proof");
transcript.append_message(b"ctx", &global);
transcript.add_bytes(challenge);
transcript.append_message(b"credential", credential);
if self.statements.len() != proofs.proofs.len() {
return false;
}
for (statement, proof) in self.statements.iter().zip(proofs.proofs.iter()) {
if !statement.verify(
version,
global,
&mut transcript,
&commitments.cmm_attributes,
proof,
) {
return false;
}
}
true
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::id::constants::ArCurve;
use crate::id::id_prover;
use crate::{
common::types::{KeyIndex, KeyPair},
curve_arithmetic::arkworks_instances::ArkGroup,
id::{constants::AttributeKind, id_prover::*},
};
use ark_bls12_381::G1Projective;
use rand::*;
use std::{
collections::{btree_map::BTreeMap, BTreeSet},
convert::TryFrom,
marker::PhantomData,
};
type G1 = ArkGroup<G1Projective>;
#[test]
fn test_verify_account_ownership() {
let mut csprng = thread_rng();
let cred_data = CredentialData {
keys: {
let mut keys = BTreeMap::new();
keys.insert(KeyIndex(0), KeyPair::generate(&mut csprng));
keys.insert(KeyIndex(1), KeyPair::generate(&mut csprng));
keys.insert(KeyIndex(2), KeyPair::generate(&mut csprng));
keys
},
threshold: SignatureThreshold::TWO,
};
let pub_data = cred_data.get_cred_key_info();
let reg_id: G1 =
Curve::hash_to_group(b"some_bytes").expect("Hashing to curve expected to succeed");
let account_address = account_address_from_registration_id(®_id);
let challenge = b"13549686546546546854651357687354";
let proof = prove_ownership_of_account(&cred_data, account_address, challenge);
assert!(verify_account_ownership(
&pub_data,
account_address,
challenge,
&proof
));
}
#[test]
fn test_verify_attribute() {
let mut csprng = thread_rng();
let keys = PedersenKey::<G1>::generate(&mut csprng);
let attribute =
AttributeKind::try_new("some attribute value".to_string()).expect("attribute kind");
let value = Value::<G1>::new(attribute.to_field_element());
let (commitment, randomness) = keys.commit(&value, &mut csprng);
assert!(
verify_attribute(&keys, &attribute, &randomness, &commitment),
"Incorrect opening of attribute."
);
}
#[test]
fn test_verify_attribute_in_range() {
let mut csprng = thread_rng();
let global = GlobalContext::<G1>::generate(String::from("genesis_string"));
let keys = global.on_chain_commitment_key;
let gens = global.bulletproof_generators();
let lower = AttributeKind::try_new("20000102".to_string()).expect("attribute kind");
let attribute = AttributeKind::try_new("20000102".to_string()).expect("attribute kind");
let upper = AttributeKind::try_new("20000103".to_string()).expect("attribute kind");
let value = Value::<G1>::new(attribute.to_field_element());
let (commitment, randomness) = keys.commit(&value, &mut csprng);
let mut transcript = RandomOracle::domain("Test");
let maybe_proof = prove_attribute_in_range(
ProofVersion::Version1,
&mut transcript.split(),
&mut thread_rng(),
gens,
&keys,
&attribute,
&lower,
&upper,
&randomness,
);
if let Some(proof) = maybe_proof {
assert_eq!(
verify_attribute_range(
ProofVersion::Version1,
&mut transcript,
&keys,
gens,
&lower,
&upper,
&commitment,
&proof
),
Ok(()),
"Incorrect version 1 range proof."
);
} else {
panic!("Failed to produce version 1 proof.");
};
let mut transcript = RandomOracle::domain("Test");
let maybe_proof = prove_attribute_in_range(
ProofVersion::Version2,
&mut transcript.split(),
&mut thread_rng(),
gens,
&keys,
&attribute,
&lower,
&upper,
&randomness,
);
if let Some(proof) = maybe_proof {
assert_eq!(
verify_attribute_range(
ProofVersion::Version2,
&mut transcript,
&keys,
gens,
&lower,
&upper,
&commitment,
&proof
),
Ok(()),
"Incorrect version 2 range proof."
);
} else {
panic!("Failed to produce version 2 proof.");
};
}
#[test]
fn test_verify_value_equal_to_commitment() {
let mut csprng = thread_rng();
let global = GlobalContext::<G1>::generate(String::from("genesis_string"));
let keys = global.on_chain_commitment_key;
let attribute = AttributeKind::try_new("testvalue".to_string()).expect("attribute kind");
let value = Value::<G1>::new(attribute.to_field_element());
let (commitment, randomness) = keys.commit(&value, &mut csprng);
let mut transcript = RandomOracle::domain("Test");
let proof = id_prover::prove_value_equal_to_commitment(
&attribute,
randomness.clone(),
ProofVersion::Version1,
&global,
&mut transcript.split(),
&mut csprng,
)
.expect("prove");
assert!(
verify_value_equal_to_commitment(
&attribute,
&commitment,
ProofVersion::Version1,
&global,
&mut transcript,
&proof
),
"verify"
);
let mut transcript = RandomOracle::domain("Test");
let proof = id_prover::prove_value_equal_to_commitment(
&attribute,
randomness,
ProofVersion::Version2,
&global,
&mut transcript.split(),
&mut csprng,
)
.expect("prove");
assert!(
verify_value_equal_to_commitment(
&attribute,
&commitment,
ProofVersion::Version2,
&global,
&mut transcript,
&proof
),
"verify"
);
let attribute2 = AttributeKind::try_new("testvalue2".to_string()).expect("attribute kind");
assert!(
!verify_value_equal_to_commitment(
&attribute2,
&commitment,
ProofVersion::Version2,
&global,
&mut transcript,
&proof
),
"verify"
);
}
#[test]
fn test_attribute_value_statement() {
let mut csprng = thread_rng();
let global = GlobalContext::<G1>::generate(String::from("genesis_string"));
let keys = global.on_chain_commitment_key;
let attribute = AttributeKind::try_new("testvalue".to_string()).expect("attribute kind");
let value = Value::<G1>::new(attribute.to_field_element());
let (commitment, randomness) = keys.commit(&value, &mut csprng);
let statement = AttributeValueStatement {
attribute_tag: AttributeTag(1),
attribute_value: attribute,
_phantom: Default::default(),
};
let attribute_randomness: BTreeMap<_, _> = [(AttributeTag(1), randomness.clone())]
.into_iter()
.collect();
let mut transcript = RandomOracle::domain("Test");
let proof = statement
.prove(
ProofVersion::Version2,
&global,
&mut transcript.split(),
&mut csprng,
&attribute_randomness,
)
.expect("prove");
let attribute_commitments: BTreeMap<_, _> =
[(AttributeTag(1), commitment)].into_iter().collect();
assert!(
statement.verify(
ProofVersion::Version2,
&global,
&mut transcript,
&attribute_commitments,
&proof
),
"verify"
);
let statement = AttributeValueStatement {
attribute_value: AttributeKind::try_new("testvalue2".to_string())
.expect("attribute kind"),
..statement
};
assert!(
!statement.verify(
ProofVersion::Version2,
&global,
&mut transcript,
&attribute_commitments,
&proof
),
"verify"
);
}
#[test]
fn test_attribute_value_statement_revealed() {
let attribute = AttributeKind::try_new("testvalue".to_string()).expect("attribute kind");
let statement = AttributeValueStatement::<ArCurve, _, _> {
attribute_tag: AttributeTag(1),
attribute_value: attribute.clone(),
_phantom: Default::default(),
};
let mut transcript = RandomOracle::domain("Test");
statement.prove_for_already_revealed(&mut transcript.split());
let revealed_attributes: BTreeMap<_, _> =
[(AttributeTag(1), &attribute)].into_iter().collect();
assert!(
statement.verify_for_already_revealed(&mut transcript, &revealed_attributes,),
"verify"
);
let statement = AttributeValueStatement {
attribute_value: AttributeKind::try_new("testvalue2".to_string())
.expect("attribute kind"),
..statement
};
assert!(
!statement.verify_for_already_revealed(&mut transcript, &revealed_attributes,),
"verify"
);
}
#[test]
fn test_verify_attribute_in_range_shift_cheat() {
let mut csprng = thread_rng();
let global = GlobalContext::<G1>::generate(String::from("genesis_string"));
let keys = global.on_chain_commitment_key;
let gens = global.bulletproof_generators();
let lower = AttributeKind::try_new("20000102".to_string()).expect("attribute kind");
let attribute = AttributeKind::try_new("20000102".to_string()).expect("attribute kind");
let upper = AttributeKind::try_new("20000103".to_string()).expect("attribute kind");
let value = Value::<G1>::new(attribute.to_field_element());
let (commitment, randomness) = keys.commit(&value, &mut csprng);
let mut transcript = RandomOracle::domain("Test");
let maybe_proof = prove_attribute_in_range(
ProofVersion::Version2,
&mut transcript.split(),
&mut thread_rng(),
gens,
&keys,
&attribute,
&lower,
&upper,
&randomness,
);
let lower_shifted = AttributeKind::try_new("20000107".to_string()).expect("attribute kind");
let upper_shifted = AttributeKind::try_new("20000108".to_string()).expect("attribute kind");
let five = G1::scalar_from_u64(5);
let five_value: Value<G1> = Value::new(five);
let five_com = keys.hide(&five_value, &PedersenRandomness::zero());
let commitment_shifted = Commitment(commitment.0.plus_point(&five_com));
if let Some(proof) = maybe_proof {
assert_eq!(
verify_attribute_range(
ProofVersion::Version2,
&mut transcript,
&keys,
gens,
&lower_shifted,
&upper_shifted,
&commitment_shifted,
&proof
)
.is_ok(),
false,
"Shifting statement and commitment using same proof should fail."
);
} else {
panic!("Failed to produce proof.");
};
}
struct TestRandomness {
randomness: BTreeMap<AttributeTag, PedersenRandomness<G1>>,
}
impl HasAttributeRandomness<G1> for TestRandomness {
type ErrorType = ImpossibleError;
fn get_attribute_commitment_randomness(
&self,
attribute_tag: &AttributeTag,
) -> Result<PedersenRandomness<G1>, Self::ErrorType> {
match self.randomness.get(attribute_tag) {
Some(r) => Ok(r.clone()),
_ => {
let mut csprng = rand::thread_rng();
Ok(PedersenRandomness::generate(&mut csprng))
}
}
}
}
#[test]
fn test_verify_id_attributes_proofs() {
let point: G1 =
Curve::hash_to_group(b"some_bytes").expect("Hashing to curve expected to succeed");
let cmm_prf = Commitment(point);
let cmm_max_accounts = Commitment(point);
let cmm_cred_counter = Commitment(point);
let attribute_name = AttributeKind::try_new(String::from("Foo")).expect("attribute kind"); let attribute_country = AttributeKind::try_new(String::from("DK")).expect("attribute kind"); let attribute_dob =
AttributeKind::try_new(String::from("19970505")).expect("attribute kind"); let attribute_doc_expiry =
AttributeKind::try_new(String::from("20250505")).expect("attribute kind");
let reveal_statement = RevealAttributeStatement {
attribute_tag: AttributeTag::from(0u8),
};
let dk = AttributeKind::try_new(String::from("DK")).expect("attribute kind");
let no = AttributeKind::try_new(String::from("NO")).expect("attribute kind");
let se = AttributeKind::try_new(String::from("SE")).expect("attribute kind");
let de = AttributeKind::try_new(String::from("DE")).expect("attribute kind");
let uk = AttributeKind::try_new(String::from("UK")).expect("attribute kind");
let set = BTreeSet::from([dk, no, se, de.clone(), uk.clone()]);
let set2 = BTreeSet::from([de, uk]);
let set_statement = AttributeInSetStatement::<G1, _, AttributeKind> {
attribute_tag: AttributeTag::from(4u8),
_phantom: PhantomData::default(),
set: set.clone(),
};
let range_statement = AttributeInRangeStatement {
attribute_tag: AttributeTag::from(3u8),
lower: AttributeKind::try_new(String::from("19950505")).expect("attribute kind"),
upper: AttributeKind::try_new(String::from("19990505")).expect("attribute kind"),
_phantom: PhantomData::default(),
};
let full_statement = StatementWithContext {
credential: point,
statement: Statement {
statements: vec![
AtomicStatement::RevealAttribute {
statement: reveal_statement,
},
AtomicStatement::AttributeInSet {
statement: set_statement,
},
AtomicStatement::AttributeInRange {
statement: range_statement,
},
],
},
};
let statement2 = Statement::new()
.older_than(18)
.unwrap()
.younger_than(35)
.unwrap()
.residence_in(set)
.unwrap()
.residence_not_in(set2)
.unwrap()
.doc_expiry_no_earlier_than(
AttributeKind::try_new(String::from("20240304")).expect("attribute kind"),
)
.unwrap();
let full_statement2 = StatementWithContext {
credential: point,
statement: statement2,
};
let mut csprng = rand::thread_rng();
let global = GlobalContext::generate(String::from("Some genesis string"));
let keys = global.on_chain_commitment_key;
let (name_com, name_randomness) = keys.commit(
&Value::<G1>::new(attribute_name.to_field_element()),
&mut csprng,
);
let (country_com, country_randomness) = keys.commit(
&Value::<G1>::new(attribute_country.to_field_element()),
&mut csprng,
);
let (dob_com, dob_randomness) = keys.commit(
&Value::<G1>::new(attribute_dob.to_field_element()),
&mut csprng,
);
let (expiry_com, expiry_randomness) = keys.commit(
&Value::<G1>::new(attribute_doc_expiry.to_field_element()),
&mut csprng,
);
let mut alist = BTreeMap::new();
alist.insert(AttributeTag::from(0u8), attribute_name);
alist.insert(AttributeTag::from(3u8), attribute_dob);
alist.insert(AttributeTag::from(4u8), attribute_country);
alist.insert(AttributeTag::from(10u8), attribute_doc_expiry);
let valid_to = YearMonth::try_from(2022 << 8 | 5).unwrap(); let created_at = YearMonth::try_from(2020 << 8 | 5).unwrap(); let attribute_list: AttributeList<_, AttributeKind> = AttributeList {
valid_to,
created_at,
max_accounts: 237,
alist,
_phantom: Default::default(),
};
let mut randomness = BTreeMap::new();
randomness.insert(AttributeTag::from(0u8), name_randomness);
randomness.insert(AttributeTag::from(3u8), dob_randomness);
randomness.insert(AttributeTag::from(4u8), country_randomness);
randomness.insert(AttributeTag::from(10u8), expiry_randomness);
let attribute_randomness = TestRandomness { randomness };
let challenge = [0u8; 32]; let proof = full_statement.prove(
ProofVersion::Version1,
&global,
&challenge,
&attribute_list,
&attribute_randomness,
);
assert!(proof.is_some());
let proof = proof.unwrap();
let challenge2 = [1u8; 32]; let proof2 = full_statement2.prove(
ProofVersion::Version1,
&global,
&challenge2,
&attribute_list,
&attribute_randomness,
);
assert!(proof2.is_some());
let proof2 = proof2.unwrap();
let mut alist = BTreeMap::new();
alist.insert(AttributeTag::from(0u8), name_com); alist.insert(AttributeTag::from(3u8), dob_com); alist.insert(AttributeTag::from(4u8), country_com); alist.insert(AttributeTag::from(10u8), expiry_com);
let coms = CredentialDeploymentCommitments {
cmm_prf,
cmm_max_accounts,
cmm_id_cred_sec_sharing_coeff: vec![],
cmm_cred_counter,
cmm_attributes: alist, };
let result =
full_statement.verify(ProofVersion::Version1, &challenge, &global, &coms, &proof);
assert!(result, "Version 1 statement should verify.");
let result2 =
full_statement2.verify(ProofVersion::Version1, &challenge2, &global, &coms, &proof2);
assert!(result2, "Version 1 statement 2 should verify.");
let proof = full_statement.prove(
ProofVersion::Version2,
&global,
&challenge,
&attribute_list,
&attribute_randomness,
);
assert!(proof.is_some());
let proof = proof.unwrap();
let proof2 = full_statement2.prove(
ProofVersion::Version2,
&global,
&challenge2,
&attribute_list,
&attribute_randomness,
);
assert!(proof2.is_some());
let proof2 = proof2.unwrap();
let result =
full_statement.verify(ProofVersion::Version2, &challenge, &global, &coms, &proof);
assert!(result, "Version 2 statement should verify.");
let result2 =
full_statement2.verify(ProofVersion::Version2, &challenge2, &global, &coms, &proof2);
assert!(result2, "Version 2 statement 2 should verify.");
}
}