#[cfg(test)]
mod tests {
use crate::id::{account_holder, chain, identity_provider};
use crate::web3id::{
Challenge, CommitmentInputs, CredentialStatement, CredentialsInputs, Request,
Web3IdAttribute,
};
use crate::{
base::CredentialRegistrationID,
id::{
id_proof_types::AtomicStatement,
types::{AttributeList, AttributeTag, GlobalContext, IpIdentity},
},
};
use crate::{
common::types::{KeyIndex, KeyPair},
id::{
constants::BaseField,
id_proof_types::AttributeInRangeStatement,
test::*,
types::{
CredentialData, IdentityObjectV1, IpData, Policy, SystemAttributeRandomness,
YearMonth,
},
},
web3id::did::Network,
};
use concordium_contracts_common::SignatureThreshold;
use either::Either::Left;
use rand::Rng;
use std::collections::BTreeMap;
use std::marker::PhantomData;
type ExampleAttributeList = AttributeList<BaseField, Web3IdAttribute>;
fn test_create_attribute_list(
attribute_tag: u8,
numeric_attribute_value: u64,
) -> ExampleAttributeList {
let mut alist = BTreeMap::new();
alist.insert(
AttributeTag::from(attribute_tag),
Web3IdAttribute::Numeric(numeric_attribute_value),
);
let valid_to = YearMonth::try_from(2022 << 8 | 5).unwrap(); let created_at = YearMonth::try_from(2020 << 8 | 5).unwrap(); ExampleAttributeList {
valid_to,
created_at,
max_accounts: 237,
alist,
_phantom: Default::default(),
}
}
#[test]
fn test_deploy_account_credentials_and_test_verifiable_presentation_from_account_credentials() {
let mut rng = rand::thread_rng();
let global_ctx = GlobalContext::generate(String::from("genesis_string"));
let numeric_attribute_value = 137u64;
let attribute_tag = AttributeTag(3u8);
let max_attrs = 10;
let num_ars = 5;
let IpData {
public_ip_info: ip_info,
ip_secret_key,
..
} = test_create_ip_info(&mut rng, num_ars, max_attrs);
let (ars_infos, _) =
test_create_ars(&global_ctx.on_chain_commitment_key.g, num_ars, &mut rng);
let id_use_data = test_create_id_use_data(&mut rng);
let (context, pio, randomness) = test_create_pio_v1(
&id_use_data,
&ip_info,
&ars_infos,
&global_ctx,
num_ars,
&mut rng,
);
assert!(
*randomness == *id_use_data.randomness,
"Returned randomness is not equal to used randomness."
);
let alist = test_create_attribute_list(attribute_tag.0, numeric_attribute_value);
let ver_ok =
identity_provider::verify_credentials_v1(&pio, context, &alist, &ip_secret_key);
assert!(ver_ok.is_ok(), "Signature on the credential is invalid.");
let ip_sig = ver_ok.unwrap();
let id_object = IdentityObjectV1 {
pre_identity_object: pio,
alist,
signature: ip_sig,
};
let valid_to = YearMonth::try_from(2022 << 8 | 5).unwrap(); let created_at = YearMonth::try_from(2020 << 8 | 5).unwrap(); let policy = Policy {
valid_to,
created_at,
policy_vec: { BTreeMap::new() },
_phantom: Default::default(),
};
let acc_data = CredentialData {
keys: {
let mut keys = BTreeMap::new();
keys.insert(KeyIndex(0), KeyPair::generate(&mut rng));
keys.insert(KeyIndex(1), KeyPair::generate(&mut rng));
keys.insert(KeyIndex(2), KeyPair::generate(&mut rng));
keys
},
threshold: SignatureThreshold::TWO,
};
let (cdi, commitment_randomness) = account_holder::create_credential(
context,
&id_object,
&id_use_data,
0,
policy.clone(),
&acc_data,
&SystemAttributeRandomness {},
&Left(EXPIRY),
)
.expect("Should generate the credential successfully.");
let cdi_check = chain::verify_cdi(&global_ctx, &ip_info, &ars_infos, &cdi, &Left(EXPIRY));
assert_eq!(cdi_check, Ok(()));
let randomness: BTreeMap<_, _> = commitment_randomness
.attributes_rand
.iter()
.map(|(a, r)| (*a, r.clone()))
.collect();
let secrets = CommitmentInputs::Account::<_, _, KeyPair> {
values: &id_object.alist.alist,
randomness: &randomness,
issuer: IpIdentity::from(0u32),
};
let commitment_inputs = [secrets];
let challenge = Challenge::new(rng.gen());
let cred_id = CredentialRegistrationID::new(cdi.values.cred_id);
let credential_statements = vec![CredentialStatement::Account {
network: Network::Testnet,
cred_id,
statement: vec![AtomicStatement::AttributeInRange {
statement: AttributeInRangeStatement {
attribute_tag,
lower: Web3IdAttribute::Numeric(0),
upper: Web3IdAttribute::Numeric(1237),
_phantom: PhantomData,
},
}],
}];
let request = Request {
challenge,
credential_statements,
};
let proof = request
.clone()
.prove(&global_ctx, commitment_inputs.into_iter())
.expect("Cannot prove");
let commitments = cdi.proofs.id_proofs.commitments.cmm_attributes.clone();
let public = vec![CredentialsInputs::Account { commitments }];
assert_eq!(
proof
.verify(&global_ctx, public.iter())
.expect("Verification of presentation failed."),
request,
"Proof verification failed."
);
}
}