Add documents.

This commit is contained in:
SoraSuegami
2023-12-17 16:00:04 +09:00
parent 45e66c7664
commit 09a2b9bca0
12 changed files with 281 additions and 231 deletions

44
Cargo.lock generated
View File

@@ -660,9 +660,9 @@ checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6"
[[package]]
name = "const-oid"
version = "0.9.5"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "constant_time_eq"
@@ -784,9 +784,9 @@ dependencies = [
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
dependencies = [
"cfg-if",
"crossbeam-epoch",
@@ -795,22 +795,21 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.15"
version = "0.9.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.16"
version = "0.8.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
dependencies = [
"cfg-if",
]
@@ -1547,9 +1546,9 @@ dependencies = [
[[package]]
name = "eyre"
version = "0.6.9"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd"
checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799"
dependencies = [
"indenter",
"once_cell",
@@ -2140,6 +2139,7 @@ dependencies = [
"halo2-regex",
"halo2-rsa",
"hex",
"home",
"itertools",
"js-sys",
"log",
@@ -4465,18 +4465,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.50"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
dependencies = [
"proc-macro2",
"quote",
@@ -4916,12 +4916,12 @@ dependencies = [
[[package]]
name = "wasm-bindgen-rayon"
version = "1.0.3"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df87c67450805c305d3ae44a3ac537b0253d029153c25afc3ecd2edc36ccafb1"
checksum = "f0a399126782d706247a5f8fb033c3976e9edd3164664d7c97162923435cc972"
dependencies = [
"js-sys",
"rayon",
"rayon-core",
"spmc",
"wasm-bindgen",
]
@@ -5280,18 +5280,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.7.30"
version = "0.7.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7"
checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.30"
version = "0.7.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba"
checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -74,6 +74,7 @@ tokio = { version = "1.16", features = [
"rt-multi-thread",
"macros",
] }
home = { version = "=0.5.5" }
[target.'cfg(target_family = "wasm")'.dependencies]

View File

@@ -34,18 +34,25 @@ You can open the API specification by executing `cargo doc --open`.
## Test
You can run the tests by executing `cargo test --release`.
## Description
## CLI
You can install CLI `zkemail` to prove and verify emails as follows:
`cargo install --path .`
To generate a proof and verify it on EVM, do:
```bash
cargo build --release
cargo run --release -- gen-params --k 18
cargo run --release -- gen-keys
cargo run --release -- gen-evm-verifier
cargo run --release -- evm-prove
cargo run --release -- evm-verify
zkemail gen-params --k 18
zkemail gen-keys
zkemail gen-evm-verifier
zkemail evm-prove
zkemail evm-verify
```
To generate regex files for a new decomposed regex definition. do:
```bash
cargo run --release -- gen-regex-files --decomposed-regex-config-path new_regex_file.json --regex-files-prefix new_regex
```
zkemail gen-regex-files --decomposed-regex-config-path new_regex_file.json --regex-files-prefix new_regex
```
## WASM prover on browser
You can generate a proof on browser with our wasm prover.
For more information, please see `examples/web-client/README.md`.

View File

@@ -35,7 +35,9 @@
"max_variable_byte_size": 1024,
"substr_regexes": [
[
"(?<=from:).*@.*(?=\r)"
"(?<=from:).*@.*(?=\r)",
"<?(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|-)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|-)+>?",
"(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|-)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|-)+"
],
[
"(?<=to:).*@.*(?=\r)"

View File

@@ -1,12 +1,12 @@
{
"degree": 13,
"num_flex_advice": 300,
"num_range_lookup_advice": 19,
"num_flex_advice": 375,
"num_range_lookup_advice": 27,
"num_flex_fixed": 3,
"range_lookup_bits": 12,
"sha256_config": {
"num_bits_lookup": 8,
"num_advice_columns": 9
"num_advice_columns": 13
},
"sign_verify_config": {
"public_key_bits": 2048
@@ -22,7 +22,7 @@
"./test_data/from_substr_0.txt"
]
],
"max_variable_byte_size": 512,
"max_variable_byte_size": 1024,
"substr_regexes": [
[
"(?<=from:).*@.*(?=\r)",

View File

@@ -1,7 +1,21 @@
# Web client
This is an example web client for tests and benchmarks of halo2_zk_email.
This is an example web client for halo2_zk_email for benchmarking purposes.
## Setup
1. Ensure that `zkemail` CLI is already installed.
2. Under the `web-client` directory, run `chmod +x setup.bash` and `./setup.bash`
3. Open http://localhost:3000 on Google Chrome browser.
## Credits
## Tests
Please set up the local web server as described above and go to http://localhost:3000 first.
To run a test of a valid case, press the "Run test" button after "Run test of valid case".
To run a test of an invalid case in which a public key is modified, press the "Run test" button after "Run test of invalid case (invalid public key)".
## Bench
Please set up the local web server as described above and go to http://localhost:3000 first.
To measure a benchmark, enter the number of bench times in the form immediately after the "Select an email file." button and press "Run bench" below it.
To use your email in the benchmark, upload it by pressing the "Select an email file." button.
Its email header must be less than 1024 bytes, and its email body must be less than 512 bytes and satisfy the regex of "Hello (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)+!".
## Acknowledgment
The web client and rust wasm code refers to [halo2 wasm guide](https://zcash.github.io/halo2/user/wasm-port.html) and [this repository](https://github.com/nalinbhardwaj/zordle/tree/main/test-client).

View File

@@ -0,0 +1,85 @@
Delivered-To: emailwallet.relayer@gmail.com
Received: by 2002:a05:7108:8190:b0:35d:a7ed:3d3f with SMTP id c16csp3477575gdv;
Sun, 10 Dec 2023 07:58:41 -0800 (PST)
X-Received: by 2002:a0d:d884:0:b0:5d7:1941:a9b with SMTP id a126-20020a0dd884000000b005d719410a9bmr2252254ywe.54.1702223921597;
Sun, 10 Dec 2023 07:58:41 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; t=1702223921; cv=none;
d=google.com; s=arc-20160816;
b=iFKf5X1Imw98UKB6r0/jT/w+8ZQUwtqYasY7oOktiIaxteVLoJ9Y+WKthOl5h8Zx/p
9QMd78mXdus08G1Uy++d974ufbKAgMNAMqUbfN27C71YLm6/vr6j62hghWqqH/hCsuIp
7NM71n9W9oqymV8VXqd33ljPOk3Q5sxJ/5qHaxKlmzpgD7cog9s+/rMkz/+GY8ADyONX
5Bjl0JjAMZD3O1ZqfyL3ZRQI7KLgFmuwKBR2VTAgO55ODUeAGfQRdCcrFC7ds3rchzpo
F1dWsmJI0wFHhvta2ZMXkWO8VgQ9Wr6HaLKi0vm9En+b9QxiHbTGLLjc4l3fICi8YTYN
XlHg==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
h=to:subject:message-id:date:from:mime-version:dkim-signature;
bh=GUspwlIIG/sP841vGpwvy3MPgVazLJpd/ow/iYyjBbU=;
fh=AKWw92sdXoMEDdHXKLL06vnizTpObKPGCfYXnoQDKO8=;
b=OwZ/cor6fk/L07nb373YlTMzD+tgh+BbSm6BUz3iElswDuKJCwq/VuPsZlOmdnBwJj
/plClik0nIxkORCzGqqpNDziiI8/TWEXD0ktLgq8CbKx7hLF0BSKPVAWwahF1OLjalm8
+owoh23vmRu0rQ/WDBbCow6gOmp6rt7XLNNJk/0kZdKwUDbIgU1+nxE+a/QV20wUb7gE
Zmco67MdshkQpMHJp7gVYUgiyWbt3BhjRAN9+pk2sf01ItR7aiqiC2ql31VBO5iPydG6
T7W1TJNTPoI8XVkh8fELytg3nVpV8vIRaG+6z5BBaXpMegFX+iWehTRQUTOdDPXg4jFi
dA3g==
ARC-Authentication-Results: i=1; mx.google.com;
dkim=pass header.i=@gmail.com header.s=20230601 header.b=MREa0ELt;
spf=pass (google.com: domain of suegamisora@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=suegamisora@gmail.com;
dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com
Return-Path: <suegamisora@gmail.com>
Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41])
by mx.google.com with SMTPS id g78-20020a0ddd51000000b005d3d815e4ccsor1991901ywe.16.2023.12.10.07.58.41
for <emailwallet.relayer@gmail.com>
(Google Transport Security);
Sun, 10 Dec 2023 07:58:41 -0800 (PST)
Received-SPF: pass (google.com: domain of suegamisora@gmail.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41;
Authentication-Results: mx.google.com;
dkim=pass header.i=@gmail.com header.s=20230601 header.b=MREa0ELt;
spf=pass (google.com: domain of suegamisora@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=suegamisora@gmail.com;
dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1702223921; x=1702828721; dara=google.com;
h=to:subject:message-id:date:from:mime-version:from:to:cc:subject
:date:message-id:reply-to;
bh=GUspwlIIG/sP841vGpwvy3MPgVazLJpd/ow/iYyjBbU=;
b=MREa0ELt0knVg0s8F6a6rPZNxgJRe7C5fQjpHS+Jlf0l6kKrsHOkf9pPW1aVScf6wt
8rCmaO7mazJF/8u2ObMrZ8v4kL0CmYGRy57/LNdzk7DMBZskajYSRX909sw2DK0w7Znv
BSexoZlIeRqHOsqXA5qJ02hRCi1REnzHOy1oNkBpKqb/iVjCM9GtfSfTDdK7psjBArru
l4wuf7DFxNMdqKgH6VacEnLUQYjHIoiGJKbK3BO/uT2d4eA8Z7flDpYWzak8gAx9lABv
mxKWxKgP6zo08RWoAEGF53WmW+6Ft/nseg1cgJy0U/Yw+KOUy5nsiJLctajuYdhWBhch
FMew==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1702223921; x=1702828721;
h=to:subject:message-id:date:from:mime-version:x-gm-message-state
:from:to:cc:subject:date:message-id:reply-to;
bh=GUspwlIIG/sP841vGpwvy3MPgVazLJpd/ow/iYyjBbU=;
b=VLNYRexFGqVaJHdiViwkzXfeFTu/dW8grgXMrqSzeH6vUW39HaOca1w0gm6euKKIQv
v/oSPdqGy+6nD0UrcNFn0Fcz0jTFa5yJ0feiuE6WCjikHOTvQsScLAKhbN97C2mOjjz9
hepDkVxF9GHA2TUBFlAAkd2lSm3BEMrxFk5JCNUfmuQSFIKqT1u8z9ToZ56Vk4R6ODip
rZ737NwB7VGv5YckRXPJH00SfdiO5R8WR8k5uxziYw02oCQ+mk0j8+2hGcodWdR2/eBs
H34DmCJAMkfIo80lTX9QFhqec2lGfA6xGnEy1WLEkB3qEtZEjlr+M0Q57Af85U1h/DK0
tH9A==
X-Gm-Message-State: AOJu0YxMAQGL7080EZPDyVk2AIVutc3APVhNDpnBr0vAgJsnGZY3ohqR
+sQorRUF1maMuWadqj9fHzjPpWqxVCS3QMAusn5OA+UgoX8=
X-Google-Smtp-Source: AGHT+IE9q/z1n4s5Z13NEuqmBcqki+H5Iev2UiPber/ECbJxVrbO6lRiSHBYTPJWdUIiGpq0SXX5L9MnF3zUv52Eylw=
X-Received: by 2002:a81:8406:0:b0:5d4:2ab1:9f0a with SMTP id
u6-20020a818406000000b005d42ab19f0amr2100524ywf.42.1702223920881; Sun, 10 Dec
2023 07:58:40 -0800 (PST)
MIME-Version: 1.0
From: Sora Suegami <suegamisora@gmail.com>
Date: Mon, 11 Dec 2023 00:58:29 +0900
Message-ID: <CAJ7Y6jeSK0pOMtGC81JFKzEZf2KE1zxbzcyKuaRvsYROwVP6qQ@mail.gmail.com>
Subject: Demo Email
To: emailwallet.relayer@gmail.com
Content-Type: multipart/alternative; boundary="00000000000021e38e060c29e4a6"
--00000000000021e38e060c29e4a6
Content-Type: text/plain; charset="UTF-8"
Hello zkemail!
--00000000000021e38e060c29e4a6
Content-Type: text/html; charset="UTF-8"
<div dir="ltr">Hello zkemail!<div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"></div></div>
--00000000000021e38e060c29e4a6--

View File

@@ -1,28 +1,28 @@
{
"degree": 13,
"num_flex_advice": 300,
"num_range_lookup_advice": 19,
"num_flex_advice": 375,
"num_range_lookup_advice": 27,
"num_flex_fixed": 3,
"range_lookup_bits": 12,
"sha256_config": {
"num_bits_lookup": 8,
"num_advice_columns": 9
"num_advice_columns": 13
},
"sign_verify_config": {
"public_key_bits": 2048
},
"header_config": {
"bodyhash_allstr_filepath": "bodyhash_allstr.txt",
"bodyhash_substr_filepath": "bodyhash_substr_0.txt",
"header_config": {
"bodyhash_allstr_filepath": "./public/bodyhash_allstr.txt",
"bodyhash_substr_filepath": "./public/bodyhash_substr_0.txt",
"allstr_filepathes": [
"from_allstr.txt"
"./public/from_allstr.txt"
],
"substr_filepathes": [
[
"from_substr_0.txt"
"./public/from_substr_0.txt"
]
],
"max_variable_byte_size": 512,
"max_variable_byte_size": 1024,
"substr_regexes": [
[
"(?<=from:).*@.*(?=\r)",
@@ -34,11 +34,11 @@
},
"body_config": {
"allstr_filepathes": [
"hello_body_allstr.txt"
"./public/hello_body_allstr.txt"
],
"substr_filepathes": [
[
"hello_body_substr_0.txt"
"./public/hello_body_substr_0.txt"
]
],
"max_variable_byte_size": 512,

7
examples/web-client/setup.bash Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
cd `dirname $0`
zkemail gen-params --k 13 --params-path ./public/params.bin
zkemail gen-keys --params-path ./public/params.bin --circuit-config-path ./public/wasm_email_verify.config --email-path ./public/demo_wasm.eml --pk-path ./public/bench.pk --vk-path ./public/bench.vk
yarn build:wasm
yarn build
yarn start

View File

@@ -1,6 +1,10 @@
import { expose, proxy } from 'comlink';
type MultiThread = typeof import('halo2-zk-email');
/**
* The public input of the default email verification circuit.
*/
interface DefaultEmailVerifyPublicInput {
// A decimal string of a commitment of the signature defined as poseidon(rsaSign).
sign_commit: string,
@@ -16,6 +20,10 @@ interface DefaultEmailVerifyPublicInput {
body_substrs: string[],
}
/**
* Fetch the trusted setup parameters for k=13.
* @returns The trusted setup parameters.
*/
export async function fetchParams() {
const response = await fetch('http://localhost:3000/params.bin');
const bytes = await response.arrayBuffer();
@@ -23,6 +31,10 @@ export async function fetchParams() {
return params;
}
/**
* Fetch the verification key of the default email verification circuit.
* @returns The verification key.
*/
export async function fetchVk() {
const response = await fetch('http://localhost:3000/bench.vk');
const bytes = await response.arrayBuffer();
@@ -30,13 +42,17 @@ export async function fetchVk() {
return vk;
}
/**
* Run a valid test of the default email verification circuit.
* @param emailStr The email string to be verified.
* @returns The result of the verification.
*/
export async function runValidTest(emailStr: string) {
const multiThread = await initMultiThread();
await fetchSaveConfigs(multiThread);
const params = await fetchParams();
console.log(params);
const publicKey = await fetchPublicKey(multiThread, emailStr);
// await genProvingKey(multiThread, params, emailStr, publicKey)
const pkChunks = await fetchPkChunks();
console.log(pkChunks);
if (pkChunks == null) {
@@ -51,15 +67,17 @@ export async function runValidTest(emailStr: string) {
return isValid;
}
/**
* Run an invalid test of the default email verification circuit.
* @param emailStr The email string to be verified.
* @returns The result of the verification.
*/
export async function runInvalidTest(emailStr: string) {
const multiThread = await initMultiThread();
await fetchSaveConfigs(multiThread);
const params = await fetchParams();
console.log(params);
let publicKey = await fetchPublicKey(multiThread, emailStr);
// for (const i = 0; i < 512; i++) {
// publicKey[i+2] =
// }
publicKey = '0x' + 'f'.repeat(publicKey.length - 2);
const pkChunks = await fetchPkChunks();
console.log(pkChunks);
@@ -75,39 +93,29 @@ export async function runInvalidTest(emailStr: string) {
return isValid;
}
/**
* Run a benchmark of the default email verification circuit.
* @param emailStr The email string to be verified.
* @param times The number of times to run the benchmark.
* @returns The benchmark results as a proxy of comlink.
*/
export async function runBench(emailStr: string, times: number) {
// const multiThread = await import(
// 'halo2-zk-email'
// );
// console.log(multiThread);
// await multiThread.default();
// console.log(`hardware: ${navigator.hardwareConcurrency}`);
// await multiThread.initThreadPool(4);
const multiThread = await initMultiThread();
await fetchSaveConfigs(multiThread);
const params = await fetchParams();
console.log(params);
const publicKey = await fetchPublicKey(multiThread, emailStr);
// await genProvingKey(multiThread, params, emailStr, publicKey)
const pkChunks = await fetchPkChunks();
console.log(pkChunks);
if (pkChunks == null) {
throw new Error("pkChunks is null");
}
const vk = await fetchVk();
// const vk = await fetchVk();
// console.log(vk);
// await fetch_save_configs();
// const privateKey = multiThread.sample_rsa_private_key(bits_len);
// const publicKey = multiThread.generate_rsa_public_key(privateKey);
// const signature = multiThread.sign(privateKey, msg);
const indexes = [];
const benches: number[] = [];
// // const results = multiThread.multi_bench_2048_1024_circuit(params, pk, vk, publicKey, msg, signature, times);
console.log("init");
for (let i = 0; i < times; i++) {
indexes.push(i);
// await multiThread.initThreadPool(4);
const start = performance.now();
const [proof, publicInput] = proveEmail(multiThread, params, pkChunks, emailStr, publicKey);
console.log(proof);
@@ -120,7 +128,6 @@ export async function runBench(emailStr: string, times: number) {
if (!isValid) {
throw new Error("verify failed");
}
// initOutput.__wbg_wbg_rayon_poolbuilder_free(navigator.hardwareConcurrency);
}
return proxy({
indexes: indexes,
@@ -128,30 +135,40 @@ export async function runBench(emailStr: string, times: number) {
})
}
// async function genProvingKey(multiThread: MultiThread, params: Uint8Array, emailStr: string, publicKey: string) {
// // const multiThread = await import(
// // 'halo2-zk-email'
// // );
// // console.log(multiThread);
// // await multiThread.default();
// // console.log(`hardware: ${navigator.hardwareConcurrency}`);
// // await multiThread.initThreadPool(4);
// // const multiThread = await fetchSaveConfigs();
// console.log(publicKey);
// await multiThread.gen_proving_key(params, emailStr, publicKey);
// }
/**
* Prove the email string.
* @param multiThread The multi-threaded WASM module.
* @param params The trusted setup parameters.
* @param pkChunks The chunks of the proving key.
* @param emailStr The email string to be verified.
* @param publicKey The RSA public key.
* @returns The hex string of the proof and the public input.
*/
export function proveEmail(multiThread: MultiThread, params: Uint8Array, pkChunks: Uint8Array[], emailStr: string, publicKey: string): [string, DefaultEmailVerifyPublicInput] {
const proofOut = multiThread.prove_email(params, pkChunks, emailStr, publicKey);
return [proofOut[0], proofOut[1]];
}
/**
* Verify the proof.
* @param multiThread The multi-threaded WASM module.
* @param params The trusted setup parameters.
* @param vk The verification key.
* @param proof The hex string of the proof.
* @param publicInput The public input.
* @returns The result of the verification.
*/
export function verifyEmailProof(multiThread: MultiThread, params: Uint8Array, vk: Uint8Array, proof: string, publicInput: DefaultEmailVerifyPublicInput): boolean {
const isValid = multiThread.verify_email_proof(params, vk, proof, publicInput);
return isValid;
}
/**
* Fetch the RSA public key from the Google DNS server.
* @param multiThread The multi-threaded WASM module.
* @param emailStr The email string to be verified.
* @returns The RSA public key.
*/
export async function fetchPublicKey(multiThread: MultiThread, emailStr: string) {
console.log(emailStr);
const url = multiThread.google_dns_url_from_email(emailStr);
@@ -164,15 +181,17 @@ export async function fetchPublicKey(multiThread: MultiThread, emailStr: string)
}
/**
* Fetch the chunks of the proving key.
* @returns The chunks of the proving key.
*/
export async function fetchPkChunks() {
const response = await fetch('http://localhost:3000/bench.pk');
// console.log(await response.blob());
if (response.body == null) {
return;
}
const chunks: Uint8Array[] = [];
let maxSize = 0;
// let idx = 0;
const reader = response.body.getReader();
while (true) {
@@ -180,8 +199,6 @@ export async function fetchPkChunks() {
if (done) {
break;
}
// console.log(value.toString());
// localStorage.setItem(`pk_chunk_${idx}`, value.toString());
chunks.push(value);
maxSize += value.byteLength;
}
@@ -190,13 +207,14 @@ export async function fetchPkChunks() {
return chunks;
}
/**
* Fetch and save the configurations for the default email verification circuit.
* You must call this function once for each `multiThread` before calling any other functions in this module.
* @param multiThread The multi-threaded WASM module.
*/
export async function fetchSaveConfigs(multiThread: MultiThread) {
const configParams = await fetchConfigParams();
let configParamsJson = JSON.parse(configParams);
// localStorage.setItem(configParamsJson.header_config.bodyhash_allstr_filepath, await fetchRegexFile(configParamsJson.header_config.bodyhash_allstr_filepath));
// localStorage.setItem(configParamsJson.header_config.bodyhash_substr_filepath, await fetchRegexFile(configParamsJson.header_config.bodyhash_substr_filepath));
const bodyHashAllstrDef = await fetchRegexFile(configParamsJson.header_config.bodyhash_allstr_filepath);
const bodyHashSubstrDef = await fetchRegexFile(configParamsJson.header_config.bodyhash_substr_filepath);
console.log(bodyHashAllstrDef);
@@ -241,128 +259,20 @@ async function fetchConfigParams() {
}
async function fetchRegexFile(filePath: string) {
const response = await fetch(`http://localhost:3000/${filePath}`);
const response = await fetch(`http://localhost:3000/${getFilename(filePath)}`);
const regexConfig = await response.text();
return regexConfig;
}
// export async function fetchParams() {
// /* eslint-disable-next-line no-restricted-globals */
// console.log(self);
// console.log(window);
// /* eslint-disable-next-line no-restricted-globals */
// window = self;
// console.log(window);
// const multiThread = await import(
// 'halo2-zk-email'
// );
// console.log(multiThread);
// await multiThread.default();
// console.log(`hardware: ${navigator.hardwareConcurrency}`);
// await multiThread.initThreadPool(4);
// const params = await multiThread.fetch_proving_key("http://localhost:3000/params.bin");
// console.log(params);
// return params;
// }
// export async function fetchPk() {
// /* eslint-disable-next-line no-restricted-globals */
// window = self;
// const multiThread = await import(
// 'halo2-zk-email'
// );
// console.log(multiThread);
// await multiThread.default();
// console.log(`hardware: ${navigator.hardwareConcurrency}`);
// await multiThread.initThreadPool(4);
// const pk = await multiThread.fetch_public_key("http://localhost:3000/bench.pk");
// console.log(pk);
// return pk;
// }
// async function bench(multiThread: typeof import("halo2-rsa"), bits_len: number, msg: Uint8Array, times: number) {
// const privateKey = multiThread.sample_rsa_private_key(bits_len);
// const publicKey = multiThread.generate_rsa_public_key(privateKey);
// const signature = multiThread.sign(privateKey, msg);
// const indexes = [];
// const benches: number[] = [];
// const params = await fetch_params();
// const pk = await fetch_pk();
// const vk = await fetch_vk();
// console.log("init");
// for (let i = 0; i < times; i++) {
// indexes.push(i);
// const multiThread = await import(
// 'halo2-rsa'
// );
// const initOutput = await multiThread.default();
// const builder = await multiThread.initThreadPool(navigator.hardwareConcurrency);
// console.log(builder);
// const start = performance.now();
// const proof = multiThread.prove_pkcs1v15_2048_1024_circuit(params, pk, publicKey, msg, signature);
// const sub = performance.now() - start;
// console.log(`index: ${ i }, bench: ${ sub } ms`);
// benches.push(sub);
// const isValid = multiThread.verify_pkcs1v15_2048_1024_circuit(params, vk, proof);
// console.log(isValid);
// // initOutput.__wbg_wbg_rayon_poolbuilder_free(navigator.hardwareConcurrency);
// }
// return proxy({
// indexes: indexes,
// benches: benches
// })
// }
// export async function initHandlers(emailStr: string, times: number) {
// // const multiThread = await import(
// // 'halo2-zk-email'
// // );
// // console.log(multiThread);
// // await multiThread.default();
// // console.log(`hardware: ${navigator.hardwareConcurrency}`);
// // await multiThread.initThreadPool(4);
// if (multiThread == null) {
// throw new Error("multiThread is null");
// }
// const params = await fetchParams();
// console.log(params);
// // const pkChunks = await fetchPk();
// // console.log(pkChunks);
// // if (pkChunks == null) {
// // throw new Error("pkChunks is null");
// // }
// // const vk = await fetchVk();
// // console.log(vk);
// // await fetch_save_configs();
// // const privateKey = multiThread.sample_rsa_private_key(bits_len);
// // const publicKey = multiThread.generate_rsa_public_key(privateKey);
// // const signature = multiThread.sign(privateKey, msg);
// const indexes = [];
// const benches: number[] = [];
// // // const results = multiThread.multi_bench_2048_1024_circuit(params, pk, vk, publicKey, msg, signature, times);
// console.log("init");
// for (let i = 0; i < times; i++) {
// indexes.push(i);
// const multiThread = await import(
// 'halo2-zk-email'
// );
// await multiThread.default();
// // await multiThread.initThreadPool(4);
// // const start = performance.now();
// // const proof = await multiThread.prove_email(params, [], emailStr);
// // const sub = performance.now() - start;
// // console.log(`index: ${i}, bench: ${sub} ms`);
// // benches.push(sub);
// // const isValid = multiThread.verify_pkcs1v15_2048_1024_circuit(params, vk, proof);
// // console.log(isValid);
// // initOutput.__wbg_wbg_rayon_poolbuilder_free(navigator.hardwareConcurrency);
// }
// return proxy({
// indexes: indexes,
// benches: benches
// })
// }
function getFilename(filePath: string) {
const parts = filePath.split('/');
return parts.pop();
}
/**
* Initialize the multi-threaded WASM module.
* @returns The multi-threaded WASM module.
*/
export async function initMultiThread() {
const multiThread = await import(
'halo2-zk-email'

View File

@@ -67,7 +67,7 @@ pub fn get_substr(input_str: &str, regexes: &[String]) -> Option<(usize, String)
let regexes = regexes.into_iter().map(|raw| Regex::new(&raw).unwrap()).collect_vec();
let mut start = 0;
let mut substr = input_str;
println!("first regex {}", regexes[0]);
// println!("first regex {}", regexes[0]);
for regex in regexes.into_iter() {
// println!(r"regex {}", regex);
match regex.find(substr).unwrap() {
@@ -80,7 +80,7 @@ pub fn get_substr(input_str: &str, regexes: &[String]) -> Option<(usize, String)
}
};
}
println!("substr {}", substr);
println!("start {}", start);
// println!("substr {}", substr);
// println!("start {}", start);
Some((start, substr.to_string()))
}

View File

@@ -59,6 +59,18 @@ pub fn init_panic_hook() {
console_error_panic_hook::set_once();
}
/// Initialize the configurations for [`DefaultEmailVerifyCircuit`].
/// You must call this function once before calling any other functions in this module.
/// # Arguments
/// * `config_params` - a json string of [`EmailVerifyConfigParams`].
/// * `bodyhash_allstr_def` - a string of [`AllstrRegexDef`] for the bodyhash.
/// * `bodyhash_substr_def` - a string of [`SubstrRegexDef`] for the bodyhash.
/// * `header_allstr_defs` - a list of strings of [`AllstrRegexDef`] for the headers.
/// * `header_substr_defs` - a list of strings of [`SubstrRegexDef`] for the headers.
/// * `body_allstr_defs` - a list of strings of [`AllstrRegexDef`] for the body.
/// * `body_substr_defs` - a list of strings of [`SubstrRegexDef`] for the body.
/// # Return values
/// Return a promise of `null`.
#[wasm_bindgen]
pub fn init_configs(
config_params: String,
@@ -144,6 +156,11 @@ pub fn init_configs(
Ok(JsValue::NULL)
}
/// Extract a selector and a domain name from the given email string and generate an url to fetch the public key from the google dns.
/// # Arguments
/// * `email_str` - an email string.
/// # Return values
/// Return a promise of the url string.
#[wasm_bindgen]
pub fn google_dns_url_from_email(email_str: String) -> Result<String, JsValue> {
console_error_panic_hook::set_once();
@@ -153,6 +170,11 @@ pub fn google_dns_url_from_email(email_str: String) -> Result<String, JsValue> {
Ok(url)
}
/// Fetch the public key from the response of the google dns.
/// # Arguments
/// * `response` - a response string from the google dns.
/// # Return values
/// Return a promise of the public key string.
#[wasm_bindgen]
pub fn fetch_rsa_public_key(response: String) -> Result<String, JsValue> {
console_error_panic_hook::set_once();
@@ -185,6 +207,14 @@ pub fn fetch_rsa_public_key(response: String) -> Result<String, JsValue> {
// Ok(JsValue::NULL)
// }
/// Generate a proof for the given email string and public key.
/// # Arguments
/// * `params` - a trusted setup parameter bytes.
/// * `pk_chunks` - a list of chunks of the proving key.
/// * `email_str` - an email string.
/// * `public_key_n` - a public key string.
/// # Return values
/// Return a promise of a list of the hex string of the proof and the public input.
#[wasm_bindgen]
pub fn prove_email(params: JsValue, pk_chunks: JsArray, email_str: String, public_key_n: String) -> Result<JsArray, JsValue> {
console_error_panic_hook::set_once();
@@ -205,27 +235,8 @@ pub fn prove_email(params: JsValue, pk_chunks: JsArray, email_str: String, publi
let public_input = circuit.gen_default_public_input();
let proof = gen_proof_shplonk(&params, &pk, circuit, instances.clone(), &mut OsRng, None);
log_1(&JsValue::from_str("proof generated"));
// {
// // let instances = public_input.instances::<Fr>();
// let mut transcript_read = PoseidonTranscript::<NativeLoader, &[u8]>::new(&proof);
// let result = VerificationStrategy::<_, VerifierSHPLONK<Bn256>>::finalize(
// verify_proof::<_, VerifierSHPLONK<Bn256>, _, _, _>(
// params.verifier_params(),
// &pk.get_vk(),
// AccumulatorStrategy::new(params.verifier_params()),
// &[&instances.iter().map(Vec::as_slice).collect_vec()],
// &mut transcript_read,
// )
// .map_err(|err| JsValue::from_str(&format!("verification error: {}", err.to_string())))?,
// );
// if !result {
// return Err(JsValue::from_str("verification failed in the proof generation"));
// }
// }
let proof_hex = format!("0x{}", hex::encode(&proof));
// serde_wasm_bindgen::to_value(&proof).map_err(|err| JsValue::from_str(&format!("fail to serialize proof. Error: {}", err.to_string())))?;
let public_input = serde_wasm_bindgen::to_value(&public_input).map_err(|err| JsValue::from_str(&format!("fail to serialize public input. Error: {}", err.to_string())))?;
let mut js_array = JsArray::new();
js_array.push(&JsValue::from_str(&proof_hex));
@@ -233,6 +244,14 @@ pub fn prove_email(params: JsValue, pk_chunks: JsArray, email_str: String, publi
Ok(js_array)
}
/// Verify the proof for the given email string and public key.
/// # Arguments
/// * `params` - a trusted setup parameter bytes.
/// * `vk` - a verification key bytes.
/// * `proof` - a hex string of the proof.
/// * `public_input` - a public input json string.
/// # Return values
/// Return a promise of a boolean value.
#[wasm_bindgen]
pub fn verify_email_proof(params: JsValue, vk: JsValue, proof: JsValue, public_input: JsValue) -> Result<JsValue, JsValue> {
console_error_panic_hook::set_once();
@@ -267,6 +286,11 @@ pub fn verify_email_proof(params: JsValue, vk: JsValue, proof: JsValue, public_i
Ok(JsValue::from_bool(result))
}
/// Configure the constraints definitions for [`DefaultEmailVerifyCircuit`].
/// # Arguments
/// * `meta` - a constraint system.
/// # Return values
/// Return a [`DefaultEmailVerifyConfig`].
pub(crate) fn configure_wasm<F: PrimeField>(meta: &mut ConstraintSystem<F>) -> DefaultEmailVerifyConfig<F> {
let params = default_config_params();
let range_config = RangeConfig::configure(
@@ -327,7 +351,7 @@ pub(crate) fn configure_wasm<F: PrimeField>(meta: &mut ConstraintSystem<F>) -> D
}
}
pub(crate) fn build_circuit<F: PrimeField>(email_str: &str, public_key_n: &str) -> DefaultEmailVerifyCircuit<F> {
fn build_circuit<F: PrimeField>(email_str: &str, public_key_n: &str) -> DefaultEmailVerifyCircuit<F> {
let email_bytes = email_str.as_bytes().to_vec();
let public_key_n = BigUint::from_bytes_le(&hex::decode(&public_key_n[2..]).unwrap());
DefaultEmailVerifyCircuit {