Skip to content

Commit

Permalink
Revise logic regarding regular accounts and initial accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
DOBEN committed Aug 15, 2024
1 parent 6fc8619 commit 7912098
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 26 deletions.
78 changes: 53 additions & 25 deletions compliant-reward-distribution/indexer-and-server/src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use axum::{
use chrono::Utc;
use clap::Parser;
use concordium_rust_sdk::{
common::types::{CredentialIndex, KeyIndex},
id::{
constants::ArCurve,
id_proof_types::Statement,
Expand Down Expand Up @@ -334,13 +333,11 @@ async fn check_zk_proof(
// above which means that one `verifiable_credential` exists.
let credential_proof = &presentation.verifiable_credential[0];

// Get the revealed `national_id`, `nationality` and `account_address` from the
// Get the revealed `national_id`, `nationality` and `cred_id` from the
// credential proof.
let (national_id, nationality, prover) = match credential_proof {
let (national_id, nationality, cred_id) = match credential_proof {
CredentialProof::Account {
proofs,
cred_id,
..
proofs, cred_id, ..
} => {
// Get the revealed `national_id` from the proof.
// Accessing the index at position `0` is safe because we checked that
Expand Down Expand Up @@ -368,23 +365,39 @@ async fn check_zk_proof(
_ => return Err(ServerError::RevealAttribute(index_1)),
};

// Get the `prover` which is the `account_address` that created the proof.
let account_info = state
.node_client
.get_account_info(
&AccountIdentifier::CredId(*cred_id),
BlockIdentifier::LastFinal,
)
.await
.map_err(ServerError::QueryError)?
.response;
let prover = account_info.account_address;

(national_id, nationality, prover)
(national_id, nationality, cred_id)
}
_ => return Err(ServerError::AccountStatement),
};

// Get the `prover` which is the `account_address` that created the proof.
let account_info = state
.node_client
.get_account_info(
&AccountIdentifier::CredId(*cred_id),
BlockIdentifier::LastFinal,
)
.await
.map_err(ServerError::QueryError)?
.response;
let prover = account_info.account_address;

// Exclude `Initial` accounts from the proof verification.

// This backend only supports regular accounts with exactly one credential (no mulit-sig account support).
if account_info.account_credentials.len() != 1 {
return Err(ServerError::OnlyRegularAccounts);
}
let credential = account_info
.account_credentials
.get(&0.into())
.ok_or(ServerError::OnlyRegularAccounts)?;
// `Initial` accounts were created by identity providers in the past
// without a Pedersen commitment deployed on chain. As such we should not verify proofs on them.
if let AccountCredentialWithoutProofs::Initial { .. } = &credential.value {
return Err(ServerError::NoCredentialCommitment);
};

Ok(ZKProofExtractedData {
national_id,
nationality,
Expand Down Expand Up @@ -450,14 +463,29 @@ where
// reduce complexity we will communicate that multi-sig accounts are not
// supported. Regular accounts have only one public-private key pair at
// index 0 in the credential map.
let signer_account_credential =
&signer_account_info.response.account_credentials[&CredentialIndex::from(0)].value;
let signer_account_credential = match signer_account_info
.response
.account_credentials
.get(&0.into())
{
Some(credential) => &credential.value,
_ => return Err(ServerError::OnlyRegularAccounts),
};

// We use/support regular accounts. Regular accounts have only one
// public-private key pair at index 0 in the key map.
let signer_public_key = match signer_account_credential {
AccountCredentialWithoutProofs::Initial { icdv } => &icdv.cred_account.keys[&KeyIndex(0)],
AccountCredentialWithoutProofs::Normal { cdv, .. } => &cdv.cred_key_info.keys[&KeyIndex(0)],
// `Initial` accounts were created by identity providers in the past
// without a Pedersen commitment deployed on chain. As such we should not verify ZK proofs
// on them so that we exclude them from this service.
AccountCredentialWithoutProofs::Initial { .. } => {
return Err(ServerError::NoCredentialCommitment)
}
// We use/support regular accounts. Regular accounts have only one
// public-private key pair at index 0 in the key map.
AccountCredentialWithoutProofs::Normal { cdv, .. } => cdv
.cred_key_info
.keys
.get(&0.into())
.ok_or(ServerError::OnlyRegularAccounts)?,
};

// Verify the signature.
Expand Down
10 changes: 9 additions & 1 deletion compliant-reward-distribution/indexer-and-server/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ pub enum ServerError {
ProofExpired(u64),
#[error("Failed to convert type `{0}`: {1}")]
TypeConversion(String, IncorrectLength),
#[error(
"Only regular accounts are supported by this backend. No support for multi-sig accounts."
)]
OnlyRegularAccounts,
#[error("No credential commitment on chain.")]
NoCredentialCommitment,
}

impl IntoResponse for ServerError {
Expand Down Expand Up @@ -152,7 +158,9 @@ impl IntoResponse for ServerError {
| ServerError::ChallengeInvalid
| ServerError::SignatureExpired(_)
| ServerError::ProofExpired(_)
| ServerError::TypeConversion(..) => {
| ServerError::TypeConversion(..)
| ServerError::OnlyRegularAccounts
| ServerError::NoCredentialCommitment => {
let error_message = format!("Bad request: {self}");
tracing::info!(error_message);
(StatusCode::BAD_REQUEST, error_message.into())
Expand Down

0 comments on commit 7912098

Please sign in to comment.