Skip to content

Commit

Permalink
Update documents and circuits (#13)
Browse files Browse the repository at this point in the history
* Feat/circuits update (#10)

* Update the zk-email version

* Update groth16 verifier

* Modify the proving key path

* Update the proving key in circuits README

* feat: add permitted wallets (#11)

* Feat/docs (#12)

* Reflect the latest changes on the main branch to the audit branch. (#7)

* Change modal server name.

* Add test to invitation code.

* Update zk-regex versions.

* update readme.

* Update modal server version.

* Fix typo.

* Fix contract unit tests.

* Fix Dockerfile in prover.

* feat: Add Relayer (#3)

* Add ECDSAOwnedDKIMRegistry.

* Update dev-setup.ts that generates Groth16Verifier.sol.

* Implement verifyEmailProof function.

* [WIP] Add implementations regarding authEmail function till step 7.

* Add isValidSignature function.

* Add EmailAccountRecovery.

* Move usedNullifiers from Verifier to EmailAuth.

* Tweak variable name.

* Update correct timestamp validation condition.

* Update isValidSignature function.

* Add unit test functions.

* Add testAuthEmail.

* Remove comment.

* Delete unused mock directory.

* Add testIsValidSignature.

* Format solidity files.

* Add deploy script.

* Modify ECSDSAOwnedDKIMRegistry to be independent of the chain id.

* Refactor EmailAuth contracts.

* Refactor EmailAccountRecovery.

* Add simple wallet to be recovered with emails.

* Fix EmailAuth.t.sol.

* Add DeploymentHelper.

* Add create SimpleWallet instance in setUp function.

* Add test EmailAccountRecovery.

* Fix EmailAccountRecovery.t.sol.

* Fix parameter decoding in recoverWallet method.

* Rename recoverWallet to processRecovery and add completeRecovery.

* Add recipient's email address commitment to the circuit.

* Add script to generate circuit inputs.

* Add prover.

* Add relayer.

* Update utils and relayer.

* Fix database.

* Remove unused code.

* Update database and web_server

* Fix config.rs

* Add ECDSAOwnedDKIMRegistry.

* Implement verifyEmailProof function.

* [WIP] Add implementations regarding authEmail function till step 7.

* Add isValidSignature function.

* Add EmailAccountRecovery.

* Move usedNullifiers from Verifier to EmailAuth.

* Tweak variable name.

* Update correct timestamp validation condition.

* Update isValidSignature function.

* Add unit test functions.

* Add testAuthEmail.

* Remove comment.

* Delete unused mock directory.

* Add testIsValidSignature.

* Format solidity files.

* Add deploy script.

* Modify ECSDSAOwnedDKIMRegistry to be independent of the chain id.

* Refactor EmailAuth contracts.

* Refactor EmailAccountRecovery.

* Add simple wallet to be recovered with emails.

* Fix EmailAuth.t.sol.

* Add DeploymentHelper.

* Add create SimpleWallet instance in setUp function.

* Add test EmailAccountRecovery.

* Fix EmailAccountRecovery.t.sol.

* Fix parameter decoding in recoverWallet method.

* Rename recoverWallet to processRecovery and add completeRecovery.

* Add recipient's email address commitment to the circuit.

* Add relayer.

* Update deployment helper.

* Fix unit testing

* Create Integration.t.sol.

* Add integration test for acceptance.

* Add integration test for recovery.

* Update README.md

* Call handleAcceptance and handleRecovery.

* Add require conditions and check the simpleWallet owner change.

* Add blank line.

* Fix database.

* Remove unused code.

* Update database and web_server

* Fix config.rs

* feat: relayer init

* feat: basic changes

* feat: changes

* feat: partial accept api

* feat: rebase

* feat: fixes

* feat: finish accept api before handling email

* feat: handle email stub

* feat: clean up

* feat: add all apis

* chore: refactor

* feat: add email templates

* feat: handle email

* Fix contract deployment scripts.

* Add github workflow.

* Add ETHERSCAN_API_KEY to env.sample.

* Add unit test functions.

* Add deploy script.

* Refactor EmailAuth contracts.

* feat: rebase

* feat: fixes

* Fix modal server name.

* feat: fixes

* feat: fixes

* Fix typo of EmailAccountRecoery.t.sol.

* feat: complete flow

* feat: fixes and refactoring

* chore: update .env.example

* Update utils package.

* feat: fixes

* feat: add k8s manifests

(cherry picked from commit 6f154f5)

* chore: fix Dockerfile

* Update the version of zk-regex-utils

---------

Co-authored-by: wshino <wshinohara@gmail.com>
Co-authored-by: SoraSuegami <suegamisora@gmail.com>

* Update OpenZeppelin libraries  (#5)

* Update @zk-email/contracts ^4.1.0 -> ^6.0.0.
Update @OpenZeppelin ^4.9.2 -> ^5.0.0.

* Regenerate verifier contract.

* Update integration test contract with regenerate eml files.

* Remove uniswap dependencies.

* Remove account abstraction dependency.

* Update the link for build_integration in google drive.

* forge install: forge-std

v1.8.1

* Re-generate yarn.lock.

* chore: update k8s manifests

(cherry picked from commit 72783078e6170f93665e5b6012d7ddd765fb44f9)

* Fix DeploySimpleWallet script to add initial owner.

* fix DeploySimpleWallet about init owner.

* Fix Groth16Verifier.

* Feat/unit testing for contracts (#6)

* Add configureTimelockPeriod to SimpleWallet.

---------

Co-authored-by: Aditya Bisht <44467788+Bisht13@users.noreply.github.com>
Co-authored-by: wshino <wshinohara@gmail.com>
Co-authored-by: Aditya Bisht <adityabisht64@gmail.com>

* Add more docs.

* Add Security Notes.

* Add Application.

* Add UX of the account recovery.

* Fix mistakes in README

* small modifications in README

* small modification to README

* Add remaining subsections.

* Write Integration to your Wallet.

* Fix mistakes.

* Add fronend description.

* Update specs.

* Complete the contracts spec.

* Add README to relayer.

---------

Co-authored-by: Aditya Bisht <44467788+Bisht13@users.noreply.github.com>
Co-authored-by: wshino <wshinohara@gmail.com>
Co-authored-by: Aditya Bisht <adityabisht64@gmail.com>

---------

Co-authored-by: Aditya Bisht <44467788+Bisht13@users.noreply.github.com>
Co-authored-by: wshino <wshinohara@gmail.com>
Co-authored-by: Aditya Bisht <adityabisht64@gmail.com>
  • Loading branch information
4 people authored Apr 27, 2024
1 parent 514df0c commit 92a86f5
Show file tree
Hide file tree
Showing 25 changed files with 803 additions and 681 deletions.
154 changes: 152 additions & 2 deletions README.md

Large diffs are not rendered by default.

33 changes: 25 additions & 8 deletions packages/circuits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ A circuit to verify that a message in the subject is authorized by a user of an

It takes as input the following data:
1. a padded email header `padded_header`.
2. an RSA public key `public_key`.
3. an RSA signature `signature`.
4. the bytes of the padded email header `padded_header_len`.
2. the bytes of the padded email header `padded_header_len`.
3. an RSA public key `public_key`.
4. an RSA signature `signature`.
5. the sender's account code `account_code`.
6. a starting position of the From field in the email header `from_addr_idx`.
7. a starting position of the Subject field in the email header `subject_idx`.
Expand All @@ -21,10 +21,10 @@ It takes as input the following data:

Its instances are as follows:
1. an email domain `domain_name`.
2. a poseidon hash of the RSA public key `public_key_hash`.
3. an nullifier of the email `email_nullifier`.
2. a Poseidon hash of the RSA public key `public_key_hash`.
3. a nullifier of the email `email_nullifier`.
4. a timestamp in the email header `timestamp`.
5. a masked subject where a character either in the email address or in the invitation code is replaced with zero `masked_subject_str`.
5. a masked subject where characters either in the email address or in the invitation code are replaced with zero `masked_subject_str`.
6. an account salt `account_salt`.
7. a flag whether the email header contains the invitation code `is_code_exist`.

Expand All @@ -33,8 +33,8 @@ Its instances are as follows:
`yarn && yarn build`

### Run tests
At `packages/circuits`, make a `build` directory, download the zip file from the following link, and place its unziped directory under `build`.
https://drive.google.com/file/d/1ky3XyabnBFwcyBoWBimhoePT9kbFyEBR/view?usp=sharing
At `packages/circuits`, make a `build` directory, download the zip file from the following link, and place its unzipped directory under `build`.
https://drive.google.com/file/d/13_RItK372JdfQFM3TmQFU_svN7q0k5iF/view?usp=drive_link

Then, move `email_auth.zkey` in the unzipped directory `params` to `build`.

Expand All @@ -44,3 +44,20 @@ Then run the following command.
### Generate proving keys and verifier contracts for main circuits
`yarn dev-setup`

## Specification
The `email_auth.circom` makes constraints and computes the public output as follows.
1. Assert that `signature` is valid for `padded_header` and `public_key`.
2. Let `public_key_hash` be `PoseidonHash(public_key)`.
3. Let `email_nullifier` be `PoseidonHash(PoseidonHash(signature))`.
4. Let `from_addr` be `padded_header[from_addr_idx:from_addr_idx+256]` .
5. Let `subject` be `padded_header[subject_idx:subject_idx+MAX_SUBJECT_BYTES]` .
6. Let `domain_name` be `padded_header[domain_idx:domain_idx+255]` .
7. Let `is_time_exist` be 1 if `padded_header` satisfies the regex of the timestamp field.
8. Let `timestamp_str` be `padded_header[timestamp_idx:timestamp_idx+10]`.
9. If `is_time_exist` is 1, let `timestamp` be an integer parsing `timestamp_str` as a digit string. Otherwise, let `timestamp` be zero.
10. Let `is_code_exist` be 1 if `padded_header` satisfies the regex of the invitation code.
11. Let `code_str` be `padded_header[code_idx:code_idx+64]`.
12. Let `embedded_code` be an integer parsing `code_str` as a hex string.
13. If `is_code_exist` is 1, assert that `embedded_code` is equal to `account_code`.
14. Let `account_salt` be `PoseidonHash(from_addr|0..0, account_code, 0)`.
15. Let `masked_subject` be a string that removes `code_str`, the prefix of the invitation code, and one email address from `subject`, if they appear in `subject`.
3 changes: 1 addition & 2 deletions packages/circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
"test": "NODE_OPTIONS=--max_old_space_size=8192 jest"
},
"dependencies": {
"@zk-email/circuits": "^3.2.4",
"@zk-email/helpers": "^3.1.3",
"@zk-email/circuits": "^6.0.2",
"@zk-email/zk-regex-circom": "^2.0.2",
"commander": "^11.0.0",
"snarkjs": "^0.7.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/circuits/src/email_auth.circom
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma circom 2.1.5;
pragma circom 2.1.6;

include "./email_auth_template.circom";

Expand Down
23 changes: 11 additions & 12 deletions packages/circuits/src/email_auth_template.circom
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/poseidon.circom";
include "@zk-email/circuits/email-verifier.circom";
include "@zk-email/circuits/helpers/extract.circom";
include "@zk-email/circuits/utils/regex.circom";
include "./utils/constants.circom";
include "./utils/account_salt.circom";
include "./utils/hash_sign.circom";
Expand Down Expand Up @@ -65,26 +64,26 @@ template EmailAuth(n, k, max_header_bytes, max_subject_bytes, recipient_enabled)

// Verify Email Signature
component email_verifier = EmailVerifier(max_header_bytes, 0, n, k, 1);
email_verifier.in_padded <== padded_header;
email_verifier.emailHeader <== padded_header;
email_verifier.pubkey <== public_key;
email_verifier.signature <== signature;
email_verifier.in_len_padded_bytes <== padded_header_len;
email_verifier.emailHeaderLength <== padded_header_len;
signal header_hash[256] <== email_verifier.sha;
public_key_hash <== email_verifier.pubkey_hash;
public_key_hash <== email_verifier.pubkeyHash;

// FROM HEADER REGEX
signal from_regex_out, from_regex_reveal[max_header_bytes];
(from_regex_out, from_regex_reveal) <== FromAddrRegex(max_header_bytes)(padded_header);
from_regex_out === 1;
signal from_email_addr[email_max_bytes];
from_email_addr <== VarShiftMaskedStr(max_header_bytes, email_max_bytes)(from_regex_reveal, from_addr_idx);
from_email_addr <== SelectRegexReveal(max_header_bytes, email_max_bytes)(from_regex_reveal, from_addr_idx);

// DOMAIN NAME HEADER REGEX
signal domain_regex_out, domain_regex_reveal[email_max_bytes];
(domain_regex_out, domain_regex_reveal) <== EmailDomainRegex(email_max_bytes)(from_email_addr);
domain_regex_out === 1;
signal domain_name_bytes[domain_len];
domain_name_bytes <== VarShiftMaskedStr(email_max_bytes, domain_len)(domain_regex_reveal, domain_idx);
domain_name_bytes <== SelectRegexReveal(email_max_bytes, domain_len)(domain_regex_reveal, domain_idx);
domain_name <== Bytes2Ints(domain_len)(domain_name_bytes);

signal sign_hash;
Expand All @@ -98,14 +97,14 @@ template EmailAuth(n, k, max_header_bytes, max_subject_bytes, recipient_enabled)
(subject_regex_out, subject_regex_reveal) <== SubjectAllRegex(max_header_bytes)(padded_header);
subject_regex_out === 1;
signal subject_all[max_subject_bytes];
subject_all <== VarShiftMaskedStr(max_header_bytes, max_subject_bytes)(subject_regex_reveal, subject_idx);
subject_all <== SelectRegexReveal(max_header_bytes, max_subject_bytes)(subject_regex_reveal, subject_idx);

// Timestamp regex + convert to decimal format
signal timestamp_regex_out, timestamp_regex_reveal[max_header_bytes];
(timestamp_regex_out, timestamp_regex_reveal) <== TimestampRegex(max_header_bytes)(padded_header);
// timestamp_regex_out === 1;
signal timestamp_str[timestamp_len];
timestamp_str <== VarShiftMaskedStr(max_header_bytes, timestamp_len)(timestamp_regex_reveal, timestamp_idx);
timestamp_str <== SelectRegexReveal(max_header_bytes, timestamp_len)(timestamp_regex_reveal, timestamp_idx);
signal raw_timestamp <== Digit2Int(timestamp_len)(timestamp_str);
timestamp <== timestamp_regex_out * raw_timestamp;

Expand Down Expand Up @@ -142,7 +141,7 @@ template EmailAuth(n, k, max_header_bytes, max_subject_bytes, recipient_enabled)
replaced_code_regex_reveal[i] <== code_regex_reveal[i] * is_code_exist;
}
}
signal shifted_code_hex[code_len] <== VarShiftMaskedStr(max_header_bytes, code_len)(replaced_code_regex_reveal, code_idx);
signal shifted_code_hex[code_len] <== SelectRegexReveal(max_header_bytes, code_len)(replaced_code_regex_reveal, code_idx);
signal invitation_code_hex[code_len];
for(var i=0; i<code_len; i++) {
invitation_code_hex[i] <== is_code_exist * (shifted_code_hex[i] - 48) + 48;
Expand Down Expand Up @@ -177,7 +176,7 @@ template EmailAuth(n, k, max_header_bytes, max_subject_bytes, recipient_enabled)
}
}
signal shifted_email_addr[email_max_bytes];
shifted_email_addr <== VarShiftMaskedStr(max_subject_bytes, email_max_bytes)(replaced_email_addr_regex_reveal, subject_email_addr_idx);
shifted_email_addr <== SelectRegexReveal(max_subject_bytes, email_max_bytes)(replaced_email_addr_regex_reveal, subject_email_addr_idx);
signal recipient_email_addr[email_max_bytes];
for(var i=0; i<email_max_bytes; i++) {
recipient_email_addr[i] <== shifted_email_addr[i] * has_email_recipient;
Expand Down
2 changes: 1 addition & 1 deletion packages/circuits/src/utils/account_salt.circom
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/poseidon.circom";

Expand Down
30 changes: 4 additions & 26 deletions packages/circuits/src/utils/bytes2ints.circom
Original file line number Diff line number Diff line change
@@ -1,41 +1,19 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/poseidon.circom";
include "./constants.circom";
include "@zk-email/circuits/utils/bytes.circom";

function compute_ints_size(bytes_size) {
var pack_bytes = pack_bytes_const();
var remain = bytes_size % pack_bytes;
var num_chunk = (bytes_size - remain) / pack_bytes;
if(remain>0) {
num_chunk += 1;
}
return num_chunk;
return computeIntChunkLength(bytes_size);
}

template Bytes2Ints(bytes_size) {
var num_chunk = compute_ints_size(bytes_size);
signal input bytes[bytes_size];
signal output ints[num_chunk];

var pack_bytes = pack_bytes_const();
signal ints_sums[num_chunk][pack_bytes];
for(var i=0; i<num_chunk; i++) {
for(var j=0; j<pack_bytes; j++) {
var idx = pack_bytes*i+j;
if(idx>=bytes_size) {
ints_sums[i][j] <== ints_sums[i][j-1];
} else if (j==0){
ints_sums[i][j] <== bytes[idx];
} else {
ints_sums[i][j] <== ints_sums[i][j-1] + (1<<(8*j)) * bytes[idx];
}
}
}
for(var i=0; i<num_chunk; i++) {
ints[i] <== ints_sums[i][pack_bytes-1];
}
ints <== PackBytes(bytes_size)(bytes);
}
11 changes: 7 additions & 4 deletions packages/circuits/src/utils/constants.circom
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
pragma circom 2.1.5;
pragma circom 2.1.6;

include "@zk-email/circuits/utils/constants.circom";


function email_max_bytes_const() {
return 256;
return EMAIL_ADDR_MAX_BYTES();
}

function domain_len_const() {
return 255;
return DOMAIN_MAX_BYTES();
}

function invitation_code_len_const() {
Expand All @@ -17,7 +20,7 @@ function field_pack_bits_const() {
}

function pack_bytes_const() {
return 31;
return MAX_BYTES_IN_FIELD();
}

function timestamp_len_const() {
Expand Down
18 changes: 2 additions & 16 deletions packages/circuits/src/utils/digit2int.circom
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
Expand All @@ -12,19 +11,6 @@ template Digit2Int(n) {
signal input in[n];
signal output out;

component digit2int[n];
signal sums[n+1];
sums[0] <== 0;
for(var i = 0; i < n; i++) {
digit2int[i] = Digit2Int1();
digit2int[i].in <== in[i];
sums[i+1] <== 10 * sums[i] + digit2int[i].out;
}
out <== sums[n];
out <== DigitBytesToInt(n)(in);
}

template Digit2Int1() {
signal input in;
signal output out;
out <== in - 48;
}
3 changes: 1 addition & 2 deletions packages/circuits/src/utils/email_addr_commit.circom
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/poseidon.circom";

Expand Down
12 changes: 1 addition & 11 deletions packages/circuits/src/utils/email_nullifier.circom
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/poseidon.circom";

Expand All @@ -9,15 +8,6 @@ template EmailNullifier() {

signal output email_nullifier;

// var field_pack_bits = field_pack_bits_const();

// signal header_hash_int[field_pack_bits+1];
// header_hash_int[0] <== 0;
// for(var i = 0; i < field_pack_bits; i++) {
// header_hash_int[i+1] <== 2 * header_hash_int[i] + header_hash[i];
// }
// signal email_nullifier_input[1];
// email_nullifier_input[0] <== sign_hash;
email_nullifier <== Poseidon(1)([sign_hash]);
}

Expand Down
14 changes: 1 addition & 13 deletions packages/circuits/src/utils/hash_sign.circom
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/poseidon.circom";

template HashSign(n,k) {
// signal input pubkey[k];
signal input signature[k];

// signal output pubkey_hash;
signal output sign_hash;

var k2_chunked_size = k >> 1;
Expand All @@ -16,15 +13,6 @@ template HashSign(n,k) {
}
signal output sign_ints[k2_chunked_size];

// signal pubkey_hash_input[k2_chunked_size];
// for(var i = 0; i < k2_chunked_size; i++) {
// if(i==k2_chunked_size-1 && k2_chunked_size % 2 == 1) {
// pubkey_hash_input[i] <== pubkey[2*i];
// } else {
// pubkey_hash_input[i] <== pubkey[2*i] + (1<<n) * pubkey[2*i+1];
// }
// }
// pubkey_hash <== Poseidon(k2_chunked_size)(pubkey_hash_input);
for(var i = 0; i < k2_chunked_size; i++) {
if(i==k2_chunked_size-1 && k2_chunked_size % 2 == 1) {
sign_ints[i] <== signature[2*i];
Expand Down
3 changes: 1 addition & 2 deletions packages/circuits/src/utils/hex2int.circom
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

pragma circom 2.1.5;
pragma circom 2.1.6;

include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
Expand Down
Loading

0 comments on commit 92a86f5

Please sign in to comment.