Skip to content

Commit

Permalink
Expand to use several ZK proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
DOBEN committed Aug 1, 2024
1 parent 7948a90 commit 6cf98f2
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 33 deletions.
43 changes: 41 additions & 2 deletions compliant-reward-distribution/indexer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ cargo run --bin indexer -- --help
## Configure the `server`

```console
cargo run --bin server -- --admin_accounts "47b6Qe2XtZANHetanWKP1PbApLKtS3AyiCtcXaqLMbypKjCaRw" --admin_accounts "4KjE4rptF1o3QX6XuSaQzm6w9KLYYQTbKm2Zd4NooarH6YwfxS"
cargo run --bin server -- --zk_statements "$(<./zk_statements_config.json)" --admin_accounts "47b6Qe2XtZANHetanWKP1PbApLKtS3AyiCtcXaqLMbypKjCaRw" --admin_accounts "4KjE4rptF1o3QX6XuSaQzm6w9KLYYQTbKm2Zd4NooarH6YwfxS"
```

```
Expand All @@ -81,6 +81,45 @@ curl -POST "http://localhost:8080/api/canClaim" -H "Content-Type: application/js
curl -POST "http://localhost:8080/api/getAccountData" -H "Content-Type: application/json" --data '{"accountAddress":"3cGEB7tTdQBFxJ9sn5JyGPNay2MSmRSKm4133UVqmKoFg4MXJ1","signingData":{"signer":"47b6Qe2XtZANHetanWKP1PbApLKtS3AyiCtcXaqLMbypKjCaRw","message":{"blockHash":"4e68a9f9a671f4b62963cbade295c1b47b74838dabf78c451740c1e060ab0069","blockHeight":3},"signature":"4e68a9f9a671f4b62963cbade295c1b47b74838dabf78c451740c1e060ab00694e68a9f9a671f4b62963cbade295c1b47b74838dabf78c451740c1e060ab0069"}}' -v
```

Proof statements:

1.Proof: Reveal "nationalIdNo"

2.Proof: Reveal "nationality"

3.Proof: Range proof (older than 18 years)

4.Proof: Not set membership proof (countryOfResidence is not in USA or North Korea -> https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)


```
[
{
"type": "RevealAttribute",
"attributeTag": "nationalIdNo"
},
{
"type": "RevealAttribute",
"attributeTag": "nationality"
},
{
"type": "AttributeInRange",
"attributeTag": "dob",
"lower": "18000101",
"upper": "20060802"
},
{
"type": "AttributeNotInSet",
"attributeTag": "countryOfResidence",
"set": [
"US", "KP"
]
}
]
```

An example proof for the above statement:

```
curl -POST "http://localhost:8080/api/postZKProof" -H "Content-Type: application/json" --data '{"presentation":{"presentationContext":"7fb546cd185db58421070aac59d0c91922c49d173fb944695c920fb15f69f947","proof":{"created":"2024-07-23T11:22:01.562Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8280babfd0a412ea2aeb2f707193e804a6104d150c5e095343c8b225ba496ad6c208a9e6bf54990a966f7d0b54cfed2e","proof":{"created":"2024-07-23T11:22:01.561Z","proofValue":[{"attribute":"John","proof":"df0ddf8d269fa2c97305ad28bafa163b0e26b3cb3d8e64fff91f5a3c97f43dd556bc8c8019845b5e670ddc9c833f38773dbbd30258aa3a6b3a7f2dbd5abaaf37","type":"RevealAttribute"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"firstName","type":"RevealAttribute"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}}' -v
curl -POST "http://localhost:8080/api/postZKProof" -H "Content-Type: application/json" --data '{"presentation":{"presentationContext":"e4ebb397c3200236e62899926dead2437b5510bc38535f1d7412acd3108bf176","proof":{"created":"2024-08-01T15:30:38.714Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8280babfd0a412ea2aeb2f707193e804a6104d150c5e095343c8b225ba496ad6c208a9e6bf54990a966f7d0b54cfed2e","proof":{"created":"2024-08-01T15:30:38.714Z","proofValue":[{"attribute":"N-1234","proof":"9460bcbed089cb2b982c5eaea5d384ea115a6e2bb64626b5a8ee63e506f210c71b63731561d539787c515e54b8dc9a03a2d76c4fd84c2f6628baf837a7ffd7f6","type":"RevealAttribute"},{"attribute":"DK","proof":"3e634eb45e9ea9eef5dbf870a2278d3415835acec501cdb2256f15da1f9873f067e88f10e69ccf2c9b68d5cbe54613fe28986fb7285ccf9c5a7b4e0831434f8f","type":"RevealAttribute"},{"proof":"9531e090941c3097bc93316340f7a5ca6eb5b753381cb9cdeae662feb0b238217daf3177dc0e814f6dc6f9751159cccf90e18307bdc0f987e599e6968e4deb7988bd02096728caaf09630b7ad97bc8dca4cf977222fe528439d419a7f08921088cbefa7d467d4e68d3881b188c89ec0c833cbe57c8eacd9f94313392148d019ed1d02dc21fd7f790b58b0425d064243e81498d32a58910f305ac088fdfaa5f540ce459c10072c8736840d7271d38b130eefa91eae56745cb94acc0e5e9a8d10464137eca11b5df9ffe0cea4fa44164c253f11204bf1b8b83781f77d5c29a26d61dcf28512e3622e36f5ae21f39463e4f44595d6a5df0e90a776e187c608952163deee44f8a55f694fac36bf7e1d8b8cc2c249819319b3fe45aa4f6b4947dacbb00000007b3359516fd5904cc76254824f39c7eeac50e70be9d9c4dbc70492d63ae694d21f8393f72254d2cc5cc598362a8238356a6d1f47e3760ee6c4b3e96178504b846eaeac90445288dcdeaa77fbbb04a066fc9152d35e9605707978ed7efc18a77c5a6cf91c37b14b451c54aa889aed60dc9f87fdfc48951094a16f7df50725360f6413a077cf3c02ec42e693bcb2116d932a784a1b1fc03a45f050364f28c753ac47d214f1d9f3c9a895766ae4b844341d5b66d592db2fedcd8d1e26ea294b0be20b3ca63fbf12b6de00f072710142c3ce4cec841962ad9e4cb86cfeb858096acaaf3cd82207826c904f823c6185c4466caa0645945a07a95f3543cd07e29188f683d8b5d9533c60165cd2d9b5bf36bfe535ddb2762c1ca1ca99d804bced24fdc678031463916aaf3b9f1b4d058c1c56078623a8758747ac8bf5ac5bad38b16540f5b721c68ffac9109943d1ed22d63a7dd837d9775dfa254ecbea3ecce4a72850a1ec214797d12591cc765ead961ac8b4518e4210e0f48bde9cc16c5c8a2453a74826cb59d10efc2331ad4e64c30e503ce05cda02434974519fd759268501b5ff64e390ac6535dde688ae46deae40c9d46b6a740ab2ae47e2a5abb7b5cd4f5e7292e54b51f1d77beab83520b3093493f5550b0583a5c65955ce7b9c1810707d30587788e386820723ab62382a1ea0c4d049befa891f4da04fd3a73632f6474dacac97e2dd1655fef6ed18f4d3a94a556b8aae09e7698cf09179a35d9c44344826a8fa11e8d2cbdd8c2f9493d990fc71a7daf77d58833f20c251e32246c7a5242adb33a535f1e2a5ecb452400b0ea0ca468828a99aeb0e7ec315513a949f63c3aebe7dae589b802533a0799b72f4c62df4ea324469e0fcbb29c378edd32ef97222bfddf37ef14547604abb012800ef39dbe3a5b41dc960345e5e2476af869d68c03387a87ec92c8432dfe9e7519d78b7f89337eb6d02ff256833efb79d24d96bfd106fe802f53b0d1883af0faea50d3f4d8201e9d699c1a3a5c232bdb7390bf1ff2","type":"AttributeInRange"},{"proof":"8a6ca0735cc329e7492121aae961d36fddfd00cdbe3ca6b1938da6d46ddc8a1cfcf42bdf18566c93d0d605b46d51d0a39987b60fb81533500c449d7374e8654278bcf770b01b34ab0c796fe7aa634588d22023ee989bd490c7d8e032e467c5e19999967add875f9ea7775c62aa16c8e193203f5f4790b6dbff19f9c2ea7a91e9c3ea7ab86f20b8afd9d8b442c38c66b190aa70eb2919015a5efa395db9c3eac339c18d01782bade45813535a01c81bdaa94aaeca917016aeee641fdce01ccdcb701d79bb0892dffb11cca8f1643cbfa21c240712ac852782f9655260008d0e0d2dba8d31369434f55f522e17ff9c3e069ba70f63e3eb9c5c2d539e583d81842b3c503d9599b92f2899af5cd9ff3d7d7089343a1fdf2e6374a9a63c5ddd97a0b700000001aa5dae6529b7d62c8173ce1cbd1a05364d37cdf0d5a2d38938f63db50c4d6ec9e65450b016de4fe5526d65261880cbc7ae800c250342895617158c1fab6f7fdcd138f39a7555ebb27f8a91e9619da1c959333e718bb6dfcb509ec6ef2fee692531d28f499093c9993089b585e314aea83e67e7a01fa7fe08ae51e07b259e285802a726fcd15271517d46c4899ca31241c95a66707bfc60850940f508bd3a6ef5","type":"AttributeNotInSet"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"nationalIdNo","type":"RevealAttribute"},{"attributeTag":"nationality","type":"RevealAttribute"},{"attributeTag":"dob","lower":"18000101","type":"AttributeInRange","upper":"20060802"},{"attributeTag":"countryOfResidence","set":["KP","US"],"type":"AttributeNotInSet"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}}' -v
```
59 changes: 28 additions & 31 deletions compliant-reward-distribution/indexer/src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use concordium_rust_sdk::{
contract_client::CredentialStatus,
id::{
constants::ArCurve,
id_proof_types::{AtomicStatement, RevealAttributeStatement},
types::{AccountAddress, AccountCredentialWithoutProofs, AttributeTag, GlobalContext},
id_proof_types::Statement,
types::{AccountAddress, AccountCredentialWithoutProofs, GlobalContext},
},
types::{AbsoluteBlockHeight, AccountInfo},
v2::{AccountIdentifier, BlockIdentifier, Client, QueryResponse},
Expand All @@ -38,12 +38,6 @@ const TESTNET_GENESIS_BLOCK_HASH: [u8; 32] = [
];

/// TODO: think if we want to save the statements in the database.
const ZK_STATEMENT_0: RevealAttributeStatement<AttributeTag> = RevealAttributeStatement {
attribute_tag: AttributeTag(0),
};
// const ZK_STATEMENT_1: RevealAttributeStatement<AttributeTag> = RevealAttributeStatement {
// attribute_tag: AttributeTag(0),
// };

/// Server struct to store the db_pool.
#[derive(Clone, Debug)]
Expand All @@ -53,6 +47,7 @@ pub struct Server {
network: Network,
cryptographic_param: GlobalContext<ArCurve>,
admin_accounts: Vec<AccountAddress>,
zk_statements: Statement<ArCurve, Web3IdAttribute>,
}

/// Errors that this server can produce.
Expand Down Expand Up @@ -80,10 +75,12 @@ pub enum ServerError<'a> {
InvalidProof(#[from] PresentationVerificationError),
#[error("Wrong length of {0}. Expect {1}. Got {2}")]
WrongLength(&'a str, usize, usize),
#[error("Statement {0} is wrong")]
WrongStatement(u8),
#[error("Wrong ZK statement proven")]
WrongStatement,
#[error("Expect account statement and not web3id statement")]
AccountStatement,
#[error("Do not expect initial account credential")]
NotInitialAccountCredential,
}

/// Mapping DatabaseError to ServerError
Expand Down Expand Up @@ -122,7 +119,8 @@ impl<'a> IntoResponse for ServerError<'a> {
| ServerError::InvalidProof(_)
| ServerError::WrongLength(..)
| ServerError::AccountStatement
| ServerError::WrongStatement(_) => {
| ServerError::WrongStatement
| ServerError::NotInitialAccountCredential => {
let error_message = format!("Bad request: {self}");
tracing::warn!(error_message);
(StatusCode::BAD_REQUEST, error_message.into())
Expand Down Expand Up @@ -180,6 +178,11 @@ struct Args {
env = "CCD_SERVER_ADMIN_ACCOUNTS"
)]
admin_accounts: Vec<AccountAddress>,
#[clap(
long = "zk_statements",
help = "The ZK statements that the server accepts proofs for."
)]
zk_statements: String,
}

/// The main function.
Expand Down Expand Up @@ -237,12 +240,17 @@ async fn main() -> anyhow::Result<()> {
.context("Unable to get cryptographic parameters.")?
.response;

// TODO: handle unwrap
let zk_statements: Statement<ArCurve, Web3IdAttribute> =
serde_json::from_str(&app.zk_statements).unwrap();

let state = Server {
db_pool,
node_client,
network,
cryptographic_param,
admin_accounts: app.admin_accounts,
zk_statements,
};

tracing::info!("Starting server...");
Expand Down Expand Up @@ -330,6 +338,7 @@ async fn post_zk_proof<'a>(
));
}

// We only use regular accounts with (exactly one credential).
let account_statement = request.credential_statements[0].clone();

match account_statement {
Expand All @@ -354,26 +363,14 @@ async fn post_zk_proof<'a>(
// TODO: use account_address to insert into database.
let _account_address = account_info.account_address;

if let Some(AtomicStatement::RevealAttribute { statement: stmt }) = statement.first() {
if stmt != &ZK_STATEMENT_0 {
return Err(ServerError::WrongStatement(0));
}
} else {
return Err(ServerError::WrongStatement(0));
if statement != state.zk_statements.statements {
return Err(ServerError::WrongStatement);
}

// if let Some(AtomicStatement::RevealAttribute { statement: stmt }) = statement.get(1) {
// if stmt != &ZK_STATEMENT_1 {
// return Err(ServerError::WrongStatement(0));
// }
// } else {
// return Err(ServerError::WrongStatement(0));
// }
}
Web3Id { .. } => return Err(ServerError::AccountStatement),
}

// TODO check that proof is not expired.
// TODO check that proof is not expired -> TODO: check the challenge

Ok(Json(true))
}
Expand Down Expand Up @@ -506,11 +503,11 @@ fn check_admin_and_signature<'a>(
// We use regular accounts as admin 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,
commitments: _,
} => &cdv.cred_key_info.keys[&KeyIndex(0)],
// TODO: usually not allowed
AccountCredentialWithoutProofs::Initial { .. } => {
return Err(ServerError::NotInitialAccountCredential)
}
AccountCredentialWithoutProofs::Normal { cdv, .. } => &cdv.cred_key_info.keys[&KeyIndex(0)],
};

let valid_signature = signer_public_key.verify(message_hash, signature);
Expand Down
23 changes: 23 additions & 0 deletions compliant-reward-distribution/indexer/zk_statements_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"type": "RevealAttribute",
"attributeTag": "nationalIdNo"
},
{
"type": "RevealAttribute",
"attributeTag": "nationality"
},
{
"type": "AttributeInRange",
"attributeTag": "dob",
"lower": "18000101",
"upper": "20060802"
},
{
"type": "AttributeNotInSet",
"attributeTag": "countryOfResidence",
"set": [
"US", "KP"
]
}
]

0 comments on commit 6cf98f2

Please sign in to comment.