Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
## Unreleased changes

- Added `web3id::v1::anchor` module that contains functionality to create verification request anchor (VRA) and verification audit anchor (VAA) on chain.
- Implemented `web3id::v1` module that contains functionality to support the verification flow of Concordium verifiable presentations V1.
This includes
- creating verification request anchor (VRA)
- verifying presentations
- creating verification audit anchor (VAA)

The main entrypoints in the module are `v1::create_verification_request_and_submit_request_anchor`
and `v1::verify_presentation_and_submit_audit_anchor`.

## 8.0.0

Expand Down
2 changes: 1 addition & 1 deletion concordium-base
Submodule concordium-base updated 68 files
+1 −0 identity-provider-service/Cargo.lock
+1 −0 idiss/Cargo.lock
+1 −0 mobile_wallet/Cargo.lock
+1 −0 rust-bins/Cargo.lock
+1 −0 rust-src/Cargo.lock
+6 −2 rust-src/concordium_base/CHANGELOG.md
+4 −0 rust-src/concordium_base/Cargo.toml
+5 −0 rust-src/concordium_base/benches/bulletproofs.rs
+6 −0 rust-src/concordium_base/benches/encrypted_transfers_benchmarks.rs
+6 −0 rust-src/concordium_base/benches/set_proof_bench.rs
+2 −0 rust-src/concordium_base/src/aggregate_sig/ffi.rs
+1 −1 rust-src/concordium_base/src/base.rs
+17 −9 rust-src/concordium_base/src/bulletproofs/inner_product_proof.rs
+22 −23 rust-src/concordium_base/src/bulletproofs/range_proof.rs
+14 −14 rust-src/concordium_base/src/bulletproofs/set_membership_proof.rs
+14 −14 rust-src/concordium_base/src/bulletproofs/set_non_membership_proof.rs
+7 −1 rust-src/concordium_base/src/common/cbor.rs
+281 −34 rust-src/concordium_base/src/common/serialize.rs
+1 −1 rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs
+2 −0 rust-src/concordium_base/src/eddsa_ed25519/ffi.rs
+4 −0 rust-src/concordium_base/src/encrypted_transfers/mod.rs
+1 −0 rust-src/concordium_base/src/encrypted_transfers/proofs/enc_to_pub_stable.hex
+1 −0 rust-src/concordium_base/src/encrypted_transfers/proofs/enc_trans_stable.hex
+118 −1 rust-src/concordium_base/src/encrypted_transfers/proofs/generate_proofs.rs
+5 −1 rust-src/concordium_base/src/id/account_holder.rs
+2 −1 rust-src/concordium_base/src/id/chain.rs
+34 −1 rust-src/concordium_base/src/id/id_proof_types.rs
+191 −66 rust-src/concordium_base/src/id/id_prover.rs
+374 −98 rust-src/concordium_base/src/id/id_verifier.rs
+14 −14 rust-src/concordium_base/src/id/identity_attributes_credentials.rs
+1 −1 rust-src/concordium_base/src/id/identity_attributes_credentials_stable_proof.hex
+4 −1 rust-src/concordium_base/src/id/identity_provider.rs
+30 −1 rust-src/concordium_base/src/id/secret_sharing.rs
+298 −0 rust-src/concordium_base/src/id/test.rs
+1 −0 rust-src/concordium_base/src/id/test/cdi_stable_bytes.hex
+1 −0 rust-src/concordium_base/src/id/test/cdi_v1_stable_bytes.hex
+1 −0 rust-src/concordium_base/src/id/test/init_cdi_stable_bytes.hex
+1 −0 rust-src/concordium_base/src/id/test/pio_stable_bytes.hex
+1 −0 rust-src/concordium_base/src/id/test/pio_v1_stable_bytes.hex
+3 −3 rust-src/concordium_base/src/id/types.rs
+471 −106 rust-src/concordium_base/src/random_oracle/mod.rs
+5 −5 rust-src/concordium_base/src/sigma_protocols/aggregate_dlog.rs
+3 −3 rust-src/concordium_base/src/sigma_protocols/com_enc_eq.rs
+3 −3 rust-src/concordium_base/src/sigma_protocols/com_eq.rs
+3 −3 rust-src/concordium_base/src/sigma_protocols/com_eq_different_groups.rs
+4 −5 rust-src/concordium_base/src/sigma_protocols/com_eq_sig.rs
+3 −1 rust-src/concordium_base/src/sigma_protocols/com_ineq.rs
+6 −7 rust-src/concordium_base/src/sigma_protocols/com_lin.rs
+5 −5 rust-src/concordium_base/src/sigma_protocols/com_mult.rs
+10 −8 rust-src/concordium_base/src/sigma_protocols/common.rs
+4 −3 rust-src/concordium_base/src/sigma_protocols/dlog.rs
+5 −3 rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs
+4 −2 rust-src/concordium_base/src/sigma_protocols/dlogeq.rs
+8 −8 rust-src/concordium_base/src/sigma_protocols/enc_trans.rs
+4 −4 rust-src/concordium_base/src/sigma_protocols/ps_sig_known.rs
+5 −5 rust-src/concordium_base/src/sigma_protocols/vcom_eq.rs
+3 −2 rust-src/concordium_base/src/web3id/did.rs
+3 −1 rust-src/concordium_base/src/web3id/proofs.rs
+460 −230 rust-src/concordium_base/src/web3id/v1.rs
+1,169 −637 rust-src/concordium_base/src/web3id/v1/anchor.rs
+1,583 −0 rust-src/concordium_base/src/web3id/v1/anchor/verify.rs
+724 −95 rust-src/concordium_base/src/web3id/v1/proofs.rs
+36 −3 rust-src/concordium_base_derive/src/cbor.rs
+139 −8 rust-src/concordium_base_derive/src/lib.rs
+66 −3 rust-src/wallet_library/src/proofs.rs
+2 −0 smart-contracts/contracts-common/concordium-contracts-common-derive/CHANGELOG.md
+5 −15 smart-contracts/contracts-common/concordium-contracts-common-derive/src/lib.rs
+4 −4 smart-contracts/contracts-common/concordium-contracts-common/src/types.rs
127 changes: 0 additions & 127 deletions examples/create_validation_request_anchor.rs

This file was deleted.

191 changes: 191 additions & 0 deletions examples/web3id_v1_verification_flow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
//! Example that shows how to verify a verifiable presentation
//! together with the verification request. See
//! [`crate::web3id::v1`].
//!
//! You can run this example as follows:
//! cargo run --example web3id_v1_verification_flow -- --node http://localhost:20100 --account 3nhMYfA59MWaxBRjfHPKSYH9S4W5HdZZ721jozVdeToBGvXTU8.export
use anyhow::Context as AnyhowContext;
use clap::AppSettings;
use concordium_base::web3id::v1::anchor;
use concordium_base::web3id::v1::anchor::{
IdentityCredentialType, IdentityProviderDid, RequestedIdentitySubjectClaimsBuilder,
RequestedStatement, UnfilledContextInformationBuilder, VerifiablePresentationV1,
VerificationRequest, VerificationRequestDataBuilder,
};
use concordium_rust_sdk::v2::BlockIdentifier;
use concordium_rust_sdk::web3id::v1::{AnchorTransactionMetadata, AuditRecordArgument};
use concordium_rust_sdk::{
base::{
common::cbor,
id::id_proof_types::AttributeInRangeStatement,
web3id::{did::Network, Web3IdAttribute},
},
common::types::TransactionTime,
types::WalletAccount,
v2::{self},
web3id,
};
use rand::Rng;
use std::{collections::HashMap, marker::PhantomData, path::PathBuf};
use structopt::*;

#[derive(StructOpt)]
struct App {
#[structopt(
long = "node",
help = "GRPC interface of the node.",
default_value = "http://localhost:20100"
)]
endpoint: v2::Endpoint,
#[structopt(long = "account", help = "Path to the account key file.")]
keys_path: PathBuf,
}

#[tokio::main(flavor = "multi_thread")]
async fn main() -> anyhow::Result<()> {
let app = {
let app = App::clap().global_setting(AppSettings::ColoredHelp);
let matches = app.get_matches();
App::from_clap(&matches)
};
let mut client = v2::Client::new(app.endpoint).await?;
let network = Network::Testnet;

// Load account keys and sender address from a file
let keys: WalletAccount =
WalletAccount::from_json_file(app.keys_path).context("Could not read the keys file.")?;

// Get the next account nonce
let account_sequence_number = client
.get_next_account_sequence_number(&keys.address)
.await?;
let account_sequence_number = account_sequence_number.nonce;

// Set expiry to now + 5min
let expiry: TransactionTime =
TransactionTime::from_seconds((chrono::Utc::now().timestamp() + 300) as u64);

// First we generate the verification request.
//
// Generating the `context` and `credential_statements` will normally happen server-side.
let mut rng = rand::thread_rng();
let nonce_bytes: [u8; 32] = rng.gen(); // todo ar use nonce bytes or hash, change back?
let nonce = anchor::Nonce(nonce_bytes); // Note: This nonce has to be generated fresh/randomly for each request.
let connection_id = "MyWalletConnectTopic".to_string(); // Note: Use the wallet connect topic in production.
let context_string = "MyGreateApp".to_string();
let context =
UnfilledContextInformationBuilder::new_simple(nonce, connection_id, context_string).build();

let attribute_in_range_statement =
RequestedStatement::AttributeInRange(AttributeInRangeStatement {
attribute_tag: 17.into(),
lower: Web3IdAttribute::Numeric(80),
upper: Web3IdAttribute::Numeric(1237),
_phantom: PhantomData,
});

let verification_request_data = VerificationRequestDataBuilder::new(context)
.subject_claim(
RequestedIdentitySubjectClaimsBuilder::default()
.issuer(IdentityProviderDid::new(0u32, network))
.source(IdentityCredentialType::IdentityCredential)
.statement(attribute_in_range_statement)
.build(),
)
.build();

let mut public_info = HashMap::new();
public_info.insert("key".to_string(), cbor::value::Value::Positive(4u64));

let anchor_transaction_metadata = AnchorTransactionMetadata {
signer: &keys,
sender: keys.address,
account_sequence_number,
expiry,
};

let verification_request = web3id::v1::create_verification_request_and_submit_request_anchor(
&mut client,
anchor_transaction_metadata,
verification_request_data,
Some(public_info.clone()),
)
.await?;

println!("Verification request: {:#?}", verification_request);

println!(
"Verification request anchor transaction hash: {}",
verification_request.anchor_transaction_hash
);

let (bh, _) = client
.wait_until_finalized(&verification_request.anchor_transaction_hash)
.await?;

println!("Verification request anchor finalized in block {}.", bh);

/// Send the verification request to the wallet/ID app and obtain the
/// verifiable presentation.
///
/// The wallet/ID app fills in the requested context in [`VerificationRequest::context`]
/// and selects and identity in order to form a
/// [`VerifiablePresentationRequestV1`](concordium_base::web3id::v1::anchor::VerifiablePresentationRequestV1).
/// that is then used to generate and prove a [`VerifiablePresentationV1`].
async fn send_request_and_receive_presentation(
_request: VerificationRequest,
) -> VerifiablePresentationV1 {
todo!("send verification request to wallet/ID app and receive verifiable presentation")
}

let presentation = send_request_and_receive_presentation(verification_request.clone()).await;

let audit_record_id = "UUID".to_string();

let audit_record_anchor_transaction_metadata = AnchorTransactionMetadata {
signer: &keys,
sender: keys.address,
account_sequence_number: account_sequence_number.next(), // We have to increase the nonce as this is the second anchor tx.
expiry,
};

let audit_record_argument = AuditRecordArgument {
audit_record_id,
audit_record_anchor_transaction_metadata,
public_info: Some(public_info),
};

let verification_data = web3id::v1::verify_presentation_and_submit_audit_anchor(
&mut client,
network,
BlockIdentifier::LastFinal,
verification_request,
presentation,
audit_record_argument,
)
.await?;

println!(
"Verification result: {:#?}",
verification_data.verification_result
);

println!(
"Generated anchored verification audit record to be stored in database: {:#?}",
verification_data.audit_record
);

if let Some(anchor_transaction_hash) = &verification_data.anchor_transaction_hash {
println!(
"Verifiable audit anchor transaction hash: {}",
anchor_transaction_hash
);

let (bh, bs) = client.wait_until_finalized(anchor_transaction_hash).await?;

println!("Verification request anchor finalized in block {}.", bh);
println!("The outcome is {:#?}", bs);
};

Ok(())
}
Loading