From 6826f4c2ff47529d95818886051f7865657a6080 Mon Sep 17 00:00:00 2001 From: aalimsahin Date: Thu, 1 Aug 2024 05:18:48 +0300 Subject: [PATCH 01/53] feat: updated forge build scripts for zksync --- packages/contracts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 624fd075..b995b92f 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -4,7 +4,7 @@ "license": "MIT", "scripts": { "build": "forge build", - "zkbuild": "forge build --zksync", + "zkbuild": "forge build -- --zksync", "test": "forge test --no-match-test \"testIntegration\"", "zktest": "forge test --no-match-test \"testIntegration\" --zksync --chain 300", "lint": "solhint 'src/**/*.sol'" From 2ad174804414e62f0d18ea716b4bfad880d8214b Mon Sep 17 00:00:00 2001 From: aalimsahin Date: Thu, 1 Aug 2024 05:21:33 +0300 Subject: [PATCH 02/53] chore: Updated README to replace wallet_eth_addr with account_eth_addr --- packages/relayer/README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/relayer/README.md b/packages/relayer/README.md index 5d859785..f0ca6436 100644 --- a/packages/relayer/README.md +++ b/packages/relayer/README.md @@ -9,12 +9,12 @@ You can run the relayer either on your local environments or cloud instances (we 3. If you have not deployed common contracts, build contract artifacts and deploy required contracts. 1. `cd packages/contracts` and run `forge build`. 2. Set the env file in `packages/contracts/.env`, an example env file is as follows, - + ```jsx LOCALHOST_RPC_URL=http://127.0.0.1:8545 SEPOLIA_RPC_URL=https://sepolia.base.org MAINNET_RPC_URL=https://mainnet.base.org - + PRIVATE_KEY="" CHAIN_ID=84532 RPC_URL="https://sepolia.base.org" @@ -38,7 +38,7 @@ You can run the relayer either on your local environments or cloud instances (we CHAIN_RPC_PROVIDER=https://sepolia.base.org CHAIN_RPC_EXPLORER=https://sepolia.basescan.org CHAIN_ID=84532 # Chain ID of the testnet. - + # IMAP + SMTP (Settings will be provided by your email provider) IMAP_DOMAIN_NAME=imap.gmail.com IMAP_PORT=993 @@ -46,18 +46,18 @@ You can run the relayer either on your local environments or cloud instances (we SMTP_DOMAIN_NAME=smtp.gmail.com LOGIN_ID= # IMAP login id - usually your email address. LOGIN_PASSWORD="" # IMAP password - usually your email password. - + PROVER_ADDRESS="http://localhost:8080" # Address of the prover. - + DATABASE_URL= "postgres://new_user:my_secure_password@localhost/my_new_database" WEB_SERVER_ADDRESS="127.0.0.1:4500" CIRCUITS_DIR_PATH= # Absolute path to packages/circuits EMAIL_TEMPLATES_PATH= # Absolute path to packages/relayer/eml_templates - + CANISTER_ID="q7eci-dyaaa-aaaak-qdbia-cai" PEM_PATH="./.ic.pem" IC_REPLICA_URL="https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=q7eci-dyaaa-aaaak-qdbia-cai" - + JSON_LOGGER=false ``` 7. You should have your entire setup up and running! @@ -76,11 +76,11 @@ Note that from June 2024, IMAP will be enabled by default. ##### Enable two-factor authentication for your Google account: -Refer to the following help link. +Refer to the following help link. [Google 2FA Setup](https://support.google.com/accounts/answer/185839?hl=en&co=GENIE.Platform%3DDesktop) -##### Create an app password: +##### Create an app password: Refer to the following help link. If you do not see the 'App passwords' option, try searching for 'app pass' in the search box to select it. @@ -97,7 +97,7 @@ Refer to the following help link. If you do not see the 'App passwords' option, 4. (Optional) Delete `db.yml` , `ingress.yml` and `relayer.yml` if applied already 5. (Optional) Build the Relayer’s Docker image and publish it. 6. Set the config in the respective manifests (Here, you can set the image of the relayer in `relayer.yml` , latest image already present in the config.) -7. Apply `db.yml` +7. Apply `db.yml` 8. Apply `relayer.yml` , ssh into the pod and run `nohup cargo run &` , this step should be done under a min to pass the liveness check. 9. Apply `ingress.yml` @@ -143,9 +143,9 @@ It exposes the following REST APIs. 5. If the contract of `account_eth_addr` is not deployed, return a 400 response. 4. If a record with `account_code` exists in the `credentials` table, return a 400 response. 6. Randomly generate a `request_id`. If a record with `request_id` exists in the `requests` table, regenerate a new `request_id`. - 7. If a record with `account_eth_addr`, `guardian_email_addr` and `is_set=true` exists in the `credentials` table, + 7. If a record with `account_eth_addr`, `guardian_email_addr` and `is_set=true` exists in the `credentials` table, 1. Insert `(request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, false, template_idx, false)` into the `requests` table. - 2. Send `guardian_email_addr` an error email to say that `account_eth_addr` tries to set you to a guardian, which is rejected since you are already its guardian. + 2. Send `guardian_email_addr` an error email to say that `account_eth_addr` tries to set you to a guardian, which is rejected since you are already its guardian. 3. Return a 200 response along with `request_id` and `subject_params` **to prevent a malicious client user from learning if the pair of the `account_eth_addr` and the `guardian_email_addr` is already set or not.** 8. Insert `(account_code, account_eth_addr, controller_eth_addr, guardian_email_addr, false)` into the `credentials` table. 9. Insert `(request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, false, template_idx)` into the `requests` table. @@ -158,12 +158,12 @@ It exposes the following REST APIs. - `POST recoveryRequest` 1. Receive `controller_eth_addr`, `guardian_email_addr`, `template_idx`, and `subject`. - 2. Let `subject_template` be the `template_idx`-th template in `recoverySubjectTemplates()` of `wallet_eth_addr`. + 2. Let `subject_template` be the `template_idx`-th template in `recoverySubjectTemplates()` of `account_eth_addr`. 3. If the `subject` does not match with `subject_template` return a 400 response. Let `subject_params` be the parsed values. 4. Extract `account_eth_addr` from the given `subject` by following `subject_template`. 5. If the contract of `account_eth_addr` is not deployed, return a 400 response. 6. Randomly generate a `request_id`. If a record with `request_id` exists in the `requests` table, regenerate a new `request_id`. - 7. If a record with `account_eth_addr`, `guardian_email_addr`, and `is_set=true` exists in the `credentials` table, + 7. If a record with `account_eth_addr`, `guardian_email_addr`, and `is_set=true` exists in the `credentials` table, 1. Insert `(request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, true, template_idx, false)` into the `requests` table. 2. Send an email as follows. - To: `guardian_email_addr` @@ -171,14 +171,14 @@ It exposes the following REST APIs. - Reply-to: `relayer_email_addr_before_domain ~~+ "+code" + hex(account_code)~~ + "@" + relayer_email_addr_domain`. - Body: Any message, but it MUST contain `"#" + digit(request_id)`. 3. Return a 200 response along with `request_id` and `subject_params`. - 7. If a record with `account_eth_addr`, `guardian_email_addr`, and `is_set=false` exists in the `credentials` table, - 1. Insert `(request_id, wallet_eth_addr, guardian_email_addr, true, template_idx, false)` into the `requests` table. + 7. If a record with `account_eth_addr`, `guardian_email_addr`, and `is_set=false` exists in the `credentials` table, + 1. Insert `(request_id, account_eth_addr, guardian_email_addr, true, template_idx, false)` into the `requests` table. 2. Send an email as follows. - To: `guardian_email_addr` - Subject: A message to say that `account_eth_addr` requests your account recovery, but you have not approved being its guardian. 3. Return a 200 response along with `request_id` and `subject_params`. - 8. If a record with `wallet_eth_addr`, `guardian_email_addr` does not exist in the `credentials` table, - 1. Insert `(request_id, wallet_eth_addr, guardian_email_addr, true, template_idx, false)` into the `requests` table. + 8. If a record with `account_eth_addr`, `guardian_email_addr` does not exist in the `credentials` table, + 1. Insert `(request_id, account_eth_addr, guardian_email_addr, true, template_idx, false)` into the `requests` table. 2. Send an email as follows. - To: `guardian_email_addr` - Subject: if the domain of `guardian_email_addr` signs the To field, `subject`. Otherwise, `subject + " Code "`. From 58f92d1c07ecec2fdd2c029e6483850dbef85af4 Mon Sep 17 00:00:00 2001 From: aalimsahin Date: Thu, 1 Aug 2024 05:41:37 +0300 Subject: [PATCH 03/53] feat: added step for creating the ic.pem file to the readme --- packages/relayer/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/relayer/README.md b/packages/relayer/README.md index f0ca6436..d4f8a333 100644 --- a/packages/relayer/README.md +++ b/packages/relayer/README.md @@ -60,6 +60,15 @@ You can run the relayer either on your local environments or cloud instances (we JSON_LOGGER=false ``` + 3. Generate the `.ic.pem` file and password. + - Create the `.ic.pem` file using OpenSSL: + ```sh + openssl genpkey -algorithm RSA -out .ic.pem -aes-256-cbc -pass pass:your_password + ``` + - If you need a password, you can generate a random password using: + ```sh + openssl rand -base64 32 + ``` 7. You should have your entire setup up and running! NOTE: You need to turn on IMAP on the email id you’d be using for the relayer. From b2db761ed2a66806afc191be2b07f4bde400f8ea Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 23 Aug 2024 14:08:18 +0100 Subject: [PATCH 04/53] Add Re: to subject in email replies --- packages/relayer/src/modules/mail.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index de7b27ce..d9c114d5 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -332,7 +332,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<()> { ); let render_data = serde_json::json!({"userEmailAddr": email_addr, "request": subject}); let body_html = render_html("acknowledgement.html", render_data).await?; - let subject = format!("Email Wallet Notification. Acknowledgement."); + let subject = format!("Re: {}", subject); let email = EmailMessage { to: email_addr, subject, From bb662050d6bc37e6bd90fdd6376017d01734c398 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 2 Sep 2024 20:08:23 +0530 Subject: [PATCH 05/53] Add note to acceptance_request.html reminding users to retain the email --- packages/relayer/eml_templates/acceptance_request.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/relayer/eml_templates/acceptance_request.html b/packages/relayer/eml_templates/acceptance_request.html index f350817a..6c20379e 100644 --- a/packages/relayer/eml_templates/acceptance_request.html +++ b/packages/relayer/eml_templates/acceptance_request.html @@ -172,6 +172,8 @@ Your request ID is #{{requestId}}.

If you did not initiate this request, please contact us immediately. +

+ Note: Do not delete this email after replying. The code in the title can be used to recover your account in absence of an available relayer

From 0d2ddf1a7b8b9971bffa17d16f65d432ad5796c8 Mon Sep 17 00:00:00 2001 From: Aditya Bisht <44467788+Bisht13@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:42:37 +0530 Subject: [PATCH 06/53] Update package.json --- packages/contracts/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 0bbbf0c5..44bae057 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "license": "MIT", "scripts": { - "build": "forge build", - "zkbuild": "forge build -- --zksync", - "test": "forge test --no-match-test \"testIntegration\"", - "zktest": "forge test --no-match-test \"testIntegration\" --zksync --chain 300", + "build": "forge build --skip '*ZKSync*'", + "zkbuild": "forge build --zksync", + "test": "forge test --no-match-test \"testIntegration\" --skip '*ZKSync*'", + "zktest": "forge test --no-match-test \"testIntegration\" --system-mode=true --zksync --gas-limit 1000000000 --chain 300", "build": "forge build --skip '*ZKSync*'", "zkbuild": "forge build --zksync", "test": "forge test --no-match-test \"testIntegration\" --skip '*ZKSync*'", @@ -25,4 +25,4 @@ "forge-std": "https://github.com/foundry-rs/forge-std", "solhint": "^3.6.1" } -} \ No newline at end of file +} From ce2fc6d0d278ed6cbf511daf606b97162b8a1ee8 Mon Sep 17 00:00:00 2001 From: SoraSuegami Date: Tue, 24 Sep 2024 08:55:40 +0900 Subject: [PATCH 07/53] Fix typo and remove unnecessary file --- packages/circuits/input.json | 2136 ------------------------------- packages/contracts/package.json | 2 +- 2 files changed, 1 insertion(+), 2137 deletions(-) delete mode 100644 packages/circuits/input.json diff --git a/packages/circuits/input.json b/packages/circuits/input.json deleted file mode 100644 index 7aec4db2..00000000 --- a/packages/circuits/input.json +++ /dev/null @@ -1,2136 +0,0 @@ -{ - "padded_header": [ - 115, - 117, - 98, - 106, - 101, - 99, - 116, - 58, - 69, - 109, - 97, - 105, - 108, - 32, - 65, - 99, - 99, - 111, - 117, - 110, - 116, - 32, - 82, - 101, - 99, - 111, - 118, - 101, - 114, - 121, - 32, - 84, - 101, - 115, - 116, - 49, - 13, - 10, - 116, - 111, - 58, - 115, - 117, - 101, - 103, - 97, - 109, - 105, - 115, - 111, - 114, - 97, - 64, - 103, - 109, - 97, - 105, - 108, - 46, - 99, - 111, - 109, - 13, - 10, - 102, - 114, - 111, - 109, - 58, - 101, - 109, - 97, - 105, - 119, - 97, - 108, - 108, - 101, - 116, - 46, - 97, - 108, - 105, - 99, - 101, - 64, - 103, - 109, - 97, - 105, - 108, - 46, - 99, - 111, - 109, - 13, - 10, - 109, - 105, - 109, - 101, - 45, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 58, - 49, - 46, - 48, - 13, - 10, - 100, - 97, - 116, - 101, - 58, - 70, - 114, - 105, - 44, - 32, - 48, - 54, - 32, - 83, - 101, - 112, - 32, - 50, - 48, - 50, - 52, - 32, - 48, - 53, - 58, - 53, - 55, - 58, - 52, - 52, - 32, - 45, - 48, - 55, - 48, - 48, - 32, - 40, - 80, - 68, - 84, - 41, - 13, - 10, - 109, - 101, - 115, - 115, - 97, - 103, - 101, - 45, - 105, - 100, - 58, - 60, - 54, - 54, - 100, - 97, - 102, - 99, - 52, - 56, - 46, - 49, - 55, - 48, - 97, - 48, - 50, - 50, - 48, - 46, - 51, - 51, - 99, - 51, - 100, - 48, - 46, - 102, - 99, - 98, - 48, - 64, - 109, - 120, - 46, - 103, - 111, - 111, - 103, - 108, - 101, - 46, - 99, - 111, - 109, - 62, - 13, - 10, - 100, - 107, - 105, - 109, - 45, - 115, - 105, - 103, - 110, - 97, - 116, - 117, - 114, - 101, - 58, - 118, - 61, - 49, - 59, - 32, - 97, - 61, - 114, - 115, - 97, - 45, - 115, - 104, - 97, - 50, - 53, - 54, - 59, - 32, - 99, - 61, - 114, - 101, - 108, - 97, - 120, - 101, - 100, - 47, - 114, - 101, - 108, - 97, - 120, - 101, - 100, - 59, - 32, - 100, - 61, - 103, - 109, - 97, - 105, - 108, - 46, - 99, - 111, - 109, - 59, - 32, - 115, - 61, - 50, - 48, - 50, - 51, - 48, - 54, - 48, - 49, - 59, - 32, - 116, - 61, - 49, - 55, - 50, - 53, - 54, - 50, - 55, - 52, - 54, - 53, - 59, - 32, - 120, - 61, - 49, - 55, - 50, - 54, - 50, - 51, - 50, - 50, - 54, - 53, - 59, - 32, - 100, - 97, - 114, - 97, - 61, - 103, - 111, - 111, - 103, - 108, - 101, - 46, - 99, - 111, - 109, - 59, - 32, - 104, - 61, - 115, - 117, - 98, - 106, - 101, - 99, - 116, - 58, - 116, - 111, - 58, - 102, - 114, - 111, - 109, - 58, - 109, - 105, - 109, - 101, - 45, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 58, - 100, - 97, - 116, - 101, - 58, - 109, - 101, - 115, - 115, - 97, - 103, - 101, - 45, - 105, - 100, - 58, - 102, - 114, - 111, - 109, - 58, - 116, - 111, - 58, - 99, - 99, - 58, - 115, - 117, - 98, - 106, - 101, - 99, - 116, - 32, - 58, - 100, - 97, - 116, - 101, - 58, - 109, - 101, - 115, - 115, - 97, - 103, - 101, - 45, - 105, - 100, - 58, - 114, - 101, - 112, - 108, - 121, - 45, - 116, - 111, - 59, - 32, - 98, - 104, - 61, - 50, - 110, - 99, - 84, - 75, - 79, - 68, - 78, - 43, - 108, - 98, - 48, - 68, - 57, - 43, - 90, - 97, - 67, - 85, - 104, - 57, - 118, - 84, - 106, - 111, - 109, - 72, - 78, - 80, - 110, - 73, - 54, - 57, - 109, - 107, - 55, - 119, - 101, - 87, - 115, - 54, - 65, - 56, - 61, - 59, - 32, - 98, - 61, - 128, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15, - 32, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "padded_body": [ - 45, - 45, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 54, - 48, - 53, - 48, - 48, - 49, - 54, - 56, - 53, - 53, - 54, - 56, - 48, - 56, - 51, - 55, - 50, - 54, - 57, - 61, - 61, - 13, - 10, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 45, - 84, - 121, - 112, - 101, - 58, - 32, - 116, - 101, - 120, - 116, - 47, - 104, - 116, - 109, - 108, - 59, - 32, - 99, - 104, - 97, - 114, - 115, - 101, - 116, - 61, - 34, - 117, - 116, - 102, - 45, - 56, - 34, - 13, - 10, - 77, - 73, - 77, - 69, - 45, - 86, - 101, - 114, - 115, - 105, - 111, - 110, - 58, - 32, - 49, - 46, - 48, - 13, - 10, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 45, - 84, - 114, - 97, - 110, - 115, - 102, - 101, - 114, - 45, - 69, - 110, - 99, - 111, - 100, - 105, - 110, - 103, - 58, - 32, - 113, - 117, - 111, - 116, - 101, - 100, - 45, - 112, - 114, - 105, - 110, - 116, - 97, - 98, - 108, - 101, - 13, - 10, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 45, - 84, - 121, - 112, - 101, - 58, - 32, - 116, - 101, - 120, - 116, - 47, - 104, - 116, - 109, - 108, - 59, - 32, - 99, - 104, - 97, - 114, - 115, - 101, - 116, - 61, - 117, - 116, - 102, - 45, - 56, - 13, - 10, - 13, - 10, - 13, - 10, - 32, - 60, - 104, - 116, - 109, - 108, - 62, - 13, - 10, - 32, - 60, - 98, - 111, - 100, - 121, - 62, - 13, - 10, - 32, - 60, - 104, - 49, - 62, - 72, - 101, - 108, - 108, - 111, - 33, - 60, - 47, - 104, - 49, - 62, - 13, - 10, - 32, - 60, - 112, - 62, - 84, - 104, - 105, - 115, - 32, - 105, - 115, - 32, - 97, - 32, - 116, - 101, - 115, - 116, - 32, - 101, - 109, - 97, - 105, - 108, - 32, - 119, - 105, - 116, - 104, - 32, - 97, - 32, - 98, - 97, - 115, - 105, - 99, - 32, - 72, - 84, - 77, - 76, - 32, - 98, - 111, - 100, - 121, - 46, - 60, - 47, - 112, - 62, - 13, - 10, - 32, - 60, - 100, - 105, - 118, - 32, - 105, - 100, - 61, - 51, - 68, - 34, - 122, - 107, - 101, - 109, - 97, - 105, - 108, - 34, - 62, - 65, - 99, - 99, - 101, - 112, - 116, - 32, - 103, - 117, - 97, - 114, - 100, - 105, - 97, - 110, - 32, - 114, - 101, - 113, - 117, - 101, - 115, - 116, - 32, - 102, - 111, - 114, - 32, - 48, - 120, - 48, - 67, - 48, - 54, - 54, - 56, - 56, - 101, - 54, - 49, - 67, - 48, - 54, - 52, - 54, - 54, - 69, - 61, - 13, - 10, - 50, - 97, - 53, - 67, - 54, - 102, - 69, - 52, - 69, - 49, - 53, - 99, - 51, - 53, - 57, - 50, - 54, - 48, - 97, - 51, - 51, - 102, - 51, - 32, - 67, - 111, - 100, - 101, - 32, - 49, - 49, - 54, - 50, - 101, - 98, - 102, - 102, - 52, - 48, - 57, - 49, - 56, - 97, - 102, - 101, - 53, - 51, - 48, - 53, - 101, - 54, - 56, - 51, - 57, - 54, - 102, - 48, - 50, - 56, - 51, - 101, - 98, - 54, - 55, - 53, - 57, - 48, - 49, - 100, - 48, - 51, - 56, - 55, - 102, - 57, - 61, - 13, - 10, - 55, - 100, - 50, - 49, - 57, - 50, - 56, - 100, - 52, - 50, - 51, - 97, - 97, - 97, - 48, - 98, - 53, - 52, - 60, - 47, - 100, - 105, - 118, - 62, - 61, - 50, - 48, - 13, - 10, - 32, - 60, - 47, - 98, - 111, - 100, - 121, - 62, - 13, - 10, - 32, - 60, - 47, - 104, - 116, - 109, - 108, - 62, - 13, - 10, - 32, - 61, - 50, - 48, - 13, - 10, - 45, - 45, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 61, - 54, - 48, - 53, - 48, - 48, - 49, - 54, - 56, - 53, - 53, - 54, - 56, - 48, - 56, - 51, - 55, - 50, - 54, - 57, - 61, - 61, - 45, - 45, - 13, - 10, - 128, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16, - 112, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "body_hash_idx": 436, - "public_key": [ - "2107195391459410975264579855291297887", - "2562632063603354817278035230349645235", - "1868388447387859563289339873373526818", - "2159353473203648408714805618210333973", - "351789365378952303483249084740952389", - "659717315519250910761248850885776286", - "1321773785542335225811636767147612036", - "258646249156909342262859240016844424", - "644872192691135519287736182201377504", - "174898460680981733302111356557122107", - "1068744134187917319695255728151595132", - "1870792114609696396265442109963534232", - "8288818605536063568933922407756344", - "1446710439657393605686016190803199177", - "2256068140678002554491951090436701670", - "518946826903468667178458656376730744", - "3222036726675473160989497427257757" - ], - "signature": [ - "170161271844255892981997056109468295", - "2042410320678089637820651285407478756", - "2235307951907446725362990721960277744", - "2558650872283482274023232178928077002", - "1125115414447411231828809260942904609", - "2396701783176084287341878147443533109", - "2128856280301536390906877240389145121", - "2428098792522595894701475799989919597", - "1647552530172515032677576620955308208", - "2527537180972491287857094609185809092", - "2132950398601810533565118801188358141", - "160538878880934704009688085302112521", - "898519688023416454463467167922781011", - "258221678414411925992593903157944861", - "1423180960707426692015227448675294049", - "1156922850624474726553341869246641892", - "1773570027362757618569452574560009" - ], - "padded_header_len": 512, - "padded_body_len": 576, - "precomputed_sha": [ - 106, - 9, - 230, - 103, - 187, - 103, - 174, - 133, - 60, - 110, - 243, - 114, - 165, - 79, - 245, - 58, - 81, - 14, - 82, - 127, - 155, - 5, - 104, - 140, - 31, - 131, - 217, - 171, - 91, - 224, - 205, - 25 - ], - "account_code": "0x1162ebff40918afe5305e68396f0283eb675901d0387f97d21928d423aaa0b54", - "from_addr_idx": 69, - "domain_idx": 17, - "timestamp_idx": 297, - "code_idx": 380, - "command_idx": 0, - "padded_cleaned_body": null -} \ No newline at end of file diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 49b972d8..3fc1d004 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -6,7 +6,7 @@ "build": "forge build --skip '*ZKSync*'", "zkbuild": "forge build --zksync", "test": "forge test --no-match-test \"testIntegration\" --no-match-contract \".*Script.*\" --skip '*ZKSync*'", - "zktest": "forge test --no-match-test \"testIntegration\" --no-match-contract \".*Script.*\" --system-mode=true --zksync --gas-limit 1000000000 --chain 300",, + "zktest": "forge test --no-match-test \"testIntegration\" --no-match-contract \".*Script.*\" --system-mode=true --zksync --gas-limit 1000000000 --chain 300", "lint": "solhint 'src/**/*.sol'" }, "dependencies": { From 0f961e653b69a451da7f607cbca8cd0b1ddcc98b Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 8 Sep 2024 20:03:56 +0530 Subject: [PATCH 08/53] chore: refactor --- .../eml_templates/credential_not_present.html | 3 ++- packages/relayer/src/core.rs | 8 +++---- packages/relayer/src/modules/mail.rs | 21 +++++++++++-------- .../src/modules/web_server/rest_api.rs | 6 ++---- ...ject_templates.rs => command_templates.rs} | 3 +-- packages/relayer/src/utils/mod.rs | 4 ++-- packages/relayer/src/utils/utils.rs | 4 ---- 7 files changed, 23 insertions(+), 26 deletions(-) rename packages/relayer/src/utils/{subject_templates.rs => command_templates.rs} (99%) diff --git a/packages/relayer/eml_templates/credential_not_present.html b/packages/relayer/eml_templates/credential_not_present.html index d823a014..b13ee178 100644 --- a/packages/relayer/eml_templates/credential_not_present.html +++ b/packages/relayer/eml_templates/credential_not_present.html @@ -167,7 +167,7 @@ " > You have received an guardian request from the wallet address {{walletAddress}}. - Add the guardian's account code in the subject and reply to this email. + Reply to this email.
Your request ID is #{{requestId}}.

@@ -414,5 +414,6 @@   +
{{command}}
diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 9939ab04..7a0a7e7c 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -85,7 +85,7 @@ pub async fn handle_email(email: String) -> Result { .await?; let command_params = - match extract_template_vals_from_command(&email_body, command_template) { + match extract_template_vals_from_command_template(&email_body, command_template) { Ok(command_params) => command_params, Err(e) => { return Ok(EmailAuthEvent::Error { @@ -134,7 +134,7 @@ pub async fn handle_email(email: String) -> Result { domain_name: parsed_email.get_email_domain()?, public_key_hash: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 0]), timestamp: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 2]).into(), - masked_command: masked_command, + masked_command, email_nullifier: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 1]), account_salt, is_code_exist, @@ -229,7 +229,7 @@ pub async fn handle_email(email: String) -> Result { .await?; let command_params = - match extract_template_vals_from_command(&email_body, command_template) { + match extract_template_vals_from_command_template(&email_body, command_template) { Ok(command_params) => command_params, Err(e) => { return Ok(EmailAuthEvent::Error { @@ -276,7 +276,7 @@ pub async fn handle_email(email: String) -> Result { domain_name: parsed_email.get_email_domain()?, public_key_hash: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 0]), timestamp: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 2]).into(), - masked_command: masked_command, + masked_command, email_nullifier: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 1]), account_salt, is_code_exist, diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index fd189d4f..98c5d0db 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -44,12 +44,12 @@ pub enum EmailAuthEvent { GuardianNotRegistered { account_eth_addr: String, guardian_email_addr: String, - subject: String, + command: String, request_id: u32, }, Ack { email_addr: String, - subject: String, + command: String, original_message_id: Option, }, NoOp, @@ -296,14 +296,14 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<()> { EmailAuthEvent::GuardianNotRegistered { account_eth_addr, guardian_email_addr, - subject, + command, request_id, } => { - let subject = format!("{} Code ", subject); + let command = format!("{} Code ", command); let body_plain = format!( "You have received an guardian request from the wallet address {}. \ - Add the guardian's account code in the subject and reply to this email. \ + Reply to this email. \ Your request ID is #{}. \ If you did not initiate this request, please contact us immediately.", account_eth_addr, request_id @@ -313,7 +313,10 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<()> { "userEmailAddr": guardian_email_addr, "walletAddress": account_eth_addr, "requestId": request_id, + "command": command, }); + + let subject = "Guardian Not Registered".to_string(); let body_html = render_html("credential_not_present.html", render_data).await?; let email = EmailMessage { @@ -330,14 +333,14 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<()> { } EmailAuthEvent::Ack { email_addr, - subject, + command, original_message_id, } => { let body_plain = format!( - "Hi {}!\nYour email with the subject {} is received.", - email_addr, subject + "Hi {}!\nYour email with the command {} is received.", + email_addr, command ); - let render_data = serde_json::json!({"userEmailAddr": email_addr, "request": subject}); + let render_data = serde_json::json!({"userEmailAddr": email_addr, "request": command}); let body_html = render_html("acknowledgement.html", render_data).await?; let subject = format!("Re: {}", subject); let email = EmailMessage { diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 2812480f..aef07158 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -445,7 +445,7 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response handle_email_event(EmailAuthEvent::GuardianNotRegistered { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), - subject: payload.command.clone(), + command: payload.command.clone(), request_id, }) .await @@ -509,8 +509,6 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response handle_email_event(EmailAuthEvent::GuardianNotSet { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), - // request_id, - // subject: payload.subject.clone(), }) .await .expect("Failed to send Recovery event"); @@ -637,7 +635,7 @@ pub async fn receive_email_api_fn(email: String) -> Result<()> { tokio::spawn(async move { match handle_email_event(EmailAuthEvent::Ack { email_addr: from_addr.clone(), - subject: parsed_email.get_subject_all().unwrap_or_default(), + command: parsed_email.get_command(false).unwrap_or_default(), original_message_id: parsed_email.get_message_id().ok(), }) .await diff --git a/packages/relayer/src/utils/subject_templates.rs b/packages/relayer/src/utils/command_templates.rs similarity index 99% rename from packages/relayer/src/utils/subject_templates.rs rename to packages/relayer/src/utils/command_templates.rs index e8ccd734..c742a323 100644 --- a/packages/relayer/src/utils/subject_templates.rs +++ b/packages/relayer/src/utils/command_templates.rs @@ -49,7 +49,7 @@ impl TemplateValue { } } -pub fn extract_template_vals_from_command( +pub fn extract_template_vals_from_command_template( input: &str, templates: Vec, ) -> Result, anyhow::Error> { @@ -178,7 +178,6 @@ pub fn extract_template_vals(input: &str, templates: Vec) -> Result String { // Convert amount to string in wei format (no decimals) let uint_str = uint.to_string(); diff --git a/packages/relayer/src/utils/mod.rs b/packages/relayer/src/utils/mod.rs index 361a451a..11b1e85f 100644 --- a/packages/relayer/src/utils/mod.rs +++ b/packages/relayer/src/utils/mod.rs @@ -1,7 +1,7 @@ +pub mod command_templates; pub mod strings; -pub mod subject_templates; pub mod utils; +pub use command_templates::*; pub use strings::*; -pub use subject_templates::*; pub use utils::*; diff --git a/packages/relayer/src/utils/utils.rs b/packages/relayer/src/utils/utils.rs index 49c021c1..948c83fe 100644 --- a/packages/relayer/src/utils/utils.rs +++ b/packages/relayer/src/utils/utils.rs @@ -11,10 +11,6 @@ use relayer_utils::*; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; -const DOMAIN_FIELDS: usize = 9; -const SUBJECT_FIELDS: usize = 17; -const EMAIL_ADDR_FIELDS: usize = 9; - #[derive(Debug, Clone, Deserialize)] pub struct ProverRes { proof: ProofJson, From 1245c2f994a9bfa00aaeb5bdf38695272a2a06d0 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 5 Sep 2024 17:26:01 +0200 Subject: [PATCH 09/53] WIP: Add custom errors --- packages/relayer/.env.example | 6 +- packages/relayer/Cargo.toml | 2 + packages/relayer/src/chain.rs | 103 +++++--- packages/relayer/src/database.rs | 83 ++++-- .../relayer/src/modules/web_server/errors.rs | 149 +++++++++++ .../relayer/src/modules/web_server/mod.rs | 2 + .../src/modules/web_server/rest_api.rs | 250 +++++++++++------- .../relayer/src/modules/web_server/server.rs | 159 +---------- packages/relayer/src/utils/utils.rs | 4 +- 9 files changed, 439 insertions(+), 319 deletions(-) create mode 100644 packages/relayer/src/modules/web_server/errors.rs diff --git a/packages/relayer/.env.example b/packages/relayer/.env.example index 0f696907..041c1f22 100644 --- a/packages/relayer/.env.example +++ b/packages/relayer/.env.example @@ -1,5 +1,5 @@ -EMAIL_ACCOUNT_RECOVERY_VERSION_ID= # Version ID of the email account recovery. -PRIVATE_KEY= # Private key for Relayer's account. +EMAIL_ACCOUNT_RECOVERY_VERSION_ID=1 # Version ID of the email account recovery. +PRIVATE_KEY="0x1413e91f9aee429e70b145db739f72dcd7250bd2b8c7907cf9f6366440f6c76f" # Private key for Relayer's account. CHAIN_RPC_PROVIDER=http://127.0.0.1:8545 CHAIN_RPC_EXPLORER= CHAIN_ID=11155111 # Chain ID of the testnet. @@ -18,4 +18,4 @@ CANISTER_ID="q7eci-dyaaa-aaaak-qdbia-cai" PEM_PATH="./.ic.pem" IC_REPLICA_URL="https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=q7eci-dyaaa-aaaak-qdbia-cai" -JSON_LOGGER=false \ No newline at end of file +JSON_LOGGER=false diff --git a/packages/relayer/Cargo.toml b/packages/relayer/Cargo.toml index 7fac6c4e..c55e95bf 100644 --- a/packages/relayer/Cargo.toml +++ b/packages/relayer/Cargo.toml @@ -54,6 +54,8 @@ http = "1.1.0" ic-agent = { version = "0.37.1", features = ["pem", "reqwest"] } ic-utils = "0.37.0" candid = "0.10.10" +thiserror = "1.0.63" +rustc-hex = "2.1.0" [build-dependencies] ethers = "2.0.10" diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index 080cf388..fbc40f31 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -108,14 +108,16 @@ impl ChainClient { Ok(email_auth_addr) } - pub async fn is_wallet_deployed(&self, wallet_addr_str: &String) -> bool { - let wallet_addr: H160 = wallet_addr_str.parse().unwrap(); + pub async fn is_wallet_deployed(&self, wallet_addr_str: &String) -> Result { + let wallet_addr: H160 = wallet_addr_str.parse().map_err(ApiError::HexError)?; match self.client.get_code(wallet_addr, None).await { - Ok(code) => !code.is_empty(), + Ok(code) => Ok(!code.is_empty()), Err(e) => { // Log the error or handle it as needed - error!(LOG, "Error querying contract code: {:?}", e); - false + Err(ApiError::signer_middleware_error( + "Failed to check if wallet is deployed", + e, + )) } } } @@ -124,14 +126,16 @@ impl ChainClient { &self, controller_eth_addr: &String, template_idx: u64, - ) -> Result, anyhow::Error> { - let controller_eth_addr: H160 = controller_eth_addr.parse()?; + ) -> Result, ApiError> { + let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let templates = contract .acceptance_command_templates() .call() .await - .map_err(|e| anyhow::Error::from(e))?; + .map_err(|e| { + ApiError::contract_error("Failed to get acceptance subject templates", e) + })?; Ok(templates[template_idx as usize].clone()) } @@ -139,14 +143,14 @@ impl ChainClient { &self, controller_eth_addr: &String, template_idx: u64, - ) -> Result, anyhow::Error> { - let controller_eth_addr: H160 = controller_eth_addr.parse()?; + ) -> Result, ApiError> { + let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let templates = contract .recovery_command_templates() .call() .await - .map_err(|e| anyhow::Error::from(e))?; + .map_err(|e| ApiError::contract_error("Failed to get recovery subject templates", e))?; Ok(templates[template_idx as usize].clone()) } @@ -155,23 +159,27 @@ impl ChainClient { controller_eth_addr: &String, account_eth_addr: &String, complete_calldata: &String, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse()?; + ) -> Result { + let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let decoded_calldata = hex::decode(&complete_calldata.trim_start_matches("0x")).expect("Decoding failed"); - let call = contract.complete_recovery( - account_eth_addr - .parse::() - .expect("Invalid H160 address"), - Bytes::from(decoded_calldata), - ); - let tx = call.send().await?; + let account_eth_addr = account_eth_addr + .parse::() + .map_err(ApiError::HexError)?; + let call = contract.complete_recovery(account_eth_addr, Bytes::from(decoded_calldata)); + let tx = call + .send() + .await + .map_err(|e| ApiError::contract_error("Failed to call complete_recovery", e))?; // If the transaction is successful, the function will return true and false otherwise. let receipt = tx .log() .confirmations(CONFIRMATIONS) - .await? + .await + .map_err(|e| { + ApiError::provider_error("Failed to get receipt after calling complete_recovery", e) + })? .ok_or(anyhow!("No receipt"))?; Ok(receipt .status @@ -223,9 +231,14 @@ impl ChainClient { .unwrap_or(false)) } - pub async fn get_bytecode(&self, wallet_addr: &String) -> Result { - let wallet_address: H160 = wallet_addr.parse()?; - Ok(self.client.get_code(wallet_address, None).await?) + pub async fn get_bytecode(&self, wallet_addr: &String) -> Result { + let wallet_address: H160 = wallet_addr.parse().map_err(ApiError::HexError)?; + let client_code = self + .client + .get_code(wallet_address, None) + .await + .map_err(|e| ApiError::signer_middleware_error("Failed to get bytecode", e))?; + Ok(client_code) } pub async fn get_storage_at( @@ -245,8 +258,8 @@ impl ChainClient { controller_eth_addr: &String, command_params: Vec, template_idx: u64, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse()?; + ) -> Result { + let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let command_params_bytes = command_params .iter() // Change here: use iter() instead of map() directly on Vec @@ -261,7 +274,13 @@ impl ChainClient { template_idx.into(), ) .call() - .await?; + .await + .map_err(|e| { + ApiError::contract_error( + "Failed to get recovered account from acceptance subject", + e, + ) + })?; Ok(recovered_account) } @@ -270,23 +289,27 @@ impl ChainClient { controller_eth_addr: &String, command_params: Vec, template_idx: u64, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse()?; + ) -> Result { + let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let command_params_bytes = command_params .iter() // Change here: use iter() instead of map() directly on Vec .map(|s| { - s.abi_encode(None) // Assuming decimal_size is not needed or can be None - .unwrap_or_else(|_| Bytes::from("Error encoding".as_bytes().to_vec())) - }) // Error handling - .collect::>(); + s.abi_encode(None).map_err(|_| { + ApiError::Validation("Error encoding subject parameters".to_string()) + }) + }) + .collect::, ApiError>>()?; let recovered_account = contract .extract_recovered_account_from_recovery_command( command_params_bytes, template_idx.into(), ) .call() - .await?; + .await + .map_err(|e| { + ApiError::contract_error("Failed to get recovered account from recovery subject", e) + })?; Ok(recovered_account) } @@ -294,11 +317,15 @@ impl ChainClient { &self, controller_eth_addr: &String, account_eth_addr: &String, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse()?; - let account_eth_addr: H160 = account_eth_addr.parse()?; + ) -> Result { + let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; + let account_eth_addr: H160 = account_eth_addr.parse().map_err(ApiError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); - let is_activated = contract.is_activated(account_eth_addr).call().await?; + let is_activated = contract + .is_activated(account_eth_addr) + .call() + .await + .map_err(|e| ApiError::contract_error("Failed to check if is activated", e))?; Ok(is_activated) } } diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index acd74822..29da457f 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -102,7 +102,7 @@ impl Database { &self, account_eth_addr: &str, email_addr: &str, - ) -> bool { + ) -> std::result::Result { let row = sqlx::query( "SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2", ) @@ -110,11 +110,13 @@ impl Database { .bind(email_addr) .fetch_optional(&self.db) .await - .unwrap(); + .map_err(|e| { + ApiError::database_error("Failed to check if wallet and email are registered", e) + })?; match row { - Some(_) => true, - None => false, + Some(_) => Ok(true), + None => Ok(false), } } @@ -132,14 +134,17 @@ impl Database { pub(crate) async fn update_credentials_of_wallet_and_email( &self, row: &Credentials, - ) -> Result<()> { + ) -> std::result::Result<(), ApiError> { let res = sqlx::query("UPDATE credentials SET account_code = $1, is_set = $2 WHERE account_eth_addr = $3 AND guardian_email_addr = $4") .bind(&row.account_code) .bind(row.is_set) .bind(&row.account_eth_addr) .bind(&row.guardian_email_addr) .execute(&self.db) - .await?; + .await + .map_err(|e| { + ApiError::database_error("Failed to insert credentials of wallet and email", e) + })?; Ok(()) } @@ -147,19 +152,26 @@ impl Database { &self, is_set: bool, account_eth_addr: &str, - ) -> Result<()> { + ) -> std::result::Result<(), ApiError> { let res = sqlx::query( "UPDATE credentials SET is_set = $1 WHERE account_eth_addr = $2 AND is_set = true", ) .bind(is_set) .bind(account_eth_addr) .execute(&self.db) - .await?; + .await + .map_err(|e| { + ApiError::database_error("Failed to update credentials of inactive guardian", e) + })?; Ok(()) } - pub(crate) async fn insert_credentials(&self, row: &Credentials) -> Result<()> { - info!(LOG, "insert row {:?}", row); + #[named] + pub(crate) async fn insert_credentials( + &self, + row: &Credentials, + ) -> std::result::Result<(), ApiError> { + info!(LOG, "insert row {:?}", row; "func" => function_name!()); let row = sqlx::query( "INSERT INTO credentials (account_code, account_eth_addr, guardian_email_addr, is_set) VALUES ($1, $2, $3, $4) RETURNING *", ) @@ -168,30 +180,44 @@ impl Database { .bind(&row.guardian_email_addr) .bind(row.is_set) .fetch_one(&self.db) - .await?; - info!(LOG, "{} row inserted", row.len()); + .await + .map_err(|e| ApiError::database_error("Failed to insert credentials", e))?; + info!( + LOG, + "{} row inserted", + row.len(); "func" => function_name!() + ); Ok(()) } - pub async fn is_guardian_set(&self, account_eth_addr: &str, guardian_email_addr: &str) -> bool { + pub async fn is_guardian_set( + &self, + account_eth_addr: &str, + guardian_email_addr: &str, + ) -> std::result::Result { let row = sqlx::query("SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2 AND is_set = TRUE") .bind(account_eth_addr) .bind(guardian_email_addr) .fetch_optional(&self.db) .await - .unwrap(); + .map_err(|e| ApiError::database_error("Failed to check if guardian is set", e))?; match row { - Some(_) => true, - None => false, + Some(_) => Ok(true), + None => Ok(false), } } - pub(crate) async fn get_request(&self, request_id: u32) -> Result> { + #[named] + pub(crate) async fn get_request( + &self, + request_id: u32, + ) -> std::result::Result, ApiError> { let row = sqlx::query("SELECT * FROM requests WHERE request_id = $1") .bind(request_id as i64) .fetch_optional(&self.db) - .await?; + .await + .map_err(|e| ApiError::database_error("Failed to get request", e))?; match row { Some(row) => { @@ -267,14 +293,17 @@ impl Database { &self, account_eth_addr: &str, email_addr: &str, - ) -> Result> { + ) -> std::result::Result, ApiError> { let row = sqlx::query( "SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2", ) .bind(account_eth_addr) .bind(email_addr) .fetch_optional(&self.db) - .await?; + .await + .map_err(|e| { + ApiError::database_error("Failed to get credentials from wallet and email", e) + })?; match row { Some(row) => { @@ -295,8 +324,9 @@ impl Database { } } - pub(crate) async fn insert_request(&self, row: &Request) -> Result<()> { - info!(LOG, "insert row {:?}", row); + #[named] + pub(crate) async fn insert_request(&self, row: &Request) -> std::result::Result<(), ApiError> { + info!(LOG, "insert row {:?}", row; "func" => function_name!()); let row = sqlx::query( "INSERT INTO requests (request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, is_for_recovery, template_idx, is_processed, is_success, email_nullifier, account_salt) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *", ) @@ -311,8 +341,13 @@ impl Database { .bind(&row.email_nullifier) .bind(&row.account_salt) .fetch_one(&self.db) - .await?; - info!(LOG, "{} row inserted", row.len()); + .await + .map_err(|e| ApiError::database_error("Failed to insert request", e))?; + info!( + LOG, + "{} row inserted", + row.len(); "func" => function_name!() + ); Ok(()) } } diff --git a/packages/relayer/src/modules/web_server/errors.rs b/packages/relayer/src/modules/web_server/errors.rs new file mode 100644 index 00000000..2b53701f --- /dev/null +++ b/packages/relayer/src/modules/web_server/errors.rs @@ -0,0 +1,149 @@ +use crate::*; +use axum::{ + response::{IntoResponse, Response}, + Json, +}; +use reqwest::StatusCode; +use rustc_hex::FromHexError; +use serde_json::json; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ApiError { + #[error("Database error: {0}")] + Database(DatabaseError), + #[error("Sqlx error: {0}")] + SqlxError(#[from] sqlx::Error), + #[error("Contract error: {0}")] + Contract(ContractErrorWrapper), + #[error("Signer middleware error: {0}")] + SignerMiddleware(SignerMiddlewareErrorWrapper), + #[error("Validation error: {0}")] + Validation(String), + // #[error("Not found: {0}")] + // NotFound(String), + #[error("Provider error: {0}")] + Provider(ProviderErrorWrapper), + #[error("Hex error: {0}")] + HexError(#[from] FromHexError), + #[error("Anyhow error: {0}")] + Anyhow(#[from] anyhow::Error), + #[error("Internal error: {0}")] + Internal(String), +} + +#[derive(Debug, thiserror::Error)] +#[error("{msg}: {source}")] +pub struct DatabaseError { + #[source] + pub source: sqlx::Error, + pub msg: String, +} + +impl DatabaseError { + pub fn new(source: sqlx::Error, msg: String) -> Self { + Self { source, msg } + } +} + +#[derive(Debug)] +pub struct ContractErrorWrapper { + msg: String, + source: String, +} + +impl std::fmt::Display for ContractErrorWrapper { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}: {}", self.msg, self.source) + } +} + +impl ContractErrorWrapper { + pub fn new(msg: String, err: ContractError) -> Self { + ContractErrorWrapper { + msg, + source: err.to_string(), + } + } +} + +#[derive(Debug)] +pub struct SignerMiddlewareErrorWrapper { + msg: String, + source: String, +} + +impl std::fmt::Display for SignerMiddlewareErrorWrapper { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}: {}", self.msg, self.source) + } +} + +impl SignerMiddlewareErrorWrapper { + pub fn new( + msg: String, + err: signer::SignerMiddlewareError, + ) -> Self { + SignerMiddlewareErrorWrapper { + msg, + source: err.to_string(), + } + } +} + +#[derive(Debug)] +pub struct ProviderErrorWrapper { + msg: String, + source: ethers::providers::ProviderError, +} + +impl std::fmt::Display for ProviderErrorWrapper { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}: {}", self.msg, self.source) + } +} + +impl ProviderErrorWrapper { + pub fn new(msg: String, err: ethers::providers::ProviderError) -> Self { + ProviderErrorWrapper { msg, source: err } + } +} + +impl ApiError { + pub fn database_error(msg: &str, source: sqlx::Error) -> Self { + Self::Database(DatabaseError::new(source, msg.to_string())) + } + + pub fn contract_error(msg: &str, err: ContractError) -> Self { + Self::Contract(ContractErrorWrapper::new(msg.to_string(), err)) + } + + pub fn signer_middleware_error( + msg: &str, + err: signer::SignerMiddlewareError, + ) -> Self { + Self::SignerMiddleware(SignerMiddlewareErrorWrapper::new(msg.to_string(), err)) + } + + pub fn provider_error(msg: &str, err: ethers::providers::ProviderError) -> Self { + Self::Provider(ProviderErrorWrapper::new(msg.to_string(), err)) + } +} + +impl IntoResponse for ApiError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + ApiError::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::Contract(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::SignerMiddleware(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::SqlxError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::Validation(e) => (StatusCode::BAD_REQUEST, e), + // ApiError::NotFound(e) => (StatusCode::NOT_FOUND, e), + ApiError::Provider(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::Anyhow(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::HexError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + }; + (status, Json(json!({ "error": error_message }))).into_response() + } +} diff --git a/packages/relayer/src/modules/web_server/mod.rs b/packages/relayer/src/modules/web_server/mod.rs index 7dffbb07..14a44e7b 100644 --- a/packages/relayer/src/modules/web_server/mod.rs +++ b/packages/relayer/src/modules/web_server/mod.rs @@ -1,5 +1,7 @@ +pub mod errors; pub mod rest_api; pub mod server; +pub use errors::*; pub use rest_api::*; pub use server::*; diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index aef07158..9c9f259b 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -1,10 +1,9 @@ use crate::*; use anyhow::Result; -use axum::{body::Body, response::Response}; +use axum::Json; use hex::decode; use rand::Rng; use relayer_utils::LOG; -use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use std::str; @@ -87,7 +86,9 @@ pub struct InactiveGuardianRequest { } // Create request status API -pub async fn request_status_api(payload: RequestStatusRequest) -> Result { +pub async fn request_status_api( + Json(payload): Json, +) -> Result, ApiError> { let row = DB.get_request(payload.request_id).await?; let status = if let Some(ref row) = row { if row.is_processed { @@ -98,7 +99,7 @@ pub async fn request_status_api(payload: RequestStatusRequest) -> Result Result Response { @@ -132,20 +133,16 @@ pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response = @@ -195,10 +192,9 @@ pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response(); @@ -206,11 +202,12 @@ pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response(); } - let account_salt = calculate_account_salt(&payload.guardian_email_addr, &payload.account_code); + let account_salt = calculate_account_salt(&payload.guardian_email_addr, &payload.account_code) + .map_err(|_| ApiError::Validation("Failed to calculate account salt".to_string()))?; if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) - .await + .await? { DB.insert_request(&Request { request_id: request_id.clone(), @@ -224,18 +221,18 @@ pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response Response Response Response Response Response Response Response command_params.clone(), payload.template_idx, ) - .await - .unwrap(); + .await?; let account_eth_addr = format!("0x{:x}", account_eth_addr); - if !CLIENT.is_wallet_deployed(&account_eth_addr).await { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Wallet not deployed")) - .unwrap(); + if !CLIENT.is_wallet_deployed(&account_eth_addr).await? { + return Err(ApiError::Validation("Wallet not deployed".to_string())); } // Check if hash of bytecode of proxy contract is equal or not - let bytecode = CLIENT.get_bytecode(&account_eth_addr).await.unwrap(); + let bytecode = CLIENT.get_bytecode(&account_eth_addr).await?; let bytecode_hash = format!("0x{}", hex::encode(keccak256(bytecode.as_ref()))); // let permitted_wallets: Vec = @@ -412,20 +403,19 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response let account = DB .get_credentials_from_wallet_and_email(&account_eth_addr, &payload.guardian_email_addr) - .await; + .await?; - let account_salt = if let Ok(Some(account_details)) = account { + let account_salt = if let Some(account_details) = account { calculate_account_salt(&payload.guardian_email_addr, &account_details.account_code) + .map_err(|_| ApiError::Validation("Failed to calculate account salt".to_string()))? } else { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Account details not found")) - .unwrap(); + return Err(ApiError::Validation("Wallet not deployed".to_string())); }; if !DB .is_wallet_and_email_registered(&account_eth_addr, &payload.guardian_email_addr) - .await + // TODO: replace + .await? { DB.insert_request(&Request { request_id: request_id.clone(), @@ -439,8 +429,7 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response email_nullifier: None, account_salt: Some(account_salt.clone()), }) - .await - .expect("Failed to insert request"); + .await?; handle_email_event(EmailAuthEvent::GuardianNotRegistered { account_eth_addr, @@ -449,6 +438,7 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response request_id, }) .await + // TODO: Add custom events for email handling .expect("Failed to send GuardianNotRegistered event"); return Response::builder() @@ -465,7 +455,7 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) - .await + .await? { DB.insert_request(&Request { request_id: request_id.clone(), @@ -479,8 +469,7 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response email_nullifier: None, account_salt: Some(account_salt.clone()), }) - .await - .expect("Failed to insert request"); + .await?; handle_email_event(EmailAuthEvent::RecoveryRequest { account_eth_addr, @@ -489,6 +478,7 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response command: payload.command.clone(), }) .await + // TODO: Add custom error for handle_email_event .expect("Failed to send Recovery event"); } else { DB.insert_request(&Request { @@ -503,14 +493,14 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response email_nullifier: None, account_salt: Some(account_salt.clone()), }) - .await - .expect("Failed to insert request"); + .await?; handle_email_event(EmailAuthEvent::GuardianNotSet { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), }) .await + // TODO: Add error handling .expect("Failed to send Recovery event"); } @@ -526,12 +516,11 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response .unwrap() } -pub async fn handle_complete_recovery_request(payload: CompleteRecoveryRequest) -> Response { - if !CLIENT.is_wallet_deployed(&payload.account_eth_addr).await { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Wallet not deployed")) - .unwrap(); +pub async fn handle_complete_recovery_request( + Json(payload): Json, +) -> Result { + if !CLIENT.is_wallet_deployed(&payload.account_eth_addr).await? { + return Err(ApiError::Validation("Wallet not deployed".to_string())); } match CLIENT @@ -542,14 +531,8 @@ pub async fn handle_complete_recovery_request(payload: CompleteRecoveryRequest) ) .await { - Ok(true) => Response::builder() - .status(StatusCode::OK) - .body(Body::from("Recovery completed")) - .unwrap(), - Ok(false) => Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Recovery failed")) - .unwrap(), + Ok(true) => Ok("Recovery completed".to_string()), + Ok(false) => Err(ApiError::Validation("Recovery failed".to_string())), Err(e) => { // Parse the error message if it follows the known format let error_message = if e @@ -565,54 +548,41 @@ pub async fn handle_complete_recovery_request(payload: CompleteRecoveryRequest) .chars() .filter(|c| c.is_ascii()) .collect::(); - Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(error_message)) - .unwrap() + Err(ApiError::Internal(error_message)) } } } -pub async fn get_account_salt(payload: GetAccountSaltRequest) -> Response { - let account_salt = calculate_account_salt(&payload.email_addr, &payload.account_code); - - Response::builder() - .status(StatusCode::OK) - .body(Body::from(account_salt)) - .unwrap() +pub async fn get_account_salt( + Json(payload): Json, +) -> Result { + let account_salt = calculate_account_salt(&payload.email_addr, &payload.account_code) + .map_err(|_| ApiError::Validation("Failed to calculate account salt".to_string()))?; + Ok(account_salt) } -pub async fn inactive_guardian(payload: InactiveGuardianRequest) -> Response { +pub async fn inactive_guardian( + Json(payload): Json, +) -> Result { let is_activated = CLIENT .get_is_activated(&payload.controller_eth_addr, &payload.account_eth_addr) - .await; - match is_activated { - Ok(true) => { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Wallet is activated")) - .unwrap() - } - Ok(false) => {} - Err(e) => { - return Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(e.to_string())) - .unwrap() - } + .await?; + + if is_activated { + return Ok("Wallet is activated".to_string()); } - trace!(LOG, "Inactive guardian"; "is_activated" => is_activated.unwrap()); - let account_eth_addr: Address = payload.account_eth_addr.parse().unwrap(); + + trace!(LOG, "Inactive guardian"; "is_activated" => is_activated); + let account_eth_addr: Address = payload + .account_eth_addr + .parse() + .map_err(|e| ApiError::Validation(format!("Failed to parse account_eth_addr: {}", e)))?; let account_eth_addr = format!("0x{:x}", &account_eth_addr); trace!(LOG, "Inactive guardian"; "account_eth_addr" => &account_eth_addr); DB.update_credentials_of_inactive_guardian(false, &account_eth_addr) - .await - .expect("Failed to update credentials"); + .await?; - Response::builder() - .status(StatusCode::OK) - .body(Body::from("Guardian inactivated")) - .unwrap() + Ok("Guardian inactivated".to_string()) } fn parse_error_message(error_data: String) -> String { @@ -672,3 +642,81 @@ pub async fn receive_email_api_fn(email: String) -> Result<()> { }); Ok(()) } + +#[derive(Serialize, Deserialize, Debug)] +pub struct RequestStatusRequest { + pub request_id: u32, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum RequestStatus { + NotExist = 0, + Pending = 1, + Processed = 2, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct RequestStatusResponse { + pub request_id: u32, + pub status: RequestStatus, + pub is_success: bool, + pub email_nullifier: Option, + pub account_salt: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct AcceptanceRequest { + pub controller_eth_addr: String, + pub guardian_email_addr: String, + pub account_code: String, + pub template_idx: u64, + pub subject: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct AcceptanceResponse { + pub request_id: u32, + pub subject_params: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct RecoveryRequest { + pub controller_eth_addr: String, + pub guardian_email_addr: String, + pub template_idx: u64, + pub subject: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct RecoveryResponse { + pub request_id: u32, + pub subject_params: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CompleteRecoveryRequest { + pub account_eth_addr: String, + pub controller_eth_addr: String, + pub complete_calldata: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct GetAccountSaltRequest { + pub account_code: String, + pub email_addr: String, +} + +#[derive(Deserialize, Debug)] +struct PermittedWallet { + wallet_name: String, + controller_eth_addr: String, + hash_of_bytecode_of_proxy: String, + impl_contract_address: String, + slot_location: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InactiveGuardianRequest { + pub account_eth_addr: String, + pub controller_eth_addr: String, +} diff --git a/packages/relayer/src/modules/web_server/server.rs b/packages/relayer/src/modules/web_server/server.rs index 195d651c..63c00b66 100644 --- a/packages/relayer/src/modules/web_server/server.rs +++ b/packages/relayer/src/modules/web_server/server.rs @@ -1,5 +1,5 @@ use crate::*; -use axum::Router; +use axum::{routing::post, Router}; use relayer_utils::LOG; use tower_http::cors::{AllowHeaders, AllowMethods, Any, CorsLayer}; @@ -11,162 +11,19 @@ pub async fn run_server() -> Result<()> { "/api/echo", axum::routing::get(move || async move { "Hello, world!" }), ) - .route( - "/api/requestStatus", - axum::routing::post(move |payload: String| async move { - let payload: Result = - serde_json::from_str(&payload).map_err(|e| anyhow::Error::from(e)); - match payload { - Ok(payload) => { - let response = request_status_api(payload).await; - match response { - Ok(response) => { - let body = serde_json::to_string(&response) - .map_err(|e| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok::<_, axum::response::Response>( - axum::http::Response::builder() - .status(axum::http::StatusCode::OK) - .body(axum::body::Body::from(body)) - .unwrap(), - ) - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - }), - ) - .route( - "/api/acceptanceRequest", - axum::routing::post(move |payload: String| async move { - let payload: Result = - serde_json::from_str(&payload).map_err(|e| anyhow::Error::from(e)); - match payload { - Ok(payload) => { - let acceptance_response = handle_acceptance_request(payload).await; - Ok::<_, axum::response::Response>(acceptance_response) - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - }), - ) - .route( - "/api/recoveryRequest", - axum::routing::post(move |payload: String| async move { - let payload: Result = - serde_json::from_str(&payload).map_err(|e| anyhow::Error::from(e)); - match payload { - Ok(payload) => { - let recovery_response = handle_recovery_request(payload).await; - Ok::<_, axum::response::Response>(recovery_response) - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - }), - ) + .route("/api/requestStatus", post(request_status_api)) + .route("/api/acceptanceRequest", post(handle_acceptance_request)) + .route("/api/recoveryRequest", post(handle_recovery_request)) .route( "/api/completeRequest", - axum::routing::post(move |payload: String| async move { - let payload: Result = - serde_json::from_str(&payload).map_err(|e| anyhow::Error::from(e)); - match payload { - Ok(payload) => { - let recovery_response = handle_complete_recovery_request(payload).await; - Ok::<_, axum::response::Response>(recovery_response) - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - }), - ) - .route( - "/api/getAccountSalt", - axum::routing::post(move |payload: String| async move { - let payload: Result = - serde_json::from_str(&payload).map_err(|e| anyhow::Error::from(e)); - match payload { - Ok(payload) => { - let response = get_account_salt(payload).await; - Ok::<_, axum::response::Response>(response) - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - }), - ) - .route( - "/api/inactiveGuardian", - axum::routing::post(move |payload: String| async move { - let payload: Result = - serde_json::from_str(&payload).map_err(|e| anyhow::Error::from(e)); - match payload { - Ok(payload) => { - let response = inactive_guardian(payload).await; - Ok::<_, axum::response::Response>(response) - } - Err(e) => { - let error_message = serde_json::to_string(&e.to_string()) - .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .unwrap(); - Ok(axum::http::Response::builder() - .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) - .body(serde_json::to_string(&e.to_string()).unwrap().into()) - .unwrap()) - } - } - }), + post(handle_complete_recovery_request), ) + .route("/api/getAccountSalt", post(get_account_salt)) + .route("/api/inactiveGuardian", post(inactive_guardian)) .route( "/api/receiveEmail", axum::routing::post::<_, _, (), _>(move |payload: String| async move { + println!("/api/receiveEmail"); info!(LOG, "Receive email payload: {}", payload); match receive_email_api_fn(payload).await { Ok(_) => "Request processed".to_string(), diff --git a/packages/relayer/src/utils/utils.rs b/packages/relayer/src/utils/utils.rs index 948c83fe..1da380f0 100644 --- a/packages/relayer/src/utils/utils.rs +++ b/packages/relayer/src/utils/utils.rs @@ -80,7 +80,7 @@ pub fn calculate_default_hash(input: &str) -> String { hash_code.to_string() } -pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> String { +pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> Result { let padded_email_addr = PaddedEmailAddr::from_email_addr(&email_addr); let account_code = if account_code.starts_with("0x") { hex_to_field(&account_code).unwrap() @@ -88,7 +88,7 @@ pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> String { hex_to_field(&format!("0x{}", account_code)).unwrap() }; let account_code = AccountCode::from(account_code); - let account_salt = AccountSalt::new(&padded_email_addr, account_code).unwrap(); + let account_salt = AccountSalt::new(&padded_email_addr, account_code)?; field_to_hex(&account_salt.0) } From 3e6ff1a20e58035cd369b66265921eaf3ae32b4f Mon Sep 17 00:00:00 2001 From: Dimi Date: Thu, 5 Sep 2024 18:27:05 +0300 Subject: [PATCH 10/53] Update .env.example --- packages/relayer/.env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relayer/.env.example b/packages/relayer/.env.example index 041c1f22..12957976 100644 --- a/packages/relayer/.env.example +++ b/packages/relayer/.env.example @@ -1,5 +1,5 @@ EMAIL_ACCOUNT_RECOVERY_VERSION_ID=1 # Version ID of the email account recovery. -PRIVATE_KEY="0x1413e91f9aee429e70b145db739f72dcd7250bd2b8c7907cf9f6366440f6c76f" # Private key for Relayer's account. +PRIVATE_KEY="" # Private key for Relayer's account. CHAIN_RPC_PROVIDER=http://127.0.0.1:8545 CHAIN_RPC_EXPLORER= CHAIN_ID=11155111 # Chain ID of the testnet. From 6da5914a454545c0b679f06b9f10376944295ba1 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 6 Sep 2024 15:28:48 +0200 Subject: [PATCH 11/53] Split up handle_email fn; Remove code duplication --- packages/relayer/src/core.rs | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 7a0a7e7c..26e3b508 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -375,3 +375,61 @@ pub fn get_masked_command(public_signals: Vec, start_idx: usize) -> Result Ok(command) } + +fn get_template_id(template_idx: u64) -> [u8; 32] { + let tokens = vec![ + Token::Uint((*EMAIL_ACCOUNT_RECOVERY_VERSION_ID.get().unwrap()).into()), + Token::String("RECOVERY".to_string()), + Token::Uint(template_idx.into()), + ]; + println!("tokens: {:?}", tokens); + + let template_id = keccak256(encode(&tokens)); + println!("template_id: {:?}", template_id); + template_id +} + +async fn get_email_proof(params: &EmailRequestContext) -> Result<(EmailProof, [u8; 32])> { + let circuit_input = generate_email_auth_input( + ¶ms.email, + &AccountCode::from(hex2field(&format!("0x{}", ¶ms.account_code_str))?), + ) + .await?; + println!("circuit_input: {:?}", circuit_input); + + let (proof, public_signals) = + generate_proof(&circuit_input, "email_auth", PROVER_ADDRESS.get().unwrap()).await?; + println!("proof: {:?}", proof); + println!("public_signals: {:?}", public_signals); + + let account_salt = u256_to_bytes32(&public_signals[SUBJECT_FIELDS + DOMAIN_FIELDS + 3]); + println!("account_salt: {:?}", account_salt); + let is_code_exist = public_signals[SUBJECT_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into(); + println!("is_code_exist: {:?}", is_code_exist); + let masked_subject = get_masked_subject(public_signals.clone(), DOMAIN_FIELDS + 3)?; + println!("masked_subject: {:?}", masked_subject); + + let email_proof = EmailProof { + proof, + domain_name: params.parsed_email.get_email_domain()?, + public_key_hash: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 0]), + timestamp: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 2]).into(), + masked_subject, + email_nullifier: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 1]), + account_salt, + is_code_exist, + }; + println!("email_proof: {:?}", email_proof); + Ok((email_proof, account_salt)) +} + +#[derive(Debug, Clone)] +struct EmailRequestContext { + request: Request, + guardian_email_addr: String, + subject: String, + invitation_code: Option, + account_code_str: String, + email: String, + parsed_email: ParsedEmail, +} From e8093d14bd1c732d02d8c22a8012c09ff10c7b97 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Mon, 9 Sep 2024 12:03:15 +0200 Subject: [PATCH 12/53] Custom errors for email --- .gitignore | 3 + Cargo.lock | 13 + packages/relayer/src/chain.rs | 102 ++++--- packages/relayer/src/core.rs | 264 +++++++++++++++++- packages/relayer/src/database.rs | 64 +++-- packages/relayer/src/modules/mail.rs | 24 +- .../relayer/src/modules/web_server/errors.rs | 125 ++++++--- .../src/modules/web_server/rest_api.rs | 6 +- .../relayer/src/modules/web_server/server.rs | 15 +- 9 files changed, 491 insertions(+), 125 deletions(-) diff --git a/.gitignore b/.gitignore index 0ee936ed..1bfbf23a 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,9 @@ book # Vs code settings .vscode +# Editor settings +.idea + # For zksync zkout .cache diff --git a/Cargo.lock b/Cargo.lock index ef6274cd..160f0fa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1657,6 +1657,17 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fancy-regex" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -4129,6 +4140,7 @@ dependencies = [ "slog-json", "slog-term", "sqlx", + "thiserror", "tiny_http", "tokio", "tower-http", @@ -4151,6 +4163,7 @@ dependencies = [ "hmac-sha256", "itertools 0.10.5", "lazy_static", + "mailparse", "neon", "num-bigint", "num-traits", diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index fbc40f31..07dc16a7 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -108,13 +108,13 @@ impl ChainClient { Ok(email_auth_addr) } - pub async fn is_wallet_deployed(&self, wallet_addr_str: &String) -> Result { - let wallet_addr: H160 = wallet_addr_str.parse().map_err(ApiError::HexError)?; + pub async fn is_wallet_deployed(&self, wallet_addr_str: &String) -> Result { + let wallet_addr: H160 = wallet_addr_str.parse().map_err(ChainError::HexError)?; match self.client.get_code(wallet_addr, None).await { Ok(code) => Ok(!code.is_empty()), Err(e) => { // Log the error or handle it as needed - Err(ApiError::signer_middleware_error( + Err(ChainError::signer_middleware_error( "Failed to check if wallet is deployed", e, )) @@ -126,15 +126,16 @@ impl ChainClient { &self, controller_eth_addr: &String, template_idx: u64, - ) -> Result, ApiError> { - let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; + ) -> Result, ChainError> { + let controller_eth_addr: H160 = + controller_eth_addr.parse().map_err(ChainError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let templates = contract .acceptance_command_templates() .call() .await .map_err(|e| { - ApiError::contract_error("Failed to get acceptance subject templates", e) + ChainError::contract_error("Failed to get acceptance subject templates", e) })?; Ok(templates[template_idx as usize].clone()) } @@ -143,14 +144,17 @@ impl ChainClient { &self, controller_eth_addr: &String, template_idx: u64, - ) -> Result, ApiError> { - let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; + ) -> Result, ChainError> { + let controller_eth_addr: H160 = + controller_eth_addr.parse().map_err(ChainError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let templates = contract .recovery_command_templates() .call() .await - .map_err(|e| ApiError::contract_error("Failed to get recovery subject templates", e))?; + .map_err(|e| { + ChainError::contract_error("Failed to get recovery subject templates", e) + })?; Ok(templates[template_idx as usize].clone()) } @@ -159,26 +163,30 @@ impl ChainClient { controller_eth_addr: &String, account_eth_addr: &String, complete_calldata: &String, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; + ) -> Result { + let controller_eth_addr: H160 = + controller_eth_addr.parse().map_err(ChainError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let decoded_calldata = hex::decode(&complete_calldata.trim_start_matches("0x")).expect("Decoding failed"); let account_eth_addr = account_eth_addr .parse::() - .map_err(ApiError::HexError)?; + .map_err(ChainError::HexError)?; let call = contract.complete_recovery(account_eth_addr, Bytes::from(decoded_calldata)); let tx = call .send() .await - .map_err(|e| ApiError::contract_error("Failed to call complete_recovery", e))?; + .map_err(|e| ChainError::contract_error("Failed to call complete_recovery", e))?; // If the transaction is successful, the function will return true and false otherwise. let receipt = tx .log() .confirmations(CONFIRMATIONS) .await .map_err(|e| { - ApiError::provider_error("Failed to get receipt after calling complete_recovery", e) + ChainError::provider_error( + "Failed to get receipt after calling complete_recovery", + e, + ) })? .ok_or(anyhow!("No receipt"))?; Ok(receipt @@ -192,16 +200,25 @@ impl ChainClient { controller_eth_addr: &String, email_auth_msg: EmailAuthMsg, template_idx: u64, - ) -> Result { + ) -> std::result::Result { let controller_eth_addr: H160 = controller_eth_addr.parse()?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let call = contract.handle_acceptance(email_auth_msg, template_idx.into()); - let tx = call.send().await?; + let tx = call + .send() + .await + .map_err(|e| ChainError::contract_error("Failed to call handle_acceptance", e))?; // If the transaction is successful, the function will return true and false otherwise. let receipt = tx .log() .confirmations(CONFIRMATIONS) - .await? + .await + .map_err(|e| { + ChainError::provider_error( + "Failed to get receipt after calling handle_acceptance", + e, + ) + })? .ok_or(anyhow!("No receipt"))?; Ok(receipt .status @@ -214,16 +231,22 @@ impl ChainClient { controller_eth_addr: &String, email_auth_msg: EmailAuthMsg, template_idx: u64, - ) -> Result { + ) -> std::result::Result { let controller_eth_addr: H160 = controller_eth_addr.parse()?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let call = contract.handle_recovery(email_auth_msg, template_idx.into()); - let tx = call.send().await?; + let tx = call + .send() + .await + .map_err(|e| ChainError::contract_error("Failed to call handle_recovery", e))?; // If the transaction is successful, the function will return true and false otherwise. let receipt = tx .log() .confirmations(CONFIRMATIONS) - .await? + .await + .map_err(|e| { + ChainError::provider_error("Failed to get receipt after calling handle_recovery", e) + })? .ok_or(anyhow!("No receipt"))?; Ok(receipt .status @@ -231,13 +254,16 @@ impl ChainClient { .unwrap_or(false)) } - pub async fn get_bytecode(&self, wallet_addr: &String) -> Result { - let wallet_address: H160 = wallet_addr.parse().map_err(ApiError::HexError)?; + pub async fn get_bytecode( + &self, + wallet_addr: &String, + ) -> std::result::Result { + let wallet_address: H160 = wallet_addr.parse().map_err(ChainError::HexError)?; let client_code = self .client .get_code(wallet_address, None) .await - .map_err(|e| ApiError::signer_middleware_error("Failed to get bytecode", e))?; + .map_err(|e| ChainError::signer_middleware_error("Failed to get bytecode", e))?; Ok(client_code) } @@ -258,8 +284,9 @@ impl ChainClient { controller_eth_addr: &String, command_params: Vec, template_idx: u64, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; + ) -> Result { + let controller_eth_addr: H160 = + controller_eth_addr.parse().map_err(ChainError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let command_params_bytes = command_params .iter() // Change here: use iter() instead of map() directly on Vec @@ -276,7 +303,7 @@ impl ChainClient { .call() .await .map_err(|e| { - ApiError::contract_error( + ChainError::contract_error( "Failed to get recovered account from acceptance subject", e, ) @@ -289,17 +316,18 @@ impl ChainClient { controller_eth_addr: &String, command_params: Vec, template_idx: u64, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; + ) -> Result { + let controller_eth_addr: H160 = + controller_eth_addr.parse().map_err(ChainError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let command_params_bytes = command_params .iter() // Change here: use iter() instead of map() directly on Vec .map(|s| { s.abi_encode(None).map_err(|_| { - ApiError::Validation("Error encoding subject parameters".to_string()) + ChainError::Validation("Error encoding subject parameters".to_string()) }) }) - .collect::, ApiError>>()?; + .collect::, ChainError>>()?; let recovered_account = contract .extract_recovered_account_from_recovery_command( command_params_bytes, @@ -308,7 +336,10 @@ impl ChainClient { .call() .await .map_err(|e| { - ApiError::contract_error("Failed to get recovered account from recovery subject", e) + ChainError::contract_error( + "Failed to get recovered account from recovery subject", + e, + ) })?; Ok(recovered_account) } @@ -317,15 +348,16 @@ impl ChainClient { &self, controller_eth_addr: &String, account_eth_addr: &String, - ) -> Result { - let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ApiError::HexError)?; - let account_eth_addr: H160 = account_eth_addr.parse().map_err(ApiError::HexError)?; + ) -> Result { + let controller_eth_addr: H160 = + controller_eth_addr.parse().map_err(ChainError::HexError)?; + let account_eth_addr: H160 = account_eth_addr.parse().map_err(ChainError::HexError)?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let is_activated = contract .is_activated(account_eth_addr) .call() .await - .map_err(|e| ApiError::contract_error("Failed to check if is activated", e))?; + .map_err(|e| ChainError::contract_error("Failed to check if is activated", e))?; Ok(is_activated) } } diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 26e3b508..64320781 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -14,7 +14,7 @@ const DOMAIN_FIELDS: usize = 9; const COMMAND_FIELDS: usize = 20; const EMAIL_ADDR_FIELDS: usize = 9; -pub async fn handle_email(email: String) -> Result { +pub async fn handle_email(email: String) -> Result { let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; trace!(LOG, "email: {}", email); let guardian_email_addr = parsed_email.get_from_addr()?; @@ -63,7 +63,8 @@ pub async fn handle_email(email: String) -> Result { &request.account_eth_addr, request.account_salt.as_deref().unwrap_or_default(), ) - .await?; + .await + .map_err(|e| EmailError::Dkim(format!("Failed to check and update dkim: {}", e)))?; if let Ok(invitation_code) = parsed_email.get_invitation_code(false) { if !request.is_for_recovery { @@ -361,6 +362,252 @@ pub fn get_masked_command(public_signals: Vec, start_idx: usize) -> Result // Gather signals from start_idx to start_idx + COMMAND_FIELDS let mut command_bytes = Vec::new(); for i in start_idx..start_idx + COMMAND_FIELDS { +#[named] +async fn get_verified_request( + email: &String, + guardian_email_addr: String, +) -> Result<(Option, String), EmailError> { + let request_decomposed_def = + serde_json::from_str(include_str!("./regex_json/request_def.json")) + .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; + println!("request_decomposed_def: {:?}", request_decomposed_def); + let request_idxes = extract_substr_idxes(email, &request_decomposed_def)?; + println!("request_idxes: {:?}", request_idxes); + if request_idxes.is_empty() { + return Err(EmailError::Subject(WRONG_SUBJECT_FORMAT.to_string())); + } + info!(LOG, "Request idxes: {:?}", request_idxes; "func" => function_name!()); + let request_id = &email[request_idxes[0].0..request_idxes[0].1]; + println!("request_id: {:?}", request_id); + let request_id_u32 = request_id + .parse::() + .map_err(|e| EmailError::Parse(format!("Failed to parse request_id to u64: {}", e)))?; + println!("request_id_u32: {:?}", request_id_u32); + let request_record = DB.get_request(request_id_u32).await?; + println!("request_record: {:?}", request_record); + let request = match request_record { + Some(req) => req, + None => return Ok((None, request_id.to_string())), + }; + println!("request: {:?}", request); + if request.guardian_email_addr != guardian_email_addr { + Err(EmailError::EmailAddress(format!( + "Guardian email address in the request {} is not equal to the one in the email {}", + request.guardian_email_addr, guardian_email_addr + ))) + } else { + Ok((Some(request), request_id.to_string())) + } +} + +async fn get_account_code( + request: &Request, + guardian_email_addr: &str, +) -> Result { + DB.get_account_code_from_wallet_and_email(&request.account_eth_addr, guardian_email_addr) + .await? + .ok_or_else(|| EmailError::NotFound("User not registered".to_string())) +} + +#[named] +async fn handle_with_invitation_code( + params: EmailRequestContext, +) -> Result { + let invitation_code = params.invitation_code.clone().unwrap_or_else(|| { + panic!("handle_with_invitation_code can only be calld with an ivitation code") + }); + + println!("invitation_code: {:?}", invitation_code); + trace!(LOG, "Email with account code"; "func" => function_name!()); + + if params.account_code_str != invitation_code { + return Err(EmailError::EmailAddress(format!( + "Stored account code is not equal to one in the email. Stored: {}, Email: {}", + params.account_code_str, invitation_code + ))); + } + + if !params.request.is_for_recovery { + accept(params, invitation_code).await + } else { + recover(params).await + } +} + +async fn handle_without_invitation_code( + params: EmailRequestContext, +) -> Result { + if params.request.is_for_recovery { + recover(params).await + } else { + Ok(EmailAuthEvent::Error { + email_addr: params.guardian_email_addr, + error: "No account code found".to_string(), + }) + } +} + +async fn accept( + params: EmailRequestContext, + invitation_code: String, +) -> Result { + let subject_template = CLIENT + .get_acceptance_subject_templates( + ¶ms.request.controller_eth_addr, + params.request.template_idx, + ) + .await?; + println!("subject_template: {:?}", subject_template); + + let (email_auth_msg, account_salt, email_proof) = + get_email_auth_message(¶ms, subject_template).await?; + + let is_guardian_accepted = CLIENT + .handle_acceptance( + ¶ms.request.controller_eth_addr, + email_auth_msg, + params.request.template_idx, + ) + .await?; + + update_request( + ¶ms, + is_guardian_accepted, + email_proof.email_nullifier, + account_salt, + ) + .await?; + + if is_guardian_accepted { + let creds = Credentials { + account_code: invitation_code, + account_eth_addr: params.request.account_eth_addr.clone(), + guardian_email_addr: params.guardian_email_addr.clone(), + is_set: true, + }; + println!("creds: {:?}", creds); + + let update_credentials_result = DB.update_credentials_of_account_code(&creds).await?; + println!("update_credentials_result: {:?}", update_credentials_result); + + Ok(EmailAuthEvent::AcceptanceSuccess { + account_eth_addr: params.request.account_eth_addr, + guardian_email_addr: params.guardian_email_addr, + request_id: params.request.request_id, + }) + } else { + Ok(EmailAuthEvent::Error { + email_addr: params.guardian_email_addr, + error: "Failed to handle acceptance".to_string(), + }) + } +} + +async fn recover(params: EmailRequestContext) -> Result { + let subject_template = CLIENT + .get_recovery_subject_templates( + ¶ms.request.controller_eth_addr, + params.request.template_idx, + ) + .await?; + println!("subject_template: {:?}", subject_template); + + let (email_auth_msg, account_salt, email_proof) = + get_email_auth_message(¶ms, subject_template).await?; + + let is_recovery_successfull = CLIENT + .handle_recovery( + ¶ms.request.controller_eth_addr, + email_auth_msg, + params.request.template_idx, + ) + .await?; + + update_request( + ¶ms, + is_recovery_successfull, + email_proof.email_nullifier, + account_salt, + ) + .await?; + + if is_recovery_successfull { + Ok(EmailAuthEvent::RecoverySuccess { + account_eth_addr: params.request.account_eth_addr, + guardian_email_addr: params.guardian_email_addr, + request_id: params.request.request_id, + }) + } else { + Ok(EmailAuthEvent::Error { + email_addr: params.guardian_email_addr, + error: "Failed to handle recovery".to_string(), + }) + } +} + +#[named] +async fn get_email_auth_message( + params: &EmailRequestContext, + subject_template: Vec, +) -> Result<(EmailAuthMsg, [u8; 32], EmailProof), EmailError> { + let (subject_params, skipped_subject_prefix) = + extract_template_vals_and_skipped_subject_idx(¶ms.subject, subject_template) + .map_err(|e| EmailError::Subject(format!("Invalid Subject, {}", e)))?; + println!("subject_params: {:?}", subject_params); + println!("skipped_subject_prefix: {:?}", skipped_subject_prefix); + + let subject_params_encoded: Vec = subject_params + .iter() + .map(|param| param.abi_encode(None).unwrap()) + .collect(); + println!("subject_params_encoded: {:?}", subject_params_encoded); + + let (email_proof, account_salt) = get_email_proof(params).await?; + + let template_id = get_template_id(params.request.template_idx); + + let email_auth_msg = EmailAuthMsg { + template_id: template_id.into(), + subject_params: subject_params_encoded, + skiped_subject_prefix: skipped_subject_prefix.into(), + proof: email_proof.clone(), + }; + println!("email_auth_msg: {:?}", email_auth_msg); + + info!(LOG, "Email Auth Msg: {:?}", email_auth_msg; "func" => function_name!()); + info!(LOG, "Request: {:?}", params.request; "func" => function_name!()); + Ok((email_auth_msg, account_salt, email_proof)) +} + +async fn update_request( + params: &EmailRequestContext, + is_success: bool, + email_nullifier: [u8; 32], + account_salt: [u8; 32], +) -> Result<(), EmailError> { + let updated_request = Request { + account_eth_addr: params.request.account_eth_addr.clone(), + controller_eth_addr: params.request.controller_eth_addr.clone(), + guardian_email_addr: params.guardian_email_addr.clone(), + template_idx: params.request.template_idx, + is_for_recovery: params.request.is_for_recovery, + is_processed: true, + request_id: params.request.request_id, + is_success: Some(is_success), + email_nullifier: Some(field2hex(&bytes32_to_fr(&email_nullifier).unwrap())), + account_salt: Some(bytes32_to_hex(&account_salt)), + }; + println!("updated_request: {:?}", updated_request); + + let update_request_result = DB.update_request(&updated_request).await?; + println!("update_request_result: {:?}", update_request_result); + Ok(()) +} + +fn get_masked_subject(public_signals: Vec, start_idx: usize) -> Result { + // Gather signals from start_idx to start_idx + SUBJECT_FIELDS + let mut subject_bytes = Vec::new(); + for i in start_idx..start_idx + SUBJECT_FIELDS { let signal = public_signals[i as usize]; if signal == U256::zero() { break; @@ -389,12 +636,19 @@ fn get_template_id(template_idx: u64) -> [u8; 32] { template_id } -async fn get_email_proof(params: &EmailRequestContext) -> Result<(EmailProof, [u8; 32])> { +async fn get_email_proof( + params: &EmailRequestContext, +) -> Result<(EmailProof, [u8; 32]), EmailError> { let circuit_input = generate_email_auth_input( ¶ms.email, - &AccountCode::from(hex2field(&format!("0x{}", ¶ms.account_code_str))?), + &AccountCode::from( + hex2field(&format!("0x{}", ¶ms.account_code_str)).map_err(|e| { + EmailError::Parse(format!("Could not convert account_code_str to hex: {}", e)) + })?, + ), ) - .await?; + .await + .map_err(|e| EmailError::Circuit(format!("Failed to generate email auth input: {}", e)))?; println!("circuit_input: {:?}", circuit_input); let (proof, public_signals) = diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index 29da457f..9af33506 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -102,7 +102,7 @@ impl Database { &self, account_eth_addr: &str, email_addr: &str, - ) -> std::result::Result { + ) -> std::result::Result { let row = sqlx::query( "SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2", ) @@ -110,9 +110,7 @@ impl Database { .bind(email_addr) .fetch_optional(&self.db) .await - .map_err(|e| { - ApiError::database_error("Failed to check if wallet and email are registered", e) - })?; + .map_err(|e| DatabaseError::new("Failed to check if wallet and email are registered", e))?; match row { Some(_) => Ok(true), @@ -120,21 +118,27 @@ impl Database { } } - pub(crate) async fn update_credentials_of_account_code(&self, row: &Credentials) -> Result<()> { + pub(crate) async fn update_credentials_of_account_code( + &self, + row: &Credentials, + ) -> std::result::Result<(), DatabaseError> { let res = sqlx::query("UPDATE credentials SET account_eth_addr = $1, guardian_email_addr = $2, is_set = $3 WHERE account_code = $4") .bind(&row.account_eth_addr) .bind(&row.guardian_email_addr) .bind(row.is_set) .bind(&row.account_code) .execute(&self.db) - .await?; + .await + .map_err(|e| { + DatabaseError::new("Failed to update credentials of account code", e) + })?; Ok(()) } pub(crate) async fn update_credentials_of_wallet_and_email( &self, row: &Credentials, - ) -> std::result::Result<(), ApiError> { + ) -> std::result::Result<(), DatabaseError> { let res = sqlx::query("UPDATE credentials SET account_code = $1, is_set = $2 WHERE account_eth_addr = $3 AND guardian_email_addr = $4") .bind(&row.account_code) .bind(row.is_set) @@ -143,7 +147,7 @@ impl Database { .execute(&self.db) .await .map_err(|e| { - ApiError::database_error("Failed to insert credentials of wallet and email", e) + DatabaseError::new("Failed to insert credentials of wallet and email", e) })?; Ok(()) } @@ -152,7 +156,7 @@ impl Database { &self, is_set: bool, account_eth_addr: &str, - ) -> std::result::Result<(), ApiError> { + ) -> std::result::Result<(), DatabaseError> { let res = sqlx::query( "UPDATE credentials SET is_set = $1 WHERE account_eth_addr = $2 AND is_set = true", ) @@ -160,9 +164,7 @@ impl Database { .bind(account_eth_addr) .execute(&self.db) .await - .map_err(|e| { - ApiError::database_error("Failed to update credentials of inactive guardian", e) - })?; + .map_err(|e| DatabaseError::new("Failed to update credentials of inactive guardian", e))?; Ok(()) } @@ -170,7 +172,7 @@ impl Database { pub(crate) async fn insert_credentials( &self, row: &Credentials, - ) -> std::result::Result<(), ApiError> { + ) -> std::result::Result<(), DatabaseError> { info!(LOG, "insert row {:?}", row; "func" => function_name!()); let row = sqlx::query( "INSERT INTO credentials (account_code, account_eth_addr, guardian_email_addr, is_set) VALUES ($1, $2, $3, $4) RETURNING *", @@ -181,7 +183,7 @@ impl Database { .bind(row.is_set) .fetch_one(&self.db) .await - .map_err(|e| ApiError::database_error("Failed to insert credentials", e))?; + .map_err(|e| DatabaseError::new("Failed to insert credentials", e))?; info!( LOG, "{} row inserted", @@ -194,13 +196,13 @@ impl Database { &self, account_eth_addr: &str, guardian_email_addr: &str, - ) -> std::result::Result { + ) -> std::result::Result { let row = sqlx::query("SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2 AND is_set = TRUE") .bind(account_eth_addr) .bind(guardian_email_addr) .fetch_optional(&self.db) .await - .map_err(|e| ApiError::database_error("Failed to check if guardian is set", e))?; + .map_err(|e| DatabaseError::new("Failed to check if guardian is set", e))?; match row { Some(_) => Ok(true), @@ -212,12 +214,12 @@ impl Database { pub(crate) async fn get_request( &self, request_id: u32, - ) -> std::result::Result, ApiError> { + ) -> std::result::Result, DatabaseError> { let row = sqlx::query("SELECT * FROM requests WHERE request_id = $1") .bind(request_id as i64) .fetch_optional(&self.db) .await - .map_err(|e| ApiError::database_error("Failed to get request", e))?; + .map_err(|e| DatabaseError::new("Failed to get request", e))?; match row { Some(row) => { @@ -250,7 +252,10 @@ impl Database { } } - pub(crate) async fn update_request(&self, row: &Request) -> Result<()> { + pub(crate) async fn update_request( + &self, + row: &Request, + ) -> std::result::Result<(), DatabaseError> { let res = sqlx::query("UPDATE requests SET account_eth_addr = $1, controller_eth_addr = $2, guardian_email_addr = $3, is_for_recovery = $4, template_idx = $5, is_processed = $6, is_success = $7, email_nullifier = $8, account_salt = $9 WHERE request_id = $10") .bind(&row.account_eth_addr) .bind(&row.controller_eth_addr) @@ -263,7 +268,8 @@ impl Database { .bind(&row.account_salt) .bind(row.request_id as i64) .execute(&self.db) - .await?; + .await + .map_err(|e| DatabaseError::new("Failed to update request", e))?; Ok(()) } @@ -271,14 +277,15 @@ impl Database { &self, account_eth_addr: &str, email_addr: &str, - ) -> Result> { + ) -> std::result::Result, DatabaseError> { let row = sqlx::query( "SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2", ) .bind(account_eth_addr) .bind(email_addr) .fetch_optional(&self.db) - .await?; + .await + .map_err(|e| DatabaseError::new("Failed to get account code from wallet and email", e))?; match row { Some(row) => { @@ -293,7 +300,7 @@ impl Database { &self, account_eth_addr: &str, email_addr: &str, - ) -> std::result::Result, ApiError> { + ) -> std::result::Result, DatabaseError> { let row = sqlx::query( "SELECT * FROM credentials WHERE account_eth_addr = $1 AND guardian_email_addr = $2", ) @@ -301,9 +308,7 @@ impl Database { .bind(email_addr) .fetch_optional(&self.db) .await - .map_err(|e| { - ApiError::database_error("Failed to get credentials from wallet and email", e) - })?; + .map_err(|e| DatabaseError::new("Failed to get credentials from wallet and email", e))?; match row { Some(row) => { @@ -325,7 +330,10 @@ impl Database { } #[named] - pub(crate) async fn insert_request(&self, row: &Request) -> std::result::Result<(), ApiError> { + pub(crate) async fn insert_request( + &self, + row: &Request, + ) -> std::result::Result<(), DatabaseError> { info!(LOG, "insert row {:?}", row; "func" => function_name!()); let row = sqlx::query( "INSERT INTO requests (request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, is_for_recovery, template_idx, is_processed, is_success, email_nullifier, account_salt) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *", @@ -342,7 +350,7 @@ impl Database { .bind(&row.account_salt) .fetch_one(&self.db) .await - .map_err(|e| ApiError::database_error("Failed to insert request", e))?; + .map_err(|e| DatabaseError::new("Failed to insert request", e))?; info!( LOG, "{} row inserted", diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index 98c5d0db..82a749a6 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -73,7 +73,7 @@ pub struct EmailAttachment { pub contents: Vec, } -pub async fn handle_email_event(event: EmailAuthEvent) -> Result<()> { +pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> { match event { EmailAuthEvent::AcceptanceRequest { account_eth_addr, @@ -360,15 +360,23 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<()> { Ok(()) } -pub async fn render_html(template_name: &str, render_data: Value) -> Result { +pub async fn render_html(template_name: &str, render_data: Value) -> Result { let email_template_filename = PathBuf::new() .join(EMAIL_TEMPLATES.get().unwrap()) .join(template_name); - let email_template = read_to_string(&email_template_filename).await?; + let email_template = read_to_string(&email_template_filename) + .await + .map_err(|e| { + EmailError::FileNotFound(format!( + "Could not get email template {}: {}", + template_name, e + )) + })?; let reg = Handlebars::new(); - Ok(reg.render_template(&email_template, &render_data)?) + let template = reg.render_template(&email_template, &render_data)?; + Ok(template) } pub fn parse_error(error: String) -> Result> { @@ -394,7 +402,7 @@ pub fn parse_error(error: String) -> Result> { } } -pub async fn send_email(email: EmailMessage) -> Result<()> { +pub async fn send_email(email: EmailMessage) -> Result<(), EmailError> { let smtp_server = SMTP_SERVER.get().unwrap(); // Send POST request to email server @@ -404,13 +412,13 @@ pub async fn send_email(email: EmailMessage) -> Result<()> { .json(&email) .send() .await - .map_err(|e| anyhow!("Failed to send email: {}", e))?; + .map_err(|e| EmailError::Send(format!("Failed to send email: {}", e)))?; if !response.status().is_success() { - return Err(anyhow!( + return Err(EmailError::Send(format!( "Failed to send email: {}", response.text().await.unwrap_or_default() - )); + ))); } Ok(()) diff --git a/packages/relayer/src/modules/web_server/errors.rs b/packages/relayer/src/modules/web_server/errors.rs index 2b53701f..a4651d64 100644 --- a/packages/relayer/src/modules/web_server/errors.rs +++ b/packages/relayer/src/modules/web_server/errors.rs @@ -3,6 +3,8 @@ use axum::{ response::{IntoResponse, Response}, Json, }; +use handlebars::RenderError; +use relayer_utils::ExtractSubstrssError; use reqwest::StatusCode; use rustc_hex::FromHexError; use serde_json::json; @@ -11,25 +13,85 @@ use thiserror::Error; #[derive(Error, Debug)] pub enum ApiError { #[error("Database error: {0}")] - Database(DatabaseError), + Database(#[from] DatabaseError), #[error("Sqlx error: {0}")] SqlxError(#[from] sqlx::Error), - #[error("Contract error: {0}")] - Contract(ContractErrorWrapper), - #[error("Signer middleware error: {0}")] - SignerMiddleware(SignerMiddlewareErrorWrapper), #[error("Validation error: {0}")] Validation(String), + #[error("Chain error: {0}")] + Chain(#[from] ChainError), // #[error("Not found: {0}")] // NotFound(String), - #[error("Provider error: {0}")] - Provider(ProviderErrorWrapper), - #[error("Hex error: {0}")] - HexError(#[from] FromHexError), #[error("Anyhow error: {0}")] Anyhow(#[from] anyhow::Error), #[error("Internal error: {0}")] Internal(String), + #[error("Error recieving email: {0}")] + Email(#[from] EmailError), +} + +#[derive(Error, Debug)] +pub enum EmailError { + #[error("Subject error: {0}")] + Subject(String), + #[error("Email address error: {0}")] + EmailAddress(String), + #[error("Parse error: {0}")] + Parse(String), + #[error("DKIM error: {0}")] + Dkim(String), + #[error("ZkRegex error: {0}")] + ZkRegex(#[from] ExtractSubstrssError), + #[error("Database error: {0}")] + Database(#[from] DatabaseError), + #[error("Not found: {0}")] + NotFound(String), + #[error("Circuit error: {0}")] + Circuit(String), + #[error("Chain error: {0}")] + Chain(#[from] ChainError), + #[error("File not found error: {0}")] + FileNotFound(String), + #[error("Render error: {0}")] + Render(#[from] RenderError), + #[error("Failed to send email: {0}")] + Send(String), + // Currently used with some relayer-utils errors + #[error("Anyhow error: {0}")] + Anyhow(#[from] anyhow::Error), +} + +#[derive(Error, Debug)] +pub enum ChainError { + #[error("Contract error: {0}")] + Contract(ContractErrorWrapper), + #[error("Signer middleware error: {0}")] + SignerMiddleware(SignerMiddlewareErrorWrapper), + #[error("Hex error: {0}")] + HexError(#[from] FromHexError), + #[error("Provider error: {0}")] + Provider(ProviderErrorWrapper), + #[error("Anyhow error: {0}")] + Anyhow(#[from] anyhow::Error), + #[error("Validation error: {0}")] + Validation(String), +} + +impl ChainError { + pub fn contract_error(msg: &str, err: ContractError) -> Self { + Self::Contract(ContractErrorWrapper::new(msg.to_string(), err)) + } + + pub fn signer_middleware_error( + msg: &str, + err: signer::SignerMiddlewareError, + ) -> Self { + Self::SignerMiddleware(SignerMiddlewareErrorWrapper::new(msg.to_string(), err)) + } + + pub fn provider_error(msg: &str, err: ethers::providers::ProviderError) -> Self { + Self::Provider(ProviderErrorWrapper::new(msg.to_string(), err)) + } } #[derive(Debug, thiserror::Error)] @@ -41,8 +103,11 @@ pub struct DatabaseError { } impl DatabaseError { - pub fn new(source: sqlx::Error, msg: String) -> Self { - Self { source, msg } + pub fn new(msg: &str, source: sqlx::Error) -> Self { + Self { + source, + msg: msg.to_string(), + } } } @@ -111,22 +176,7 @@ impl ProviderErrorWrapper { impl ApiError { pub fn database_error(msg: &str, source: sqlx::Error) -> Self { - Self::Database(DatabaseError::new(source, msg.to_string())) - } - - pub fn contract_error(msg: &str, err: ContractError) -> Self { - Self::Contract(ContractErrorWrapper::new(msg.to_string(), err)) - } - - pub fn signer_middleware_error( - msg: &str, - err: signer::SignerMiddlewareError, - ) -> Self { - Self::SignerMiddleware(SignerMiddlewareErrorWrapper::new(msg.to_string(), err)) - } - - pub fn provider_error(msg: &str, err: ethers::providers::ProviderError) -> Self { - Self::Provider(ProviderErrorWrapper::new(msg.to_string(), err)) + Self::Database(DatabaseError::new(msg, source)) } } @@ -134,15 +184,26 @@ impl IntoResponse for ApiError { fn into_response(self) -> Response { let (status, error_message) = match self { ApiError::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), - ApiError::Contract(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), - ApiError::SignerMiddleware(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::Chain(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::SqlxError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Validation(e) => (StatusCode::BAD_REQUEST, e), - // ApiError::NotFound(e) => (StatusCode::NOT_FOUND, e), - ApiError::Provider(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Anyhow(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), - ApiError::HexError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + ApiError::Email(e) => match e { + EmailError::Subject(e) => (StatusCode::BAD_REQUEST, e.to_string()), + EmailError::EmailAddress(e) => (StatusCode::BAD_REQUEST, e.to_string()), + EmailError::Parse(e) => (StatusCode::BAD_REQUEST, e.to_string()), + EmailError::NotFound(e) => (StatusCode::BAD_REQUEST, e.to_string()), + EmailError::Dkim(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::ZkRegex(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::Circuit(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::Chain(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::FileNotFound(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::Render(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::Send(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::Anyhow(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + }, }; (status, Json(json!({ "error": error_message }))).into_response() } diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 9c9f259b..ac6d4f5b 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -599,9 +599,9 @@ fn parse_error_message(error_data: String) -> String { format!("Failed to parse contract error: {}", error_data) } -pub async fn receive_email_api_fn(email: String) -> Result<()> { - let parsed_email = ParsedEmail::new_from_raw_email(&email).await.unwrap(); - let from_addr = parsed_email.get_from_addr().unwrap(); +pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { + let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; + let from_addr = parsed_email.get_from_addr()?; tokio::spawn(async move { match handle_email_event(EmailAuthEvent::Ack { email_addr: from_addr.clone(), diff --git a/packages/relayer/src/modules/web_server/server.rs b/packages/relayer/src/modules/web_server/server.rs index 63c00b66..fbf85e77 100644 --- a/packages/relayer/src/modules/web_server/server.rs +++ b/packages/relayer/src/modules/web_server/server.rs @@ -20,20 +20,7 @@ pub async fn run_server() -> Result<()> { ) .route("/api/getAccountSalt", post(get_account_salt)) .route("/api/inactiveGuardian", post(inactive_guardian)) - .route( - "/api/receiveEmail", - axum::routing::post::<_, _, (), _>(move |payload: String| async move { - println!("/api/receiveEmail"); - info!(LOG, "Receive email payload: {}", payload); - match receive_email_api_fn(payload).await { - Ok(_) => "Request processed".to_string(), - Err(err) => { - error!(LOG, "Failed to complete the receive email request: {}", err); - err.to_string() - } - } - }), - ); + .route("/api/receiveEmail", post(receive_email_api_fn)); app = app.layer( CorsLayer::new() From f8d73e8ab16e7d0295a01cb0855881c49b1bb46e Mon Sep 17 00:00:00 2001 From: Dimitri Date: Wed, 11 Sep 2024 12:03:24 +0700 Subject: [PATCH 13/53] Rebase solve conflicts of body-parser refacor --- packages/relayer/src/chain.rs | 1 - packages/relayer/src/core.rs | 358 +++++++++--------- packages/relayer/src/database.rs | 17 +- packages/relayer/src/lib.rs | 2 +- .../relayer/src/modules/web_server/errors.rs | 12 +- .../src/modules/web_server/rest_api.rs | 308 ++++----------- packages/relayer/src/utils/utils.rs | 4 +- 7 files changed, 261 insertions(+), 441 deletions(-) diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index 07dc16a7..b124488f 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -4,7 +4,6 @@ use ethers::middleware::Middleware; use ethers::prelude::*; use ethers::signers::Signer; use relayer_utils::converters::u64_to_u8_array_32; -use relayer_utils::LOG; const CONFIRMATIONS: usize = 1; diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 64320781..08d99abe 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -23,10 +23,11 @@ pub async fn handle_email(email: String) -> Result { let email_body = parsed_email.get_cleaned_body()?; let request_decomposed_def = - serde_json::from_str(include_str!("./regex_json/request_def.json"))?; + serde_json::from_str(include_str!("./regex_json/request_def.json")) + .map_err(|e| EmailError::Parse(e.to_string()))?; let request_idxes = extract_substr_idxes(&email, &request_decomposed_def)?; if request_idxes.is_empty() { - bail!(WRONG_COMMAND_FORMAT); + return Err(EmailError::Body(WRONG_COMMAND_FORMAT.to_string())); } info!(LOG, "Request idxes: {:?}", request_idxes); let request_id = &email[request_idxes[0].0..request_idxes[0].1]; @@ -34,19 +35,20 @@ pub async fn handle_email(email: String) -> Result { .parse::() .map_err(|e| anyhow!("Failed to parse request_id to u64: {}", e))?; let request_record = DB.get_request(request_id_u32).await?; - if request_record.is_none() { - return Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: format!("Request {} not found", request_id), - }); - } - let request = request_record.unwrap(); + let request = match request_record { + Some(r) => r, + None => { + return Ok(EmailAuthEvent::Error { + email_addr: guardian_email_addr, + error: format!("Request {} not found", request_id), + }); + } + }; if request.guardian_email_addr != guardian_email_addr { - return Err(anyhow!( + return Err(EmailError::EmailAddress(format!( "Guardian email address in the request {} is not equal to the one in the email {}", - request.guardian_email_addr, - guardian_email_addr - )); + request.guardian_email_addr, guardian_email_addr + ))); } let account_code_str = DB .get_account_code_from_wallet_and_email(&request.account_eth_addr, &guardian_email_addr) @@ -63,8 +65,7 @@ pub async fn handle_email(email: String) -> Result { &request.account_eth_addr, request.account_salt.as_deref().unwrap_or_default(), ) - .await - .map_err(|e| EmailError::Dkim(format!("Failed to check and update dkim: {}", e)))?; + .await?; if let Ok(invitation_code) = parsed_email.get_invitation_code(false) { if !request.is_for_recovery { @@ -388,62 +389,46 @@ async fn get_verified_request( let request = match request_record { Some(req) => req, None => return Ok((None, request_id.to_string())), + let invitation_code = match parsed_email.get_invitation_code(false) { + Ok(code) => Some(code), + Err(_) => None, }; - println!("request: {:?}", request); - if request.guardian_email_addr != guardian_email_addr { - Err(EmailError::EmailAddress(format!( - "Guardian email address in the request {} is not equal to the one in the email {}", - request.guardian_email_addr, guardian_email_addr - ))) - } else { - Ok((Some(request), request_id.to_string())) - } -} - -async fn get_account_code( - request: &Request, - guardian_email_addr: &str, -) -> Result { - DB.get_account_code_from_wallet_and_email(&request.account_eth_addr, guardian_email_addr) - .await? - .ok_or_else(|| EmailError::NotFound("User not registered".to_string())) -} - -#[named] -async fn handle_with_invitation_code( - params: EmailRequestContext, -) -> Result { - let invitation_code = params.invitation_code.clone().unwrap_or_else(|| { - panic!("handle_with_invitation_code can only be calld with an ivitation code") - }); - - println!("invitation_code: {:?}", invitation_code); - trace!(LOG, "Email with account code"; "func" => function_name!()); - if params.account_code_str != invitation_code { - return Err(EmailError::EmailAddress(format!( - "Stored account code is not equal to one in the email. Stored: {}, Email: {}", - params.account_code_str, invitation_code - ))); - } + let params = EmailRequestContext { + request, + email_body, + account_code_str, + email, + parsed_email, + }; - if !params.request.is_for_recovery { - accept(params, invitation_code).await - } else { - recover(params).await - } + handle_email_request(params, invitation_code).await } -async fn handle_without_invitation_code( +async fn handle_email_request( params: EmailRequestContext, + invitation_code: Option, ) -> Result { - if params.request.is_for_recovery { - recover(params).await - } else { - Ok(EmailAuthEvent::Error { - email_addr: params.guardian_email_addr, - error: "No account code found".to_string(), - }) + match (invitation_code, params.request.is_for_recovery) { + (Some(invitation_code), is_for_recovery) if !is_for_recovery => { + if params.account_code_str != invitation_code { + return Err(EmailError::Body(format!( + "Stored account code is not equal to one in the email. Stored: {}, Email: {}", + params.account_code_str, invitation_code + ))); + }; + trace!(LOG, "Email with account code"); + accept(params, invitation_code).await + } + (None, is_for_recovery) if is_for_recovery => recover(params).await, + (Some(_), _) => Ok(EmailAuthEvent::Error { + email_addr: params.request.guardian_email_addr, + error: "Account code found and for recovery".to_string(), + }), + (None, _) => Ok(EmailAuthEvent::Error { + email_addr: params.request.guardian_email_addr, + error: "No account code found and not for recovery".to_string(), + }), } } @@ -451,18 +436,12 @@ async fn accept( params: EmailRequestContext, invitation_code: String, ) -> Result { - let subject_template = CLIENT - .get_acceptance_subject_templates( - ¶ms.request.controller_eth_addr, - params.request.template_idx, - ) - .await?; - println!("subject_template: {:?}", subject_template); + let (email_auth_msg, email_proof, account_salt) = get_email_auth_msg(¶ms).await?; - let (email_auth_msg, account_salt, email_proof) = - get_email_auth_message(¶ms, subject_template).await?; + info!(LOG, "Email Auth Msg: {:?}", email_auth_msg); + info!(LOG, "Request: {:?}", params.request); - let is_guardian_accepted = CLIENT + let is_accepted = CLIENT .handle_acceptance( ¶ms.request.controller_eth_addr, email_auth_msg, @@ -472,50 +451,41 @@ async fn accept( update_request( ¶ms, - is_guardian_accepted, + is_accepted, email_proof.email_nullifier, account_salt, ) .await?; - if is_guardian_accepted { + if is_accepted { let creds = Credentials { account_code: invitation_code, account_eth_addr: params.request.account_eth_addr.clone(), - guardian_email_addr: params.guardian_email_addr.clone(), + guardian_email_addr: params.request.guardian_email_addr.clone(), is_set: true, }; - println!("creds: {:?}", creds); - - let update_credentials_result = DB.update_credentials_of_account_code(&creds).await?; - println!("update_credentials_result: {:?}", update_credentials_result); + DB.update_credentials_of_account_code(&creds).await?; Ok(EmailAuthEvent::AcceptanceSuccess { account_eth_addr: params.request.account_eth_addr, - guardian_email_addr: params.guardian_email_addr, + guardian_email_addr: params.request.guardian_email_addr, request_id: params.request.request_id, }) } else { Ok(EmailAuthEvent::Error { - email_addr: params.guardian_email_addr, + email_addr: params.request.guardian_email_addr, error: "Failed to handle acceptance".to_string(), }) } } async fn recover(params: EmailRequestContext) -> Result { - let subject_template = CLIENT - .get_recovery_subject_templates( - ¶ms.request.controller_eth_addr, - params.request.template_idx, - ) - .await?; - println!("subject_template: {:?}", subject_template); + let (email_auth_msg, email_proof, account_salt) = get_email_auth_msg(¶ms).await?; - let (email_auth_msg, account_salt, email_proof) = - get_email_auth_message(¶ms, subject_template).await?; + info!(LOG, "Email Auth Msg: {:?}", email_auth_msg); + info!(LOG, "Request: {:?}", params.request); - let is_recovery_successfull = CLIENT + let is_success = CLIENT .handle_recovery( ¶ms.request.controller_eth_addr, email_auth_msg, @@ -525,58 +495,43 @@ async fn recover(params: EmailRequestContext) -> Result, -) -> Result<(EmailAuthMsg, [u8; 32], EmailProof), EmailError> { - let (subject_params, skipped_subject_prefix) = - extract_template_vals_and_skipped_subject_idx(¶ms.subject, subject_template) - .map_err(|e| EmailError::Subject(format!("Invalid Subject, {}", e)))?; - println!("subject_params: {:?}", subject_params); - println!("skipped_subject_prefix: {:?}", skipped_subject_prefix); - - let subject_params_encoded: Vec = subject_params - .iter() - .map(|param| param.abi_encode(None).unwrap()) - .collect(); - println!("subject_params_encoded: {:?}", subject_params_encoded); - - let (email_proof, account_salt) = get_email_proof(params).await?; - - let template_id = get_template_id(params.request.template_idx); +fn get_masked_command(public_signals: Vec, start_idx: usize) -> Result { + // Gather signals from start_idx to start_idx + COMMAND_FIELDS + let mut command_bytes = Vec::new(); + for i in start_idx..start_idx + COMMAND_FIELDS { + let signal = public_signals[i as usize]; + if signal == U256::zero() { + break; + } + let bytes = u256_to_bytes32_little(&signal); + command_bytes.extend_from_slice(&bytes); + } - let email_auth_msg = EmailAuthMsg { - template_id: template_id.into(), - subject_params: subject_params_encoded, - skiped_subject_prefix: skipped_subject_prefix.into(), - proof: email_proof.clone(), - }; - println!("email_auth_msg: {:?}", email_auth_msg); + // Bytes to string, removing null bytes + let command = String::from_utf8(command_bytes.into_iter().filter(|&b| b != 0u8).collect()) + .map_err(|e| anyhow!("Failed to convert bytes to string: {}", e))?; - info!(LOG, "Email Auth Msg: {:?}", email_auth_msg; "func" => function_name!()); - info!(LOG, "Request: {:?}", params.request; "func" => function_name!()); - Ok((email_auth_msg, account_salt, email_proof)) + Ok(command) } async fn update_request( @@ -588,13 +543,13 @@ async fn update_request( let updated_request = Request { account_eth_addr: params.request.account_eth_addr.clone(), controller_eth_addr: params.request.controller_eth_addr.clone(), - guardian_email_addr: params.guardian_email_addr.clone(), + guardian_email_addr: params.request.guardian_email_addr.clone(), template_idx: params.request.template_idx, is_for_recovery: params.request.is_for_recovery, is_processed: true, request_id: params.request.request_id, is_success: Some(is_success), - email_nullifier: Some(field2hex(&bytes32_to_fr(&email_nullifier).unwrap())), + email_nullifier: Some(field_to_hex(&bytes32_to_fr(&email_nullifier)?)), account_salt: Some(bytes32_to_hex(&account_salt)), }; println!("updated_request: {:?}", updated_request); @@ -604,85 +559,120 @@ async fn update_request( Ok(()) } -fn get_masked_subject(public_signals: Vec, start_idx: usize) -> Result { - // Gather signals from start_idx to start_idx + SUBJECT_FIELDS - let mut subject_bytes = Vec::new(); - for i in start_idx..start_idx + SUBJECT_FIELDS { - let signal = public_signals[i as usize]; - if signal == U256::zero() { - break; - } - let bytes = u256_to_bytes32_little(&signal); - command_bytes.extend_from_slice(&bytes); - } - - // Bytes to string, removing null bytes - let command = String::from_utf8(command_bytes.into_iter().filter(|&b| b != 0u8).collect()) - .map_err(|e| anyhow!("Failed to convert bytes to string: {}", e))?; - - Ok(command) -} - -fn get_template_id(template_idx: u64) -> [u8; 32] { - let tokens = vec![ - Token::Uint((*EMAIL_ACCOUNT_RECOVERY_VERSION_ID.get().unwrap()).into()), - Token::String("RECOVERY".to_string()), - Token::Uint(template_idx.into()), - ]; - println!("tokens: {:?}", tokens); - - let template_id = keccak256(encode(&tokens)); - println!("template_id: {:?}", template_id); - template_id -} - -async fn get_email_proof( +async fn generate_email_proof( params: &EmailRequestContext, ) -> Result<(EmailProof, [u8; 32]), EmailError> { - let circuit_input = generate_email_auth_input( + let circuit_input = generate_email_circuit_input( ¶ms.email, - &AccountCode::from( - hex2field(&format!("0x{}", ¶ms.account_code_str)).map_err(|e| { - EmailError::Parse(format!("Could not convert account_code_str to hex: {}", e)) - })?, - ), + &AccountCode::from(hex_to_field(&format!("0x{}", ¶ms.account_code_str))?), + Some(EmailCircuitParams { + max_header_length: Some(1024), + max_body_length: Some(1024), + sha_precompute_selector: Some(SHA_PRECOMPUTE_SELECTOR.to_string()), + ignore_body_hash_check: Some(false), + }), ) - .await - .map_err(|e| EmailError::Circuit(format!("Failed to generate email auth input: {}", e)))?; - println!("circuit_input: {:?}", circuit_input); + .await?; let (proof, public_signals) = generate_proof(&circuit_input, "email_auth", PROVER_ADDRESS.get().unwrap()).await?; - println!("proof: {:?}", proof); - println!("public_signals: {:?}", public_signals); - let account_salt = u256_to_bytes32(&public_signals[SUBJECT_FIELDS + DOMAIN_FIELDS + 3]); - println!("account_salt: {:?}", account_salt); - let is_code_exist = public_signals[SUBJECT_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into(); - println!("is_code_exist: {:?}", is_code_exist); - let masked_subject = get_masked_subject(public_signals.clone(), DOMAIN_FIELDS + 3)?; - println!("masked_subject: {:?}", masked_subject); + info!(LOG, "Public signals: {:?}", public_signals); + + let account_salt = u256_to_bytes32(&public_signals[COMMAND_FIELDS + DOMAIN_FIELDS + 3]); + let is_code_exist = public_signals[COMMAND_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into(); + let masked_command = get_masked_command(public_signals.clone(), DOMAIN_FIELDS + 3)?; let email_proof = EmailProof { proof, domain_name: params.parsed_email.get_email_domain()?, public_key_hash: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 0]), timestamp: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 2]).into(), - masked_subject, + masked_command, email_nullifier: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 1]), account_salt, is_code_exist, }; - println!("email_proof: {:?}", email_proof); + Ok((email_proof, account_salt)) } +fn get_template_id(params: &EmailRequestContext) -> [u8; 32] { + let action = if params.request.is_for_recovery { + "RECOVERY".to_string() + } else { + "ACCEPTANCE".to_string() + }; + + let tokens = vec![ + Token::Uint((*EMAIL_ACCOUNT_RECOVERY_VERSION_ID.get().unwrap()).into()), + // TODO: Continue here + Token::String(action), + Token::Uint(params.request.template_idx.into()), + ]; + + let template_id = keccak256(encode(&tokens)); + template_id +} + +async fn get_encoded_command_params( + params: &EmailRequestContext, +) -> Result, EmailError> { + let command_template = if params.request.is_for_recovery { + CLIENT + .get_recovery_command_templates( + ¶ms.request.controller_eth_addr, + params.request.template_idx, + ) + .await? + } else { + CLIENT + .get_acceptance_command_templates( + ¶ms.request.controller_eth_addr, + params.request.template_idx, + ) + .await? + }; + + let command_params = + extract_template_vals_from_command_template(¶ms.email_body, command_template) + .map_err(|e| EmailError::Body(format!("Invalid commad: {}", e)))?; + + // let command_params_encoded: Vec = command_params + // .iter() + // .map(|param| param.abi_encode(None).unwrap()) + // .collect(); + + let command_params_encoded = command_params + .iter() + .map(|param| { + param + .abi_encode(None) + .map_err(|e| EmailError::AbiError(e.to_string())) + }) + .collect::, EmailError>>()?; + + Ok(command_params_encoded) +} + +async fn get_email_auth_msg( + params: &EmailRequestContext, +) -> Result<(EmailAuthMsg, EmailProof, [u8; 32]), EmailError> { + let command_params_encoded = get_encoded_command_params(params).await?; + let template_id = get_template_id(params); + let (email_proof, account_salt) = generate_email_proof(params).await?; + let email_auth_msg = EmailAuthMsg { + template_id: template_id.into(), + command_params: command_params_encoded, + proof: email_proof.clone(), + }; + Ok((email_auth_msg, email_proof, account_salt)) +} + #[derive(Debug, Clone)] struct EmailRequestContext { request: Request, - guardian_email_addr: String, - subject: String, - invitation_code: Option, + email_body: String, account_code_str: String, email: String, parsed_email: ParsedEmail, diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index 9af33506..5dd0fbb9 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -168,12 +168,10 @@ impl Database { Ok(()) } - #[named] pub(crate) async fn insert_credentials( &self, row: &Credentials, ) -> std::result::Result<(), DatabaseError> { - info!(LOG, "insert row {:?}", row; "func" => function_name!()); let row = sqlx::query( "INSERT INTO credentials (account_code, account_eth_addr, guardian_email_addr, is_set) VALUES ($1, $2, $3, $4) RETURNING *", ) @@ -184,11 +182,7 @@ impl Database { .fetch_one(&self.db) .await .map_err(|e| DatabaseError::new("Failed to insert credentials", e))?; - info!( - LOG, - "{} row inserted", - row.len(); "func" => function_name!() - ); + info!(LOG, "Credentials inserted",); Ok(()) } @@ -210,7 +204,6 @@ impl Database { } } - #[named] pub(crate) async fn get_request( &self, request_id: u32, @@ -329,12 +322,10 @@ impl Database { } } - #[named] pub(crate) async fn insert_request( &self, row: &Request, ) -> std::result::Result<(), DatabaseError> { - info!(LOG, "insert row {:?}", row; "func" => function_name!()); let row = sqlx::query( "INSERT INTO requests (request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, is_for_recovery, template_idx, is_processed, is_success, email_nullifier, account_salt) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *", ) @@ -351,11 +342,7 @@ impl Database { .fetch_one(&self.db) .await .map_err(|e| DatabaseError::new("Failed to insert request", e))?; - info!( - LOG, - "{} row inserted", - row.len(); "func" => function_name!() - ); + info!(LOG, "Request inserted"); Ok(()) } } diff --git a/packages/relayer/src/lib.rs b/packages/relayer/src/lib.rs index 5f31b8f9..c9c8a781 100644 --- a/packages/relayer/src/lib.rs +++ b/packages/relayer/src/lib.rs @@ -21,7 +21,7 @@ pub use utils::*; use tokio::sync::Mutex; -use anyhow::{anyhow, bail, Result}; +use anyhow::{anyhow, Result}; use dotenv::dotenv; use ethers::prelude::*; use lazy_static::lazy_static; diff --git a/packages/relayer/src/modules/web_server/errors.rs b/packages/relayer/src/modules/web_server/errors.rs index a4651d64..85c4d178 100644 --- a/packages/relayer/src/modules/web_server/errors.rs +++ b/packages/relayer/src/modules/web_server/errors.rs @@ -32,8 +32,8 @@ pub enum ApiError { #[derive(Error, Debug)] pub enum EmailError { - #[error("Subject error: {0}")] - Subject(String), + #[error("Email body error: {0}")] + Body(String), #[error("Email address error: {0}")] EmailAddress(String), #[error("Parse error: {0}")] @@ -56,6 +56,10 @@ pub enum EmailError { Render(#[from] RenderError), #[error("Failed to send email: {0}")] Send(String), + #[error("Hex error: {0}")] + HexError(#[from] hex::FromHexError), + #[error("ABI encode error: {0}")] + AbiError(String), // Currently used with some relayer-utils errors #[error("Anyhow error: {0}")] Anyhow(#[from] anyhow::Error), @@ -190,13 +194,15 @@ impl IntoResponse for ApiError { ApiError::Anyhow(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Email(e) => match e { - EmailError::Subject(e) => (StatusCode::BAD_REQUEST, e.to_string()), + EmailError::Body(e) => (StatusCode::BAD_REQUEST, e.to_string()), EmailError::EmailAddress(e) => (StatusCode::BAD_REQUEST, e.to_string()), EmailError::Parse(e) => (StatusCode::BAD_REQUEST, e.to_string()), EmailError::NotFound(e) => (StatusCode::BAD_REQUEST, e.to_string()), EmailError::Dkim(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), EmailError::ZkRegex(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), EmailError::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::HexError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + EmailError::AbiError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), EmailError::Circuit(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), EmailError::Chain(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), EmailError::FileNotFound(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index ac6d4f5b..7e39b8b5 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -7,84 +7,6 @@ use relayer_utils::LOG; use serde::{Deserialize, Serialize}; use std::str; -#[derive(Serialize, Deserialize)] -pub struct RequestStatusRequest { - pub request_id: u32, -} - -#[derive(Serialize, Deserialize)] -pub enum RequestStatus { - NotExist = 0, - Pending = 1, - Processed = 2, -} - -#[derive(Serialize, Deserialize)] -pub struct RequestStatusResponse { - pub request_id: u32, - pub status: RequestStatus, - pub is_success: bool, - pub email_nullifier: Option, - pub account_salt: Option, -} - -#[derive(Serialize, Deserialize)] -pub struct AcceptanceRequest { - pub controller_eth_addr: String, - pub guardian_email_addr: String, - pub account_code: String, - pub template_idx: u64, - pub command: String, -} - -#[derive(Serialize, Deserialize)] -pub struct AcceptanceResponse { - pub request_id: u32, - pub command_params: Vec, -} - -#[derive(Serialize, Deserialize)] -pub struct RecoveryRequest { - pub controller_eth_addr: String, - pub guardian_email_addr: String, - pub template_idx: u64, - pub command: String, -} - -#[derive(Serialize, Deserialize)] -pub struct RecoveryResponse { - pub request_id: u32, - pub command_params: Vec, -} - -#[derive(Serialize, Deserialize)] -pub struct CompleteRecoveryRequest { - pub account_eth_addr: String, - pub controller_eth_addr: String, - pub complete_calldata: String, -} - -#[derive(Serialize, Deserialize)] -pub struct GetAccountSaltRequest { - pub account_code: String, - pub email_addr: String, -} - -#[derive(Deserialize)] -struct PermittedWallet { - wallet_name: String, - controller_eth_addr: String, - hash_of_bytecode_of_proxy: String, - impl_contract_address: String, - slot_location: String, -} - -#[derive(Serialize, Deserialize)] -pub struct InactiveGuardianRequest { - pub account_eth_addr: String, - pub controller_eth_addr: String, -} - // Create request status API pub async fn request_status_api( Json(payload): Json, @@ -110,22 +32,15 @@ pub async fn request_status_api( })) } -pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response { +pub async fn handle_acceptance_request( + Json(payload): Json, +) -> Result, ApiError> { let command_template = CLIENT .get_acceptance_command_templates(&payload.controller_eth_addr, payload.template_idx) - .await - .unwrap(); - - let command_params = extract_template_vals(&payload.command, command_template); - - if command_params.is_err() { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Invalid command")) - .unwrap(); - } + .await?; - let command_params = command_params.unwrap(); + let command_params = extract_template_vals(&payload.command, command_template) + .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; let account_eth_addr = CLIENT .get_recovered_account_from_acceptance_command( @@ -202,27 +117,26 @@ pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response(); } - let account_salt = calculate_account_salt(&payload.guardian_email_addr, &payload.account_code) - .map_err(|_| ApiError::Validation("Failed to calculate account salt".to_string()))?; + let account_salt = calculate_account_salt(&payload.guardian_email_addr, &payload.account_code); + + DB.insert_request(&Request { + request_id: request_id.clone(), + account_eth_addr: account_eth_addr.clone(), + controller_eth_addr: payload.controller_eth_addr.clone(), + guardian_email_addr: payload.guardian_email_addr.clone(), + is_for_recovery: false, + template_idx: payload.template_idx, + is_processed: false, + is_success: None, + email_nullifier: None, + account_salt: Some(account_salt.clone()), + }) + .await?; if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) .await? { - DB.insert_request(&Request { - request_id: request_id.clone(), - account_eth_addr: account_eth_addr.clone(), - controller_eth_addr: payload.controller_eth_addr.clone(), - guardian_email_addr: payload.guardian_email_addr.clone(), - is_for_recovery: false, - template_idx: payload.template_idx, - is_processed: false, - is_success: None, - email_nullifier: None, - account_salt: Some(account_salt.clone()), - }) - .await?; - handle_email_event(EmailAuthEvent::GuardianAlreadyExists { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -244,20 +158,6 @@ pub async fn handle_acceptance_request(payload: AcceptanceRequest) -> Response Response Response Response Response { +pub async fn handle_recovery_request( + Json(payload): Json, +) -> Result, ApiError> { let command_template = CLIENT .get_recovery_command_templates(&payload.controller_eth_addr, payload.template_idx) - .await - .unwrap(); - - let command_params = extract_template_vals(&payload.command, command_template); - - if command_params.is_err() { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::from("Invalid command")) - .unwrap(); - } + .await?; - let command_params = command_params.unwrap(); + let command_params = extract_template_vals(&payload.command, command_template) + .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; let account_eth_addr = CLIENT .get_recovered_account_from_recovery_command( @@ -407,14 +276,12 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response let account_salt = if let Some(account_details) = account { calculate_account_salt(&payload.guardian_email_addr, &account_details.account_code) - .map_err(|_| ApiError::Validation("Failed to calculate account salt".to_string()))? } else { return Err(ApiError::Validation("Wallet not deployed".to_string())); }; if !DB .is_wallet_and_email_registered(&account_eth_addr, &payload.guardian_email_addr) - // TODO: replace .await? { DB.insert_request(&Request { @@ -437,40 +304,32 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response command: payload.command.clone(), request_id, }) - .await - // TODO: Add custom events for email handling - .expect("Failed to send GuardianNotRegistered event"); - - return Response::builder() - .status(StatusCode::OK) - .body(Body::from( - serde_json::to_string(&RecoveryResponse { - request_id, - command_params, - }) - .unwrap(), - )) - .unwrap(); + .await?; + + return Ok(Json(RecoveryResponse { + request_id, + command_params, + })); } + DB.insert_request(&Request { + request_id: request_id.clone(), + account_eth_addr: account_eth_addr.clone(), + controller_eth_addr: payload.controller_eth_addr.clone(), + guardian_email_addr: payload.guardian_email_addr.clone(), + is_for_recovery: true, + template_idx: payload.template_idx, + is_processed: false, + is_success: None, + email_nullifier: None, + account_salt: Some(account_salt.clone()), + }) + .await?; + if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) .await? { - DB.insert_request(&Request { - request_id: request_id.clone(), - account_eth_addr: account_eth_addr.clone(), - controller_eth_addr: payload.controller_eth_addr.clone(), - guardian_email_addr: payload.guardian_email_addr.clone(), - is_for_recovery: true, - template_idx: payload.template_idx, - is_processed: false, - is_success: None, - email_nullifier: None, - account_salt: Some(account_salt.clone()), - }) - .await?; - handle_email_event(EmailAuthEvent::RecoveryRequest { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -481,20 +340,6 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response // TODO: Add custom error for handle_email_event .expect("Failed to send Recovery event"); } else { - DB.insert_request(&Request { - request_id: request_id.clone(), - account_eth_addr: account_eth_addr.clone(), - controller_eth_addr: payload.controller_eth_addr.clone(), - guardian_email_addr: payload.guardian_email_addr.clone(), - is_for_recovery: true, - template_idx: payload.template_idx, - is_processed: false, - is_success: None, - email_nullifier: None, - account_salt: Some(account_salt.clone()), - }) - .await?; - handle_email_event(EmailAuthEvent::GuardianNotSet { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -504,16 +349,10 @@ pub async fn handle_recovery_request(payload: RecoveryRequest) -> Response .expect("Failed to send Recovery event"); } - Response::builder() - .status(StatusCode::OK) - .body(Body::from( - serde_json::to_string(&RecoveryResponse { - request_id, - command_params, - }) - .unwrap(), - )) - .unwrap() + Ok(Json(RecoveryResponse { + request_id, + command_params, + })) } pub async fn handle_complete_recovery_request( @@ -556,8 +395,7 @@ pub async fn handle_complete_recovery_request( pub async fn get_account_salt( Json(payload): Json, ) -> Result { - let account_salt = calculate_account_salt(&payload.email_addr, &payload.account_code) - .map_err(|_| ApiError::Validation("Failed to calculate account salt".to_string()))?; + let account_salt = calculate_account_salt(&payload.email_addr, &payload.account_code); Ok(account_salt) } @@ -643,19 +481,19 @@ pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { Ok(()) } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct RequestStatusRequest { pub request_id: u32, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub enum RequestStatus { NotExist = 0, Pending = 1, Processed = 2, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct RequestStatusResponse { pub request_id: u32, pub status: RequestStatus, @@ -664,49 +502,49 @@ pub struct RequestStatusResponse { pub account_salt: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct AcceptanceRequest { pub controller_eth_addr: String, pub guardian_email_addr: String, pub account_code: String, pub template_idx: u64, - pub subject: String, + pub command: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct AcceptanceResponse { pub request_id: u32, - pub subject_params: Vec, + pub command_params: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct RecoveryRequest { pub controller_eth_addr: String, pub guardian_email_addr: String, pub template_idx: u64, - pub subject: String, + pub command: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct RecoveryResponse { pub request_id: u32, - pub subject_params: Vec, + pub command_params: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct CompleteRecoveryRequest { pub account_eth_addr: String, pub controller_eth_addr: String, pub complete_calldata: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct GetAccountSaltRequest { pub account_code: String, pub email_addr: String, } -#[derive(Deserialize, Debug)] +#[derive(Deserialize)] struct PermittedWallet { wallet_name: String, controller_eth_addr: String, @@ -715,7 +553,7 @@ struct PermittedWallet { slot_location: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize)] pub struct InactiveGuardianRequest { pub account_eth_addr: String, pub controller_eth_addr: String, diff --git a/packages/relayer/src/utils/utils.rs b/packages/relayer/src/utils/utils.rs index 1da380f0..948c83fe 100644 --- a/packages/relayer/src/utils/utils.rs +++ b/packages/relayer/src/utils/utils.rs @@ -80,7 +80,7 @@ pub fn calculate_default_hash(input: &str) -> String { hash_code.to_string() } -pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> Result { +pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> String { let padded_email_addr = PaddedEmailAddr::from_email_addr(&email_addr); let account_code = if account_code.starts_with("0x") { hex_to_field(&account_code).unwrap() @@ -88,7 +88,7 @@ pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> Result Date: Wed, 11 Sep 2024 12:04:07 +0700 Subject: [PATCH 14/53] Rebase solve conflicts of body-parser refacor --- Cargo.lock | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 160f0fa2..fa7bc496 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1657,17 +1657,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "fancy-regex" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" -dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", -] - [[package]] name = "fastrand" version = "1.9.0" @@ -4132,6 +4121,7 @@ dependencies = [ "regex", "relayer-utils", "reqwest 0.11.27", + "rustc-hex", "serde", "serde_json", "sled", @@ -4163,7 +4153,6 @@ dependencies = [ "hmac-sha256", "itertools 0.10.5", "lazy_static", - "mailparse", "neon", "num-bigint", "num-traits", From 87340f451a4c7098276b852ef9727059429b9af9 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Wed, 11 Sep 2024 17:12:08 +0700 Subject: [PATCH 15/53] Rebase fixes --- packages/relayer/src/core.rs | 350 ++--------------------------------- 1 file changed, 17 insertions(+), 333 deletions(-) diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 08d99abe..67fe5194 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -24,24 +24,27 @@ pub async fn handle_email(email: String) -> Result { let request_decomposed_def = serde_json::from_str(include_str!("./regex_json/request_def.json")) - .map_err(|e| EmailError::Parse(e.to_string()))?; + .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; + println!("request_decomposed_def: {:?}", request_decomposed_def); let request_idxes = extract_substr_idxes(&email, &request_decomposed_def)?; + println!("request_idxes: {:?}", request_idxes); if request_idxes.is_empty() { return Err(EmailError::Body(WRONG_COMMAND_FORMAT.to_string())); } info!(LOG, "Request idxes: {:?}", request_idxes); let request_id = &email[request_idxes[0].0..request_idxes[0].1]; + println!("request_id: {:?}", request_id); let request_id_u32 = request_id .parse::() - .map_err(|e| anyhow!("Failed to parse request_id to u64: {}", e))?; - let request_record = DB.get_request(request_id_u32).await?; - let request = match request_record { - Some(r) => r, + .map_err(|e| EmailError::Parse(format!("Failed to parse request_id to u64: {}", e)))?; + println!("request_id_u32: {:?}", request_id_u32); + let request = match DB.get_request(request_id_u32).await? { + Some(req) => req, None => { return Ok(EmailAuthEvent::Error { email_addr: guardian_email_addr, error: format!("Request {} not found", request_id), - }); + }) } }; if request.guardian_email_addr != guardian_email_addr { @@ -50,14 +53,15 @@ pub async fn handle_email(email: String) -> Result { request.guardian_email_addr, guardian_email_addr ))); } + let account_code_str = DB .get_account_code_from_wallet_and_email(&request.account_eth_addr, &guardian_email_addr) .await? - .ok_or(anyhow!( + .ok_or(EmailError::NotFound(format!( "The user of the wallet address {} and the email address {} is not registered.", - request.account_eth_addr, - guardian_email_addr - ))?; + request.account_eth_addr, guardian_email_addr + )))?; + check_and_update_dkim( &email, &parsed_email, @@ -65,330 +69,9 @@ pub async fn handle_email(email: String) -> Result { &request.account_eth_addr, request.account_salt.as_deref().unwrap_or_default(), ) - .await?; - - if let Ok(invitation_code) = parsed_email.get_invitation_code(false) { - if !request.is_for_recovery { - trace!(LOG, "Email with account code"); - - if account_code_str != invitation_code { - return Err(anyhow!( - "Stored account code is not equal to one in the email. Stored: {}, Email: {}", - account_code_str, - invitation_code - )); - } - - let command_template = CLIENT - .get_acceptance_command_templates( - &request.controller_eth_addr, - request.template_idx, - ) - .await?; - - let command_params = - match extract_template_vals_from_command_template(&email_body, command_template) { - Ok(command_params) => command_params, - Err(e) => { - return Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: format!("Invalid Command, {}", e), - }); - } - }; - - let command_params_encoded: Vec = command_params - .iter() - .map(|param| param.abi_encode(None).unwrap()) - .collect(); - - let tokens = vec![ - Token::Uint((*EMAIL_ACCOUNT_RECOVERY_VERSION_ID.get().unwrap()).into()), - Token::String("ACCEPTANCE".to_string()), - Token::Uint(request.template_idx.into()), - ]; - - let template_id = keccak256(encode(&tokens)); - - let circuit_input = generate_email_circuit_input( - &email, - &AccountCode::from(hex_to_field(&format!("0x{}", &account_code_str))?), - Some(EmailCircuitParams { - max_header_length: Some(1024), - max_body_length: Some(1024), - sha_precompute_selector: Some(SHA_PRECOMPUTE_SELECTOR.to_string()), - ignore_body_hash_check: Some(false), - }), - ) - .await?; - - let (proof, public_signals) = - generate_proof(&circuit_input, "email_auth", PROVER_ADDRESS.get().unwrap()).await?; - - info!(LOG, "Public signals: {:?}", public_signals); - - let account_salt = u256_to_bytes32(&public_signals[COMMAND_FIELDS + DOMAIN_FIELDS + 3]); - let is_code_exist = public_signals[COMMAND_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into(); - let masked_command = get_masked_command(public_signals.clone(), DOMAIN_FIELDS + 3)?; - - let email_proof = EmailProof { - proof: proof, - domain_name: parsed_email.get_email_domain()?, - public_key_hash: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 0]), - timestamp: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 2]).into(), - masked_command, - email_nullifier: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 1]), - account_salt, - is_code_exist, - }; - - let email_auth_msg = EmailAuthMsg { - template_id: template_id.into(), - command_params: command_params_encoded, - skipped_command_prefix: U256::zero(), - proof: email_proof.clone(), - }; - - info!(LOG, "Email Auth Msg: {:?}", email_auth_msg); - info!(LOG, "Request: {:?}", request); - - match CLIENT - .handle_acceptance( - &request.controller_eth_addr, - email_auth_msg, - request.template_idx, - ) - .await - { - Ok(true) => { - let creds = Credentials { - account_code: invitation_code, - account_eth_addr: request.account_eth_addr.clone(), - guardian_email_addr: guardian_email_addr.clone(), - is_set: true, - }; - - DB.update_credentials_of_account_code(&creds).await?; - - let updated_request = Request { - account_eth_addr: request.account_eth_addr.clone(), - controller_eth_addr: request.controller_eth_addr.clone(), - guardian_email_addr: guardian_email_addr.clone(), - template_idx: request.template_idx, - is_for_recovery: request.is_for_recovery, - is_processed: true, - request_id: request.request_id, - is_success: Some(true), - email_nullifier: Some(field_to_hex( - &bytes32_to_fr(&email_proof.email_nullifier).unwrap(), - )), - account_salt: Some(bytes32_to_hex(&account_salt)), - }; - - DB.update_request(&updated_request).await?; - - Ok(EmailAuthEvent::AcceptanceSuccess { - account_eth_addr: request.account_eth_addr, - guardian_email_addr, - request_id: request_id_u32, - }) - } - Ok(false) => { - let updated_request = Request { - account_eth_addr: request.account_eth_addr.clone(), - controller_eth_addr: request.controller_eth_addr.clone(), - guardian_email_addr: guardian_email_addr.clone(), - template_idx: request.template_idx, - is_for_recovery: request.is_for_recovery, - is_processed: true, - request_id: request.request_id, - is_success: Some(false), - email_nullifier: Some(field_to_hex( - &bytes32_to_fr(&email_proof.email_nullifier).unwrap(), - )), - account_salt: Some(bytes32_to_hex(&account_salt)), - }; - - DB.update_request(&updated_request).await?; - - Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: "Failed to handle acceptance".to_string(), - }) - } - Err(e) => Err(anyhow!("Failed to handle acceptance: {}", e)), - } - } else { - return Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: "Account code found and for recovery".to_string(), - }); - } - } else { - if request.is_for_recovery { - let command_template = CLIENT - .get_recovery_command_templates(&request.controller_eth_addr, request.template_idx) - .await?; - - let command_params = - match extract_template_vals_from_command_template(&email_body, command_template) { - Ok(command_params) => command_params, - Err(e) => { - return Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: format!("Invalid Command, {}", e), - }); - } - }; - - let command_params_encoded: Vec = command_params - .iter() - .map(|param| param.abi_encode(None).unwrap()) - .collect(); - - let tokens = vec![ - Token::Uint((*EMAIL_ACCOUNT_RECOVERY_VERSION_ID.get().unwrap()).into()), - Token::String("RECOVERY".to_string()), - Token::Uint(request.template_idx.into()), - ]; - - let template_id = keccak256(encode(&tokens)); - - let circuit_input = generate_email_circuit_input( - &email, - &AccountCode::from(hex_to_field(&format!("0x{}", &account_code_str))?), - Some(EmailCircuitParams { - max_header_length: Some(1024), - max_body_length: Some(1024), - sha_precompute_selector: Some(SHA_PRECOMPUTE_SELECTOR.to_string()), - ignore_body_hash_check: Some(false), - }), - ) - .await?; - - let (proof, public_signals) = - generate_proof(&circuit_input, "email_auth", PROVER_ADDRESS.get().unwrap()).await?; - - let account_salt = u256_to_bytes32(&public_signals[COMMAND_FIELDS + DOMAIN_FIELDS + 3]); - let is_code_exist = public_signals[COMMAND_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into(); - let masked_command = get_masked_command(public_signals.clone(), DOMAIN_FIELDS + 3)?; - - let email_proof = EmailProof { - proof: proof, - domain_name: parsed_email.get_email_domain()?, - public_key_hash: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 0]), - timestamp: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 2]).into(), - masked_command, - email_nullifier: u256_to_bytes32(&public_signals[DOMAIN_FIELDS + 1]), - account_salt, - is_code_exist, - }; + .await + .map_err(|e| EmailError::Dkim(e.to_string()))?; - let email_auth_msg = EmailAuthMsg { - template_id: template_id.into(), - command_params: command_params_encoded, - skipped_command_prefix: U256::zero(), - proof: email_proof.clone(), - }; - - println!("Email Auth Msg: {:?}", email_auth_msg); - - match CLIENT - .handle_recovery( - &request.controller_eth_addr, - email_auth_msg, - request.template_idx, - ) - .await - { - Ok(true) => { - let updated_request = Request { - account_eth_addr: request.account_eth_addr.clone(), - controller_eth_addr: request.controller_eth_addr.clone(), - guardian_email_addr: guardian_email_addr.clone(), - template_idx: request.template_idx, - is_for_recovery: request.is_for_recovery, - is_processed: true, - request_id: request.request_id, - is_success: Some(true), - email_nullifier: Some(field_to_hex( - &bytes32_to_fr(&email_proof.email_nullifier).unwrap(), - )), - account_salt: Some(bytes32_to_hex(&account_salt)), - }; - - DB.update_request(&updated_request).await?; - - Ok(EmailAuthEvent::RecoverySuccess { - account_eth_addr: request.account_eth_addr, - guardian_email_addr, - request_id: request_id_u32, - }) - } - Ok(false) => { - let updated_request = Request { - account_eth_addr: request.account_eth_addr.clone(), - controller_eth_addr: request.controller_eth_addr.clone(), - guardian_email_addr: guardian_email_addr.clone(), - template_idx: request.template_idx, - is_for_recovery: request.is_for_recovery, - is_processed: true, - request_id: request.request_id, - is_success: Some(false), - email_nullifier: Some(field_to_hex( - &bytes32_to_fr(&email_proof.email_nullifier).unwrap(), - )), - account_salt: Some(bytes32_to_hex(&account_salt)), - }; - - DB.update_request(&updated_request).await?; - - Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: "Failed to handle recovery".to_string(), - }) - } - Err(e) => Err(anyhow!("Failed to handle recovery: {}", e)), - } - } else { - return Ok(EmailAuthEvent::Error { - email_addr: guardian_email_addr, - error: "No account code found and not for recovery".to_string(), - }); - } - } -} - -pub fn get_masked_command(public_signals: Vec, start_idx: usize) -> Result { - // Gather signals from start_idx to start_idx + COMMAND_FIELDS - let mut command_bytes = Vec::new(); - for i in start_idx..start_idx + COMMAND_FIELDS { -#[named] -async fn get_verified_request( - email: &String, - guardian_email_addr: String, -) -> Result<(Option, String), EmailError> { - let request_decomposed_def = - serde_json::from_str(include_str!("./regex_json/request_def.json")) - .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; - println!("request_decomposed_def: {:?}", request_decomposed_def); - let request_idxes = extract_substr_idxes(email, &request_decomposed_def)?; - println!("request_idxes: {:?}", request_idxes); - if request_idxes.is_empty() { - return Err(EmailError::Subject(WRONG_SUBJECT_FORMAT.to_string())); - } - info!(LOG, "Request idxes: {:?}", request_idxes; "func" => function_name!()); - let request_id = &email[request_idxes[0].0..request_idxes[0].1]; - println!("request_id: {:?}", request_id); - let request_id_u32 = request_id - .parse::() - .map_err(|e| EmailError::Parse(format!("Failed to parse request_id to u64: {}", e)))?; - println!("request_id_u32: {:?}", request_id_u32); - let request_record = DB.get_request(request_id_u32).await?; - println!("request_record: {:?}", request_record); - let request = match request_record { - Some(req) => req, - None => return Ok((None, request_id.to_string())), let invitation_code = match parsed_email.get_invitation_code(false) { Ok(code) => Some(code), Err(_) => None, @@ -664,6 +347,7 @@ async fn get_email_auth_msg( let email_auth_msg = EmailAuthMsg { template_id: template_id.into(), command_params: command_params_encoded, + skipped_command_prefix: U256::zero(), proof: email_proof.clone(), }; Ok((email_auth_msg, email_proof, account_salt)) From bb9ce3849eba07869179f0f50cbd8840582e7ad0 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 12 Sep 2024 08:21:28 +0700 Subject: [PATCH 16/53] Acknowledgement as replies in email thread --- packages/relayer/src/modules/mail.rs | 4 +++- packages/relayer/src/modules/web_server/rest_api.rs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index 82a749a6..ab792c39 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -51,6 +51,7 @@ pub enum EmailAuthEvent { email_addr: String, command: String, original_message_id: Option, + original_subject: String, }, NoOp, } @@ -335,6 +336,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> email_addr, command, original_message_id, + original_subject, } => { let body_plain = format!( "Hi {}!\nYour email with the command {} is received.", @@ -342,7 +344,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> ); let render_data = serde_json::json!({"userEmailAddr": email_addr, "request": command}); let body_html = render_html("acknowledgement.html", render_data).await?; - let subject = format!("Re: {}", subject); + let subject = format!("Re: {}", original_subject); let email = EmailMessage { to: email_addr, subject, diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 7e39b8b5..f099b5fb 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -440,11 +440,13 @@ fn parse_error_message(error_data: String) -> String { pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; let from_addr = parsed_email.get_from_addr()?; + let original_subject = parsed_email.get_subject_all()?; tokio::spawn(async move { match handle_email_event(EmailAuthEvent::Ack { email_addr: from_addr.clone(), command: parsed_email.get_command(false).unwrap_or_default(), original_message_id: parsed_email.get_message_id().ok(), + original_subject, }) .await { From d545cbb00b640dba4ff5b99be8fbc6bc03079349 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 13 Sep 2024 13:09:33 +0700 Subject: [PATCH 17/53] Add Re: to subject for reply emails --- packages/relayer/src/chain.rs | 14 +++- packages/relayer/src/core.rs | 65 +++++++++++-------- packages/relayer/src/modules/mail.rs | 38 +++++++---- .../relayer/src/modules/web_server/errors.rs | 2 +- .../src/modules/web_server/rest_api.rs | 43 +++++++++++- packages/relayer/src/utils/mod.rs | 4 +- ...mand_templates.rs => subject_templates.rs} | 3 +- 7 files changed, 126 insertions(+), 43 deletions(-) rename packages/relayer/src/utils/{command_templates.rs => subject_templates.rs} (99%) diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index b124488f..8de83d4e 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -152,7 +152,7 @@ impl ChainClient { .call() .await .map_err(|e| { - ChainError::contract_error("Failed to get recovery subject templates", e) + ChainError::contract_error("Failed to get recovery command templates", e) })?; Ok(templates[template_idx as usize].clone()) } @@ -163,19 +163,29 @@ impl ChainClient { account_eth_addr: &String, complete_calldata: &String, ) -> Result { + println!("doing complete recovery"); let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; + println!("controller_eth_addr: {:?}", controller_eth_addr); + let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let decoded_calldata = hex::decode(&complete_calldata.trim_start_matches("0x")).expect("Decoding failed"); + println!("decoded_calldata : {:?}", decoded_calldata); + let account_eth_addr = account_eth_addr .parse::() .map_err(ChainError::HexError)?; + println!("account_eth_addr : {:?}", account_eth_addr); + let call = contract.complete_recovery(account_eth_addr, Bytes::from(decoded_calldata)); + println!("call: {:?}", call); + let tx = call .send() .await .map_err(|e| ChainError::contract_error("Failed to call complete_recovery", e))?; + println!("tx: {:?}", tx); // If the transaction is successful, the function will return true and false otherwise. let receipt = tx .log() @@ -188,6 +198,8 @@ impl ChainClient { ) })? .ok_or(anyhow!("No receipt"))?; + println!("receipt : {:?}", receipt); + Ok(receipt .status .map(|status| status == U64::from(1)) diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 67fe5194..7af369ae 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -25,26 +25,25 @@ pub async fn handle_email(email: String) -> Result { let request_decomposed_def = serde_json::from_str(include_str!("./regex_json/request_def.json")) .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; - println!("request_decomposed_def: {:?}", request_decomposed_def); let request_idxes = extract_substr_idxes(&email, &request_decomposed_def)?; - println!("request_idxes: {:?}", request_idxes); if request_idxes.is_empty() { return Err(EmailError::Body(WRONG_COMMAND_FORMAT.to_string())); } info!(LOG, "Request idxes: {:?}", request_idxes); let request_id = &email[request_idxes[0].0..request_idxes[0].1]; - println!("request_id: {:?}", request_id); let request_id_u32 = request_id .parse::() .map_err(|e| EmailError::Parse(format!("Failed to parse request_id to u64: {}", e)))?; - println!("request_id_u32: {:?}", request_id_u32); let request = match DB.get_request(request_id_u32).await? { Some(req) => req, None => { + let original_subject = parsed_email.get_subject_all()?; return Ok(EmailAuthEvent::Error { email_addr: guardian_email_addr, error: format!("Request {} not found", request_id), - }) + original_subject, + original_message_id: parsed_email.get_message_id().ok(), + }); } }; if request.guardian_email_addr != guardian_email_addr { @@ -104,14 +103,24 @@ async fn handle_email_request( accept(params, invitation_code).await } (None, is_for_recovery) if is_for_recovery => recover(params).await, - (Some(_), _) => Ok(EmailAuthEvent::Error { - email_addr: params.request.guardian_email_addr, - error: "Account code found and for recovery".to_string(), - }), - (None, _) => Ok(EmailAuthEvent::Error { - email_addr: params.request.guardian_email_addr, - error: "No account code found and not for recovery".to_string(), - }), + (Some(_), _) => { + let original_subject = params.parsed_email.get_subject_all()?; + Ok(EmailAuthEvent::Error { + email_addr: params.request.guardian_email_addr, + error: "Account code found and for recovery".to_string(), + original_subject, + original_message_id: params.parsed_email.get_message_id().ok(), + }) + } + (None, _) => { + let original_subject = params.parsed_email.get_subject_all()?; + Ok(EmailAuthEvent::Error { + email_addr: params.request.guardian_email_addr, + error: "No account code found and not for recovery".to_string(), + original_subject, + original_message_id: params.parsed_email.get_message_id().ok(), + }) + } } } @@ -140,6 +149,7 @@ async fn accept( ) .await?; + let original_subject = params.parsed_email.get_subject_all()?; if is_accepted { let creds = Credentials { account_code: invitation_code, @@ -153,11 +163,16 @@ async fn accept( account_eth_addr: params.request.account_eth_addr, guardian_email_addr: params.request.guardian_email_addr, request_id: params.request.request_id, + original_subject, + original_message_id: params.parsed_email.get_message_id().ok(), }) } else { + let original_subject = params.parsed_email.get_subject_all()?; Ok(EmailAuthEvent::Error { email_addr: params.request.guardian_email_addr, error: "Failed to handle acceptance".to_string(), + original_subject, + original_message_id: params.parsed_email.get_message_id().ok(), }) } } @@ -184,16 +199,22 @@ async fn recover(params: EmailRequestContext) -> Result = command_params - // .iter() - // .map(|param| param.abi_encode(None).unwrap()) - // .collect(); + let command_params = extract_template_vals_from_command(¶ms.email_body, command_template) + .map_err(|e| EmailError::Body(format!("Invalid commad: {}", e)))?; let command_params_encoded = command_params .iter() diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index ab792c39..dfb237dc 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -20,6 +20,8 @@ pub enum EmailAuthEvent { Error { email_addr: String, error: String, + original_subject: String, + original_message_id: Option, }, RecoveryRequest { account_eth_addr: String, @@ -31,11 +33,15 @@ pub enum EmailAuthEvent { account_eth_addr: String, guardian_email_addr: String, request_id: u32, + original_subject: String, + original_message_id: Option, }, RecoverySuccess { account_eth_addr: String, guardian_email_addr: String, request_id: u32, + original_subject: String, + original_message_id: Option, }, GuardianNotSet { account_eth_addr: String, @@ -116,8 +122,14 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> send_email(email).await?; } - EmailAuthEvent::Error { email_addr, error } => { - let subject = "Error"; + EmailAuthEvent::Error { + email_addr, + error, + original_subject, + original_message_id, + } => { + let subject = format!("Re: {}", original_subject); + let body_plain = format!( "An error occurred while processing your request. \ Error: {}", @@ -132,9 +144,9 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let email = EmailMessage { to: email_addr, - subject: subject.to_string(), - reference: None, - reply_to: None, + subject, + reference: original_message_id.clone(), + reply_to: original_message_id, body_plain, body_html, body_attachments: None, @@ -211,8 +223,10 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, guardian_email_addr, request_id, + original_subject, + original_message_id, } => { - let subject = "Acceptance Success"; + let subject = format!("Re: {}", original_subject); let body_plain = format!( "Your guardian request for the wallet address {} has been set. \ Your request ID is #{} is now complete.", @@ -229,8 +243,8 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let email = EmailMessage { to: guardian_email_addr, subject: subject.to_string(), - reference: None, - reply_to: None, + reference: original_message_id.clone(), + reply_to: original_message_id, body_plain, body_html, body_attachments: None, @@ -242,8 +256,10 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, guardian_email_addr, request_id, + original_subject, + original_message_id, } => { - let subject = "Recovery Success"; + let subject = format!("Re: {}", original_subject); let body_plain = format!( "Your recovery request for the wallet address {} is successful. \ Your request ID is #{}.", @@ -260,8 +276,8 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let email = EmailMessage { to: guardian_email_addr, subject: subject.to_string(), - reference: None, - reply_to: None, + reference: original_message_id.clone(), + reply_to: original_message_id, body_plain, body_html, body_attachments: None, diff --git a/packages/relayer/src/modules/web_server/errors.rs b/packages/relayer/src/modules/web_server/errors.rs index 85c4d178..10959c21 100644 --- a/packages/relayer/src/modules/web_server/errors.rs +++ b/packages/relayer/src/modules/web_server/errors.rs @@ -190,7 +190,7 @@ impl IntoResponse for ApiError { ApiError::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Chain(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::SqlxError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), - ApiError::Validation(e) => (StatusCode::BAD_REQUEST, e), + ApiError::Validation(e) => (StatusCode::BAD_REQUEST, e.to_string()), ApiError::Anyhow(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), ApiError::Email(e) => match e { diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index f099b5fb..823eb6e0 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -11,6 +11,7 @@ use std::str; pub async fn request_status_api( Json(payload): Json, ) -> Result, ApiError> { + println!("requesting status"); let row = DB.get_request(payload.request_id).await?; let status = if let Some(ref row) = row { if row.is_processed { @@ -35,6 +36,7 @@ pub async fn request_status_api( pub async fn handle_acceptance_request( Json(payload): Json, ) -> Result, ApiError> { + println!("handle_acceptance_request"); let command_template = CLIENT .get_acceptance_command_templates(&payload.controller_eth_addr, payload.template_idx) .await?; @@ -194,12 +196,15 @@ pub async fn handle_acceptance_request( pub async fn handle_recovery_request( Json(payload): Json, ) -> Result, ApiError> { + println!("handle_recovery_request: {:?}", payload); let command_template = CLIENT .get_recovery_command_templates(&payload.controller_eth_addr, payload.template_idx) .await?; + println!("command_template: {:?}", command_template); let command_params = extract_template_vals(&payload.command, command_template) .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; + println!("command_params"); let account_eth_addr = CLIENT .get_recovered_account_from_recovery_command( @@ -209,15 +214,22 @@ pub async fn handle_recovery_request( ) .await?; + println!("account_eth_addr"); + let account_eth_addr = format!("0x{:x}", account_eth_addr); + println!("account_eth_addr"); if !CLIENT.is_wallet_deployed(&account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } + println!("wallet is deployed"); + // Check if hash of bytecode of proxy contract is equal or not let bytecode = CLIENT.get_bytecode(&account_eth_addr).await?; + println!("bytecode"); let bytecode_hash = format!("0x{}", hex::encode(keccak256(bytecode.as_ref()))); + println!("bytecode_hash"); // let permitted_wallets: Vec = // serde_json::from_str(include_str!("../../permitted_wallets.json")).unwrap(); @@ -266,24 +278,37 @@ pub async fn handle_recovery_request( // } let mut request_id = rand::thread_rng().gen::(); + println!("got request_id"); while let Ok(Some(request)) = DB.get_request(request_id).await { request_id = rand::thread_rng().gen::(); } + println!("got request: {:?}", request_id); + println!("account_eth_addr: {:?}", account_eth_addr); + println!( + "payload.guardian_email_addr: {:?}", + payload.guardian_email_addr + ); + let account = DB .get_credentials_from_wallet_and_email(&account_eth_addr, &payload.guardian_email_addr) .await?; + println!("got account: {:?}", account); + let account_salt = if let Some(account_details) = account { calculate_account_salt(&payload.guardian_email_addr, &account_details.account_code) } else { return Err(ApiError::Validation("Wallet not deployed".to_string())); }; + println!("got account_salt"); + if !DB .is_wallet_and_email_registered(&account_eth_addr, &payload.guardian_email_addr) .await? { + println!("email and wallet are not registered"); DB.insert_request(&Request { request_id: request_id.clone(), account_eth_addr: account_eth_addr.clone(), @@ -326,10 +351,13 @@ pub async fn handle_recovery_request( }) .await?; + println!("inserted request"); + if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) .await? { + println!("guardian is set"); handle_email_event(EmailAuthEvent::RecoveryRequest { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -340,6 +368,7 @@ pub async fn handle_recovery_request( // TODO: Add custom error for handle_email_event .expect("Failed to send Recovery event"); } else { + println!("guardian is not set"); handle_email_event(EmailAuthEvent::GuardianNotSet { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -349,6 +378,8 @@ pub async fn handle_recovery_request( .expect("Failed to send Recovery event"); } + println!("all done"); + Ok(Json(RecoveryResponse { request_id, command_params, @@ -358,9 +389,11 @@ pub async fn handle_recovery_request( pub async fn handle_complete_recovery_request( Json(payload): Json, ) -> Result { + println!("handle_complete_recovery_request"); if !CLIENT.is_wallet_deployed(&payload.account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } + println!("wallet is deployed"); match CLIENT .complete_recovery( @@ -395,6 +428,7 @@ pub async fn handle_complete_recovery_request( pub async fn get_account_salt( Json(payload): Json, ) -> Result { + println!("get_account_salt"); let account_salt = calculate_account_salt(&payload.email_addr, &payload.account_code); Ok(account_salt) } @@ -402,6 +436,7 @@ pub async fn get_account_salt( pub async fn inactive_guardian( Json(payload): Json, ) -> Result { + println!("inactive_guardian"); let is_activated = CLIENT .get_is_activated(&payload.controller_eth_addr, &payload.account_eth_addr) .await?; @@ -438,6 +473,7 @@ fn parse_error_message(error_data: String) -> String { } pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { + println!("receive_email_api_fn"); let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; let from_addr = parsed_email.get_from_addr()?; let original_subject = parsed_email.get_subject_all()?; @@ -466,9 +502,14 @@ pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { }, Err(e) => { error!(LOG, "Error handling email: {:?}", e); + let original_subject = parsed_email + .get_subject_all() + .unwrap_or("Unknown Error".to_string()); match handle_email_event(EmailAuthEvent::Error { email_addr: from_addr, error: e.to_string(), + original_subject, + original_message_id: parsed_email.get_message_id().ok(), }) .await { @@ -519,7 +560,7 @@ pub struct AcceptanceResponse { pub command_params: Vec, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] pub struct RecoveryRequest { pub controller_eth_addr: String, pub guardian_email_addr: String, diff --git a/packages/relayer/src/utils/mod.rs b/packages/relayer/src/utils/mod.rs index 11b1e85f..361a451a 100644 --- a/packages/relayer/src/utils/mod.rs +++ b/packages/relayer/src/utils/mod.rs @@ -1,7 +1,7 @@ -pub mod command_templates; pub mod strings; +pub mod subject_templates; pub mod utils; -pub use command_templates::*; pub use strings::*; +pub use subject_templates::*; pub use utils::*; diff --git a/packages/relayer/src/utils/command_templates.rs b/packages/relayer/src/utils/subject_templates.rs similarity index 99% rename from packages/relayer/src/utils/command_templates.rs rename to packages/relayer/src/utils/subject_templates.rs index c742a323..e8ccd734 100644 --- a/packages/relayer/src/utils/command_templates.rs +++ b/packages/relayer/src/utils/subject_templates.rs @@ -49,7 +49,7 @@ impl TemplateValue { } } -pub fn extract_template_vals_from_command_template( +pub fn extract_template_vals_from_command( input: &str, templates: Vec, ) -> Result, anyhow::Error> { @@ -178,6 +178,7 @@ pub fn extract_template_vals(input: &str, templates: Vec) -> Result String { // Convert amount to string in wei format (no decimals) let uint_str = uint.to_string(); From 37ef80b9f1feb7d3fc2a34daa16864bc3d40e0be Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Fri, 13 Sep 2024 15:30:34 +0530 Subject: [PATCH 18/53] Update email templates UI --- .../eml_templates/acceptance_request.html | 609 +++++++----------- .../eml_templates/acceptance_success.html | 598 +++++++---------- .../eml_templates/acknowledgement.html | 595 +++++++---------- .../eml_templates/credential_not_present.html | 606 +++++++---------- packages/relayer/eml_templates/error.html | 416 +----------- .../guardian_already_exists.html | 599 +++++++---------- .../eml_templates/guardian_not_set.html | 595 +++++++---------- .../eml_templates/recovery_request.html | 606 +++++++---------- .../eml_templates/recovery_success.html | 598 +++++++---------- 9 files changed, 1757 insertions(+), 3465 deletions(-) diff --git a/packages/relayer/eml_templates/acceptance_request.html b/packages/relayer/eml_templates/acceptance_request.html index 01f4178a..3e0cd15d 100644 --- a/packages/relayer/eml_templates/acceptance_request.html +++ b/packages/relayer/eml_templates/acceptance_request.html @@ -1,421 +1,258 @@ + - Email Auth + - Set Your Guardian Email - - + + + + + -   -
{{command}}
diff --git a/packages/relayer/eml_templates/acceptance_success.html b/packages/relayer/eml_templates/acceptance_success.html index 4e45a5b4..b144424f 100644 --- a/packages/relayer/eml_templates/acceptance_success.html +++ b/packages/relayer/eml_templates/acceptance_success.html @@ -1,414 +1,252 @@ + - Email Auth + - Guardian Email Set! - - + + + + + -   diff --git a/packages/relayer/eml_templates/acknowledgement.html b/packages/relayer/eml_templates/acknowledgement.html index 713ce805..7e77ea74 100644 --- a/packages/relayer/eml_templates/acknowledgement.html +++ b/packages/relayer/eml_templates/acknowledgement.html @@ -1,412 +1,251 @@ + - Email Wallet + - Email Wallet Acknowledgement - - + + + + + -   diff --git a/packages/relayer/eml_templates/credential_not_present.html b/packages/relayer/eml_templates/credential_not_present.html index b13ee178..b7929fac 100644 --- a/packages/relayer/eml_templates/credential_not_present.html +++ b/packages/relayer/eml_templates/credential_not_present.html @@ -1,419 +1,257 @@ + - Email Auth + - Credential Not Present - - + + + + + -   -
{{command}}
diff --git a/packages/relayer/eml_templates/error.html b/packages/relayer/eml_templates/error.html index aef12c26..b2ebb779 100644 --- a/packages/relayer/eml_templates/error.html +++ b/packages/relayer/eml_templates/error.html @@ -1,415 +1 @@ - - - - - - Email Auth - - - Error - - - - - - - - - + \ No newline at end of file diff --git a/packages/relayer/eml_templates/guardian_already_exists.html b/packages/relayer/eml_templates/guardian_already_exists.html index 8d52d462..0d2ef79c 100644 --- a/packages/relayer/eml_templates/guardian_already_exists.html +++ b/packages/relayer/eml_templates/guardian_already_exists.html @@ -1,414 +1,253 @@ + - Email Auth + - Guardian Already Set - - + + + + + -   diff --git a/packages/relayer/eml_templates/guardian_not_set.html b/packages/relayer/eml_templates/guardian_not_set.html index 853bb3d6..868e9e77 100644 --- a/packages/relayer/eml_templates/guardian_not_set.html +++ b/packages/relayer/eml_templates/guardian_not_set.html @@ -1,412 +1,251 @@ + - Email Auth + - Guardian Not Set - - + + + + + -   diff --git a/packages/relayer/eml_templates/recovery_request.html b/packages/relayer/eml_templates/recovery_request.html index 0081a8a6..48293fee 100644 --- a/packages/relayer/eml_templates/recovery_request.html +++ b/packages/relayer/eml_templates/recovery_request.html @@ -1,419 +1,257 @@ + - Email Auth + - Recovery Request - - + + + + + -   -
{{command}}
diff --git a/packages/relayer/eml_templates/recovery_success.html b/packages/relayer/eml_templates/recovery_success.html index d067c2f6..6ddb168d 100644 --- a/packages/relayer/eml_templates/recovery_success.html +++ b/packages/relayer/eml_templates/recovery_success.html @@ -1,414 +1,252 @@ + - Email Auth + - Recovery Successful - - + + + + + -   From d862ec6f6c55edc9598c0d6a53cf8a707e2cbb74 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 13 Sep 2024 15:27:26 +0700 Subject: [PATCH 19/53] Add cloud build to build on gcp --- Relayer.Dockerfile | 4 +- cloudbuild-base.yaml | 19 + cloudbuild-relayer.yaml | 19 + kubernetes/relayer.staging.yml | 163 +++++++ kubernetes/relayer.yml | 30 +- ...countRecoveryZKSync_completeRecovery.t.sol | 265 ----------- ...countRecoveryZKSync_handleAcceptance.t.sol | 218 --------- ...AccountRecoveryZKSync_handleRecovery.t.sol | 433 ------------------ ...AccountRecoveryZKSync_rejectRecovery.t.sol | 265 ----------- ...ccountRecoveryZKSync_requestGuardian.t.sol | 88 ---- .../EmailAccountRecoveryZKSync_transfer.t.sol | 68 --- .../EmailAccountRecoveryZKSync_withdraw.t.sol | 67 --- ...eryZkSync_acceptanceCommandTemplates.t.sol | 32 -- ...overyZkSync_recoveryCommandTemplates.t.sol | 35 -- 14 files changed, 218 insertions(+), 1488 deletions(-) create mode 100644 cloudbuild-base.yaml create mode 100644 cloudbuild-relayer.yaml create mode 100644 kubernetes/relayer.staging.yml delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_completeRecovery.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleAcceptance.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleRecovery.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_rejectRecovery.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_requestGuardian.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_transfer.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_withdraw.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_acceptanceCommandTemplates.t.sol delete mode 100644 packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_recoveryCommandTemplates.t.sol diff --git a/Relayer.Dockerfile b/Relayer.Dockerfile index fd362f3b..cd99b0ff 100644 --- a/Relayer.Dockerfile +++ b/Relayer.Dockerfile @@ -1,5 +1,5 @@ # Use the base image -FROM bisht13/ar-relayer-base:latest +FROM us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer-base:v1 # Copy the project files COPY packages/relayer /relayer/packages/relayer @@ -14,4 +14,4 @@ RUN cargo build EXPOSE 4500 # Set the default command -CMD ["cargo", "run"] \ No newline at end of file +CMD ["cargo", "run"] diff --git a/cloudbuild-base.yaml b/cloudbuild-base.yaml new file mode 100644 index 00000000..0bd58620 --- /dev/null +++ b/cloudbuild-base.yaml @@ -0,0 +1,19 @@ +steps: + # Build the base container image + - name: 'gcr.io/cloud-builders/docker' + args: + [ + 'build', + '-t', + 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer-base:v1', + '-f', + 'Base.Dockerfile', + '.', + ] + # Push the base container image to Artifact Registry + - name: 'gcr.io/cloud-builders/docker' + args: + [ + 'push', + 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer-base:v1', + ] diff --git a/cloudbuild-relayer.yaml b/cloudbuild-relayer.yaml new file mode 100644 index 00000000..45422673 --- /dev/null +++ b/cloudbuild-relayer.yaml @@ -0,0 +1,19 @@ +steps: + # Build the base container image + - name: 'gcr.io/cloud-builders/docker' + args: + [ + 'build', + '-t', + 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v1', + '-f', + 'Relayer.Dockerfile', + '.', + ] + # Push the base container image to Artifact Registry + - name: 'gcr.io/cloud-builders/docker' + args: + [ + 'push', + 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v1', + ] diff --git a/kubernetes/relayer.staging.yml b/kubernetes/relayer.staging.yml new file mode 100644 index 00000000..7e97ee50 --- /dev/null +++ b/kubernetes/relayer.staging.yml @@ -0,0 +1,163 @@ +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: relayer-config-email-auth +# namespace: ar-base-sepolia-staging +# labels: +# app: relayer +# data: +# EMAIL_ACCOUNT_RECOVERY_VERSION_ID: '' +# CHAIN_RPC_PROVIDER: '' +# CHAIN_RPC_EXPLORER: '' +# CHAIN_ID: '' +# WEB_SERVER_ADDRESS: '' +# CIRCUITS_DIR_PATH: '' +# EMAIL_TEMPLATES_PATH: '' +# CANISTER_ID: '' +# IC_REPLICA_URL: '' +# JSON_LOGGER: '' +# PEM_PATH: '' +# SMTP_SERVER: '' + +# --- +# apiVersion: v1 +# kind: Secret +# metadata: +# name: relayer-secret-email-auth +# namespace: ar-base-sepolia-staging +# labels: +# app: relayer +# type: Opaque +# data: +# PRIVATE_KEY: +# DATABASE_URL: +# PROVER_ADDRESS: +# ICPEM: + +# --- +# apiVersion: v1 +# kind: Secret +# metadata: +# name: relayer-smtp-secret +# namespace: ar-base-sepolia-staging +# labels: +# app: relayer +# type: Opaque +# data: +# SMTP_LOGIN_ID: +# SMTP_LOGIN_PASSWORD: +# SMTP_DOMAIN_NAME: +# SERVER_HOST: +# SERVER_PORT: +# JSON_LOGGER: + +# --- +# apiVersion: v1 +# kind: Secret +# metadata: +# name: relayer-imap-secret +# namespace: ar-base-sepolia-staging +# labels: +# app: relayer +# type: Opaque +# data: +# RELAYER_ENDPOINT: +# IMAP_LOGIN_ID: +# IMAP_LOGIN_PASSWORD: +# IMAP_PORT: +# IMAP_DOMAIN_NAME: +# SERVER_HOST: +# AUTH_TYPE: +# JSON_LOGGER: + +# --- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: relayer-email-auth + namespace: ar-base-sepolia-staging + labels: + app: relayer +spec: + selector: + matchLabels: + app: relayer + template: + metadata: + labels: + app: relayer + spec: + containers: + - name: relayer-container + image: us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v1 + ports: + - containerPort: 4500 + envFrom: + - configMapRef: + name: relayer-config-email-auth + - secretRef: + name: relayer-secret-email-auth + livenessProbe: + httpGet: + path: /api/echo + port: 4500 + initialDelaySeconds: 60 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /api/echo + port: 4500 + initialDelaySeconds: 60 + periodSeconds: 30 + volumeMounts: + - name: pem-volume + mountPath: '/relayer/packages/relayer/.ic.pem' + subPath: '.ic.pem' + - name: smtp-container + image: bisht13/relayer-smtp-new:latest + ports: + - containerPort: 8080 + envFrom: + - secretRef: + name: relayer-smtp-secret + - name: imap-container + image: bisht13/relayer-imap-new:latest + envFrom: + - secretRef: + name: relayer-imap-secret + volumes: + - name: pem-volume + secret: + secretName: relayer-secret-email-auth + items: + - key: ICPEM + path: '.ic.pem' +# --- +# apiVersion: v1 +# kind: Service +# metadata: +# name: relayer-svc-email-auth +# namespace: ar-base-sepolia-staging +# spec: +# selector: +# app: relayer +# ports: +# - protocol: TCP +# port: 443 +# targetPort: 4500 +# type: ClusterIP + +# --- +# apiVersion: v1 +# kind: Service +# metadata: +# name: relayer-smtp-svc +# namespace: ar-base-sepolia-staging +# spec: +# selector: +# app: relayer +# ports: +# - protocol: TCP +# port: 443 +# targetPort: 8080 +# type: ClusterIP diff --git a/kubernetes/relayer.yml b/kubernetes/relayer.yml index e815f95b..83c3da5f 100644 --- a/kubernetes/relayer.yml +++ b/kubernetes/relayer.yml @@ -6,18 +6,18 @@ metadata: labels: app: relayer data: - EMAIL_ACCOUNT_RECOVERY_VERSION_ID: "" - CHAIN_RPC_PROVIDER: "" - CHAIN_RPC_EXPLORER: "" - CHAIN_ID: "" - WEB_SERVER_ADDRESS: "" - CIRCUITS_DIR_PATH: "" - EMAIL_TEMPLATES_PATH: "" - CANISTER_ID: "" - IC_REPLICA_URL: "" - JSON_LOGGER: "" - PEM_PATH: "" - SMTP_SERVER: "" + EMAIL_ACCOUNT_RECOVERY_VERSION_ID: '' + CHAIN_RPC_PROVIDER: '' + CHAIN_RPC_EXPLORER: '' + CHAIN_ID: '' + WEB_SERVER_ADDRESS: '' + CIRCUITS_DIR_PATH: '' + EMAIL_TEMPLATES_PATH: '' + CANISTER_ID: '' + IC_REPLICA_URL: '' + JSON_LOGGER: '' + PEM_PATH: '' + SMTP_SERVER: '' --- apiVersion: v1 @@ -111,8 +111,8 @@ spec: periodSeconds: 30 volumeMounts: - name: pem-volume - mountPath: "/relayer/packages/relayer/.ic.pem" - subPath: ".ic.pem" + mountPath: '/relayer/packages/relayer/.ic.pem' + subPath: '.ic.pem' - name: smtp-container image: bisht13/relayer-smtp-new:latest ports: @@ -131,7 +131,7 @@ spec: secretName: relayer-secret-email-auth items: - key: ICPEM - path: ".ic.pem" + path: '.ic.pem' --- apiVersion: v1 diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_completeRecovery.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_completeRecovery.t.sol deleted file mode 100644 index 435a403b..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_completeRecovery.t.sol +++ /dev/null @@ -1,265 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_completeRecovery is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function requestGuardian() public { - setUp(); - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - recoveryControllerZKSync.requestGuardian(guardian); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - } - - function handleAcceptance() public { - requestGuardian(); - - console.log("guardian", guardian); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - // acceptGuardian is internal, we call handleAcceptance, which calls acceptGuardian internally. - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.ACCEPTED - ); - } - - function handleRecovery() public { - handleAcceptance(); - - assertEq( - recoveryControllerZKSync.isRecovering(address(simpleWallet)), - false - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount( - address(simpleWallet) - ), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - - assertEq( - recoveryControllerZKSync.isRecovering(address(simpleWallet)), - true - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount( - address(simpleWallet) - ), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - } - - function testCompleteRecovery() public { - skipIfNotZkSync(); - - handleRecovery(); - - assertEq( - recoveryControllerZKSync.isRecovering(address(simpleWallet)), - true - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount( - address(simpleWallet) - ), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - - vm.startPrank(someRelayer); - vm.warp(4 days); - recoveryControllerZKSync.completeRecovery( - address(simpleWallet), - new bytes(0) - ); - vm.stopPrank(); - - assertEq( - recoveryControllerZKSync.isRecovering(address(simpleWallet)), - false - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount( - address(simpleWallet) - ), - 0 - ); - assertEq(simpleWallet.owner(), newSigner); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - } - - function testExpectRevertCompleteRecoveryRecoveryNotInProgress() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq( - recoveryControllerZKSync.isRecovering(address(simpleWallet)), - false - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount( - address(simpleWallet) - ), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - vm.startPrank(someRelayer); - vm.warp(4 days); - vm.expectRevert(bytes("recovery not in progress")); - bytes memory recoveryCalldata; - recoveryControllerZKSync.completeRecovery( - address(simpleWallet), - recoveryCalldata - ); - - vm.stopPrank(); - } - - function testExpectRevertCompleteRecovery() public { - vm.warp(block.timestamp + 3 days); - - handleRecovery(); - - assertEq( - recoveryControllerZKSync.isRecovering(address(simpleWallet)), - true - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount( - address(simpleWallet) - ), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - - vm.warp(0); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("timelock not expired")); - bytes memory recoveryCalldata; - recoveryControllerZKSync.completeRecovery( - address(simpleWallet), - recoveryCalldata - ); - - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleAcceptance.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleAcceptance.t.sol deleted file mode 100644 index fa88af64..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleAcceptance.t.sol +++ /dev/null @@ -1,218 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_handleAcceptance is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function requestGuardian() public { - skipIfNotZkSync(); - - setUp(); - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - recoveryControllerZKSync.requestGuardian(guardian); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - } - - function testHandleAcceptance() public { - skipIfNotZkSync(); - - requestGuardian(); - - console.log("guardian", guardian); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - // acceptGuardian is internal, we call handleAcceptance, which calls acceptGuardian internally. - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.ACCEPTED - ); - } - - // Can not test recovery in progress using handleAcceptance - // Can not test invalid guardian using handleAcceptance - - function testExpectRevertHandleAcceptanceGuardianStatusMustBeRequested() - public - { - skipIfNotZkSync(); - - requestGuardian(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - emailAuthMsg.proof.accountSalt = 0x0; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("guardian status must be REQUESTED")); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - function testExpectRevertHandleAcceptanceInvalidTemplateIndex() public { - skipIfNotZkSync(); - - requestGuardian(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 1; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid template index")); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - function testExpectRevertHandleAcceptanceInvalidcommandParams() public { - skipIfNotZkSync(); - - requestGuardian(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](2); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - commandParamsForAcceptance[1] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid command params")); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - function testExpectRevertHandleAcceptanceInvalidWalletAddressInEmail() - public - { - skipIfNotZkSync(); - - requestGuardian(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(0x0)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid account in email")); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleRecovery.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleRecovery.t.sol deleted file mode 100644 index 288b234f..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_handleRecovery.t.sol +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_handleRecovery is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function requestGuardian() public { - setUp(); - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - recoveryControllerZKSync.requestGuardian(guardian); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - } - - function handleAcceptance() public { - skipIfNotZkSync(); - - requestGuardian(); - - console.log("guardian", guardian); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - // acceptGuardian is internal, we call handleAcceptance, which calls acceptGuardian internally. - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.ACCEPTED - ); - } - - function testHandleRecovery() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), true); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - } - - function testExpectRevertHandleRecoveryGuardianIsNotDeployed() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - emailAuthMsg.proof.accountSalt = 0x0; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("guardian is not deployed")); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - function testExpectRevertHandleRecoveryInvalidTemplateId() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid template id")); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - // Can not test recovery in progress using handleRecovery - // Can not test invalid guardian using handleRecovery - - function testExpectRevertHandleRecoveryGuardianStatusMustBeAccepted() - public - { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - emailAuthMsg.proof.accountSalt = 0x0; - - // vm.mockCall( - // address(simpleWallet.emailAuthImplementationAddr()), - // abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - // abi.encode(0x0) - // ); - - // // Deploy mock guardian, that status is NONE - // address mockCallAddress; - // if(block.chainid == 300) { - // mockCallAddress = address(0x889170C6bEe9053626f8460A9875d22Cf6DE0782); - // } else { - // mockCallAddress = address(0x2Cfb66029975B1c8881adaa3b79c5Caa4FEB84B5); - // } - // vm.mockCall( - // mockCallAddress, - // abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - // abi.encode(0x0) - // ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("guardian is not deployed")); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - function testExpectRevertHandleRecoveryInvalidTemplateIndex() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - uint templateIdx = 1; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid template index")); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - function testExpectRevertHandleRecoveryInvalidcommandParams() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](3); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - commandParamsForRecovery[1] = abi.encode(address(0x0)); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid command params")); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - } - - // function testExpectRevertHandleRecoveryInvalidGuardianInEmail() public { - // handleAcceptance(); - - // assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - // assertEq( - // recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - // 0 - // ); - // assertEq(simpleWallet.owner(), deployer); - // assertEq( - // recoveryControllerZKSync.newSignerCandidateOfAccount(address(simpleWallet)), - // address(0x0) - // ); - // uint templateIdx = 0; - - // EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - // uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId(templateIdx); - // emailAuthMsg.templateId = templateId; - // bytes[] memory commandParamsForRecovery = new bytes[](2); - // commandParamsForRecovery[0] = abi.encode(address(0x0)); - // commandParamsForRecovery[1] = abi.encode(newSigner); - // emailAuthMsg.commandParams = commandParamsForRecovery; - - // vm.mockCall( - // address(recoveryControllerZKSync.emailAuthImplementationAddr()), - // abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - // abi.encode(0x0) - // ); - - // vm.startPrank(someRelayer); - // vm.expectRevert(bytes("invalid guardian in email")); - // recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - // vm.stopPrank(); - // } - - function testExpectRevertHandleRecoveryInvalidNewSigner() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(address(0x0)); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - vm.expectRevert(bytes("invalid new signer")); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_rejectRecovery.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_rejectRecovery.t.sol deleted file mode 100644 index e17c900e..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_rejectRecovery.t.sol +++ /dev/null @@ -1,265 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_rejectRecovery is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - /** - * Set up functions - */ - function requestGuardian() public { - setUp(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - recoveryControllerZKSync.requestGuardian(guardian); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - } - - function handleAcceptance() public { - requestGuardian(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - - console.log("guardian", guardian); - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - bytes[] memory commandParamsForAcceptance = new bytes[](1); - commandParamsForAcceptance[0] = abi.encode(address(simpleWallet)); - emailAuthMsg.commandParams = commandParamsForAcceptance; - address recoveredAccount = recoveryControllerZKSync - .extractRecoveredAccountFromAcceptanceCommand( - emailAuthMsg.commandParams, - templateIdx - ); - address computedGuardian = recoveryControllerZKSync.computeEmailAuthAddress( - recoveredAccount, - emailAuthMsg.proof.accountSalt - ); - console.log("computed guardian", computedGuardian); - uint templateId = recoveryControllerZKSync.computeAcceptanceTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - // acceptGuardian is internal, we call handleAcceptance, which calls acceptGuardian internally. - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleAcceptance(emailAuthMsg, templateIdx); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.ACCEPTED - ); - } - - function handleRecovery() public { - handleAcceptance(); - - assertEq(simpleWallet.owner(), deployer); - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - uint templateIdx = 0; - - EmailAuthMsg memory emailAuthMsg = buildEmailAuthMsg(); - uint templateId = recoveryControllerZKSync.computeRecoveryTemplateId( - templateIdx - ); - emailAuthMsg.templateId = templateId; - bytes[] memory commandParamsForRecovery = new bytes[](2); - commandParamsForRecovery[0] = abi.encode(simpleWallet); - commandParamsForRecovery[1] = abi.encode(newSigner); - emailAuthMsg.commandParams = commandParamsForRecovery; - - vm.mockCall( - address(recoveryControllerZKSync.emailAuthImplementationAddr()), - abi.encodeWithSelector(EmailAuth.authEmail.selector, emailAuthMsg), - abi.encode(0x0) - ); - - vm.startPrank(someRelayer); - recoveryControllerZKSync.handleRecovery(emailAuthMsg, templateIdx); - vm.stopPrank(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), true); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - } - - function testRejectRecovery() public { - skipIfNotZkSync(); - - vm.warp(block.timestamp + 3 days); - - handleRecovery(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), true); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - - vm.warp(0); - - vm.startPrank(address(simpleWallet)); - recoveryControllerZKSync.rejectRecovery(); - vm.stopPrank(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - } - - function testExpectRevertRejectRecoveryRecoveryNotInProgress() public { - skipIfNotZkSync(); - - handleAcceptance(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), false); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - 0 - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - address(0x0) - ); - - vm.startPrank(deployer); - vm.expectRevert(bytes("recovery not in progress")); - recoveryControllerZKSync.rejectRecovery(); - vm.stopPrank(); - } - - function testExpectRevertRejectRecovery() public { - skipIfNotZkSync(); - - vm.warp(block.timestamp + 1 days); - - handleRecovery(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), true); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - - vm.startPrank(address(simpleWallet)); - vm.warp(block.timestamp + 4 days); - vm.expectRevert(bytes("timelock expired")); - recoveryControllerZKSync.rejectRecovery(); - vm.stopPrank(); - } - - function testExpectRevertRejectRecoveryOwnableUnauthorizedAccount() public { - skipIfNotZkSync(); - - handleRecovery(); - - assertEq(recoveryControllerZKSync.isRecovering(address(simpleWallet)), true); - assertEq( - recoveryControllerZKSync.currentTimelockOfAccount(address(simpleWallet)), - block.timestamp + - recoveryControllerZKSync.timelockPeriodOfAccount( - address(simpleWallet) - ) - ); - assertEq(simpleWallet.owner(), deployer); - assertEq( - recoveryControllerZKSync.newSignerCandidateOfAccount( - address(simpleWallet) - ), - newSigner - ); - - vm.startPrank(deployer); - vm.expectRevert("recovery not in progress"); - recoveryControllerZKSync.rejectRecovery(); - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_requestGuardian.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_requestGuardian.t.sol deleted file mode 100644 index 03418653..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_requestGuardian.t.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_requestGuardian is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function testRequestGuardian() public { - skipIfNotZkSync(); - - setUp(); - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - recoveryControllerZKSync.requestGuardian(guardian); - vm.stopPrank(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.REQUESTED - ); - } - - // function testRequestGuardianNotOwner() public { - // setUp(); - - // require( - // recoveryControllerZKSync.guardians(guardian) == - // recoveryControllerZKSync.GuardianStatus.NONE - // ); - - // vm.startPrank(receiver); - // recoveryControllerZKSync.requestGuardian(guardian); - // vm.stopPrank(); - - // require( - // recoveryControllerZKSync.guardians(guardian) == - // recoveryControllerZKSync.GuardianStatus.NONE - // ); - // } - - function testExpectRevertRequestGuardianInvalidGuardian() public { - skipIfNotZkSync(); - - setUp(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - vm.expectRevert(bytes("invalid guardian")); - recoveryControllerZKSync.requestGuardian(address(0x0)); - vm.stopPrank(); - } - - function testExpectRevertRequestGuardianGuardianStatusMustBeNone() public { - skipIfNotZkSync(); - - setUp(); - - require( - recoveryControllerZKSync.guardians(guardian) == - RecoveryControllerZKSync.GuardianStatus.NONE - ); - - vm.startPrank(deployer); - recoveryControllerZKSync.requestGuardian(guardian); - vm.expectRevert(bytes("guardian status must be NONE")); - recoveryControllerZKSync.requestGuardian(guardian); - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_transfer.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_transfer.t.sol deleted file mode 100644 index b784847d..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_transfer.t.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_transfer is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function testTransfer() public { - skipIfNotZkSync(); - - setUp(); - - assertEq(address(simpleWallet).balance, 1 ether); - assertEq(receiver.balance, 0 ether); - - vm.startPrank(deployer); - simpleWallet.transfer(receiver, 1 ether); - vm.stopPrank(); - - assertEq(address(simpleWallet).balance, 0 ether); - assertEq(receiver.balance, 1 ether); - } - - function testExpectRevertTransferOnlyOwner() public { - skipIfNotZkSync(); - - setUp(); - - assertEq(address(simpleWallet).balance, 1 ether); - assertEq(receiver.balance, 0 ether); - - vm.startPrank(receiver); - vm.expectRevert( - abi.encodeWithSelector( - OwnableUpgradeable.OwnableUnauthorizedAccount.selector, - receiver - ) - ); - simpleWallet.transfer(receiver, 1 ether); - vm.stopPrank(); - } - - function testExpectRevertTransferOnlyOwnerInsufficientBalance() public { - skipIfNotZkSync(); - - setUp(); - - assertEq(address(simpleWallet).balance, 1 ether); - assertEq(receiver.balance, 0 ether); - - vm.startPrank(deployer); - assertEq(receiver.balance, 0 ether); - vm.expectRevert(bytes("insufficient balance")); - simpleWallet.transfer(receiver, 2 ether); - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_withdraw.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_withdraw.t.sol deleted file mode 100644 index 07d347d6..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZKSync_withdraw.t.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_withdraw is StructHelper { - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function testWithdraw() public { - skipIfNotZkSync(); - - setUp(); - - assertEq(address(simpleWallet).balance, 1 ether); - assertEq(deployer.balance, 0 ether); - - vm.startPrank(deployer); - simpleWallet.withdraw(1 ether); - vm.stopPrank(); - - assertEq(address(simpleWallet).balance, 0 ether); - assertEq(deployer.balance, 1 ether); - } - - function testExpectRevertWithdrawOnlyOwner() public { - skipIfNotZkSync(); - - setUp(); - - assertEq(address(simpleWallet).balance, 1 ether); - assertEq(deployer.balance, 0 ether); - - vm.startPrank(receiver); - vm.expectRevert( - abi.encodeWithSelector( - OwnableUpgradeable.OwnableUnauthorizedAccount.selector, - address(receiver) - ) - ); - simpleWallet.withdraw(1 ether); - vm.stopPrank(); - } - - function testExpectRevertWithdrawInsufficientBalance() public { - skipIfNotZkSync(); - - setUp(); - - assertEq(address(simpleWallet).balance, 1 ether); - assertEq(deployer.balance, 0 ether); - - vm.startPrank(deployer); - vm.expectRevert(bytes("insufficient balance")); - simpleWallet.withdraw(10 ether); - vm.stopPrank(); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_acceptanceCommandTemplates.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_acceptanceCommandTemplates.t.sol deleted file mode 100644 index 81d9a67c..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_acceptanceCommandTemplates.t.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryControllerZKSync} from "../helpers/RecoveryControllerZKSync.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_acceptanceCommandTemplates is - StructHelper -{ - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function testAcceptanceCommandTemplates() public { - skipIfNotZkSync(); - - setUp(); - string[][] memory res = recoveryController.acceptanceCommandTemplates(); - assertEq(res[0][0], "Accept"); - assertEq(res[0][1], "guardian"); - assertEq(res[0][2], "request"); - assertEq(res[0][3], "for"); - assertEq(res[0][4], "{ethAddr}"); - } -} diff --git a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_recoveryCommandTemplates.t.sol b/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_recoveryCommandTemplates.t.sol deleted file mode 100644 index 62271e43..00000000 --- a/packages/contracts/test/EmailAccountRecoveryZkSync/EmailAccountRecoveryZkSync_recoveryCommandTemplates.t.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {EmailAuth, EmailAuthMsg} from "../../src/EmailAuth.sol"; -import {RecoveryController} from "../helpers/RecoveryController.sol"; -import {StructHelper} from "../helpers/StructHelper.sol"; -import {SimpleWallet} from "../helpers/SimpleWallet.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -contract EmailAccountRecoveryZKSyncTest_recoveryCommandTemplates is - StructHelper -{ - constructor() {} - - function setUp() public override { - super.setUp(); - } - - function testRecoveryCommandTemplates() public { - skipIfNotZkSync(); - - setUp(); - string[][] memory res = recoveryController.recoveryCommandTemplates(); - assertEq(res[0][0], "Set"); - assertEq(res[0][1], "the"); - assertEq(res[0][2], "new"); - assertEq(res[0][3], "signer"); - assertEq(res[0][4], "of"); - assertEq(res[0][5], "{ethAddr}"); - assertEq(res[0][6], "to"); - assertEq(res[0][7], "{ethAddr}"); - } -} From ac511f540d2efdc7a52c195ffb058afaa913b0db Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 13 Sep 2024 17:06:04 +0700 Subject: [PATCH 20/53] Bump relayer version --- cloudbuild-relayer.yaml | 6 +- kubernetes/relayer.staging.yml | 196 ++++++++++++++++----------------- 2 files changed, 102 insertions(+), 100 deletions(-) diff --git a/cloudbuild-relayer.yaml b/cloudbuild-relayer.yaml index 45422673..baab474d 100644 --- a/cloudbuild-relayer.yaml +++ b/cloudbuild-relayer.yaml @@ -1,3 +1,5 @@ +options: + machineType: 'N1_HIGHCPU_32' steps: # Build the base container image - name: 'gcr.io/cloud-builders/docker' @@ -5,7 +7,7 @@ steps: [ 'build', '-t', - 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v1', + 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v2', '-f', 'Relayer.Dockerfile', '.', @@ -15,5 +17,5 @@ steps: args: [ 'push', - 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v1', + 'us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v2', ] diff --git a/kubernetes/relayer.staging.yml b/kubernetes/relayer.staging.yml index 7e97ee50..2c9855bd 100644 --- a/kubernetes/relayer.staging.yml +++ b/kubernetes/relayer.staging.yml @@ -1,76 +1,76 @@ -# apiVersion: v1 -# kind: ConfigMap -# metadata: -# name: relayer-config-email-auth -# namespace: ar-base-sepolia-staging -# labels: -# app: relayer -# data: -# EMAIL_ACCOUNT_RECOVERY_VERSION_ID: '' -# CHAIN_RPC_PROVIDER: '' -# CHAIN_RPC_EXPLORER: '' -# CHAIN_ID: '' -# WEB_SERVER_ADDRESS: '' -# CIRCUITS_DIR_PATH: '' -# EMAIL_TEMPLATES_PATH: '' -# CANISTER_ID: '' -# IC_REPLICA_URL: '' -# JSON_LOGGER: '' -# PEM_PATH: '' -# SMTP_SERVER: '' +apiVersion: v1 +kind: ConfigMap +metadata: + name: relayer-config-email-auth + namespace: ar-base-sepolia-staging + labels: + app: relayer +data: + EMAIL_ACCOUNT_RECOVERY_VERSION_ID: '' + CHAIN_RPC_PROVIDER: '' + CHAIN_RPC_EXPLORER: '' + CHAIN_ID: '' + WEB_SERVER_ADDRESS: '' + CIRCUITS_DIR_PATH: '' + EMAIL_TEMPLATES_PATH: '' + CANISTER_ID: '' + IC_REPLICA_URL: '' + JSON_LOGGER: '' + PEM_PATH: '' + SMTP_SERVER: '' -# --- -# apiVersion: v1 -# kind: Secret -# metadata: -# name: relayer-secret-email-auth -# namespace: ar-base-sepolia-staging -# labels: -# app: relayer -# type: Opaque -# data: -# PRIVATE_KEY: -# DATABASE_URL: -# PROVER_ADDRESS: -# ICPEM: +--- +apiVersion: v1 +kind: Secret +metadata: + name: relayer-secret-email-auth + namespace: ar-base-sepolia-staging + labels: + app: relayer +type: Opaque +data: + PRIVATE_KEY: + DATABASE_URL: + PROVER_ADDRESS: + ICPEM: -# --- -# apiVersion: v1 -# kind: Secret -# metadata: -# name: relayer-smtp-secret -# namespace: ar-base-sepolia-staging -# labels: -# app: relayer -# type: Opaque -# data: -# SMTP_LOGIN_ID: -# SMTP_LOGIN_PASSWORD: -# SMTP_DOMAIN_NAME: -# SERVER_HOST: -# SERVER_PORT: -# JSON_LOGGER: +--- +apiVersion: v1 +kind: Secret +metadata: + name: relayer-smtp-secret + namespace: ar-base-sepolia-staging + labels: + app: relayer +type: Opaque +data: + SMTP_LOGIN_ID: + SMTP_LOGIN_PASSWORD: + SMTP_DOMAIN_NAME: + SERVER_HOST: + SERVER_PORT: + JSON_LOGGER: -# --- -# apiVersion: v1 -# kind: Secret -# metadata: -# name: relayer-imap-secret -# namespace: ar-base-sepolia-staging -# labels: -# app: relayer -# type: Opaque -# data: -# RELAYER_ENDPOINT: -# IMAP_LOGIN_ID: -# IMAP_LOGIN_PASSWORD: -# IMAP_PORT: -# IMAP_DOMAIN_NAME: -# SERVER_HOST: -# AUTH_TYPE: -# JSON_LOGGER: +--- +apiVersion: v1 +kind: Secret +metadata: + name: relayer-imap-secret + namespace: ar-base-sepolia-staging + labels: + app: relayer +type: Opaque +data: + RELAYER_ENDPOINT: + IMAP_LOGIN_ID: + IMAP_LOGIN_PASSWORD: + IMAP_PORT: + IMAP_DOMAIN_NAME: + SERVER_HOST: + AUTH_TYPE: + JSON_LOGGER: -# --- +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -89,7 +89,7 @@ spec: spec: containers: - name: relayer-container - image: us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v1 + image: us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer:v2 ports: - containerPort: 4500 envFrom: @@ -132,32 +132,32 @@ spec: items: - key: ICPEM path: '.ic.pem' -# --- -# apiVersion: v1 -# kind: Service -# metadata: -# name: relayer-svc-email-auth -# namespace: ar-base-sepolia-staging -# spec: -# selector: -# app: relayer -# ports: -# - protocol: TCP -# port: 443 -# targetPort: 4500 -# type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: relayer-svc-email-auth + namespace: ar-base-sepolia-staging +spec: + selector: + app: relayer + ports: + - protocol: TCP + port: 443 + targetPort: 4500 + type: ClusterIP -# --- -# apiVersion: v1 -# kind: Service -# metadata: -# name: relayer-smtp-svc -# namespace: ar-base-sepolia-staging -# spec: -# selector: -# app: relayer -# ports: -# - protocol: TCP -# port: 443 -# targetPort: 8080 -# type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: relayer-smtp-svc + namespace: ar-base-sepolia-staging +spec: + selector: + app: relayer + ports: + - protocol: TCP + port: 443 + targetPort: 8080 + type: ClusterIP From 399126a0488d951d854dcefb97825e28167027bf Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Fri, 13 Sep 2024 15:55:00 +0530 Subject: [PATCH 21/53] fix: add command in email templates --- packages/relayer/eml_templates/acceptance_request.html | 1 + packages/relayer/eml_templates/recovery_request.html | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/relayer/eml_templates/acceptance_request.html b/packages/relayer/eml_templates/acceptance_request.html index 3e0cd15d..6950b8c8 100644 --- a/packages/relayer/eml_templates/acceptance_request.html +++ b/packages/relayer/eml_templates/acceptance_request.html @@ -254,5 +254,6 @@ +
{{command}}
diff --git a/packages/relayer/eml_templates/recovery_request.html b/packages/relayer/eml_templates/recovery_request.html index 48293fee..c9ae4bfc 100644 --- a/packages/relayer/eml_templates/recovery_request.html +++ b/packages/relayer/eml_templates/recovery_request.html @@ -253,5 +253,6 @@ +
{{command}}
From ede8e54bd9ee68c8040b2a87b33bb1a271770ebd Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sat, 14 Sep 2024 10:29:37 +0530 Subject: [PATCH 22/53] feat: add CONTRIBUTING.md & CODING_GUIDELINES.md --- CODING_GUIDELINES.md | 98 +++++++++++++++ CONTRIBUTING.md | 116 ++++++++++++++++++ .../cloudbuild-base.yml | 0 .../cloudbuild-relayer.yml | 0 4 files changed, 214 insertions(+) create mode 100644 CODING_GUIDELINES.md create mode 100644 CONTRIBUTING.md rename cloudbuild-base.yaml => kubernetes/cloudbuild-base.yml (100%) rename cloudbuild-relayer.yaml => kubernetes/cloudbuild-relayer.yml (100%) diff --git a/CODING_GUIDELINES.md b/CODING_GUIDELINES.md new file mode 100644 index 00000000..195805e5 --- /dev/null +++ b/CODING_GUIDELINES.md @@ -0,0 +1,98 @@ +# Coding Guidelines for Relayer Utils + +This document outlines the coding guidelines for contributing to Relayer Utils. Following these guidelines will help maintain a consistent and high-quality codebase. + +## 1. Code Formatting + +- **Tool**: Use `rustfmt` to automatically format your code. Ensure that all code is formatted before committing. Run `cargo fmt` to format your code according to the project's style guidelines. +- **Indentation**: Use 4 spaces per indentation level. Do not use tabs. +- **Line Length**: Aim to keep lines under 100 characters, but it's not a strict rule. Use your judgment to ensure readability. +- **Imports**: Group imports into four sections: `extern crate`, `use`, `use crate`, and `use super`. + - Example: + ```rust + extern crate serde; + + use std::collections::HashMap; + use std::io::{self, Read}; + + use crate::utils::config; + + use super::super::common::logger; + ``` +- **Braces**: Use the Allman style for braces, where the opening brace is on the same line as the function signature. + - Example: + ```rust + fn main() { + // function body + } + ``` +- **Comments**: Use `//` for single-line comments and `/* ... */` for multi-line comments. +- **Whitespace**: Use a single space after commas and colons, and no space before commas and colons. + - Example: + ```rust + let numbers = vec![1, 2, 3]; + let user = User { name: "Alice", age: 30 }; + ``` +- **Function Length**: Aim to keep functions short and focused. If a function is too long, consider breaking it up into smaller functions. +- **Code Duplication**: Avoid duplicating code. If you find yourself copying and pasting code, consider refactoring it into a shared function or module. +- **No warnings**: Ensure that your code compiles without warnings. Fix any warnings before committing. + +## 2. Code Linting + +- **Tool**: Use `cargo clippy` to lint your code and catch common mistakes and improve your Rust code. Run `cargo clippy` before committing your code to ensure it adheres to Rust's best practices and the project's specific requirements. +- **Handling Lints**: Address all warnings and errors reported by `clippy`. If you must ignore a lint, use `#[allow(clippy::lint_name)]` and provide a comment explaining why. + +## 3. Naming Conventions + +- **Variables and Functions**: Use `snake_case`. + - Example: `let user_name = "Alice";` +- **Structs and Enums**: Use `PascalCase`. + - Example: `struct UserAccount { ... }` +- **Constants**: Use `UPPER_SNAKE_CASE`. + - Example: `const MAX_USERS: u32 = 100;` +- **Module Names**: Use `snake_case`. + - Example: `mod user_account;` + +## 4. Documentation + +- **Public Items**: All public functions, structs, and modules must have documentation comments using `///`. + - Example: + ```rust + /// Creates a new user account. + /// + /// # Arguments + /// + /// * `name` - The name of the user. + /// + /// # Returns + /// + /// A `UserAccount` struct. + pub fn create_user_account(name: &str) -> UserAccount { + // function body + } + ``` +- **Private Items**: Document private items where the intent or functionality is not immediately clear. +- **Module Documentation**: Each module should have a comment at the top explaining its purpose. + - Example: + ```rust + //! This module contains utility functions for user management. + + // module contents + ``` + +## 5. Error Handling + +- **Use of `Result` and `Option`**: + - Use `Result` for operations that can fail and `Option` for values that may or may not be present. + - Example: + ```rust + fn find_user(id: u32) -> Option { + // function body + } + + fn open_file(path: &str) -> Result { + // function body + } + ``` +- **Custom Error Types**: When appropriate, define custom error types using `enum` and implement the `anyhow::Error` trait. +- **Error Propagation**: Propagate errors using `?` where possible to simplify error handling. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..39a0dcee --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,116 @@ +# Contributing to Relayer Utils + +Thank you for considering contributing to our project! We welcome contributions of all kinds, including code, documentation, bug reports, feature requests, and more. This document outlines the process for contributing to this project. + +## Table of Contents +- [Contributing to Relayer Utils](#contributing-to-relayer-utils) + - [Table of Contents](#table-of-contents) + - [1. Code of Conduct](#1-code-of-conduct) + - [2. Getting Started](#2-getting-started) + - [3. Coding Guidelines](#3-coding-guidelines) + - [4. Testing](#4-testing) + - [5. Commit Messages](#5-commit-messages) + - [6. Pull Request Process](#6-pull-request-process) + - [7. Contact](#7-contact) + +## 1. Code of Conduct +We are committed to providing a welcoming and inspiring community for all and expect our Code of Conduct to be honored. Anyone who violates this code of conduct may be banned from the community. + +Our community strives to: + +- **Be friendly and patient.** +- **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. +- **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. +- **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. +- **Be careful in the words that you choose**: We are a community of professionals, and we conduct ourselves professionally. +- **Be kind to others**: Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable. + +This includes, but is not limited to: + +- Violent threats or language directed against another person. +- Discriminatory jokes and language. +- Posting sexually explicit or violent material. +- Posting (or threatening to post) other people's personally identifying information ("doxing"). +- Personal insults, especially those using racist or sexist terms. +- Unwelcome sexual attention. +- Advocating for, or encouraging, any of the above behavior. +- Repeated harassment of others. In general, if someone asks you to stop, then stop. + +Moderation + +These are the policies for upholding our community’s standards of conduct. If you feel that a thread needs moderation, please contact the community team at [paradox@pse.dev](mailto:paradox@pse.dev). + +1. **Remarks that violate the Relayer Utils standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed.** (Cursing is allowed, but never targeting another user, and never in a hateful manner.) +2. **Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.** +3. **Moderators will first respond to such remarks with a warning.** +4. **If the warning is unheeded, the user will be “kicked,” i.e., temporarily banned from the community.** +5. **If the user comes back and continues to make trouble, they will be banned permanently from the community.** +6. **Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology.** +7. **If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, in a private discussion.** + +**Please try to emulate these behaviors, especially when debating the merits of different options.** + +Thank you for helping make this a welcoming, friendly community for all. + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) + + +## 2. Getting Started +To start contributing, follow these steps: + +1. Fork the repository. +2. Clone your fork to your local machine: + ```bash + git clone https://github.com/zkemail/relayer-utils.git + ``` +3. Create a new branch for your feature or bugfix: + ```bash + git checkout -b feat/your-feature-name + ``` +4. Install the necessary dependencies: + ```bash + cargo build + ``` +5. Make your changes. + +## 3. Coding Guidelines + +Please follow the coding guidelines in [CODING_GUIDELINES.md](CODING_GUIDELINES.md) when contributing to this project. + +## 4. Testing + +Please write tests for your contributions. We aim for high test coverage. + + • Unit Tests: Place unit tests in the same file as the code they are testing. + • Integration Tests: Place integration tests in the tests/ directory. + +Run all tests before submitting your code with cargo test. + +Run all tests before submitting your code with cargo test. + +## 5. Commit Messages + +Use conventional commit messages for your commits. This helps us automatically generate the changelog and follow semantic versioning. + + • Format: `: ` + • Example: `feat: add new feature` + +For more information, see [Conventional Commits](https://www.conventionalcommits.org/). + +## 6. Pull Request Process + + 1. Ensure your branch is up-to-date with the main branch: + • git fetch origin + • git checkout main + • git merge origin/main + 2. Push your branch to your fork: + • git push origin feature/your-feature-name + 3. Open a pull request from your branch to the main branch of the original repository. + 4. Ensure that your pull request passes all checks (e.g., CI tests). + 5. A reviewer will review your pull request. Be prepared to make adjustments based on feedback. + +## 7. Contact + +If you have any questions or need further assistance, feel free to open an issue or contact us at [paradox@pse.dev](mailto:paradox@pse.dev). + +Thank you for your contributions! \ No newline at end of file diff --git a/cloudbuild-base.yaml b/kubernetes/cloudbuild-base.yml similarity index 100% rename from cloudbuild-base.yaml rename to kubernetes/cloudbuild-base.yml diff --git a/cloudbuild-relayer.yaml b/kubernetes/cloudbuild-relayer.yml similarity index 100% rename from cloudbuild-relayer.yaml rename to kubernetes/cloudbuild-relayer.yml From 0ba5fb15c0063c195d1cb46b43131028d8cc4aae Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sat, 14 Sep 2024 10:35:22 +0530 Subject: [PATCH 23/53] chore: move md files --- CODING_GUIDELINES.md => packages/relayer/CODING_GUIDELINES.md | 0 CONTRIBUTING.md => packages/relayer/CONTRIBUTING.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename CODING_GUIDELINES.md => packages/relayer/CODING_GUIDELINES.md (100%) rename CONTRIBUTING.md => packages/relayer/CONTRIBUTING.md (100%) diff --git a/CODING_GUIDELINES.md b/packages/relayer/CODING_GUIDELINES.md similarity index 100% rename from CODING_GUIDELINES.md rename to packages/relayer/CODING_GUIDELINES.md diff --git a/CONTRIBUTING.md b/packages/relayer/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to packages/relayer/CONTRIBUTING.md From 52a40054424cfe7020013fc7507b9a1d747fb306 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 15 Sep 2024 15:56:39 +0530 Subject: [PATCH 24/53] feat: add github workflows --- .github/workflows/build-test-fmt.yml | 55 --------------------------- .github/workflows/build.yml | 51 +++++++++++++++++++++++++ .github/workflows/clippy.yml | 13 +++++++ .github/workflows/rustfmt.yml | 13 +++++++ .github/workflows/unit-tests.yml | 32 +++++++++++++++- packages/relayer/CODING_GUIDELINES.md | 4 +- packages/relayer/CONTRIBUTING.md | 4 +- 7 files changed, 112 insertions(+), 60 deletions(-) delete mode 100644 .github/workflows/build-test-fmt.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/clippy.yml create mode 100644 .github/workflows/rustfmt.yml diff --git a/.github/workflows/build-test-fmt.yml b/.github/workflows/build-test-fmt.yml deleted file mode 100644 index 17f94353..00000000 --- a/.github/workflows/build-test-fmt.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Build-Test-Fmt - -on: - [push] - -jobs: - build-test-fmt: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - run: rustup show - - - uses: Swatinem/rust-cache@v2 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: "yarn" - - - name: Install dependencies - run: yarn install --frozen-lockfile - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly-0079a1146b79a4aeda58b0258215bedb1f92700b - - - name: Run tests - working-directory: packages/contracts - run: yarn build - - - name: Free Disk Space (Ubuntu) - uses: jlumbroso/free-disk-space@main - with: - # this might remove tools that are actually needed, - # if set to "true" but frees about 6 GB - tool-cache: false - - # all of these default to true, but feel free to set to - # "false" if necessary for your workflow - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - - name: Build - run: cargo build --release - - - name: Test - run: cargo test --release diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..083784e1 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,51 @@ +name: Build-Test-Fmt + +on: [push] + +jobs: + build-test-fmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - run: rustup show + + - uses: Swatinem/rust-cache@v2 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly-0079a1146b79a4aeda58b0258215bedb1f92700b + + - name: Run tests + working-directory: packages/contracts + run: yarn build + + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + # this might remove tools that are actually needed, + # if set to "true" but frees about 6 GB + tool-cache: false + + # all of these default to true, but feel free to set to + # "false" if necessary for your workflow + android: true + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: true + + - name: Build and check for warnings + run: cargo build --release -D warnings diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 00000000..584a0ff3 --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,13 @@ +name: Clippy Lint Check + +on: [pull_request] + +jobs: + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install clippy + run: rustup component add clippy + - name: Run clippy + run: cargo clippy -- -D warnings diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml new file mode 100644 index 00000000..9764b118 --- /dev/null +++ b/.github/workflows/rustfmt.yml @@ -0,0 +1,13 @@ +name: Rustfmt Check + +on: [pull_request] + +jobs: + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install rustfmt + run: rustup component add rustfmt + - name: Check formatting + run: cargo fmt -- --check diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 29740de9..457f42e1 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -47,7 +47,7 @@ jobs: uses: actions/setup-node@v3 with: node-version: 18 - + - name: Install yarn run: npm install -g yarn @@ -62,3 +62,33 @@ jobs: - name: Run tests working-directory: packages/contracts run: yarn test + + relayer: + name: relayer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install yarn + run: npm install -g yarn + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1.2.0 + with: + version: nightly-0079a1146b79a4aeda58b0258215bedb1f92700b + + - name: Forge Build + working-directory: packages/contracts + run: forge build + + - name: Run tests + working-directory: packages/relayer + run: cargo test diff --git a/packages/relayer/CODING_GUIDELINES.md b/packages/relayer/CODING_GUIDELINES.md index 195805e5..93043ca2 100644 --- a/packages/relayer/CODING_GUIDELINES.md +++ b/packages/relayer/CODING_GUIDELINES.md @@ -1,6 +1,6 @@ -# Coding Guidelines for Relayer Utils +# Coding Guidelines for Relayer -This document outlines the coding guidelines for contributing to Relayer Utils. Following these guidelines will help maintain a consistent and high-quality codebase. +This document outlines the coding guidelines for contributing to the Relayer. Following these guidelines will help maintain a consistent and high-quality codebase. ## 1. Code Formatting diff --git a/packages/relayer/CONTRIBUTING.md b/packages/relayer/CONTRIBUTING.md index 39a0dcee..b249c89d 100644 --- a/packages/relayer/CONTRIBUTING.md +++ b/packages/relayer/CONTRIBUTING.md @@ -1,9 +1,9 @@ -# Contributing to Relayer Utils +# Contributing to Relayer Thank you for considering contributing to our project! We welcome contributions of all kinds, including code, documentation, bug reports, feature requests, and more. This document outlines the process for contributing to this project. ## Table of Contents -- [Contributing to Relayer Utils](#contributing-to-relayer-utils) +- [Contributing to Relayer](#contributing-to-relayer) - [Table of Contents](#table-of-contents) - [1. Code of Conduct](#1-code-of-conduct) - [2. Getting Started](#2-getting-started) From b268d72f0d9caf0e084a1a227e3f4b13d240fdda Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 15 Sep 2024 17:38:28 +0530 Subject: [PATCH 25/53] chore: remove abis --- .gitignore | 4 + .../src/abis/ecdsa_owned_dkim_registry.rs | 2333 ------------- .../src/abis/email_account_recovery.rs | 1588 --------- packages/relayer/src/abis/email_auth.rs | 3055 ----------------- 4 files changed, 4 insertions(+), 6976 deletions(-) delete mode 100644 packages/relayer/src/abis/ecdsa_owned_dkim_registry.rs delete mode 100644 packages/relayer/src/abis/email_account_recovery.rs delete mode 100644 packages/relayer/src/abis/email_auth.rs diff --git a/.gitignore b/.gitignore index 1bfbf23a..dd8c2c66 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,10 @@ sql_database.db .sqlx .ic.pem +# ABIs +packages/relayer/src/abis/* +!packages/realyer/src/abis/mod.rs + # Prover packages/prover/build/* packages/prover/params/*.zkey diff --git a/packages/relayer/src/abis/ecdsa_owned_dkim_registry.rs b/packages/relayer/src/abis/ecdsa_owned_dkim_registry.rs deleted file mode 100644 index 98f2b254..00000000 --- a/packages/relayer/src/abis/ecdsa_owned_dkim_registry.rs +++ /dev/null @@ -1,2333 +0,0 @@ -pub use ecdsa_owned_dkim_registry::*; -/// This module was auto-generated with ethers-rs Abigen. -/// More information at: -#[allow( - clippy::enum_variant_names, - clippy::too_many_arguments, - clippy::upper_case_acronyms, - clippy::type_complexity, - dead_code, - non_camel_case_types, -)] -pub mod ecdsa_owned_dkim_registry { - #[allow(deprecated)] - fn __abi() -> ::ethers::core::abi::Abi { - ::ethers::core::abi::ethabi::Contract { - constructor: ::core::option::Option::Some(::ethers::core::abi::ethabi::Constructor { - inputs: ::std::vec![], - }), - functions: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("REVOKE_PREFIX"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("REVOKE_PREFIX"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("SET_PREFIX"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("SET_PREFIX"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("UPGRADE_INTERFACE_VERSION"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "UPGRADE_INTERFACE_VERSION", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("changeSigner"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("changeSigner"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_newSigner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("computeSignedMsg"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("computeSignedMsg"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("prefix"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("selector"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("domainName"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("publicKeyHash"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::Pure, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("dkimRegistry"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("dkimRegistry"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("contract DKIMRegistry"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("initialize"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("initialize"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_initialOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_signer"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("isDKIMPublicKeyHashValid"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "isDKIMPublicKeyHashValid", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("domainName"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("publicKeyHash"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bool"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("owner"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("owner"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("proxiableUUID"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("proxiableUUID"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("renounceOwnership"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("renounceOwnership"), - inputs: ::std::vec![], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("revokeDKIMPublicKeyHash"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "revokeDKIMPublicKeyHash", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("selector"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("domainName"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("publicKeyHash"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("signature"), - kind: ::ethers::core::abi::ethabi::ParamType::Bytes, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("setDKIMPublicKeyHash"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "setDKIMPublicKeyHash", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("selector"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("domainName"), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("publicKeyHash"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("signature"), - kind: ::ethers::core::abi::ethabi::ParamType::Bytes, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("signer"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("signer"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("transferOwnership"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("transferOwnership"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("newOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("upgradeToAndCall"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("upgradeToAndCall"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("newImplementation"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("data"), - kind: ::ethers::core::abi::ethabi::ParamType::Bytes, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::Payable, - }, - ], - ), - ]), - events: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("Initialized"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned("Initialized"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("version"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint(64usize), - indexed: false, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("OwnershipTransferred"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "OwnershipTransferred", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("previousOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("newOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("Upgraded"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned("Upgraded"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("implementation"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ]), - errors: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("AddressEmptyCode"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("AddressEmptyCode"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("target"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ECDSAInvalidSignature"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "ECDSAInvalidSignature", - ), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ECDSAInvalidSignatureLength"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "ECDSAInvalidSignatureLength", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("length"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ECDSAInvalidSignatureS"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "ECDSAInvalidSignatureS", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("s"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ERC1967InvalidImplementation"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "ERC1967InvalidImplementation", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("implementation"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ERC1967NonPayable"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("ERC1967NonPayable"), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("FailedInnerCall"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("FailedInnerCall"), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("InvalidInitialization"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "InvalidInitialization", - ), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("NotInitializing"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("NotInitializing"), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("OwnableInvalidOwner"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "OwnableInvalidOwner", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("owner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("OwnableUnauthorizedAccount"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "OwnableUnauthorizedAccount", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("account"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("StringsInsufficientHexLength"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "StringsInsufficientHexLength", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("value"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("length"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("UUPSUnauthorizedCallContext"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "UUPSUnauthorizedCallContext", - ), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("UUPSUnsupportedProxiableUUID"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "UUPSUnsupportedProxiableUUID", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("slot"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - }, - ], - ), - ]), - receive: false, - fallback: false, - } - } - ///The parsed JSON ABI of the contract. - pub static ECDSAOWNEDDKIMREGISTRY_ABI: ::ethers::contract::Lazy< - ::ethers::core::abi::Abi, - > = ::ethers::contract::Lazy::new(__abi); - #[rustfmt::skip] - const __BYTECODE: &[u8] = b"`\xA0`@R0`\x80R4\x80\x15`\x13W`\0\x80\xFD[P`\x80Qa/~a\0=`\09`\0\x81\x81a\x115\x01R\x81\x81a\x11^\x01Ra\x13\x7F\x01Ra/~`\0\xF3\xFE`\x80`@R`\x046\x10a\0\xF3W`\x005`\xE0\x1C\x80c\x97\x17\x0F+\x11a\0\x8AW\x80c\xD5\x07\xC3 \x11a\0YW\x80c\xD5\x07\xC3 \x14a\x036W\x80c\xE7\xA7\x97z\x14a\x03\x7FW\x80c\xF2\xFD\xE3\x8B\x14a\x03\xAFW\x80c\xF6\xB4\x93D\x14a\x03\xCFW`\0\x80\xFD[\x80c\x97\x17\x0F+\x14a\x02\x8DW\x80c\xAA\xD2\xB7#\x14a\x02\xADW\x80c\xAD<\xB1\xCC\x14a\x02\xCDW\x80c\xAE\xC7\x93a\x14a\x03\x16W`\0\x80\xFD[\x80cR\xD1\x90-\x11a\0\xC6W\x80cR\xD1\x90-\x14a\x01\xDEW\x80cd#\xF1\xE2\x14a\x02\x01W\x80cqP\x18\xA6\x14a\x02.W\x80c\x8D\xA5\xCB[\x14a\x02CW`\0\x80\xFD[\x80c\x07\xF1\xEA\xF5\x14a\0\xF8W\x80c#\x8A\xC93\x14a\x01WW\x80cH\\\xC9U\x14a\x01\xA9W\x80cO\x1E\xF2\x86\x14a\x01\xCBW[`\0\x80\xFD[4\x80\x15a\x01\x04W`\0\x80\xFD[Pa\x01A`@Q\x80`@\x01`@R\x80`\x04\x81R` \x01\x7FSET:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x81V[`@Qa\x01N\x91\x90a\x1F\x9CV[`@Q\x80\x91\x03\x90\xF3[4\x80\x15a\x01cW`\0\x80\xFD[P`\x01Ta\x01\x84\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[`@Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x81R` \x01a\x01NV[4\x80\x15a\x01\xB5W`\0\x80\xFD[Pa\x01\xC9a\x01\xC46`\x04a\x1F\xD8V[a\x03\xEFV[\0[a\x01\xC9a\x01\xD96`\x04a \xEEV[a\x06\x0BV[4\x80\x15a\x01\xEAW`\0\x80\xFD[Pa\x01\xF3a\x06*V[`@Q\x90\x81R` \x01a\x01NV[4\x80\x15a\x02\rW`\0\x80\xFD[P`\0Ta\x01\x84\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[4\x80\x15a\x02:W`\0\x80\xFD[Pa\x01\xC9a\x06YV[4\x80\x15a\x02OW`\0\x80\xFD[P\x7F\x90\x16\xD0\x9Dr\xD4\x0F\xDA\xE2\xFD\x8C\xEA\xC6\xB6#Lw\x06!O\xD3\x9C\x1C\xD1\xE6\t\xA0R\x8C\x19\x93\0Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x01\x84V[4\x80\x15a\x02\x99W`\0\x80\xFD[Pa\x01\xC9a\x02\xA86`\x04a!#\xA9f.\xFC\x9C\"\x9Cj\0\x80Th\x01\0\0\0\0\0\0\0\0\x81\x04`\xFF\x16\x15\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\0\x81\x15\x80\x15a\x04:WP\x82[\x90P`\0\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x01\x14\x80\x15a\x04WWP0;\x15[\x90P\x81\x15\x80\x15a\x04eWP\x80\x15[\x15a\x04\x9CW`@Q\x7F\xF9.\xE8\xA9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[\x84T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\x16`\x01\x17\x85U\x83\x15a\x04\xFDW\x84T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16h\x01\0\0\0\0\0\0\0\0\x17\x85U[a\x05\x06\x87a\x11\x0CV[0`@Qa\x05\x13\x90a\x1F!V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x81R` \x01`@Q\x80\x91\x03\x90`\0\xF0\x80\x15\x80\x15a\x05LW=`\0\x80>=`\0\xFD[P`\0\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x81\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x93\x84\x16\x17\x90\x91U`\x01\x80T\x90\x91\x16\x91\x88\x16\x91\x90\x91\x17\x90U\x83\x15a\x06\x02W\x84T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x85U`@Q`\x01\x81R\x7F\xC7\xF5\x05\xB2\xF3q\xAE!u\xEEI\x13\xF4I\x9E\x1F&3\xA7\xB5\x93c!\xEE\xD1\xCD\xAE\xB6\x11Q\x81\xD2\x90` \x01`@Q\x80\x91\x03\x90\xA1[PPPPPPPV[a\x06\x13a\x11\x1DV[a\x06\x1C\x82a\x12!V[a\x06&\x82\x82a\x12)V[PPV[`\0a\x064a\x13gV[P\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBC\x90V[a\x06aa\x13\xD6V[a\x06k`\0a\x14dV[V[\x83Q`\0\x03a\x06\xDDW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x10`$\x82\x01R\x7FInvalid selector\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01[`@Q\x80\x91\x03\x90\xFD[\x82Q`\0\x03a\x07HW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x13`$\x82\x01R\x7FInvalid domain name\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[\x81a\x07\xAFW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x17`$\x82\x01R\x7FInvalid public key hash\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[a\x07\xB9\x83\x83a\x0C\x1DV[\x15a\x08 W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x1C`$\x82\x01R\x7FpublicKeyHash is already set\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7FB\xD7\xCB\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x84\x90Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90cB\xD7\xCB\x98\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x08\x8FW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\xB3\x91\x90a\"\xD6V[\x15a\t\x1AW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x18`$\x82\x01R\x7FpublicKeyHash is revoked\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0a\t]`@Q\x80`@\x01`@R\x80`\x04\x81R` \x01\x7FSET:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x86\x86\x86a\x0B\xE3V[\x90P`\0a\tj\x82a\x14\xFAV[\x90P`\0a\tx\x82\x85a\x155V[`\x01T\x90\x91Ps\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16\x91\x16\x14a\t\xFFW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x11`$\x82\x01R\x7FInvalid signature\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7F\xC1\\\xFF\xAB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90c\xC1\\\xFF\xAB\x90a\nW\x90\x89\x90\x89\x90`\x04\x01a\"\xF8V[`\0`@Q\x80\x83\x03\x81`\0\x87\x80;\x15\x80\x15a\nqW`\0\x80\xFD[PZ\xF1\x15\x80\x15a\n\x85W=`\0\x80>=`\0\xFD[PPPPPPPPPPPV[a\n\x9Aa\x13\xD6V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\x0B\x17W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x0E`$\x82\x01R\x7FInvalid signer\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\x01Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x81\x16\x90\x82\x16\x03a\x0B\x9CW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x0B`$\x82\x01R\x7FSame signer\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\x01\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[``\x84\x84\x84a\x0B\xF1\x85a\x15_V[`@Q` \x01a\x0C\x04\x94\x93\x92\x91\x90a#\x1AV[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x90P\x94\x93PPPPV[`\0\x80T`@Q\x7F\xE7\xA7\x97z\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90c\xE7\xA7\x97z\x90a\x0Cv\x90\x86\x90\x86\x90`\x04\x01a\"\xF8V[` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x0C\x93W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0C\xB7\x91\x90a\"\xD6V[\x90P[\x92\x91PPV[a\x0C\xC8a\x13\xD6V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\r\x18W`@Q\x7F\x1EO\xBD\xF7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\0`\x04\x82\x01R`$\x01a\x06\xD4V[a\r!\x81a\x14dV[PV[\x83Q`\0\x03a\r\x8FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x10`$\x82\x01R\x7FInvalid selector\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[\x82Q`\0\x03a\r\xFAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x13`$\x82\x01R\x7FInvalid domain name\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[\x81a\x0EaW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x17`$\x82\x01R\x7FInvalid public key hash\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[a\x0Ek\x83\x83a\x0C\x1DV[\x15\x15`\x01\x14a\x0E\xD6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x18`$\x82\x01R\x7FpublicKeyHash is not set\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7FB\xD7\xCB\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x84\x90Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90cB\xD7\xCB\x98\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x0FEW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0Fi\x91\x90a\"\xD6V[\x15a\x0F\xD0W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01\x81\x90R`$\x82\x01R\x7FpublicKeyHash is already revoked`D\x82\x01R`d\x01a\x06\xD4V[`\0a\x10\x13`@Q\x80`@\x01`@R\x80`\x07\x81R` \x01\x7FREVOKE:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x86\x86\x86a\x0B\xE3V[\x90P`\0a\x10 \x82a\x14\xFAV[\x90P`\0a\x10.\x82\x85a\x155V[`\x01T\x90\x91Ps\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16\x91\x16\x14a\x10\xB5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x11`$\x82\x01R\x7FInvalid signature\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7F\x15\xD2Q.\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x87\x90Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90c\x15\xD2Q.\x90`$\x01a\nWV[a\x11\x14a\x15vV[a\r!\x81a\x15\xDDV[0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16\x14\x80a\x11\xEAWP\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x11\xD1\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBCTs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x06kW`@Q\x7F\xE0|\x8D\xBA\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\r!a\x13\xD6V[\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16cR\xD1\x90-`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x92PPP\x80\x15a\x12\xAEWP`@\x80Q`\x1F=\x90\x81\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x82\x01\x90\x92Ra\x12\xAB\x91\x81\x01\x90a$\x1EV[`\x01[a\x12\xFCW`@Q\x7FL\x9C\x8C\xE3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x16`\x04\x82\x01R`$\x01a\x06\xD4V[\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBC\x81\x14a\x13XW`@Q\x7F\xAA\x1DI\xA4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x82\x90R`$\x01a\x06\xD4V[a\x13b\x83\x83a\x15\xE5V[PPPV[0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16\x14a\x06kW`@Q\x7F\xE0|\x8D\xBA\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[3a\x14\x15\x7F\x90\x16\xD0\x9Dr\xD4\x0F\xDA\xE2\xFD\x8C\xEA\xC6\xB6#Lw\x06!O\xD3\x9C\x1C\xD1\xE6\t\xA0R\x8C\x19\x93\0Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x06kW`@Q\x7F\x11\x8C\xDA\xA7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R3`\x04\x82\x01R`$\x01a\x06\xD4V[\x7F\x90\x16\xD0\x9Dr\xD4\x0F\xDA\xE2\xFD\x8C\xEA\xC6\xB6#Lw\x06!O\xD3\x9C\x1C\xD1\xE6\t\xA0R\x8C\x19\x93\0\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x81\x16\x91\x82\x17\x84U`@Q\x92\x16\x91\x82\x90\x7F\x8B\xE0\x07\x9CS\x16Y\x14\x13D\xCD\x1F\xD0\xA4\xF2\x84\x19I\x7F\x97\"\xA3\xDA\xAF\xE3\xB4\x18okdW\xE0\x90`\0\x90\xA3PPPV[`\0a\x15\x06\x82Qa\x16HV[\x82`@Q` \x01a\x15\x18\x92\x91\x90a$7V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90P\x91\x90PV[`\0\x80`\0\x80a\x15E\x86\x86a\x17\x06V[\x92P\x92P\x92Pa\x15U\x82\x82a\x17SV[P\x90\x94\x93PPPPV[``a\x0C\xBA\x82a\x15n\x84a\x18WV[`\x01\x01a\x18\xC1V[\x7F\xF0\xC5~\x16\x84\r\xF0@\xF1P\x88\xDC/\x81\xFE9\x1C9#\xBE\xC7>#\xA9f.\xFC\x9C\"\x9Cj\0Th\x01\0\0\0\0\0\0\0\0\x90\x04`\xFF\x16a\x06kW`@Q\x7F\xD7\xE6\xBC\xF8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\x0C\xC8a\x15vV[a\x15\xEE\x82a\x1A\xE7V[`@Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x16\x90\x7F\xBC|\xD7Z \xEE'\xFD\x9A\xDE\xBA\xB3 A\xF7U!M\xBCk\xFF\xA9\x0C\xC0\"[9\xDA.\\-;\x90`\0\x90\xA2\x80Q\x15a\x16@Wa\x13b\x82\x82a\x1B\xB6V[a\x06&a\x1C9V[```\0a\x16U\x83a\x1CqV[`\x01\x01\x90P`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x16uWa\x16ua \x0BV[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x16\x9FW` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x81\x81\x01` \x01[\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01\x7F0123456789abcdef\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\n\x86\x06\x1A\x81S`\n\x85\x04\x94P\x84a\x16\xA9WP\x93\x92PPPV[`\0\x80`\0\x83Q`A\x03a\x17@W` \x84\x01Q`@\x85\x01Q``\x86\x01Q`\0\x1Aa\x172\x88\x82\x85\x85a\x1DSV[\x95P\x95P\x95PPPPa\x17LV[PP\x81Q`\0\x91P`\x02\x90[\x92P\x92P\x92V[`\0\x82`\x03\x81\x11\x15a\x17gWa\x17ga$\x92V[\x03a\x17pWPPV[`\x01\x82`\x03\x81\x11\x15a\x17\x84Wa\x17\x84a$\x92V[\x03a\x17\xBBW`@Q\x7F\xF6E\xEE\xDF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\x02\x82`\x03\x81\x11\x15a\x17\xCFWa\x17\xCFa$\x92V[\x03a\x18\tW`@Q\x7F\xFC\xE6\x98\xF7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x82\x90R`$\x01a\x06\xD4V[`\x03\x82`\x03\x81\x11\x15a\x18\x1DWa\x18\x1Da$\x92V[\x03a\x06&W`@Q\x7F\xD7\x8B\xCE\x0C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x82\x90R`$\x01a\x06\xD4V[`\0\x80`\x80\x83\x90\x1C\x15a\x18oW`\x80\x92\x90\x92\x1C\x91`\x10\x01[`@\x83\x90\x1C\x15a\x18\x84W`@\x92\x90\x92\x1C\x91`\x08\x01[` \x83\x90\x1C\x15a\x18\x99W` \x92\x90\x92\x1C\x91`\x04\x01[`\x10\x83\x90\x1C\x15a\x18\xAEW`\x10\x92\x90\x92\x1C\x91`\x02\x01[`\x08\x83\x90\x1C\x15a\x0C\xBAW`\x01\x01\x92\x91PPV[``\x82`\0a\x18\xD1\x84`\x02a$\xF0V[a\x18\xDC\x90`\x02a%\x07V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x18\xF4Wa\x18\xF4a \x0BV[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x19\x1EW` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x7F0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81`\0\x81Q\x81\x10a\x19UWa\x19Ua%\x1AV[` \x01\x01\x90~\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x90\x81`\0\x1A\x90SP\x7Fx\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81`\x01\x81Q\x81\x10a\x19\xB8Wa\x19\xB8a%\x1AV[` \x01\x01\x90~\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x90\x81`\0\x1A\x90SP`\0a\x19\xF4\x85`\x02a$\xF0V[a\x19\xFF\x90`\x01a%\x07V[\x90P[`\x01\x81\x11\x15a\x1A\x9CW\x7F0123456789abcdef\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x83`\x0F\x16`\x10\x81\x10a\x1A@Wa\x1A@a%\x1AV[\x1A`\xF8\x1B\x82\x82\x81Q\x81\x10a\x1AVWa\x1AVa%\x1AV[` \x01\x01\x90~\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x90\x81`\0\x1A\x90SP`\x04\x92\x90\x92\x1C\x91a\x1A\x95\x81a%IV[\x90Pa\x1A\x02V[P\x81\x15a\x1A\xDFW`@Q\x7F\xE2.'\xEB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x86\x90R`$\x81\x01\x85\x90R`D\x01a\x06\xD4V[\x94\x93PPPPV[\x80s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16;`\0\x03a\x1BPW`@Q\x7FL\x9C\x8C\xE3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16`\x04\x82\x01R`$\x01a\x06\xD4V[\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBC\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[```\0\x80\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`@Qa\x1B\xE0\x91\x90a%~V[`\0`@Q\x80\x83\x03\x81\x85Z\xF4\x91PP=\x80`\0\x81\x14a\x1C\x1BW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x1C V[``\x91P[P\x91P\x91Pa\x1C0\x85\x83\x83a\x1EMV[\x95\x94PPPPPV[4\x15a\x06kW`@Q\x7F\xB3\x98\x97\x9F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\0\x80z\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01\0\0\0\0\0\0\0\0\x83\x10a\x1C\xBAWz\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01\0\0\0\0\0\0\0\0\x83\x04\x92P`@\x01[m\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x10a\x1C\xE6Wm\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x04\x92P` \x01[f#\x86\xF2o\xC1\0\0\x83\x10a\x1D\x04Wf#\x86\xF2o\xC1\0\0\x83\x04\x92P`\x10\x01[c\x05\xF5\xE1\0\x83\x10a\x1D\x1CWc\x05\xF5\xE1\0\x83\x04\x92P`\x08\x01[a'\x10\x83\x10a\x1D0Wa'\x10\x83\x04\x92P`\x04\x01[`d\x83\x10a\x1DBW`d\x83\x04\x92P`\x02\x01[`\n\x83\x10a\x0C\xBAW`\x01\x01\x92\x91PPV[`\0\x80\x80\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF]WnsW\xA4P\x1D\xDF\xE9/Fh\x1B \xA0\x84\x11\x15a\x1D\x8EWP`\0\x91P`\x03\x90P\x82a\x1ECV[`@\x80Q`\0\x80\x82R` \x82\x01\x80\x84R\x8A\x90R`\xFF\x89\x16\x92\x82\x01\x92\x90\x92R``\x81\x01\x87\x90R`\x80\x81\x01\x86\x90R`\x01\x90`\xA0\x01` `@Q` \x81\x03\x90\x80\x84\x03\x90\x85Z\xFA\x15\x80\x15a\x1D\xE2W=`\0\x80>=`\0\xFD[PP`@Q\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x01Q\x91PPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\x1E9WP`\0\x92P`\x01\x91P\x82\x90Pa\x1ECV[\x92P`\0\x91P\x81\x90P[\x94P\x94P\x94\x91PPV[``\x82a\x1EbWa\x1E]\x82a\x1E\xDFV[a\x1E\xD8V[\x81Q\x15\x80\x15a\x1E\x86WPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16;\x15[\x15a\x1E\xD5W`@Q\x7F\x99\x96\xB3\x15\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x85\x16`\x04\x82\x01R`$\x01a\x06\xD4V[P\x80[\x93\x92PPPV[\x80Q\x15a\x1E\xEFW\x80Q\x80\x82` \x01\xFD[`@Q\x7F\x14%\xEAB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\t\xAE\x80a%\x9B\x839\x01\x90V[`\0[\x83\x81\x10\x15a\x1FIW\x81\x81\x01Q\x83\x82\x01R` \x01a\x1F1V[PP`\0\x91\x01RV[`\0\x81Q\x80\x84Ra\x1Fj\x81` \x86\x01` \x86\x01a\x1F.V[`\x1F\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x92\x90\x92\x01` \x01\x92\x91PPV[` \x81R`\0a\x0C\xB7` \x83\x01\x84a\x1FRV[\x805s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x1F\xD3W`\0\x80\xFD[\x91\x90PV[`\0\x80`@\x83\x85\x03\x12\x15a\x1F\xEBW`\0\x80\xFD[a\x1F\xF4\x83a\x1F\xAFV[\x91Pa \x02` \x84\x01a\x1F\xAFV[\x90P\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`A`\x04R`$`\0\xFD[`\0\x82`\x1F\x83\x01\x12a KW`\0\x80\xFD[\x815` \x83\x01`\0\x80g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11\x15a lWa la \x0BV[P`@Q\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0`\x1F\x85\x01\x81\x16`?\x01\x16\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a \xB9Wa \xB9a \x0BV[`@R\x83\x81R\x90P\x80\x82\x84\x01\x87\x10\x15a \xD1W`\0\x80\xFD[\x83\x83` \x83\x017`\0` \x85\x83\x01\x01R\x80\x94PPPPP\x92\x91PPV[`\0\x80`@\x83\x85\x03\x12\x15a!\x01W`\0\x80\xFD[a!\n\x83a\x1F\xAFV[\x91P` \x83\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!&W`\0\x80\xFD[a!2\x85\x82\x86\x01a :V[\x91PP\x92P\x92\x90PV[`\0\x80`\0\x80`\x80\x85\x87\x03\x12\x15a!RW`\0\x80\xFD[\x845g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!iW`\0\x80\xFD[a!u\x87\x82\x88\x01a :V[\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!\x92W`\0\x80\xFD[a!\x9E\x87\x82\x88\x01a :V[\x93PP`@\x85\x015\x91P``\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!\xC2W`\0\x80\xFD[a!\xCE\x87\x82\x88\x01a :V[\x91PP\x92\x95\x91\x94P\x92PV[`\0` \x82\x84\x03\x12\x15a!\xECW`\0\x80\xFD[a\x0C\xB7\x82a\x1F\xAFV[`\0\x80`\0\x80`\x80\x85\x87\x03\x12\x15a\"\x0BW`\0\x80\xFD[\x845g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"\"W`\0\x80\xFD[a\".\x87\x82\x88\x01a :V[\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"KW`\0\x80\xFD[a\"W\x87\x82\x88\x01a :V[\x93PP`@\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"tW`\0\x80\xFD[a\"\x80\x87\x82\x88\x01a :V[\x94\x97\x93\x96P\x93\x94``\x015\x93PPPV[`\0\x80`@\x83\x85\x03\x12\x15a\"\xA4W`\0\x80\xFD[\x825g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"\xBBW`\0\x80\xFD[a\"\xC7\x85\x82\x86\x01a :V[\x95` \x94\x90\x94\x015\x94PPPPV[`\0` \x82\x84\x03\x12\x15a\"\xE8W`\0\x80\xFD[\x81Q\x80\x15\x15\x81\x14a\x1E\xD8W`\0\x80\xFD[`@\x81R`\0a#\x0B`@\x83\x01\x85a\x1FRV[\x90P\x82` \x83\x01R\x93\x92PPPV[`\0\x85Qa#,\x81\x84` \x8A\x01a\x1F.V[\x7Fselector=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x83\x01\x90\x81R\x85Qa#f\x81`\t\x84\x01` \x8A\x01a\x1F.V[\x7F;domain=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\t\x92\x90\x91\x01\x91\x82\x01R\x84Qa#\xA4\x81`\x11\x84\x01` \x89\x01a\x1F.V[`\t\x81\x83\x01\x01\x91PP\x7F;public_key_hash=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\x08\x82\x01R\x83Qa#\xE6\x81`\x19\x84\x01` \x88\x01a\x1F.V[\x7F;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\x19\x92\x90\x91\x01\x91\x82\x01R`\x1A\x01\x96\x95PPPPPPV[`\0` \x82\x84\x03\x12\x15a$0W`\0\x80\xFD[PQ\x91\x90PV[\x7F\x19Ethereum Signed Message:\n\0\0\0\0\0\0\x81R`\0\x83Qa$o\x81`\x1A\x85\x01` \x88\x01a\x1F.V[\x83Q\x90\x83\x01\x90a$\x86\x81`\x1A\x84\x01` \x88\x01a\x1F.V[\x01`\x1A\x01\x94\x93PPPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`!`\x04R`$`\0\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\x11`\x04R`$`\0\xFD[\x80\x82\x02\x81\x15\x82\x82\x04\x84\x14\x17a\x0C\xBAWa\x0C\xBAa$\xC1V[\x80\x82\x01\x80\x82\x11\x15a\x0C\xBAWa\x0C\xBAa$\xC1V[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`2`\x04R`$`\0\xFD[`\0\x81a%XWa%Xa$\xC1V[P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01\x90V[`\0\x82Qa%\x90\x81\x84` \x87\x01a\x1F.V[\x91\x90\x91\x01\x92\x91PPV\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`@Qa\t\xAE8\x03\x80a\t\xAE\x839\x81\x01`@\x81\x90Ra\0/\x91a\0\xBEV[\x80`\x01`\x01`\xA0\x1B\x03\x81\x16a\0^W`@Qc\x1EO\xBD\xF7`\xE0\x1B\x81R`\0`\x04\x82\x01R`$\x01`@Q\x80\x91\x03\x90\xFD[a\0g\x81a\0nV[PPa\0\xEEV[`\0\x80T`\x01`\x01`\xA0\x1B\x03\x83\x81\x16`\x01`\x01`\xA0\x1B\x03\x19\x83\x16\x81\x17\x84U`@Q\x91\x90\x92\x16\x92\x83\x91\x7F\x8B\xE0\x07\x9CS\x16Y\x14\x13D\xCD\x1F\xD0\xA4\xF2\x84\x19I\x7F\x97\"\xA3\xDA\xAF\xE3\xB4\x18okdW\xE0\x91\x90\xA3PPV[`\0` \x82\x84\x03\x12\x15a\0\xD0W`\0\x80\xFD[\x81Q`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\0\xE7W`\0\x80\xFD[\x93\x92PPPV[a\x08\xB1\x80a\0\xFD`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\0\xA3W`\x005`\xE0\x1C\x80c\x8D\xA5\xCB[\x11a\0vW\x80c\xE7\xA7\x97z\x11a\0[W\x80c\xE7\xA7\x97z\x14a\x01vW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x89W\x80c\xF4\x9E\xB1d\x14a\x01\x9CW`\0\x80\xFD[\x80c\x8D\xA5\xCB[\x14a\x01;W\x80c\xC1\\\xFF\xAB\x14a\x01cW`\0\x80\xFD[\x80c\x06\x90\xBD8\x14a\0\xA8W\x80c\x15\xD2Q.\x14a\0\xFBW\x80cB\xD7\xCB\x98\x14a\x01\x10W\x80cqP\x18\xA6\x14a\x013W[`\0\x80\xFD[a\0\xE6a\0\xB66`\x04a\x069V[\x81Q` \x81\x84\x01\x81\x01\x80Q`\x01\x82R\x92\x82\x01\x94\x82\x01\x94\x90\x94 \x91\x90\x93R\x90\x91R`\0\x90\x81R`@\x90 T`\xFF\x16\x81V[`@Q\x90\x15\x15\x81R` \x01[`@Q\x80\x91\x03\x90\xF3[a\x01\x0Ea\x01\t6`\x04a\x06~V[a\x01\xAFV[\0[a\0\xE6a\x01\x1E6`\x04a\x06~V[`\x02` R`\0\x90\x81R`@\x90 T`\xFF\x16\x81V[a\x01\x0Ea\x02+V[`\0T`@Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x81R` \x01a\0\xF2V[a\x01\x0Ea\x01q6`\x04a\x069V[a\x02?V[a\0\xE6a\x01\x846`\x04a\x069V[a\x03YV[a\x01\x0Ea\x01\x976`\x04a\x06\x97V[a\x03\xBDV[a\x01\x0Ea\x01\xAA6`\x04a\x06\xD4V[a\x04!V[a\x01\xB7a\x04eV[`\0\x81\x81R`\x02` R`@\x90\x81\x90 \x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x16`\x01\x17\x90UQ\x7F\xB8\x0F\xFF+Lo=\xDF\x80Hw\x92|w\xB2\xFE\x18q\xCE\xCA\xA5\xADC\xD2\xC7\xC4/As1\xF8e\x90a\x02 \x90\x83\x81R` \x01\x90V[`@Q\x80\x91\x03\x90\xA1PV[a\x023a\x04eV[a\x02=`\0a\x04\xB8V[V[a\x02Ga\x04eV[`\0\x81\x81R`\x02` R`@\x90 T`\xFF\x16\x15a\x02\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x19`$\x82\x01R\x7Fcannot set revoked pubkey\0\0\0\0\0\0\0`D\x82\x01R`d\x01[`@Q\x80\x91\x03\x90\xFD[`\x01\x80\x83`@Qa\x02\xD6\x91\x90a\x07\xD7V[\x90\x81R`@\x80Q` \x92\x81\x90\x03\x83\x01\x81 `\0\x86\x81R\x93R\x91 \x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x16\x92\x15\x15\x92\x90\x92\x17\x90\x91U\x7FQ\r\xAC\x88\xEA\xF2\xDF\xBDS\x90BA\xFC\x19\x9A\xD4k c\xE6\xBFl?\xB2\x91\xF8\xCE\x86Cf4\x19\x90a\x03M\x90\x84\x90\x84\x90a\x07\xF3V[`@Q\x80\x91\x03\x90\xA1PPV[`\0\x81\x81R`\x02` R`@\x81 T`\xFF\x16\x15a\x03xWP`\0a\x03\xB7V[`\x01\x83`@Qa\x03\x88\x91\x90a\x07\xD7V[\x90\x81R`@\x80Q` \x92\x81\x90\x03\x83\x01\x90 `\0\x85\x81R\x92R\x90 T`\xFF\x16\x15a\x03\xB3WP`\x01a\x03\xB7V[P`\0[\x92\x91PPV[a\x03\xC5a\x04eV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\x04\x15W`@Q\x7F\x1EO\xBD\xF7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\0`\x04\x82\x01R`$\x01a\x02\xBCV[a\x04\x1E\x81a\x04\xB8V[PV[a\x04)a\x04eV[`\0[\x81Q\x81\x10\x15a\x04`Wa\x04X\x83\x83\x83\x81Q\x81\x10a\x04KWa\x04Ka\x08LV[` \x02` \x01\x01Qa\x02?V[`\x01\x01a\x04,V[PPPV[`\0Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163\x14a\x02=W`@Q\x7F\x11\x8C\xDA\xA7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R3`\x04\x82\x01R`$\x01a\x02\xBCV[`\0\x80Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x16\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x83\x16\x81\x17\x84U`@Q\x91\x90\x92\x16\x92\x83\x91\x7F\x8B\xE0\x07\x9CS\x16Y\x14\x13D\xCD\x1F\xD0\xA4\xF2\x84\x19I\x7F\x97\"\xA3\xDA\xAF\xE3\xB4\x18okdW\xE0\x91\x90\xA3PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`A`\x04R`$`\0\xFD[`@Q`\x1F\x82\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x81\x01g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x82\x82\x10\x17\x15a\x05\xA3Wa\x05\xA3a\x05-V[`@R\x91\x90PV[`\0\x82`\x1F\x83\x01\x12a\x05\xBCW`\0\x80\xFD[\x815g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x05\xD6Wa\x05\xD6a\x05-V[a\x06\x07` \x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0`\x1F\x84\x01\x16\x01a\x05\\V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x06\x1CW`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[`\0\x80`@\x83\x85\x03\x12\x15a\x06LW`\0\x80\xFD[\x825g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06cW`\0\x80\xFD[a\x06o\x85\x82\x86\x01a\x05\xABV[\x95` \x94\x90\x94\x015\x94PPPPV[`\0` \x82\x84\x03\x12\x15a\x06\x90W`\0\x80\xFD[P5\x91\x90PV[`\0` \x82\x84\x03\x12\x15a\x06\xA9W`\0\x80\xFD[\x815s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x06\xCDW`\0\x80\xFD[\x93\x92PPPV[`\0\x80`@\x83\x85\x03\x12\x15a\x06\xE7W`\0\x80\xFD[\x825g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06\xFEW`\0\x80\xFD[a\x07\n\x85\x82\x86\x01a\x05\xABV[\x92PP` \x83\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07'W`\0\x80\xFD[\x83\x01`\x1F\x81\x01\x85\x13a\x078W`\0\x80\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07RWa\x07Ra\x05-V[\x80`\x05\x1Ba\x07b` \x82\x01a\x05\\V[\x91\x82R` \x81\x84\x01\x81\x01\x92\x90\x81\x01\x90\x88\x84\x11\x15a\x07~W`\0\x80\xFD[` \x85\x01\x94P[\x83\x85\x10\x15a\x07\xA4W\x845\x80\x83R` \x95\x86\x01\x95\x90\x93P\x90\x91\x01\x90a\x07\x85V[\x80\x95PPPPPP\x92P\x92\x90PV[`\0[\x83\x81\x10\x15a\x07\xCEW\x81\x81\x01Q\x83\x82\x01R` \x01a\x07\xB6V[PP`\0\x91\x01RV[`\0\x82Qa\x07\xE9\x81\x84` \x87\x01a\x07\xB3V[\x91\x90\x91\x01\x92\x91PPV[`@\x81R`\0\x83Q\x80`@\x84\x01Ra\x08\x12\x81``\x85\x01` \x88\x01a\x07\xB3V[` \x83\x01\x93\x90\x93RP`\x1F\x91\x90\x91\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x01``\x01\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`2`\x04R`$`\0\xFD\xFE\xA2dipfsX\"\x12 -\x9Ee\xDAg\xA8\x9E\x94XP\xBB\xE47ClV\x95\xD85 \x14\x95XA\xAAs\xAA\x1C\xC4\x15\xD3IdsolcC\0\x08\x1A\x003\xA2dipfsX\"\x12 \x0E[\xF6h\xD37\xAE[\x83m\x7F\x86So\xD0\x05\xCE\xD9Ui~\xD1\xF0\x7F\xC3\xF4C\xC1b\xFE\x136dsolcC\0\x08\x1A\x003"; - /// The bytecode of the contract. - pub static ECDSAOWNEDDKIMREGISTRY_BYTECODE: ::ethers::core::types::Bytes = ::ethers::core::types::Bytes::from_static( - __BYTECODE, - ); - #[rustfmt::skip] - const __DEPLOYED_BYTECODE: &[u8] = b"`\x80`@R`\x046\x10a\0\xF3W`\x005`\xE0\x1C\x80c\x97\x17\x0F+\x11a\0\x8AW\x80c\xD5\x07\xC3 \x11a\0YW\x80c\xD5\x07\xC3 \x14a\x036W\x80c\xE7\xA7\x97z\x14a\x03\x7FW\x80c\xF2\xFD\xE3\x8B\x14a\x03\xAFW\x80c\xF6\xB4\x93D\x14a\x03\xCFW`\0\x80\xFD[\x80c\x97\x17\x0F+\x14a\x02\x8DW\x80c\xAA\xD2\xB7#\x14a\x02\xADW\x80c\xAD<\xB1\xCC\x14a\x02\xCDW\x80c\xAE\xC7\x93a\x14a\x03\x16W`\0\x80\xFD[\x80cR\xD1\x90-\x11a\0\xC6W\x80cR\xD1\x90-\x14a\x01\xDEW\x80cd#\xF1\xE2\x14a\x02\x01W\x80cqP\x18\xA6\x14a\x02.W\x80c\x8D\xA5\xCB[\x14a\x02CW`\0\x80\xFD[\x80c\x07\xF1\xEA\xF5\x14a\0\xF8W\x80c#\x8A\xC93\x14a\x01WW\x80cH\\\xC9U\x14a\x01\xA9W\x80cO\x1E\xF2\x86\x14a\x01\xCBW[`\0\x80\xFD[4\x80\x15a\x01\x04W`\0\x80\xFD[Pa\x01A`@Q\x80`@\x01`@R\x80`\x04\x81R` \x01\x7FSET:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x81V[`@Qa\x01N\x91\x90a\x1F\x9CV[`@Q\x80\x91\x03\x90\xF3[4\x80\x15a\x01cW`\0\x80\xFD[P`\x01Ta\x01\x84\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[`@Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x81R` \x01a\x01NV[4\x80\x15a\x01\xB5W`\0\x80\xFD[Pa\x01\xC9a\x01\xC46`\x04a\x1F\xD8V[a\x03\xEFV[\0[a\x01\xC9a\x01\xD96`\x04a \xEEV[a\x06\x0BV[4\x80\x15a\x01\xEAW`\0\x80\xFD[Pa\x01\xF3a\x06*V[`@Q\x90\x81R` \x01a\x01NV[4\x80\x15a\x02\rW`\0\x80\xFD[P`\0Ta\x01\x84\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[4\x80\x15a\x02:W`\0\x80\xFD[Pa\x01\xC9a\x06YV[4\x80\x15a\x02OW`\0\x80\xFD[P\x7F\x90\x16\xD0\x9Dr\xD4\x0F\xDA\xE2\xFD\x8C\xEA\xC6\xB6#Lw\x06!O\xD3\x9C\x1C\xD1\xE6\t\xA0R\x8C\x19\x93\0Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x01\x84V[4\x80\x15a\x02\x99W`\0\x80\xFD[Pa\x01\xC9a\x02\xA86`\x04a!#\xA9f.\xFC\x9C\"\x9Cj\0\x80Th\x01\0\0\0\0\0\0\0\0\x81\x04`\xFF\x16\x15\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\0\x81\x15\x80\x15a\x04:WP\x82[\x90P`\0\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x01\x14\x80\x15a\x04WWP0;\x15[\x90P\x81\x15\x80\x15a\x04eWP\x80\x15[\x15a\x04\x9CW`@Q\x7F\xF9.\xE8\xA9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[\x84T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\x16`\x01\x17\x85U\x83\x15a\x04\xFDW\x84T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16h\x01\0\0\0\0\0\0\0\0\x17\x85U[a\x05\x06\x87a\x11\x0CV[0`@Qa\x05\x13\x90a\x1F!V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x81R` \x01`@Q\x80\x91\x03\x90`\0\xF0\x80\x15\x80\x15a\x05LW=`\0\x80>=`\0\xFD[P`\0\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x81\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x93\x84\x16\x17\x90\x91U`\x01\x80T\x90\x91\x16\x91\x88\x16\x91\x90\x91\x17\x90U\x83\x15a\x06\x02W\x84T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x85U`@Q`\x01\x81R\x7F\xC7\xF5\x05\xB2\xF3q\xAE!u\xEEI\x13\xF4I\x9E\x1F&3\xA7\xB5\x93c!\xEE\xD1\xCD\xAE\xB6\x11Q\x81\xD2\x90` \x01`@Q\x80\x91\x03\x90\xA1[PPPPPPPV[a\x06\x13a\x11\x1DV[a\x06\x1C\x82a\x12!V[a\x06&\x82\x82a\x12)V[PPV[`\0a\x064a\x13gV[P\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBC\x90V[a\x06aa\x13\xD6V[a\x06k`\0a\x14dV[V[\x83Q`\0\x03a\x06\xDDW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x10`$\x82\x01R\x7FInvalid selector\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01[`@Q\x80\x91\x03\x90\xFD[\x82Q`\0\x03a\x07HW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x13`$\x82\x01R\x7FInvalid domain name\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[\x81a\x07\xAFW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x17`$\x82\x01R\x7FInvalid public key hash\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[a\x07\xB9\x83\x83a\x0C\x1DV[\x15a\x08 W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x1C`$\x82\x01R\x7FpublicKeyHash is already set\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7FB\xD7\xCB\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x84\x90Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90cB\xD7\xCB\x98\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x08\x8FW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\xB3\x91\x90a\"\xD6V[\x15a\t\x1AW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x18`$\x82\x01R\x7FpublicKeyHash is revoked\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0a\t]`@Q\x80`@\x01`@R\x80`\x04\x81R` \x01\x7FSET:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x86\x86\x86a\x0B\xE3V[\x90P`\0a\tj\x82a\x14\xFAV[\x90P`\0a\tx\x82\x85a\x155V[`\x01T\x90\x91Ps\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16\x91\x16\x14a\t\xFFW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x11`$\x82\x01R\x7FInvalid signature\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7F\xC1\\\xFF\xAB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90c\xC1\\\xFF\xAB\x90a\nW\x90\x89\x90\x89\x90`\x04\x01a\"\xF8V[`\0`@Q\x80\x83\x03\x81`\0\x87\x80;\x15\x80\x15a\nqW`\0\x80\xFD[PZ\xF1\x15\x80\x15a\n\x85W=`\0\x80>=`\0\xFD[PPPPPPPPPPPV[a\n\x9Aa\x13\xD6V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\x0B\x17W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x0E`$\x82\x01R\x7FInvalid signer\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\x01Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x81\x16\x90\x82\x16\x03a\x0B\x9CW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x0B`$\x82\x01R\x7FSame signer\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\x01\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[``\x84\x84\x84a\x0B\xF1\x85a\x15_V[`@Q` \x01a\x0C\x04\x94\x93\x92\x91\x90a#\x1AV[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x90P\x94\x93PPPPV[`\0\x80T`@Q\x7F\xE7\xA7\x97z\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90c\xE7\xA7\x97z\x90a\x0Cv\x90\x86\x90\x86\x90`\x04\x01a\"\xF8V[` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x0C\x93W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0C\xB7\x91\x90a\"\xD6V[\x90P[\x92\x91PPV[a\x0C\xC8a\x13\xD6V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\r\x18W`@Q\x7F\x1EO\xBD\xF7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\0`\x04\x82\x01R`$\x01a\x06\xD4V[a\r!\x81a\x14dV[PV[\x83Q`\0\x03a\r\x8FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x10`$\x82\x01R\x7FInvalid selector\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[\x82Q`\0\x03a\r\xFAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x13`$\x82\x01R\x7FInvalid domain name\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[\x81a\x0EaW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x17`$\x82\x01R\x7FInvalid public key hash\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[a\x0Ek\x83\x83a\x0C\x1DV[\x15\x15`\x01\x14a\x0E\xD6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x18`$\x82\x01R\x7FpublicKeyHash is not set\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7FB\xD7\xCB\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x84\x90Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90cB\xD7\xCB\x98\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x0FEW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0Fi\x91\x90a\"\xD6V[\x15a\x0F\xD0W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01\x81\x90R`$\x82\x01R\x7FpublicKeyHash is already revoked`D\x82\x01R`d\x01a\x06\xD4V[`\0a\x10\x13`@Q\x80`@\x01`@R\x80`\x07\x81R` \x01\x7FREVOKE:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x86\x86\x86a\x0B\xE3V[\x90P`\0a\x10 \x82a\x14\xFAV[\x90P`\0a\x10.\x82\x85a\x155V[`\x01T\x90\x91Ps\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16\x91\x16\x14a\x10\xB5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x11`$\x82\x01R\x7FInvalid signature\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`D\x82\x01R`d\x01a\x06\xD4V[`\0T`@Q\x7F\x15\xD2Q.\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x87\x90Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x90c\x15\xD2Q.\x90`$\x01a\nWV[a\x11\x14a\x15vV[a\r!\x81a\x15\xDDV[0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16\x14\x80a\x11\xEAWP\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x11\xD1\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBCTs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x06kW`@Q\x7F\xE0|\x8D\xBA\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\r!a\x13\xD6V[\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16cR\xD1\x90-`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x92PPP\x80\x15a\x12\xAEWP`@\x80Q`\x1F=\x90\x81\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x82\x01\x90\x92Ra\x12\xAB\x91\x81\x01\x90a$\x1EV[`\x01[a\x12\xFCW`@Q\x7FL\x9C\x8C\xE3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x16`\x04\x82\x01R`$\x01a\x06\xD4V[\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBC\x81\x14a\x13XW`@Q\x7F\xAA\x1DI\xA4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x82\x90R`$\x01a\x06\xD4V[a\x13b\x83\x83a\x15\xE5V[PPPV[0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16\x14a\x06kW`@Q\x7F\xE0|\x8D\xBA\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[3a\x14\x15\x7F\x90\x16\xD0\x9Dr\xD4\x0F\xDA\xE2\xFD\x8C\xEA\xC6\xB6#Lw\x06!O\xD3\x9C\x1C\xD1\xE6\t\xA0R\x8C\x19\x93\0Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x06kW`@Q\x7F\x11\x8C\xDA\xA7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R3`\x04\x82\x01R`$\x01a\x06\xD4V[\x7F\x90\x16\xD0\x9Dr\xD4\x0F\xDA\xE2\xFD\x8C\xEA\xC6\xB6#Lw\x06!O\xD3\x9C\x1C\xD1\xE6\t\xA0R\x8C\x19\x93\0\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x81\x16\x91\x82\x17\x84U`@Q\x92\x16\x91\x82\x90\x7F\x8B\xE0\x07\x9CS\x16Y\x14\x13D\xCD\x1F\xD0\xA4\xF2\x84\x19I\x7F\x97\"\xA3\xDA\xAF\xE3\xB4\x18okdW\xE0\x90`\0\x90\xA3PPPV[`\0a\x15\x06\x82Qa\x16HV[\x82`@Q` \x01a\x15\x18\x92\x91\x90a$7V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90P\x91\x90PV[`\0\x80`\0\x80a\x15E\x86\x86a\x17\x06V[\x92P\x92P\x92Pa\x15U\x82\x82a\x17SV[P\x90\x94\x93PPPPV[``a\x0C\xBA\x82a\x15n\x84a\x18WV[`\x01\x01a\x18\xC1V[\x7F\xF0\xC5~\x16\x84\r\xF0@\xF1P\x88\xDC/\x81\xFE9\x1C9#\xBE\xC7>#\xA9f.\xFC\x9C\"\x9Cj\0Th\x01\0\0\0\0\0\0\0\0\x90\x04`\xFF\x16a\x06kW`@Q\x7F\xD7\xE6\xBC\xF8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\x0C\xC8a\x15vV[a\x15\xEE\x82a\x1A\xE7V[`@Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x16\x90\x7F\xBC|\xD7Z \xEE'\xFD\x9A\xDE\xBA\xB3 A\xF7U!M\xBCk\xFF\xA9\x0C\xC0\"[9\xDA.\\-;\x90`\0\x90\xA2\x80Q\x15a\x16@Wa\x13b\x82\x82a\x1B\xB6V[a\x06&a\x1C9V[```\0a\x16U\x83a\x1CqV[`\x01\x01\x90P`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x16uWa\x16ua \x0BV[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x16\x9FW` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x81\x81\x01` \x01[\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01\x7F0123456789abcdef\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\n\x86\x06\x1A\x81S`\n\x85\x04\x94P\x84a\x16\xA9WP\x93\x92PPPV[`\0\x80`\0\x83Q`A\x03a\x17@W` \x84\x01Q`@\x85\x01Q``\x86\x01Q`\0\x1Aa\x172\x88\x82\x85\x85a\x1DSV[\x95P\x95P\x95PPPPa\x17LV[PP\x81Q`\0\x91P`\x02\x90[\x92P\x92P\x92V[`\0\x82`\x03\x81\x11\x15a\x17gWa\x17ga$\x92V[\x03a\x17pWPPV[`\x01\x82`\x03\x81\x11\x15a\x17\x84Wa\x17\x84a$\x92V[\x03a\x17\xBBW`@Q\x7F\xF6E\xEE\xDF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\x02\x82`\x03\x81\x11\x15a\x17\xCFWa\x17\xCFa$\x92V[\x03a\x18\tW`@Q\x7F\xFC\xE6\x98\xF7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x82\x90R`$\x01a\x06\xD4V[`\x03\x82`\x03\x81\x11\x15a\x18\x1DWa\x18\x1Da$\x92V[\x03a\x06&W`@Q\x7F\xD7\x8B\xCE\x0C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x82\x90R`$\x01a\x06\xD4V[`\0\x80`\x80\x83\x90\x1C\x15a\x18oW`\x80\x92\x90\x92\x1C\x91`\x10\x01[`@\x83\x90\x1C\x15a\x18\x84W`@\x92\x90\x92\x1C\x91`\x08\x01[` \x83\x90\x1C\x15a\x18\x99W` \x92\x90\x92\x1C\x91`\x04\x01[`\x10\x83\x90\x1C\x15a\x18\xAEW`\x10\x92\x90\x92\x1C\x91`\x02\x01[`\x08\x83\x90\x1C\x15a\x0C\xBAW`\x01\x01\x92\x91PPV[``\x82`\0a\x18\xD1\x84`\x02a$\xF0V[a\x18\xDC\x90`\x02a%\x07V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x18\xF4Wa\x18\xF4a \x0BV[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x19\x1EW` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x7F0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81`\0\x81Q\x81\x10a\x19UWa\x19Ua%\x1AV[` \x01\x01\x90~\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x90\x81`\0\x1A\x90SP\x7Fx\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81`\x01\x81Q\x81\x10a\x19\xB8Wa\x19\xB8a%\x1AV[` \x01\x01\x90~\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x90\x81`\0\x1A\x90SP`\0a\x19\xF4\x85`\x02a$\xF0V[a\x19\xFF\x90`\x01a%\x07V[\x90P[`\x01\x81\x11\x15a\x1A\x9CW\x7F0123456789abcdef\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x83`\x0F\x16`\x10\x81\x10a\x1A@Wa\x1A@a%\x1AV[\x1A`\xF8\x1B\x82\x82\x81Q\x81\x10a\x1AVWa\x1AVa%\x1AV[` \x01\x01\x90~\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x90\x81`\0\x1A\x90SP`\x04\x92\x90\x92\x1C\x91a\x1A\x95\x81a%IV[\x90Pa\x1A\x02V[P\x81\x15a\x1A\xDFW`@Q\x7F\xE2.'\xEB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x81\x01\x86\x90R`$\x81\x01\x85\x90R`D\x01a\x06\xD4V[\x94\x93PPPPV[\x80s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16;`\0\x03a\x1BPW`@Q\x7FL\x9C\x8C\xE3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16`\x04\x82\x01R`$\x01a\x06\xD4V[\x7F6\x08\x94\xA1;\xA1\xA3!\x06g\xC8(I-\xB9\x8D\xCA> v\xCC75\xA9 \xA3\xCAP]8+\xBC\x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[```\0\x80\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`@Qa\x1B\xE0\x91\x90a%~V[`\0`@Q\x80\x83\x03\x81\x85Z\xF4\x91PP=\x80`\0\x81\x14a\x1C\x1BW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x1C V[``\x91P[P\x91P\x91Pa\x1C0\x85\x83\x83a\x1EMV[\x95\x94PPPPPV[4\x15a\x06kW`@Q\x7F\xB3\x98\x97\x9F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\0\x80z\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01\0\0\0\0\0\0\0\0\x83\x10a\x1C\xBAWz\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01\0\0\0\0\0\0\0\0\x83\x04\x92P`@\x01[m\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x10a\x1C\xE6Wm\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x04\x92P` \x01[f#\x86\xF2o\xC1\0\0\x83\x10a\x1D\x04Wf#\x86\xF2o\xC1\0\0\x83\x04\x92P`\x10\x01[c\x05\xF5\xE1\0\x83\x10a\x1D\x1CWc\x05\xF5\xE1\0\x83\x04\x92P`\x08\x01[a'\x10\x83\x10a\x1D0Wa'\x10\x83\x04\x92P`\x04\x01[`d\x83\x10a\x1DBW`d\x83\x04\x92P`\x02\x01[`\n\x83\x10a\x0C\xBAW`\x01\x01\x92\x91PPV[`\0\x80\x80\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF]WnsW\xA4P\x1D\xDF\xE9/Fh\x1B \xA0\x84\x11\x15a\x1D\x8EWP`\0\x91P`\x03\x90P\x82a\x1ECV[`@\x80Q`\0\x80\x82R` \x82\x01\x80\x84R\x8A\x90R`\xFF\x89\x16\x92\x82\x01\x92\x90\x92R``\x81\x01\x87\x90R`\x80\x81\x01\x86\x90R`\x01\x90`\xA0\x01` `@Q` \x81\x03\x90\x80\x84\x03\x90\x85Z\xFA\x15\x80\x15a\x1D\xE2W=`\0\x80>=`\0\xFD[PP`@Q\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x01Q\x91PPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\x1E9WP`\0\x92P`\x01\x91P\x82\x90Pa\x1ECV[\x92P`\0\x91P\x81\x90P[\x94P\x94P\x94\x91PPV[``\x82a\x1EbWa\x1E]\x82a\x1E\xDFV[a\x1E\xD8V[\x81Q\x15\x80\x15a\x1E\x86WPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16;\x15[\x15a\x1E\xD5W`@Q\x7F\x99\x96\xB3\x15\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x85\x16`\x04\x82\x01R`$\x01a\x06\xD4V[P\x80[\x93\x92PPPV[\x80Q\x15a\x1E\xEFW\x80Q\x80\x82` \x01\xFD[`@Q\x7F\x14%\xEAB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\t\xAE\x80a%\x9B\x839\x01\x90V[`\0[\x83\x81\x10\x15a\x1FIW\x81\x81\x01Q\x83\x82\x01R` \x01a\x1F1V[PP`\0\x91\x01RV[`\0\x81Q\x80\x84Ra\x1Fj\x81` \x86\x01` \x86\x01a\x1F.V[`\x1F\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x92\x90\x92\x01` \x01\x92\x91PPV[` \x81R`\0a\x0C\xB7` \x83\x01\x84a\x1FRV[\x805s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x1F\xD3W`\0\x80\xFD[\x91\x90PV[`\0\x80`@\x83\x85\x03\x12\x15a\x1F\xEBW`\0\x80\xFD[a\x1F\xF4\x83a\x1F\xAFV[\x91Pa \x02` \x84\x01a\x1F\xAFV[\x90P\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`A`\x04R`$`\0\xFD[`\0\x82`\x1F\x83\x01\x12a KW`\0\x80\xFD[\x815` \x83\x01`\0\x80g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11\x15a lWa la \x0BV[P`@Q\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0`\x1F\x85\x01\x81\x16`?\x01\x16\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a \xB9Wa \xB9a \x0BV[`@R\x83\x81R\x90P\x80\x82\x84\x01\x87\x10\x15a \xD1W`\0\x80\xFD[\x83\x83` \x83\x017`\0` \x85\x83\x01\x01R\x80\x94PPPPP\x92\x91PPV[`\0\x80`@\x83\x85\x03\x12\x15a!\x01W`\0\x80\xFD[a!\n\x83a\x1F\xAFV[\x91P` \x83\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!&W`\0\x80\xFD[a!2\x85\x82\x86\x01a :V[\x91PP\x92P\x92\x90PV[`\0\x80`\0\x80`\x80\x85\x87\x03\x12\x15a!RW`\0\x80\xFD[\x845g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!iW`\0\x80\xFD[a!u\x87\x82\x88\x01a :V[\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!\x92W`\0\x80\xFD[a!\x9E\x87\x82\x88\x01a :V[\x93PP`@\x85\x015\x91P``\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a!\xC2W`\0\x80\xFD[a!\xCE\x87\x82\x88\x01a :V[\x91PP\x92\x95\x91\x94P\x92PV[`\0` \x82\x84\x03\x12\x15a!\xECW`\0\x80\xFD[a\x0C\xB7\x82a\x1F\xAFV[`\0\x80`\0\x80`\x80\x85\x87\x03\x12\x15a\"\x0BW`\0\x80\xFD[\x845g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"\"W`\0\x80\xFD[a\".\x87\x82\x88\x01a :V[\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"KW`\0\x80\xFD[a\"W\x87\x82\x88\x01a :V[\x93PP`@\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"tW`\0\x80\xFD[a\"\x80\x87\x82\x88\x01a :V[\x94\x97\x93\x96P\x93\x94``\x015\x93PPPV[`\0\x80`@\x83\x85\x03\x12\x15a\"\xA4W`\0\x80\xFD[\x825g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\"\xBBW`\0\x80\xFD[a\"\xC7\x85\x82\x86\x01a :V[\x95` \x94\x90\x94\x015\x94PPPPV[`\0` \x82\x84\x03\x12\x15a\"\xE8W`\0\x80\xFD[\x81Q\x80\x15\x15\x81\x14a\x1E\xD8W`\0\x80\xFD[`@\x81R`\0a#\x0B`@\x83\x01\x85a\x1FRV[\x90P\x82` \x83\x01R\x93\x92PPPV[`\0\x85Qa#,\x81\x84` \x8A\x01a\x1F.V[\x7Fselector=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x83\x01\x90\x81R\x85Qa#f\x81`\t\x84\x01` \x8A\x01a\x1F.V[\x7F;domain=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\t\x92\x90\x91\x01\x91\x82\x01R\x84Qa#\xA4\x81`\x11\x84\x01` \x89\x01a\x1F.V[`\t\x81\x83\x01\x01\x91PP\x7F;public_key_hash=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\x08\x82\x01R\x83Qa#\xE6\x81`\x19\x84\x01` \x88\x01a\x1F.V[\x7F;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\x19\x92\x90\x91\x01\x91\x82\x01R`\x1A\x01\x96\x95PPPPPPV[`\0` \x82\x84\x03\x12\x15a$0W`\0\x80\xFD[PQ\x91\x90PV[\x7F\x19Ethereum Signed Message:\n\0\0\0\0\0\0\x81R`\0\x83Qa$o\x81`\x1A\x85\x01` \x88\x01a\x1F.V[\x83Q\x90\x83\x01\x90a$\x86\x81`\x1A\x84\x01` \x88\x01a\x1F.V[\x01`\x1A\x01\x94\x93PPPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`!`\x04R`$`\0\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\x11`\x04R`$`\0\xFD[\x80\x82\x02\x81\x15\x82\x82\x04\x84\x14\x17a\x0C\xBAWa\x0C\xBAa$\xC1V[\x80\x82\x01\x80\x82\x11\x15a\x0C\xBAWa\x0C\xBAa$\xC1V[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`2`\x04R`$`\0\xFD[`\0\x81a%XWa%Xa$\xC1V[P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01\x90V[`\0\x82Qa%\x90\x81\x84` \x87\x01a\x1F.V[\x91\x90\x91\x01\x92\x91PPV\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`@Qa\t\xAE8\x03\x80a\t\xAE\x839\x81\x01`@\x81\x90Ra\0/\x91a\0\xBEV[\x80`\x01`\x01`\xA0\x1B\x03\x81\x16a\0^W`@Qc\x1EO\xBD\xF7`\xE0\x1B\x81R`\0`\x04\x82\x01R`$\x01`@Q\x80\x91\x03\x90\xFD[a\0g\x81a\0nV[PPa\0\xEEV[`\0\x80T`\x01`\x01`\xA0\x1B\x03\x83\x81\x16`\x01`\x01`\xA0\x1B\x03\x19\x83\x16\x81\x17\x84U`@Q\x91\x90\x92\x16\x92\x83\x91\x7F\x8B\xE0\x07\x9CS\x16Y\x14\x13D\xCD\x1F\xD0\xA4\xF2\x84\x19I\x7F\x97\"\xA3\xDA\xAF\xE3\xB4\x18okdW\xE0\x91\x90\xA3PPV[`\0` \x82\x84\x03\x12\x15a\0\xD0W`\0\x80\xFD[\x81Q`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\0\xE7W`\0\x80\xFD[\x93\x92PPPV[a\x08\xB1\x80a\0\xFD`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\0\xA3W`\x005`\xE0\x1C\x80c\x8D\xA5\xCB[\x11a\0vW\x80c\xE7\xA7\x97z\x11a\0[W\x80c\xE7\xA7\x97z\x14a\x01vW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x89W\x80c\xF4\x9E\xB1d\x14a\x01\x9CW`\0\x80\xFD[\x80c\x8D\xA5\xCB[\x14a\x01;W\x80c\xC1\\\xFF\xAB\x14a\x01cW`\0\x80\xFD[\x80c\x06\x90\xBD8\x14a\0\xA8W\x80c\x15\xD2Q.\x14a\0\xFBW\x80cB\xD7\xCB\x98\x14a\x01\x10W\x80cqP\x18\xA6\x14a\x013W[`\0\x80\xFD[a\0\xE6a\0\xB66`\x04a\x069V[\x81Q` \x81\x84\x01\x81\x01\x80Q`\x01\x82R\x92\x82\x01\x94\x82\x01\x94\x90\x94 \x91\x90\x93R\x90\x91R`\0\x90\x81R`@\x90 T`\xFF\x16\x81V[`@Q\x90\x15\x15\x81R` \x01[`@Q\x80\x91\x03\x90\xF3[a\x01\x0Ea\x01\t6`\x04a\x06~V[a\x01\xAFV[\0[a\0\xE6a\x01\x1E6`\x04a\x06~V[`\x02` R`\0\x90\x81R`@\x90 T`\xFF\x16\x81V[a\x01\x0Ea\x02+V[`\0T`@Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x91\x16\x81R` \x01a\0\xF2V[a\x01\x0Ea\x01q6`\x04a\x069V[a\x02?V[a\0\xE6a\x01\x846`\x04a\x069V[a\x03YV[a\x01\x0Ea\x01\x976`\x04a\x06\x97V[a\x03\xBDV[a\x01\x0Ea\x01\xAA6`\x04a\x06\xD4V[a\x04!V[a\x01\xB7a\x04eV[`\0\x81\x81R`\x02` R`@\x90\x81\x90 \x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x16`\x01\x17\x90UQ\x7F\xB8\x0F\xFF+Lo=\xDF\x80Hw\x92|w\xB2\xFE\x18q\xCE\xCA\xA5\xADC\xD2\xC7\xC4/As1\xF8e\x90a\x02 \x90\x83\x81R` \x01\x90V[`@Q\x80\x91\x03\x90\xA1PV[a\x023a\x04eV[a\x02=`\0a\x04\xB8V[V[a\x02Ga\x04eV[`\0\x81\x81R`\x02` R`@\x90 T`\xFF\x16\x15a\x02\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x19`$\x82\x01R\x7Fcannot set revoked pubkey\0\0\0\0\0\0\0`D\x82\x01R`d\x01[`@Q\x80\x91\x03\x90\xFD[`\x01\x80\x83`@Qa\x02\xD6\x91\x90a\x07\xD7V[\x90\x81R`@\x80Q` \x92\x81\x90\x03\x83\x01\x81 `\0\x86\x81R\x93R\x91 \x80T\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x16\x92\x15\x15\x92\x90\x92\x17\x90\x91U\x7FQ\r\xAC\x88\xEA\xF2\xDF\xBDS\x90BA\xFC\x19\x9A\xD4k c\xE6\xBFl?\xB2\x91\xF8\xCE\x86Cf4\x19\x90a\x03M\x90\x84\x90\x84\x90a\x07\xF3V[`@Q\x80\x91\x03\x90\xA1PPV[`\0\x81\x81R`\x02` R`@\x81 T`\xFF\x16\x15a\x03xWP`\0a\x03\xB7V[`\x01\x83`@Qa\x03\x88\x91\x90a\x07\xD7V[\x90\x81R`@\x80Q` \x92\x81\x90\x03\x83\x01\x90 `\0\x85\x81R\x92R\x90 T`\xFF\x16\x15a\x03\xB3WP`\x01a\x03\xB7V[P`\0[\x92\x91PPV[a\x03\xC5a\x04eV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16a\x04\x15W`@Q\x7F\x1EO\xBD\xF7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\0`\x04\x82\x01R`$\x01a\x02\xBCV[a\x04\x1E\x81a\x04\xB8V[PV[a\x04)a\x04eV[`\0[\x81Q\x81\x10\x15a\x04`Wa\x04X\x83\x83\x83\x81Q\x81\x10a\x04KWa\x04Ka\x08LV[` \x02` \x01\x01Qa\x02?V[`\x01\x01a\x04,V[PPPV[`\0Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163\x14a\x02=W`@Q\x7F\x11\x8C\xDA\xA7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R3`\x04\x82\x01R`$\x01a\x02\xBCV[`\0\x80Ts\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x16\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x83\x16\x81\x17\x84U`@Q\x91\x90\x92\x16\x92\x83\x91\x7F\x8B\xE0\x07\x9CS\x16Y\x14\x13D\xCD\x1F\xD0\xA4\xF2\x84\x19I\x7F\x97\"\xA3\xDA\xAF\xE3\xB4\x18okdW\xE0\x91\x90\xA3PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`A`\x04R`$`\0\xFD[`@Q`\x1F\x82\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x81\x01g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x82\x82\x10\x17\x15a\x05\xA3Wa\x05\xA3a\x05-V[`@R\x91\x90PV[`\0\x82`\x1F\x83\x01\x12a\x05\xBCW`\0\x80\xFD[\x815g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x05\xD6Wa\x05\xD6a\x05-V[a\x06\x07` \x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0`\x1F\x84\x01\x16\x01a\x05\\V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x06\x1CW`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[`\0\x80`@\x83\x85\x03\x12\x15a\x06LW`\0\x80\xFD[\x825g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06cW`\0\x80\xFD[a\x06o\x85\x82\x86\x01a\x05\xABV[\x95` \x94\x90\x94\x015\x94PPPPV[`\0` \x82\x84\x03\x12\x15a\x06\x90W`\0\x80\xFD[P5\x91\x90PV[`\0` \x82\x84\x03\x12\x15a\x06\xA9W`\0\x80\xFD[\x815s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x06\xCDW`\0\x80\xFD[\x93\x92PPPV[`\0\x80`@\x83\x85\x03\x12\x15a\x06\xE7W`\0\x80\xFD[\x825g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06\xFEW`\0\x80\xFD[a\x07\n\x85\x82\x86\x01a\x05\xABV[\x92PP` \x83\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07'W`\0\x80\xFD[\x83\x01`\x1F\x81\x01\x85\x13a\x078W`\0\x80\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07RWa\x07Ra\x05-V[\x80`\x05\x1Ba\x07b` \x82\x01a\x05\\V[\x91\x82R` \x81\x84\x01\x81\x01\x92\x90\x81\x01\x90\x88\x84\x11\x15a\x07~W`\0\x80\xFD[` \x85\x01\x94P[\x83\x85\x10\x15a\x07\xA4W\x845\x80\x83R` \x95\x86\x01\x95\x90\x93P\x90\x91\x01\x90a\x07\x85V[\x80\x95PPPPPP\x92P\x92\x90PV[`\0[\x83\x81\x10\x15a\x07\xCEW\x81\x81\x01Q\x83\x82\x01R` \x01a\x07\xB6V[PP`\0\x91\x01RV[`\0\x82Qa\x07\xE9\x81\x84` \x87\x01a\x07\xB3V[\x91\x90\x91\x01\x92\x91PPV[`@\x81R`\0\x83Q\x80`@\x84\x01Ra\x08\x12\x81``\x85\x01` \x88\x01a\x07\xB3V[` \x83\x01\x93\x90\x93RP`\x1F\x91\x90\x91\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x16\x01``\x01\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`2`\x04R`$`\0\xFD\xFE\xA2dipfsX\"\x12 -\x9Ee\xDAg\xA8\x9E\x94XP\xBB\xE47ClV\x95\xD85 \x14\x95XA\xAAs\xAA\x1C\xC4\x15\xD3IdsolcC\0\x08\x1A\x003\xA2dipfsX\"\x12 \x0E[\xF6h\xD37\xAE[\x83m\x7F\x86So\xD0\x05\xCE\xD9Ui~\xD1\xF0\x7F\xC3\xF4C\xC1b\xFE\x136dsolcC\0\x08\x1A\x003"; - /// The deployed bytecode of the contract. - pub static ECDSAOWNEDDKIMREGISTRY_DEPLOYED_BYTECODE: ::ethers::core::types::Bytes = ::ethers::core::types::Bytes::from_static( - __DEPLOYED_BYTECODE, - ); - pub struct ECDSAOwnedDKIMRegistry(::ethers::contract::Contract); - impl ::core::clone::Clone for ECDSAOwnedDKIMRegistry { - fn clone(&self) -> Self { - Self(::core::clone::Clone::clone(&self.0)) - } - } - impl ::core::ops::Deref for ECDSAOwnedDKIMRegistry { - type Target = ::ethers::contract::Contract; - fn deref(&self) -> &Self::Target { - &self.0 - } - } - impl ::core::ops::DerefMut for ECDSAOwnedDKIMRegistry { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } - } - impl ::core::fmt::Debug for ECDSAOwnedDKIMRegistry { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(::core::stringify!(ECDSAOwnedDKIMRegistry)) - .field(&self.address()) - .finish() - } - } - impl ECDSAOwnedDKIMRegistry { - /// Creates a new contract instance with the specified `ethers` client at - /// `address`. The contract derefs to a `ethers::Contract` object. - pub fn new>( - address: T, - client: ::std::sync::Arc, - ) -> Self { - Self( - ::ethers::contract::Contract::new( - address.into(), - ECDSAOWNEDDKIMREGISTRY_ABI.clone(), - client, - ), - ) - } - /// Constructs the general purpose `Deployer` instance based on the provided constructor arguments and sends it. - /// Returns a new instance of a deployer that returns an instance of this contract after sending the transaction - /// - /// Notes: - /// - If there are no constructor arguments, you should pass `()` as the argument. - /// - The default poll duration is 7 seconds. - /// - The default number of confirmations is 1 block. - /// - /// - /// # Example - /// - /// Generate contract bindings with `abigen!` and deploy a new contract instance. - /// - /// *Note*: this requires a `bytecode` and `abi` object in the `greeter.json` artifact. - /// - /// ```ignore - /// # async fn deploy(client: ::std::sync::Arc) { - /// abigen!(Greeter, "../greeter.json"); - /// - /// let greeter_contract = Greeter::deploy(client, "Hello world!".to_string()).unwrap().send().await.unwrap(); - /// let msg = greeter_contract.greet().call().await.unwrap(); - /// # } - /// ``` - pub fn deploy( - client: ::std::sync::Arc, - constructor_args: T, - ) -> ::core::result::Result< - ::ethers::contract::builders::ContractDeployer, - ::ethers::contract::ContractError, - > { - let factory = ::ethers::contract::ContractFactory::new( - ECDSAOWNEDDKIMREGISTRY_ABI.clone(), - ECDSAOWNEDDKIMREGISTRY_BYTECODE.clone().into(), - client, - ); - let deployer = factory.deploy(constructor_args)?; - let deployer = ::ethers::contract::ContractDeployer::new(deployer); - Ok(deployer) - } - ///Calls the contract's `REVOKE_PREFIX` (0xd507c320) function - pub fn revoke_prefix( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([213, 7, 195, 32], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `SET_PREFIX` (0x07f1eaf5) function - pub fn set_prefix( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([7, 241, 234, 245], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `UPGRADE_INTERFACE_VERSION` (0xad3cb1cc) function - pub fn upgrade_interface_version( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([173, 60, 177, 204], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `changeSigner` (0xaad2b723) function - pub fn change_signer( - &self, - new_signer: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([170, 210, 183, 35], new_signer) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `computeSignedMsg` (0xaec79361) function - pub fn compute_signed_msg( - &self, - prefix: ::std::string::String, - selector: ::std::string::String, - domain_name: ::std::string::String, - public_key_hash: [u8; 32], - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash( - [174, 199, 147, 97], - (prefix, selector, domain_name, public_key_hash), - ) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `dkimRegistry` (0x6423f1e2) function - pub fn dkim_registry( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([100, 35, 241, 226], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `initialize` (0x485cc955) function - pub fn initialize( - &self, - initial_owner: ::ethers::core::types::Address, - signer: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([72, 92, 201, 85], (initial_owner, signer)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `isDKIMPublicKeyHashValid` (0xe7a7977a) function - pub fn is_dkim_public_key_hash_valid( - &self, - domain_name: ::std::string::String, - public_key_hash: [u8; 32], - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([231, 167, 151, 122], (domain_name, public_key_hash)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `owner` (0x8da5cb5b) function - pub fn owner( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([141, 165, 203, 91], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `proxiableUUID` (0x52d1902d) function - pub fn proxiable_uuid( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([82, 209, 144, 45], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `renounceOwnership` (0x715018a6) function - pub fn renounce_ownership( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([113, 80, 24, 166], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `revokeDKIMPublicKeyHash` (0xf6b49344) function - pub fn revoke_dkim_public_key_hash( - &self, - selector: ::std::string::String, - domain_name: ::std::string::String, - public_key_hash: [u8; 32], - signature: ::ethers::core::types::Bytes, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash( - [246, 180, 147, 68], - (selector, domain_name, public_key_hash, signature), - ) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `setDKIMPublicKeyHash` (0x97170f2b) function - pub fn set_dkim_public_key_hash( - &self, - selector: ::std::string::String, - domain_name: ::std::string::String, - public_key_hash: [u8; 32], - signature: ::ethers::core::types::Bytes, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash( - [151, 23, 15, 43], - (selector, domain_name, public_key_hash, signature), - ) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `signer` (0x238ac933) function - pub fn signer( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([35, 138, 201, 51], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `transferOwnership` (0xf2fde38b) function - pub fn transfer_ownership( - &self, - new_owner: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([242, 253, 227, 139], new_owner) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `upgradeToAndCall` (0x4f1ef286) function - pub fn upgrade_to_and_call( - &self, - new_implementation: ::ethers::core::types::Address, - data: ::ethers::core::types::Bytes, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([79, 30, 242, 134], (new_implementation, data)) - .expect("method not found (this should never happen)") - } - ///Gets the contract's `Initialized` event - pub fn initialized_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - InitializedFilter, - > { - self.0.event() - } - ///Gets the contract's `OwnershipTransferred` event - pub fn ownership_transferred_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - OwnershipTransferredFilter, - > { - self.0.event() - } - ///Gets the contract's `Upgraded` event - pub fn upgraded_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - UpgradedFilter, - > { - self.0.event() - } - /// Returns an `Event` builder for all the events of this contract. - pub fn events( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - ECDSAOwnedDKIMRegistryEvents, - > { - self.0.event_with_filter(::core::default::Default::default()) - } - } - impl From<::ethers::contract::Contract> - for ECDSAOwnedDKIMRegistry { - fn from(contract: ::ethers::contract::Contract) -> Self { - Self::new(contract.address(), contract.client()) - } - } - ///Custom Error type `AddressEmptyCode` with signature `AddressEmptyCode(address)` and selector `0x9996b315` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "AddressEmptyCode", abi = "AddressEmptyCode(address)")] - pub struct AddressEmptyCode { - pub target: ::ethers::core::types::Address, - } - ///Custom Error type `ECDSAInvalidSignature` with signature `ECDSAInvalidSignature()` and selector `0xf645eedf` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "ECDSAInvalidSignature", abi = "ECDSAInvalidSignature()")] - pub struct ECDSAInvalidSignature; - ///Custom Error type `ECDSAInvalidSignatureLength` with signature `ECDSAInvalidSignatureLength(uint256)` and selector `0xfce698f7` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "ECDSAInvalidSignatureLength", - abi = "ECDSAInvalidSignatureLength(uint256)" - )] - pub struct ECDSAInvalidSignatureLength { - pub length: ::ethers::core::types::U256, - } - ///Custom Error type `ECDSAInvalidSignatureS` with signature `ECDSAInvalidSignatureS(bytes32)` and selector `0xd78bce0c` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "ECDSAInvalidSignatureS", abi = "ECDSAInvalidSignatureS(bytes32)")] - pub struct ECDSAInvalidSignatureS { - pub s: [u8; 32], - } - ///Custom Error type `ERC1967InvalidImplementation` with signature `ERC1967InvalidImplementation(address)` and selector `0x4c9c8ce3` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "ERC1967InvalidImplementation", - abi = "ERC1967InvalidImplementation(address)" - )] - pub struct ERC1967InvalidImplementation { - pub implementation: ::ethers::core::types::Address, - } - ///Custom Error type `ERC1967NonPayable` with signature `ERC1967NonPayable()` and selector `0xb398979f` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "ERC1967NonPayable", abi = "ERC1967NonPayable()")] - pub struct ERC1967NonPayable; - ///Custom Error type `FailedInnerCall` with signature `FailedInnerCall()` and selector `0x1425ea42` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "FailedInnerCall", abi = "FailedInnerCall()")] - pub struct FailedInnerCall; - ///Custom Error type `InvalidInitialization` with signature `InvalidInitialization()` and selector `0xf92ee8a9` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "InvalidInitialization", abi = "InvalidInitialization()")] - pub struct InvalidInitialization; - ///Custom Error type `NotInitializing` with signature `NotInitializing()` and selector `0xd7e6bcf8` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "NotInitializing", abi = "NotInitializing()")] - pub struct NotInitializing; - ///Custom Error type `OwnableInvalidOwner` with signature `OwnableInvalidOwner(address)` and selector `0x1e4fbdf7` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "OwnableInvalidOwner", abi = "OwnableInvalidOwner(address)")] - pub struct OwnableInvalidOwner { - pub owner: ::ethers::core::types::Address, - } - ///Custom Error type `OwnableUnauthorizedAccount` with signature `OwnableUnauthorizedAccount(address)` and selector `0x118cdaa7` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "OwnableUnauthorizedAccount", - abi = "OwnableUnauthorizedAccount(address)" - )] - pub struct OwnableUnauthorizedAccount { - pub account: ::ethers::core::types::Address, - } - ///Custom Error type `StringsInsufficientHexLength` with signature `StringsInsufficientHexLength(uint256,uint256)` and selector `0xe22e27eb` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "StringsInsufficientHexLength", - abi = "StringsInsufficientHexLength(uint256,uint256)" - )] - pub struct StringsInsufficientHexLength { - pub value: ::ethers::core::types::U256, - pub length: ::ethers::core::types::U256, - } - ///Custom Error type `UUPSUnauthorizedCallContext` with signature `UUPSUnauthorizedCallContext()` and selector `0xe07c8dba` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "UUPSUnauthorizedCallContext", - abi = "UUPSUnauthorizedCallContext()" - )] - pub struct UUPSUnauthorizedCallContext; - ///Custom Error type `UUPSUnsupportedProxiableUUID` with signature `UUPSUnsupportedProxiableUUID(bytes32)` and selector `0xaa1d49a4` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "UUPSUnsupportedProxiableUUID", - abi = "UUPSUnsupportedProxiableUUID(bytes32)" - )] - pub struct UUPSUnsupportedProxiableUUID { - pub slot: [u8; 32], - } - ///Container type for all of the contract's custom errors - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum ECDSAOwnedDKIMRegistryErrors { - AddressEmptyCode(AddressEmptyCode), - ECDSAInvalidSignature(ECDSAInvalidSignature), - ECDSAInvalidSignatureLength(ECDSAInvalidSignatureLength), - ECDSAInvalidSignatureS(ECDSAInvalidSignatureS), - ERC1967InvalidImplementation(ERC1967InvalidImplementation), - ERC1967NonPayable(ERC1967NonPayable), - FailedInnerCall(FailedInnerCall), - InvalidInitialization(InvalidInitialization), - NotInitializing(NotInitializing), - OwnableInvalidOwner(OwnableInvalidOwner), - OwnableUnauthorizedAccount(OwnableUnauthorizedAccount), - StringsInsufficientHexLength(StringsInsufficientHexLength), - UUPSUnauthorizedCallContext(UUPSUnauthorizedCallContext), - UUPSUnsupportedProxiableUUID(UUPSUnsupportedProxiableUUID), - /// The standard solidity revert string, with selector - /// Error(string) -- 0x08c379a0 - RevertString(::std::string::String), - } - impl ::ethers::core::abi::AbiDecode for ECDSAOwnedDKIMRegistryErrors { - fn decode( - data: impl AsRef<[u8]>, - ) -> ::core::result::Result { - let data = data.as_ref(); - if let Ok(decoded) = <::std::string::String as ::ethers::core::abi::AbiDecode>::decode( - data, - ) { - return Ok(Self::RevertString(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::AddressEmptyCode(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ECDSAInvalidSignature(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ECDSAInvalidSignatureLength(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ECDSAInvalidSignatureS(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ERC1967InvalidImplementation(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ERC1967NonPayable(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::FailedInnerCall(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::InvalidInitialization(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::NotInitializing(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::OwnableInvalidOwner(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::OwnableUnauthorizedAccount(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::StringsInsufficientHexLength(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UUPSUnauthorizedCallContext(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UUPSUnsupportedProxiableUUID(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData.into()) - } - } - impl ::ethers::core::abi::AbiEncode for ECDSAOwnedDKIMRegistryErrors { - fn encode(self) -> ::std::vec::Vec { - match self { - Self::AddressEmptyCode(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ECDSAInvalidSignature(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ECDSAInvalidSignatureLength(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ECDSAInvalidSignatureS(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ERC1967InvalidImplementation(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ERC1967NonPayable(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::FailedInnerCall(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::InvalidInitialization(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::NotInitializing(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::OwnableInvalidOwner(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::OwnableUnauthorizedAccount(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::StringsInsufficientHexLength(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UUPSUnauthorizedCallContext(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UUPSUnsupportedProxiableUUID(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::RevertString(s) => ::ethers::core::abi::AbiEncode::encode(s), - } - } - } - impl ::ethers::contract::ContractRevert for ECDSAOwnedDKIMRegistryErrors { - fn valid_selector(selector: [u8; 4]) -> bool { - match selector { - [0x08, 0xc3, 0x79, 0xa0] => true, - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ => false, - } - } - } - impl ::core::fmt::Display for ECDSAOwnedDKIMRegistryErrors { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::AddressEmptyCode(element) => ::core::fmt::Display::fmt(element, f), - Self::ECDSAInvalidSignature(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ECDSAInvalidSignatureLength(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ECDSAInvalidSignatureS(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ERC1967InvalidImplementation(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ERC1967NonPayable(element) => ::core::fmt::Display::fmt(element, f), - Self::FailedInnerCall(element) => ::core::fmt::Display::fmt(element, f), - Self::InvalidInitialization(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::NotInitializing(element) => ::core::fmt::Display::fmt(element, f), - Self::OwnableInvalidOwner(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::OwnableUnauthorizedAccount(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::StringsInsufficientHexLength(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UUPSUnauthorizedCallContext(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UUPSUnsupportedProxiableUUID(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::RevertString(s) => ::core::fmt::Display::fmt(s, f), - } - } - } - impl ::core::convert::From<::std::string::String> for ECDSAOwnedDKIMRegistryErrors { - fn from(value: String) -> Self { - Self::RevertString(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: AddressEmptyCode) -> Self { - Self::AddressEmptyCode(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: ECDSAInvalidSignature) -> Self { - Self::ECDSAInvalidSignature(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryErrors { - fn from(value: ECDSAInvalidSignatureLength) -> Self { - Self::ECDSAInvalidSignatureLength(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: ECDSAInvalidSignatureS) -> Self { - Self::ECDSAInvalidSignatureS(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryErrors { - fn from(value: ERC1967InvalidImplementation) -> Self { - Self::ERC1967InvalidImplementation(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: ERC1967NonPayable) -> Self { - Self::ERC1967NonPayable(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: FailedInnerCall) -> Self { - Self::FailedInnerCall(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: InvalidInitialization) -> Self { - Self::InvalidInitialization(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: NotInitializing) -> Self { - Self::NotInitializing(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryErrors { - fn from(value: OwnableInvalidOwner) -> Self { - Self::OwnableInvalidOwner(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryErrors { - fn from(value: OwnableUnauthorizedAccount) -> Self { - Self::OwnableUnauthorizedAccount(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryErrors { - fn from(value: StringsInsufficientHexLength) -> Self { - Self::StringsInsufficientHexLength(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryErrors { - fn from(value: UUPSUnauthorizedCallContext) -> Self { - Self::UUPSUnauthorizedCallContext(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryErrors { - fn from(value: UUPSUnsupportedProxiableUUID) -> Self { - Self::UUPSUnsupportedProxiableUUID(value) - } - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "Initialized", abi = "Initialized(uint64)")] - pub struct InitializedFilter { - pub version: u64, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent( - name = "OwnershipTransferred", - abi = "OwnershipTransferred(address,address)" - )] - pub struct OwnershipTransferredFilter { - #[ethevent(indexed)] - pub previous_owner: ::ethers::core::types::Address, - #[ethevent(indexed)] - pub new_owner: ::ethers::core::types::Address, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "Upgraded", abi = "Upgraded(address)")] - pub struct UpgradedFilter { - #[ethevent(indexed)] - pub implementation: ::ethers::core::types::Address, - } - ///Container type for all of the contract's events - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum ECDSAOwnedDKIMRegistryEvents { - InitializedFilter(InitializedFilter), - OwnershipTransferredFilter(OwnershipTransferredFilter), - UpgradedFilter(UpgradedFilter), - } - impl ::ethers::contract::EthLogDecode for ECDSAOwnedDKIMRegistryEvents { - fn decode_log( - log: &::ethers::core::abi::RawLog, - ) -> ::core::result::Result { - if let Ok(decoded) = InitializedFilter::decode_log(log) { - return Ok(ECDSAOwnedDKIMRegistryEvents::InitializedFilter(decoded)); - } - if let Ok(decoded) = OwnershipTransferredFilter::decode_log(log) { - return Ok( - ECDSAOwnedDKIMRegistryEvents::OwnershipTransferredFilter(decoded), - ); - } - if let Ok(decoded) = UpgradedFilter::decode_log(log) { - return Ok(ECDSAOwnedDKIMRegistryEvents::UpgradedFilter(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData) - } - } - impl ::core::fmt::Display for ECDSAOwnedDKIMRegistryEvents { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::InitializedFilter(element) => ::core::fmt::Display::fmt(element, f), - Self::OwnershipTransferredFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UpgradedFilter(element) => ::core::fmt::Display::fmt(element, f), - } - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryEvents { - fn from(value: InitializedFilter) -> Self { - Self::InitializedFilter(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryEvents { - fn from(value: OwnershipTransferredFilter) -> Self { - Self::OwnershipTransferredFilter(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryEvents { - fn from(value: UpgradedFilter) -> Self { - Self::UpgradedFilter(value) - } - } - ///Container type for all input parameters for the `REVOKE_PREFIX` function with signature `REVOKE_PREFIX()` and selector `0xd507c320` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "REVOKE_PREFIX", abi = "REVOKE_PREFIX()")] - pub struct RevokePrefixCall; - ///Container type for all input parameters for the `SET_PREFIX` function with signature `SET_PREFIX()` and selector `0x07f1eaf5` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "SET_PREFIX", abi = "SET_PREFIX()")] - pub struct SetPrefixCall; - ///Container type for all input parameters for the `UPGRADE_INTERFACE_VERSION` function with signature `UPGRADE_INTERFACE_VERSION()` and selector `0xad3cb1cc` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "UPGRADE_INTERFACE_VERSION", abi = "UPGRADE_INTERFACE_VERSION()")] - pub struct UpgradeInterfaceVersionCall; - ///Container type for all input parameters for the `changeSigner` function with signature `changeSigner(address)` and selector `0xaad2b723` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "changeSigner", abi = "changeSigner(address)")] - pub struct ChangeSignerCall { - pub new_signer: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `computeSignedMsg` function with signature `computeSignedMsg(string,string,string,bytes32)` and selector `0xaec79361` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "computeSignedMsg", - abi = "computeSignedMsg(string,string,string,bytes32)" - )] - pub struct ComputeSignedMsgCall { - pub prefix: ::std::string::String, - pub selector: ::std::string::String, - pub domain_name: ::std::string::String, - pub public_key_hash: [u8; 32], - } - ///Container type for all input parameters for the `dkimRegistry` function with signature `dkimRegistry()` and selector `0x6423f1e2` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "dkimRegistry", abi = "dkimRegistry()")] - pub struct DkimRegistryCall; - ///Container type for all input parameters for the `initialize` function with signature `initialize(address,address)` and selector `0x485cc955` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "initialize", abi = "initialize(address,address)")] - pub struct InitializeCall { - pub initial_owner: ::ethers::core::types::Address, - pub signer: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `isDKIMPublicKeyHashValid` function with signature `isDKIMPublicKeyHashValid(string,bytes32)` and selector `0xe7a7977a` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "isDKIMPublicKeyHashValid", - abi = "isDKIMPublicKeyHashValid(string,bytes32)" - )] - pub struct IsDKIMPublicKeyHashValidCall { - pub domain_name: ::std::string::String, - pub public_key_hash: [u8; 32], - } - ///Container type for all input parameters for the `owner` function with signature `owner()` and selector `0x8da5cb5b` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "owner", abi = "owner()")] - pub struct OwnerCall; - ///Container type for all input parameters for the `proxiableUUID` function with signature `proxiableUUID()` and selector `0x52d1902d` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "proxiableUUID", abi = "proxiableUUID()")] - pub struct ProxiableUUIDCall; - ///Container type for all input parameters for the `renounceOwnership` function with signature `renounceOwnership()` and selector `0x715018a6` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "renounceOwnership", abi = "renounceOwnership()")] - pub struct RenounceOwnershipCall; - ///Container type for all input parameters for the `revokeDKIMPublicKeyHash` function with signature `revokeDKIMPublicKeyHash(string,string,bytes32,bytes)` and selector `0xf6b49344` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "revokeDKIMPublicKeyHash", - abi = "revokeDKIMPublicKeyHash(string,string,bytes32,bytes)" - )] - pub struct RevokeDKIMPublicKeyHashCall { - pub selector: ::std::string::String, - pub domain_name: ::std::string::String, - pub public_key_hash: [u8; 32], - pub signature: ::ethers::core::types::Bytes, - } - ///Container type for all input parameters for the `setDKIMPublicKeyHash` function with signature `setDKIMPublicKeyHash(string,string,bytes32,bytes)` and selector `0x97170f2b` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "setDKIMPublicKeyHash", - abi = "setDKIMPublicKeyHash(string,string,bytes32,bytes)" - )] - pub struct SetDKIMPublicKeyHashCall { - pub selector: ::std::string::String, - pub domain_name: ::std::string::String, - pub public_key_hash: [u8; 32], - pub signature: ::ethers::core::types::Bytes, - } - ///Container type for all input parameters for the `signer` function with signature `signer()` and selector `0x238ac933` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "signer", abi = "signer()")] - pub struct SignerCall; - ///Container type for all input parameters for the `transferOwnership` function with signature `transferOwnership(address)` and selector `0xf2fde38b` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "transferOwnership", abi = "transferOwnership(address)")] - pub struct TransferOwnershipCall { - pub new_owner: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `upgradeToAndCall` function with signature `upgradeToAndCall(address,bytes)` and selector `0x4f1ef286` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "upgradeToAndCall", abi = "upgradeToAndCall(address,bytes)")] - pub struct UpgradeToAndCallCall { - pub new_implementation: ::ethers::core::types::Address, - pub data: ::ethers::core::types::Bytes, - } - ///Container type for all of the contract's call - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum ECDSAOwnedDKIMRegistryCalls { - RevokePrefix(RevokePrefixCall), - SetPrefix(SetPrefixCall), - UpgradeInterfaceVersion(UpgradeInterfaceVersionCall), - ChangeSigner(ChangeSignerCall), - ComputeSignedMsg(ComputeSignedMsgCall), - DkimRegistry(DkimRegistryCall), - Initialize(InitializeCall), - IsDKIMPublicKeyHashValid(IsDKIMPublicKeyHashValidCall), - Owner(OwnerCall), - ProxiableUUID(ProxiableUUIDCall), - RenounceOwnership(RenounceOwnershipCall), - RevokeDKIMPublicKeyHash(RevokeDKIMPublicKeyHashCall), - SetDKIMPublicKeyHash(SetDKIMPublicKeyHashCall), - Signer(SignerCall), - TransferOwnership(TransferOwnershipCall), - UpgradeToAndCall(UpgradeToAndCallCall), - } - impl ::ethers::core::abi::AbiDecode for ECDSAOwnedDKIMRegistryCalls { - fn decode( - data: impl AsRef<[u8]>, - ) -> ::core::result::Result { - let data = data.as_ref(); - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::RevokePrefix(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::SetPrefix(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpgradeInterfaceVersion(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ChangeSigner(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ComputeSignedMsg(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::DkimRegistry(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Initialize(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::IsDKIMPublicKeyHashValid(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Owner(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ProxiableUUID(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::RenounceOwnership(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::RevokeDKIMPublicKeyHash(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::SetDKIMPublicKeyHash(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Signer(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::TransferOwnership(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpgradeToAndCall(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData.into()) - } - } - impl ::ethers::core::abi::AbiEncode for ECDSAOwnedDKIMRegistryCalls { - fn encode(self) -> Vec { - match self { - Self::RevokePrefix(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::SetPrefix(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UpgradeInterfaceVersion(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ChangeSigner(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ComputeSignedMsg(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::DkimRegistry(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Initialize(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::IsDKIMPublicKeyHashValid(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Owner(element) => ::ethers::core::abi::AbiEncode::encode(element), - Self::ProxiableUUID(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::RenounceOwnership(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::RevokeDKIMPublicKeyHash(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::SetDKIMPublicKeyHash(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Signer(element) => ::ethers::core::abi::AbiEncode::encode(element), - Self::TransferOwnership(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UpgradeToAndCall(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - } - } - } - impl ::core::fmt::Display for ECDSAOwnedDKIMRegistryCalls { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::RevokePrefix(element) => ::core::fmt::Display::fmt(element, f), - Self::SetPrefix(element) => ::core::fmt::Display::fmt(element, f), - Self::UpgradeInterfaceVersion(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ChangeSigner(element) => ::core::fmt::Display::fmt(element, f), - Self::ComputeSignedMsg(element) => ::core::fmt::Display::fmt(element, f), - Self::DkimRegistry(element) => ::core::fmt::Display::fmt(element, f), - Self::Initialize(element) => ::core::fmt::Display::fmt(element, f), - Self::IsDKIMPublicKeyHashValid(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::Owner(element) => ::core::fmt::Display::fmt(element, f), - Self::ProxiableUUID(element) => ::core::fmt::Display::fmt(element, f), - Self::RenounceOwnership(element) => ::core::fmt::Display::fmt(element, f), - Self::RevokeDKIMPublicKeyHash(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::SetDKIMPublicKeyHash(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::Signer(element) => ::core::fmt::Display::fmt(element, f), - Self::TransferOwnership(element) => ::core::fmt::Display::fmt(element, f), - Self::UpgradeToAndCall(element) => ::core::fmt::Display::fmt(element, f), - } - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: RevokePrefixCall) -> Self { - Self::RevokePrefix(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: SetPrefixCall) -> Self { - Self::SetPrefix(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryCalls { - fn from(value: UpgradeInterfaceVersionCall) -> Self { - Self::UpgradeInterfaceVersion(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: ChangeSignerCall) -> Self { - Self::ChangeSigner(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: ComputeSignedMsgCall) -> Self { - Self::ComputeSignedMsg(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: DkimRegistryCall) -> Self { - Self::DkimRegistry(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: InitializeCall) -> Self { - Self::Initialize(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryCalls { - fn from(value: IsDKIMPublicKeyHashValidCall) -> Self { - Self::IsDKIMPublicKeyHashValid(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: OwnerCall) -> Self { - Self::Owner(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: ProxiableUUIDCall) -> Self { - Self::ProxiableUUID(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: RenounceOwnershipCall) -> Self { - Self::RenounceOwnership(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryCalls { - fn from(value: RevokeDKIMPublicKeyHashCall) -> Self { - Self::RevokeDKIMPublicKeyHash(value) - } - } - impl ::core::convert::From - for ECDSAOwnedDKIMRegistryCalls { - fn from(value: SetDKIMPublicKeyHashCall) -> Self { - Self::SetDKIMPublicKeyHash(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: SignerCall) -> Self { - Self::Signer(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: TransferOwnershipCall) -> Self { - Self::TransferOwnership(value) - } - } - impl ::core::convert::From for ECDSAOwnedDKIMRegistryCalls { - fn from(value: UpgradeToAndCallCall) -> Self { - Self::UpgradeToAndCall(value) - } - } - ///Container type for all return fields from the `REVOKE_PREFIX` function with signature `REVOKE_PREFIX()` and selector `0xd507c320` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct RevokePrefixReturn(pub ::std::string::String); - ///Container type for all return fields from the `SET_PREFIX` function with signature `SET_PREFIX()` and selector `0x07f1eaf5` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct SetPrefixReturn(pub ::std::string::String); - ///Container type for all return fields from the `UPGRADE_INTERFACE_VERSION` function with signature `UPGRADE_INTERFACE_VERSION()` and selector `0xad3cb1cc` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct UpgradeInterfaceVersionReturn(pub ::std::string::String); - ///Container type for all return fields from the `computeSignedMsg` function with signature `computeSignedMsg(string,string,string,bytes32)` and selector `0xaec79361` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ComputeSignedMsgReturn(pub ::std::string::String); - ///Container type for all return fields from the `dkimRegistry` function with signature `dkimRegistry()` and selector `0x6423f1e2` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct DkimRegistryReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `isDKIMPublicKeyHashValid` function with signature `isDKIMPublicKeyHashValid(string,bytes32)` and selector `0xe7a7977a` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct IsDKIMPublicKeyHashValidReturn(pub bool); - ///Container type for all return fields from the `owner` function with signature `owner()` and selector `0x8da5cb5b` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct OwnerReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `proxiableUUID` function with signature `proxiableUUID()` and selector `0x52d1902d` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ProxiableUUIDReturn(pub [u8; 32]); - ///Container type for all return fields from the `signer` function with signature `signer()` and selector `0x238ac933` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct SignerReturn(pub ::ethers::core::types::Address); -} diff --git a/packages/relayer/src/abis/email_account_recovery.rs b/packages/relayer/src/abis/email_account_recovery.rs deleted file mode 100644 index 72cf8eb6..00000000 --- a/packages/relayer/src/abis/email_account_recovery.rs +++ /dev/null @@ -1,1588 +0,0 @@ -pub use email_account_recovery::*; -/// This module was auto-generated with ethers-rs Abigen. -/// More information at: -#[allow( - clippy::enum_variant_names, - clippy::too_many_arguments, - clippy::upper_case_acronyms, - clippy::type_complexity, - dead_code, - non_camel_case_types, -)] -pub mod email_account_recovery { - #[allow(deprecated)] - fn __abi() -> ::ethers::core::abi::Abi { - ::ethers::core::abi::ethabi::Contract { - constructor: ::core::option::Option::None, - functions: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("acceptanceCommandTemplates"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "acceptanceCommandTemplates", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::String, - ), - ), - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string[][]"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("completeRecovery"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("completeRecovery"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("account"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("completeCalldata"), - kind: ::ethers::core::abi::ethabi::ParamType::Bytes, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("computeAcceptanceTemplateId"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "computeAcceptanceTemplateId", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("templateIdx"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::Pure, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("computeEmailAuthAddress"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "computeEmailAuthAddress", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("recoveredAccount"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("accountSalt"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("computeRecoveryTemplateId"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "computeRecoveryTemplateId", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("templateIdx"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::Pure, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("dkim"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("dkim"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("dkimAddr"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("dkimAddr"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("emailAuthImplementation"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "emailAuthImplementation", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("emailAuthImplementationAddr"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "emailAuthImplementationAddr", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned( - "extractRecoveredAccountFromAcceptanceCommand", - ), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "extractRecoveredAccountFromAcceptanceCommand", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("commandParams"), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Bytes, - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes[]"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("templateIdx"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned( - "extractRecoveredAccountFromRecoveryCommand", - ), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "extractRecoveredAccountFromRecoveryCommand", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("commandParams"), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Bytes, - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes[]"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("templateIdx"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("handleAcceptance"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("handleAcceptance"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("emailAuthMsg"), - kind: ::ethers::core::abi::ethabi::ParamType::Tuple( - ::std::vec![ - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Bytes, - ), - ), - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::Tuple( - ::std::vec![ - ::ethers::core::abi::ethabi::ParamType::String, - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::String, - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::Bool, - ::ethers::core::abi::ethabi::ParamType::Bytes, - ], - ), - ], - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("struct EmailAuthMsg"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("templateIdx"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("handleRecovery"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("handleRecovery"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("emailAuthMsg"), - kind: ::ethers::core::abi::ethabi::ParamType::Tuple( - ::std::vec![ - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Bytes, - ), - ), - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::Tuple( - ::std::vec![ - ::ethers::core::abi::ethabi::ParamType::String, - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::String, - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::Bool, - ::ethers::core::abi::ethabi::ParamType::Bytes, - ], - ), - ], - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("struct EmailAuthMsg"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("templateIdx"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("isActivated"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("isActivated"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("recoveredAccount"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bool"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("recoveryCommandTemplates"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "recoveryCommandTemplates", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::String, - ), - ), - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string[][]"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("verifier"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("verifier"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("verifierAddr"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("verifierAddr"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ]), - events: ::std::collections::BTreeMap::new(), - errors: ::std::collections::BTreeMap::new(), - receive: false, - fallback: false, - } - } - ///The parsed JSON ABI of the contract. - pub static EMAILACCOUNTRECOVERY_ABI: ::ethers::contract::Lazy< - ::ethers::core::abi::Abi, - > = ::ethers::contract::Lazy::new(__abi); - pub struct EmailAccountRecovery(::ethers::contract::Contract); - impl ::core::clone::Clone for EmailAccountRecovery { - fn clone(&self) -> Self { - Self(::core::clone::Clone::clone(&self.0)) - } - } - impl ::core::ops::Deref for EmailAccountRecovery { - type Target = ::ethers::contract::Contract; - fn deref(&self) -> &Self::Target { - &self.0 - } - } - impl ::core::ops::DerefMut for EmailAccountRecovery { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } - } - impl ::core::fmt::Debug for EmailAccountRecovery { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(::core::stringify!(EmailAccountRecovery)) - .field(&self.address()) - .finish() - } - } - impl EmailAccountRecovery { - /// Creates a new contract instance with the specified `ethers` client at - /// `address`. The contract derefs to a `ethers::Contract` object. - pub fn new>( - address: T, - client: ::std::sync::Arc, - ) -> Self { - Self( - ::ethers::contract::Contract::new( - address.into(), - EMAILACCOUNTRECOVERY_ABI.clone(), - client, - ), - ) - } - ///Calls the contract's `acceptanceCommandTemplates` (0x222f6cb5) function - pub fn acceptance_command_templates( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::std::vec::Vec<::std::vec::Vec<::std::string::String>>, - > { - self.0 - .method_hash([34, 47, 108, 181], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `completeRecovery` (0xc18d09cf) function - pub fn complete_recovery( - &self, - account: ::ethers::core::types::Address, - complete_calldata: ::ethers::core::types::Bytes, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([193, 141, 9, 207], (account, complete_calldata)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `computeAcceptanceTemplateId` (0x32ccc2f2) function - pub fn compute_acceptance_template_id( - &self, - template_idx: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([50, 204, 194, 242], template_idx) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `computeEmailAuthAddress` (0x3a8eab14) function - pub fn compute_email_auth_address( - &self, - recovered_account: ::ethers::core::types::Address, - account_salt: [u8; 32], - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([58, 142, 171, 20], (recovered_account, account_salt)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `computeRecoveryTemplateId` (0x6da99515) function - pub fn compute_recovery_template_id( - &self, - template_idx: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([109, 169, 149, 21], template_idx) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `dkim` (0x400ad5ce) function - pub fn dkim( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([64, 10, 213, 206], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `dkimAddr` (0x73357f85) function - pub fn dkim_addr( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([115, 53, 127, 133], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `emailAuthImplementation` (0xb6201692) function - pub fn email_auth_implementation( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([182, 32, 22, 146], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `emailAuthImplementationAddr` (0x1098e02e) function - pub fn email_auth_implementation_addr( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([16, 152, 224, 46], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `extractRecoveredAccountFromAcceptanceCommand` (0x2c4ce129) function - pub fn extract_recovered_account_from_acceptance_command( - &self, - command_params: ::std::vec::Vec<::ethers::core::types::Bytes>, - template_idx: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([44, 76, 225, 41], (command_params, template_idx)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `extractRecoveredAccountFromRecoveryCommand` (0xa5e3ee70) function - pub fn extract_recovered_account_from_recovery_command( - &self, - command_params: ::std::vec::Vec<::ethers::core::types::Bytes>, - template_idx: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([165, 227, 238, 112], (command_params, template_idx)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `handleAcceptance` (0x0481af67) function - pub fn handle_acceptance( - &self, - email_auth_msg: EmailAuthMsg, - template_idx: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([4, 129, 175, 103], (email_auth_msg, template_idx)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `handleRecovery` (0xb68126fa) function - pub fn handle_recovery( - &self, - email_auth_msg: EmailAuthMsg, - template_idx: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([182, 129, 38, 250], (email_auth_msg, template_idx)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `isActivated` (0xc9faa7c5) function - pub fn is_activated( - &self, - recovered_account: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([201, 250, 167, 197], recovered_account) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `recoveryCommandTemplates` (0x3ef01b8f) function - pub fn recovery_command_templates( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::std::vec::Vec<::std::vec::Vec<::std::string::String>>, - > { - self.0 - .method_hash([62, 240, 27, 143], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `verifier` (0x2b7ac3f3) function - pub fn verifier( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([43, 122, 195, 243], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `verifierAddr` (0x663ea2e2) function - pub fn verifier_addr( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([102, 62, 162, 226], ()) - .expect("method not found (this should never happen)") - } - } - impl From<::ethers::contract::Contract> - for EmailAccountRecovery { - fn from(contract: ::ethers::contract::Contract) -> Self { - Self::new(contract.address(), contract.client()) - } - } - ///Container type for all input parameters for the `acceptanceCommandTemplates` function with signature `acceptanceCommandTemplates()` and selector `0x222f6cb5` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "acceptanceCommandTemplates", abi = "acceptanceCommandTemplates()")] - pub struct AcceptanceCommandTemplatesCall; - ///Container type for all input parameters for the `completeRecovery` function with signature `completeRecovery(address,bytes)` and selector `0xc18d09cf` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "completeRecovery", abi = "completeRecovery(address,bytes)")] - pub struct CompleteRecoveryCall { - pub account: ::ethers::core::types::Address, - pub complete_calldata: ::ethers::core::types::Bytes, - } - ///Container type for all input parameters for the `computeAcceptanceTemplateId` function with signature `computeAcceptanceTemplateId(uint256)` and selector `0x32ccc2f2` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "computeAcceptanceTemplateId", - abi = "computeAcceptanceTemplateId(uint256)" - )] - pub struct ComputeAcceptanceTemplateIdCall { - pub template_idx: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `computeEmailAuthAddress` function with signature `computeEmailAuthAddress(address,bytes32)` and selector `0x3a8eab14` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "computeEmailAuthAddress", - abi = "computeEmailAuthAddress(address,bytes32)" - )] - pub struct ComputeEmailAuthAddressCall { - pub recovered_account: ::ethers::core::types::Address, - pub account_salt: [u8; 32], - } - ///Container type for all input parameters for the `computeRecoveryTemplateId` function with signature `computeRecoveryTemplateId(uint256)` and selector `0x6da99515` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "computeRecoveryTemplateId", - abi = "computeRecoveryTemplateId(uint256)" - )] - pub struct ComputeRecoveryTemplateIdCall { - pub template_idx: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `dkim` function with signature `dkim()` and selector `0x400ad5ce` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "dkim", abi = "dkim()")] - pub struct DkimCall; - ///Container type for all input parameters for the `dkimAddr` function with signature `dkimAddr()` and selector `0x73357f85` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "dkimAddr", abi = "dkimAddr()")] - pub struct DkimAddrCall; - ///Container type for all input parameters for the `emailAuthImplementation` function with signature `emailAuthImplementation()` and selector `0xb6201692` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "emailAuthImplementation", abi = "emailAuthImplementation()")] - pub struct EmailAuthImplementationCall; - ///Container type for all input parameters for the `emailAuthImplementationAddr` function with signature `emailAuthImplementationAddr()` and selector `0x1098e02e` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "emailAuthImplementationAddr", - abi = "emailAuthImplementationAddr()" - )] - pub struct EmailAuthImplementationAddrCall; - ///Container type for all input parameters for the `extractRecoveredAccountFromAcceptanceCommand` function with signature `extractRecoveredAccountFromAcceptanceCommand(bytes[],uint256)` and selector `0x2c4ce129` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "extractRecoveredAccountFromAcceptanceCommand", - abi = "extractRecoveredAccountFromAcceptanceCommand(bytes[],uint256)" - )] - pub struct ExtractRecoveredAccountFromAcceptanceCommandCall { - pub command_params: ::std::vec::Vec<::ethers::core::types::Bytes>, - pub template_idx: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `extractRecoveredAccountFromRecoveryCommand` function with signature `extractRecoveredAccountFromRecoveryCommand(bytes[],uint256)` and selector `0xa5e3ee70` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "extractRecoveredAccountFromRecoveryCommand", - abi = "extractRecoveredAccountFromRecoveryCommand(bytes[],uint256)" - )] - pub struct ExtractRecoveredAccountFromRecoveryCommandCall { - pub command_params: ::std::vec::Vec<::ethers::core::types::Bytes>, - pub template_idx: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `handleAcceptance` function with signature `handleAcceptance((uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)),uint256)` and selector `0x0481af67` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "handleAcceptance", - abi = "handleAcceptance((uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)),uint256)" - )] - pub struct HandleAcceptanceCall { - pub email_auth_msg: EmailAuthMsg, - pub template_idx: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `handleRecovery` function with signature `handleRecovery((uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)),uint256)` and selector `0xb68126fa` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "handleRecovery", - abi = "handleRecovery((uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)),uint256)" - )] - pub struct HandleRecoveryCall { - pub email_auth_msg: EmailAuthMsg, - pub template_idx: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `isActivated` function with signature `isActivated(address)` and selector `0xc9faa7c5` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "isActivated", abi = "isActivated(address)")] - pub struct IsActivatedCall { - pub recovered_account: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `recoveryCommandTemplates` function with signature `recoveryCommandTemplates()` and selector `0x3ef01b8f` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "recoveryCommandTemplates", abi = "recoveryCommandTemplates()")] - pub struct RecoveryCommandTemplatesCall; - ///Container type for all input parameters for the `verifier` function with signature `verifier()` and selector `0x2b7ac3f3` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "verifier", abi = "verifier()")] - pub struct VerifierCall; - ///Container type for all input parameters for the `verifierAddr` function with signature `verifierAddr()` and selector `0x663ea2e2` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "verifierAddr", abi = "verifierAddr()")] - pub struct VerifierAddrCall; - ///Container type for all of the contract's call - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum EmailAccountRecoveryCalls { - AcceptanceCommandTemplates(AcceptanceCommandTemplatesCall), - CompleteRecovery(CompleteRecoveryCall), - ComputeAcceptanceTemplateId(ComputeAcceptanceTemplateIdCall), - ComputeEmailAuthAddress(ComputeEmailAuthAddressCall), - ComputeRecoveryTemplateId(ComputeRecoveryTemplateIdCall), - Dkim(DkimCall), - DkimAddr(DkimAddrCall), - EmailAuthImplementation(EmailAuthImplementationCall), - EmailAuthImplementationAddr(EmailAuthImplementationAddrCall), - ExtractRecoveredAccountFromAcceptanceCommand( - ExtractRecoveredAccountFromAcceptanceCommandCall, - ), - ExtractRecoveredAccountFromRecoveryCommand( - ExtractRecoveredAccountFromRecoveryCommandCall, - ), - HandleAcceptance(HandleAcceptanceCall), - HandleRecovery(HandleRecoveryCall), - IsActivated(IsActivatedCall), - RecoveryCommandTemplates(RecoveryCommandTemplatesCall), - Verifier(VerifierCall), - VerifierAddr(VerifierAddrCall), - } - impl ::ethers::core::abi::AbiDecode for EmailAccountRecoveryCalls { - fn decode( - data: impl AsRef<[u8]>, - ) -> ::core::result::Result { - let data = data.as_ref(); - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::AcceptanceCommandTemplates(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::CompleteRecovery(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ComputeAcceptanceTemplateId(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ComputeEmailAuthAddress(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ComputeRecoveryTemplateId(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Dkim(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::DkimAddr(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::EmailAuthImplementation(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::EmailAuthImplementationAddr(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ExtractRecoveredAccountFromAcceptanceCommand(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ExtractRecoveredAccountFromRecoveryCommand(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::HandleAcceptance(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::HandleRecovery(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::IsActivated(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::RecoveryCommandTemplates(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Verifier(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::VerifierAddr(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData.into()) - } - } - impl ::ethers::core::abi::AbiEncode for EmailAccountRecoveryCalls { - fn encode(self) -> Vec { - match self { - Self::AcceptanceCommandTemplates(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::CompleteRecovery(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ComputeAcceptanceTemplateId(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ComputeEmailAuthAddress(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ComputeRecoveryTemplateId(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Dkim(element) => ::ethers::core::abi::AbiEncode::encode(element), - Self::DkimAddr(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::EmailAuthImplementation(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::EmailAuthImplementationAddr(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ExtractRecoveredAccountFromAcceptanceCommand(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ExtractRecoveredAccountFromRecoveryCommand(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::HandleAcceptance(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::HandleRecovery(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::IsActivated(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::RecoveryCommandTemplates(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Verifier(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::VerifierAddr(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - } - } - } - impl ::core::fmt::Display for EmailAccountRecoveryCalls { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::AcceptanceCommandTemplates(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::CompleteRecovery(element) => ::core::fmt::Display::fmt(element, f), - Self::ComputeAcceptanceTemplateId(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ComputeEmailAuthAddress(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ComputeRecoveryTemplateId(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::Dkim(element) => ::core::fmt::Display::fmt(element, f), - Self::DkimAddr(element) => ::core::fmt::Display::fmt(element, f), - Self::EmailAuthImplementation(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::EmailAuthImplementationAddr(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ExtractRecoveredAccountFromAcceptanceCommand(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ExtractRecoveredAccountFromRecoveryCommand(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::HandleAcceptance(element) => ::core::fmt::Display::fmt(element, f), - Self::HandleRecovery(element) => ::core::fmt::Display::fmt(element, f), - Self::IsActivated(element) => ::core::fmt::Display::fmt(element, f), - Self::RecoveryCommandTemplates(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::Verifier(element) => ::core::fmt::Display::fmt(element, f), - Self::VerifierAddr(element) => ::core::fmt::Display::fmt(element, f), - } - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: AcceptanceCommandTemplatesCall) -> Self { - Self::AcceptanceCommandTemplates(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: CompleteRecoveryCall) -> Self { - Self::CompleteRecovery(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: ComputeAcceptanceTemplateIdCall) -> Self { - Self::ComputeAcceptanceTemplateId(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: ComputeEmailAuthAddressCall) -> Self { - Self::ComputeEmailAuthAddress(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: ComputeRecoveryTemplateIdCall) -> Self { - Self::ComputeRecoveryTemplateId(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: DkimCall) -> Self { - Self::Dkim(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: DkimAddrCall) -> Self { - Self::DkimAddr(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: EmailAuthImplementationCall) -> Self { - Self::EmailAuthImplementation(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: EmailAuthImplementationAddrCall) -> Self { - Self::EmailAuthImplementationAddr(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: ExtractRecoveredAccountFromAcceptanceCommandCall) -> Self { - Self::ExtractRecoveredAccountFromAcceptanceCommand(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: ExtractRecoveredAccountFromRecoveryCommandCall) -> Self { - Self::ExtractRecoveredAccountFromRecoveryCommand(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: HandleAcceptanceCall) -> Self { - Self::HandleAcceptance(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: HandleRecoveryCall) -> Self { - Self::HandleRecovery(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: IsActivatedCall) -> Self { - Self::IsActivated(value) - } - } - impl ::core::convert::From - for EmailAccountRecoveryCalls { - fn from(value: RecoveryCommandTemplatesCall) -> Self { - Self::RecoveryCommandTemplates(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: VerifierCall) -> Self { - Self::Verifier(value) - } - } - impl ::core::convert::From for EmailAccountRecoveryCalls { - fn from(value: VerifierAddrCall) -> Self { - Self::VerifierAddr(value) - } - } - ///Container type for all return fields from the `acceptanceCommandTemplates` function with signature `acceptanceCommandTemplates()` and selector `0x222f6cb5` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct AcceptanceCommandTemplatesReturn( - pub ::std::vec::Vec<::std::vec::Vec<::std::string::String>>, - ); - ///Container type for all return fields from the `computeAcceptanceTemplateId` function with signature `computeAcceptanceTemplateId(uint256)` and selector `0x32ccc2f2` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ComputeAcceptanceTemplateIdReturn(pub ::ethers::core::types::U256); - ///Container type for all return fields from the `computeEmailAuthAddress` function with signature `computeEmailAuthAddress(address,bytes32)` and selector `0x3a8eab14` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ComputeEmailAuthAddressReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `computeRecoveryTemplateId` function with signature `computeRecoveryTemplateId(uint256)` and selector `0x6da99515` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ComputeRecoveryTemplateIdReturn(pub ::ethers::core::types::U256); - ///Container type for all return fields from the `dkim` function with signature `dkim()` and selector `0x400ad5ce` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct DkimReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `dkimAddr` function with signature `dkimAddr()` and selector `0x73357f85` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct DkimAddrReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `emailAuthImplementation` function with signature `emailAuthImplementation()` and selector `0xb6201692` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct EmailAuthImplementationReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `emailAuthImplementationAddr` function with signature `emailAuthImplementationAddr()` and selector `0x1098e02e` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct EmailAuthImplementationAddrReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `extractRecoveredAccountFromAcceptanceCommand` function with signature `extractRecoveredAccountFromAcceptanceCommand(bytes[],uint256)` and selector `0x2c4ce129` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ExtractRecoveredAccountFromAcceptanceCommandReturn( - pub ::ethers::core::types::Address, - ); - ///Container type for all return fields from the `extractRecoveredAccountFromRecoveryCommand` function with signature `extractRecoveredAccountFromRecoveryCommand(bytes[],uint256)` and selector `0xa5e3ee70` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ExtractRecoveredAccountFromRecoveryCommandReturn( - pub ::ethers::core::types::Address, - ); - ///Container type for all return fields from the `isActivated` function with signature `isActivated(address)` and selector `0xc9faa7c5` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct IsActivatedReturn(pub bool); - ///Container type for all return fields from the `recoveryCommandTemplates` function with signature `recoveryCommandTemplates()` and selector `0x3ef01b8f` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct RecoveryCommandTemplatesReturn( - pub ::std::vec::Vec<::std::vec::Vec<::std::string::String>>, - ); - ///Container type for all return fields from the `verifier` function with signature `verifier()` and selector `0x2b7ac3f3` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct VerifierReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `verifierAddr` function with signature `verifierAddr()` and selector `0x663ea2e2` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct VerifierAddrReturn(pub ::ethers::core::types::Address); - ///`EmailAuthMsg(uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes))` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct EmailAuthMsg { - pub template_id: ::ethers::core::types::U256, - pub command_params: ::std::vec::Vec<::ethers::core::types::Bytes>, - pub skipped_command_prefix: ::ethers::core::types::U256, - pub proof: EmailProof, - } - ///`EmailProof(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct EmailProof { - pub domain_name: ::std::string::String, - pub public_key_hash: [u8; 32], - pub timestamp: ::ethers::core::types::U256, - pub masked_command: ::std::string::String, - pub email_nullifier: [u8; 32], - pub account_salt: [u8; 32], - pub is_code_exist: bool, - pub proof: ::ethers::core::types::Bytes, - } -} diff --git a/packages/relayer/src/abis/email_auth.rs b/packages/relayer/src/abis/email_auth.rs deleted file mode 100644 index 01764e80..00000000 --- a/packages/relayer/src/abis/email_auth.rs +++ /dev/null @@ -1,3055 +0,0 @@ -pub use email_auth::*; -/// This module was auto-generated with ethers-rs Abigen. -/// More information at: -#[allow( - clippy::enum_variant_names, - clippy::too_many_arguments, - clippy::upper_case_acronyms, - clippy::type_complexity, - dead_code, - non_camel_case_types, -)] -pub mod email_auth { - #[allow(deprecated)] - fn __abi() -> ::ethers::core::abi::Abi { - ::ethers::core::abi::ethabi::Contract { - constructor: ::core::option::Option::Some(::ethers::core::abi::ethabi::Constructor { - inputs: ::std::vec![], - }), - functions: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("UPGRADE_INTERFACE_VERSION"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "UPGRADE_INTERFACE_VERSION", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("accountSalt"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("accountSalt"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("authEmail"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("authEmail"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("emailAuthMsg"), - kind: ::ethers::core::abi::ethabi::ParamType::Tuple( - ::std::vec![ - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::Bytes, - ), - ), - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::Tuple( - ::std::vec![ - ::ethers::core::abi::ethabi::ParamType::String, - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::Uint(256usize), - ::ethers::core::abi::ethabi::ParamType::String, - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::FixedBytes(32usize), - ::ethers::core::abi::ethabi::ParamType::Bool, - ::ethers::core::abi::ethabi::ParamType::Bytes, - ], - ), - ], - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("struct EmailAuthMsg"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("commandTemplates"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("commandTemplates"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::String, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("controller"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("controller"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("deleteCommandTemplate"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "deleteCommandTemplate", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("dkimRegistryAddr"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("dkimRegistryAddr"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("getCommandTemplate"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("getCommandTemplate"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::String, - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string[]"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("initDKIMRegistry"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("initDKIMRegistry"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_dkimRegistryAddr"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("initVerifier"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("initVerifier"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_verifierAddr"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("initialize"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("initialize"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_initialOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_accountSalt"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_controller"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("insertCommandTemplate"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "insertCommandTemplate", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_commandTemplate"), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::String, - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string[]"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("lastTimestamp"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("lastTimestamp"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("owner"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("owner"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("proxiableUUID"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("proxiableUUID"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("renounceOwnership"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("renounceOwnership"), - inputs: ::std::vec![], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("setTimestampCheckEnabled"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "setTimestampCheckEnabled", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_enabled"), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bool"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("timestampCheckEnabled"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "timestampCheckEnabled", - ), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bool"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("transferOwnership"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("transferOwnership"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("newOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("updateCommandTemplate"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned( - "updateCommandTemplate", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("uint256"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_commandTemplate"), - kind: ::ethers::core::abi::ethabi::ParamType::Array( - ::std::boxed::Box::new( - ::ethers::core::abi::ethabi::ParamType::String, - ), - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("string[]"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("updateDKIMRegistry"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("updateDKIMRegistry"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_dkimRegistryAddr"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("updateVerifier"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("updateVerifier"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("_verifierAddr"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::NonPayable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("upgradeToAndCall"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("upgradeToAndCall"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("newImplementation"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("data"), - kind: ::ethers::core::abi::ethabi::ParamType::Bytes, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes"), - ), - }, - ], - outputs: ::std::vec![], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::Payable, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("usedNullifiers"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("usedNullifiers"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bool"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("verifierAddr"), - ::std::vec![ - ::ethers::core::abi::ethabi::Function { - name: ::std::borrow::ToOwned::to_owned("verifierAddr"), - inputs: ::std::vec![], - outputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::string::String::new(), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - constant: ::core::option::Option::None, - state_mutability: ::ethers::core::abi::ethabi::StateMutability::View, - }, - ], - ), - ]), - events: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("CommandTemplateDeleted"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "CommandTemplateDeleted", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("CommandTemplateInserted"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "CommandTemplateInserted", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("CommandTemplateUpdated"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "CommandTemplateUpdated", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("DKIMRegistryUpdated"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "DKIMRegistryUpdated", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("dkimRegistry"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("EmailAuthed"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned("EmailAuthed"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("emailNullifier"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - indexed: true, - }, - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("accountSalt"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - indexed: true, - }, - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("isCodeExist"), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - indexed: false, - }, - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("templateId"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint( - 256usize, - ), - indexed: false, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("Initialized"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned("Initialized"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("version"), - kind: ::ethers::core::abi::ethabi::ParamType::Uint(64usize), - indexed: false, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("OwnershipTransferred"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "OwnershipTransferred", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("previousOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("newOwner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("TimestampCheckEnabled"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned( - "TimestampCheckEnabled", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("enabled"), - kind: ::ethers::core::abi::ethabi::ParamType::Bool, - indexed: false, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("Upgraded"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned("Upgraded"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("implementation"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("VerifierUpdated"), - ::std::vec![ - ::ethers::core::abi::ethabi::Event { - name: ::std::borrow::ToOwned::to_owned("VerifierUpdated"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::EventParam { - name: ::std::borrow::ToOwned::to_owned("verifier"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - indexed: true, - }, - ], - anonymous: false, - }, - ], - ), - ]), - errors: ::core::convert::From::from([ - ( - ::std::borrow::ToOwned::to_owned("AddressEmptyCode"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("AddressEmptyCode"), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("target"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ERC1967InvalidImplementation"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "ERC1967InvalidImplementation", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("implementation"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("ERC1967NonPayable"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("ERC1967NonPayable"), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("FailedInnerCall"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("FailedInnerCall"), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("InvalidInitialization"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "InvalidInitialization", - ), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("NotInitializing"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned("NotInitializing"), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("OwnableInvalidOwner"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "OwnableInvalidOwner", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("owner"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("OwnableUnauthorizedAccount"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "OwnableUnauthorizedAccount", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("account"), - kind: ::ethers::core::abi::ethabi::ParamType::Address, - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("address"), - ), - }, - ], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("UUPSUnauthorizedCallContext"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "UUPSUnauthorizedCallContext", - ), - inputs: ::std::vec![], - }, - ], - ), - ( - ::std::borrow::ToOwned::to_owned("UUPSUnsupportedProxiableUUID"), - ::std::vec![ - ::ethers::core::abi::ethabi::AbiError { - name: ::std::borrow::ToOwned::to_owned( - "UUPSUnsupportedProxiableUUID", - ), - inputs: ::std::vec![ - ::ethers::core::abi::ethabi::Param { - name: ::std::borrow::ToOwned::to_owned("slot"), - kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( - 32usize, - ), - internal_type: ::core::option::Option::Some( - ::std::borrow::ToOwned::to_owned("bytes32"), - ), - }, - ], - }, - ], - ), - ]), - receive: false, - fallback: false, - } - } - ///The parsed JSON ABI of the contract. - pub static EMAILAUTH_ABI: ::ethers::contract::Lazy<::ethers::core::abi::Abi> = ::ethers::contract::Lazy::new( - __abi, - ); - pub struct EmailAuth(::ethers::contract::Contract); - impl ::core::clone::Clone for EmailAuth { - fn clone(&self) -> Self { - Self(::core::clone::Clone::clone(&self.0)) - } - } - impl ::core::ops::Deref for EmailAuth { - type Target = ::ethers::contract::Contract; - fn deref(&self) -> &Self::Target { - &self.0 - } - } - impl ::core::ops::DerefMut for EmailAuth { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } - } - impl ::core::fmt::Debug for EmailAuth { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(::core::stringify!(EmailAuth)).field(&self.address()).finish() - } - } - impl EmailAuth { - /// Creates a new contract instance with the specified `ethers` client at - /// `address`. The contract derefs to a `ethers::Contract` object. - pub fn new>( - address: T, - client: ::std::sync::Arc, - ) -> Self { - Self( - ::ethers::contract::Contract::new( - address.into(), - EMAILAUTH_ABI.clone(), - client, - ), - ) - } - ///Calls the contract's `UPGRADE_INTERFACE_VERSION` (0xad3cb1cc) function - pub fn upgrade_interface_version( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([173, 60, 177, 204], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `accountSalt` (0x6c74921e) function - pub fn account_salt( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([108, 116, 146, 30], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `authEmail` (0xad3f5f9b) function - pub fn auth_email( - &self, - email_auth_msg: EmailAuthMsg, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([173, 63, 95, 155], (email_auth_msg,)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `commandTemplates` (0x091c1650) function - pub fn command_templates( - &self, - p0: ::ethers::core::types::U256, - p1: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([9, 28, 22, 80], (p0, p1)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `controller` (0xf77c4791) function - pub fn controller( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([247, 124, 71, 145], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `deleteCommandTemplate` (0x640e8b69) function - pub fn delete_command_template( - &self, - template_id: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([100, 14, 139, 105], template_id) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `dkimRegistryAddr` (0x1bc01b83) function - pub fn dkim_registry_addr( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([27, 192, 27, 131], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `getCommandTemplate` (0x95e33c08) function - pub fn get_command_template( - &self, - template_id: ::ethers::core::types::U256, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::std::vec::Vec<::std::string::String>, - > { - self.0 - .method_hash([149, 227, 60, 8], template_id) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `initDKIMRegistry` (0x557cf5ef) function - pub fn init_dkim_registry( - &self, - dkim_registry_addr: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([85, 124, 245, 239], dkim_registry_addr) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `initVerifier` (0x4141407c) function - pub fn init_verifier( - &self, - verifier_addr: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([65, 65, 64, 124], verifier_addr) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `initialize` (0xd26b3e6e) function - pub fn initialize( - &self, - initial_owner: ::ethers::core::types::Address, - account_salt: [u8; 32], - controller: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash( - [210, 107, 62, 110], - (initial_owner, account_salt, controller), - ) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `insertCommandTemplate` (0x8ff3730f) function - pub fn insert_command_template( - &self, - template_id: ::ethers::core::types::U256, - command_template: ::std::vec::Vec<::std::string::String>, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([143, 243, 115, 15], (template_id, command_template)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `lastTimestamp` (0x19d8ac61) function - pub fn last_timestamp( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([25, 216, 172, 97], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `owner` (0x8da5cb5b) function - pub fn owner( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([141, 165, 203, 91], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `proxiableUUID` (0x52d1902d) function - pub fn proxiable_uuid( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([82, 209, 144, 45], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `renounceOwnership` (0x715018a6) function - pub fn renounce_ownership( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([113, 80, 24, 166], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `setTimestampCheckEnabled` (0xe453c0f3) function - pub fn set_timestamp_check_enabled( - &self, - enabled: bool, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([228, 83, 192, 243], enabled) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `timestampCheckEnabled` (0x3e56f529) function - pub fn timestamp_check_enabled( - &self, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([62, 86, 245, 41], ()) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `transferOwnership` (0xf2fde38b) function - pub fn transfer_ownership( - &self, - new_owner: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([242, 253, 227, 139], new_owner) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `updateCommandTemplate` (0x24e33f11) function - pub fn update_command_template( - &self, - template_id: ::ethers::core::types::U256, - command_template: ::std::vec::Vec<::std::string::String>, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([36, 227, 63, 17], (template_id, command_template)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `updateDKIMRegistry` (0xa500125c) function - pub fn update_dkim_registry( - &self, - dkim_registry_addr: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([165, 0, 18, 92], dkim_registry_addr) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `updateVerifier` (0x97fc007c) function - pub fn update_verifier( - &self, - verifier_addr: ::ethers::core::types::Address, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([151, 252, 0, 124], verifier_addr) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `upgradeToAndCall` (0x4f1ef286) function - pub fn upgrade_to_and_call( - &self, - new_implementation: ::ethers::core::types::Address, - data: ::ethers::core::types::Bytes, - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([79, 30, 242, 134], (new_implementation, data)) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `usedNullifiers` (0x206137aa) function - pub fn used_nullifiers( - &self, - p0: [u8; 32], - ) -> ::ethers::contract::builders::ContractCall { - self.0 - .method_hash([32, 97, 55, 170], p0) - .expect("method not found (this should never happen)") - } - ///Calls the contract's `verifierAddr` (0x663ea2e2) function - pub fn verifier_addr( - &self, - ) -> ::ethers::contract::builders::ContractCall< - M, - ::ethers::core::types::Address, - > { - self.0 - .method_hash([102, 62, 162, 226], ()) - .expect("method not found (this should never happen)") - } - ///Gets the contract's `CommandTemplateDeleted` event - pub fn command_template_deleted_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - CommandTemplateDeletedFilter, - > { - self.0.event() - } - ///Gets the contract's `CommandTemplateInserted` event - pub fn command_template_inserted_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - CommandTemplateInsertedFilter, - > { - self.0.event() - } - ///Gets the contract's `CommandTemplateUpdated` event - pub fn command_template_updated_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - CommandTemplateUpdatedFilter, - > { - self.0.event() - } - ///Gets the contract's `DKIMRegistryUpdated` event - pub fn dkim_registry_updated_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - DkimregistryUpdatedFilter, - > { - self.0.event() - } - ///Gets the contract's `EmailAuthed` event - pub fn email_authed_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - EmailAuthedFilter, - > { - self.0.event() - } - ///Gets the contract's `Initialized` event - pub fn initialized_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - InitializedFilter, - > { - self.0.event() - } - ///Gets the contract's `OwnershipTransferred` event - pub fn ownership_transferred_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - OwnershipTransferredFilter, - > { - self.0.event() - } - ///Gets the contract's `TimestampCheckEnabled` event - pub fn timestamp_check_enabled_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - TimestampCheckEnabledFilter, - > { - self.0.event() - } - ///Gets the contract's `Upgraded` event - pub fn upgraded_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - UpgradedFilter, - > { - self.0.event() - } - ///Gets the contract's `VerifierUpdated` event - pub fn verifier_updated_filter( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - VerifierUpdatedFilter, - > { - self.0.event() - } - /// Returns an `Event` builder for all the events of this contract. - pub fn events( - &self, - ) -> ::ethers::contract::builders::Event< - ::std::sync::Arc, - M, - EmailAuthEvents, - > { - self.0.event_with_filter(::core::default::Default::default()) - } - } - impl From<::ethers::contract::Contract> - for EmailAuth { - fn from(contract: ::ethers::contract::Contract) -> Self { - Self::new(contract.address(), contract.client()) - } - } - ///Custom Error type `AddressEmptyCode` with signature `AddressEmptyCode(address)` and selector `0x9996b315` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "AddressEmptyCode", abi = "AddressEmptyCode(address)")] - pub struct AddressEmptyCode { - pub target: ::ethers::core::types::Address, - } - ///Custom Error type `ERC1967InvalidImplementation` with signature `ERC1967InvalidImplementation(address)` and selector `0x4c9c8ce3` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "ERC1967InvalidImplementation", - abi = "ERC1967InvalidImplementation(address)" - )] - pub struct ERC1967InvalidImplementation { - pub implementation: ::ethers::core::types::Address, - } - ///Custom Error type `ERC1967NonPayable` with signature `ERC1967NonPayable()` and selector `0xb398979f` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "ERC1967NonPayable", abi = "ERC1967NonPayable()")] - pub struct ERC1967NonPayable; - ///Custom Error type `FailedInnerCall` with signature `FailedInnerCall()` and selector `0x1425ea42` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "FailedInnerCall", abi = "FailedInnerCall()")] - pub struct FailedInnerCall; - ///Custom Error type `InvalidInitialization` with signature `InvalidInitialization()` and selector `0xf92ee8a9` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "InvalidInitialization", abi = "InvalidInitialization()")] - pub struct InvalidInitialization; - ///Custom Error type `NotInitializing` with signature `NotInitializing()` and selector `0xd7e6bcf8` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "NotInitializing", abi = "NotInitializing()")] - pub struct NotInitializing; - ///Custom Error type `OwnableInvalidOwner` with signature `OwnableInvalidOwner(address)` and selector `0x1e4fbdf7` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror(name = "OwnableInvalidOwner", abi = "OwnableInvalidOwner(address)")] - pub struct OwnableInvalidOwner { - pub owner: ::ethers::core::types::Address, - } - ///Custom Error type `OwnableUnauthorizedAccount` with signature `OwnableUnauthorizedAccount(address)` and selector `0x118cdaa7` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "OwnableUnauthorizedAccount", - abi = "OwnableUnauthorizedAccount(address)" - )] - pub struct OwnableUnauthorizedAccount { - pub account: ::ethers::core::types::Address, - } - ///Custom Error type `UUPSUnauthorizedCallContext` with signature `UUPSUnauthorizedCallContext()` and selector `0xe07c8dba` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "UUPSUnauthorizedCallContext", - abi = "UUPSUnauthorizedCallContext()" - )] - pub struct UUPSUnauthorizedCallContext; - ///Custom Error type `UUPSUnsupportedProxiableUUID` with signature `UUPSUnsupportedProxiableUUID(bytes32)` and selector `0xaa1d49a4` - #[derive( - Clone, - ::ethers::contract::EthError, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[etherror( - name = "UUPSUnsupportedProxiableUUID", - abi = "UUPSUnsupportedProxiableUUID(bytes32)" - )] - pub struct UUPSUnsupportedProxiableUUID { - pub slot: [u8; 32], - } - ///Container type for all of the contract's custom errors - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum EmailAuthErrors { - AddressEmptyCode(AddressEmptyCode), - ERC1967InvalidImplementation(ERC1967InvalidImplementation), - ERC1967NonPayable(ERC1967NonPayable), - FailedInnerCall(FailedInnerCall), - InvalidInitialization(InvalidInitialization), - NotInitializing(NotInitializing), - OwnableInvalidOwner(OwnableInvalidOwner), - OwnableUnauthorizedAccount(OwnableUnauthorizedAccount), - UUPSUnauthorizedCallContext(UUPSUnauthorizedCallContext), - UUPSUnsupportedProxiableUUID(UUPSUnsupportedProxiableUUID), - /// The standard solidity revert string, with selector - /// Error(string) -- 0x08c379a0 - RevertString(::std::string::String), - } - impl ::ethers::core::abi::AbiDecode for EmailAuthErrors { - fn decode( - data: impl AsRef<[u8]>, - ) -> ::core::result::Result { - let data = data.as_ref(); - if let Ok(decoded) = <::std::string::String as ::ethers::core::abi::AbiDecode>::decode( - data, - ) { - return Ok(Self::RevertString(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::AddressEmptyCode(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ERC1967InvalidImplementation(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ERC1967NonPayable(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::FailedInnerCall(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::InvalidInitialization(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::NotInitializing(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::OwnableInvalidOwner(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::OwnableUnauthorizedAccount(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UUPSUnauthorizedCallContext(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UUPSUnsupportedProxiableUUID(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData.into()) - } - } - impl ::ethers::core::abi::AbiEncode for EmailAuthErrors { - fn encode(self) -> ::std::vec::Vec { - match self { - Self::AddressEmptyCode(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ERC1967InvalidImplementation(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::ERC1967NonPayable(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::FailedInnerCall(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::InvalidInitialization(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::NotInitializing(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::OwnableInvalidOwner(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::OwnableUnauthorizedAccount(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UUPSUnauthorizedCallContext(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UUPSUnsupportedProxiableUUID(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::RevertString(s) => ::ethers::core::abi::AbiEncode::encode(s), - } - } - } - impl ::ethers::contract::ContractRevert for EmailAuthErrors { - fn valid_selector(selector: [u8; 4]) -> bool { - match selector { - [0x08, 0xc3, 0x79, 0xa0] => true, - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ if selector - == ::selector() => { - true - } - _ => false, - } - } - } - impl ::core::fmt::Display for EmailAuthErrors { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::AddressEmptyCode(element) => ::core::fmt::Display::fmt(element, f), - Self::ERC1967InvalidImplementation(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::ERC1967NonPayable(element) => ::core::fmt::Display::fmt(element, f), - Self::FailedInnerCall(element) => ::core::fmt::Display::fmt(element, f), - Self::InvalidInitialization(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::NotInitializing(element) => ::core::fmt::Display::fmt(element, f), - Self::OwnableInvalidOwner(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::OwnableUnauthorizedAccount(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UUPSUnauthorizedCallContext(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UUPSUnsupportedProxiableUUID(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::RevertString(s) => ::core::fmt::Display::fmt(s, f), - } - } - } - impl ::core::convert::From<::std::string::String> for EmailAuthErrors { - fn from(value: String) -> Self { - Self::RevertString(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: AddressEmptyCode) -> Self { - Self::AddressEmptyCode(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: ERC1967InvalidImplementation) -> Self { - Self::ERC1967InvalidImplementation(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: ERC1967NonPayable) -> Self { - Self::ERC1967NonPayable(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: FailedInnerCall) -> Self { - Self::FailedInnerCall(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: InvalidInitialization) -> Self { - Self::InvalidInitialization(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: NotInitializing) -> Self { - Self::NotInitializing(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: OwnableInvalidOwner) -> Self { - Self::OwnableInvalidOwner(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: OwnableUnauthorizedAccount) -> Self { - Self::OwnableUnauthorizedAccount(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: UUPSUnauthorizedCallContext) -> Self { - Self::UUPSUnauthorizedCallContext(value) - } - } - impl ::core::convert::From for EmailAuthErrors { - fn from(value: UUPSUnsupportedProxiableUUID) -> Self { - Self::UUPSUnsupportedProxiableUUID(value) - } - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "CommandTemplateDeleted", abi = "CommandTemplateDeleted(uint256)")] - pub struct CommandTemplateDeletedFilter { - #[ethevent(indexed)] - pub template_id: ::ethers::core::types::U256, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent( - name = "CommandTemplateInserted", - abi = "CommandTemplateInserted(uint256)" - )] - pub struct CommandTemplateInsertedFilter { - #[ethevent(indexed)] - pub template_id: ::ethers::core::types::U256, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "CommandTemplateUpdated", abi = "CommandTemplateUpdated(uint256)")] - pub struct CommandTemplateUpdatedFilter { - #[ethevent(indexed)] - pub template_id: ::ethers::core::types::U256, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "DKIMRegistryUpdated", abi = "DKIMRegistryUpdated(address)")] - pub struct DkimregistryUpdatedFilter { - #[ethevent(indexed)] - pub dkim_registry: ::ethers::core::types::Address, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "EmailAuthed", abi = "EmailAuthed(bytes32,bytes32,bool,uint256)")] - pub struct EmailAuthedFilter { - #[ethevent(indexed)] - pub email_nullifier: [u8; 32], - #[ethevent(indexed)] - pub account_salt: [u8; 32], - pub is_code_exist: bool, - pub template_id: ::ethers::core::types::U256, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "Initialized", abi = "Initialized(uint64)")] - pub struct InitializedFilter { - pub version: u64, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent( - name = "OwnershipTransferred", - abi = "OwnershipTransferred(address,address)" - )] - pub struct OwnershipTransferredFilter { - #[ethevent(indexed)] - pub previous_owner: ::ethers::core::types::Address, - #[ethevent(indexed)] - pub new_owner: ::ethers::core::types::Address, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "TimestampCheckEnabled", abi = "TimestampCheckEnabled(bool)")] - pub struct TimestampCheckEnabledFilter { - pub enabled: bool, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "Upgraded", abi = "Upgraded(address)")] - pub struct UpgradedFilter { - #[ethevent(indexed)] - pub implementation: ::ethers::core::types::Address, - } - #[derive( - Clone, - ::ethers::contract::EthEvent, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethevent(name = "VerifierUpdated", abi = "VerifierUpdated(address)")] - pub struct VerifierUpdatedFilter { - #[ethevent(indexed)] - pub verifier: ::ethers::core::types::Address, - } - ///Container type for all of the contract's events - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum EmailAuthEvents { - CommandTemplateDeletedFilter(CommandTemplateDeletedFilter), - CommandTemplateInsertedFilter(CommandTemplateInsertedFilter), - CommandTemplateUpdatedFilter(CommandTemplateUpdatedFilter), - DkimregistryUpdatedFilter(DkimregistryUpdatedFilter), - EmailAuthedFilter(EmailAuthedFilter), - InitializedFilter(InitializedFilter), - OwnershipTransferredFilter(OwnershipTransferredFilter), - TimestampCheckEnabledFilter(TimestampCheckEnabledFilter), - UpgradedFilter(UpgradedFilter), - VerifierUpdatedFilter(VerifierUpdatedFilter), - } - impl ::ethers::contract::EthLogDecode for EmailAuthEvents { - fn decode_log( - log: &::ethers::core::abi::RawLog, - ) -> ::core::result::Result { - if let Ok(decoded) = CommandTemplateDeletedFilter::decode_log(log) { - return Ok(EmailAuthEvents::CommandTemplateDeletedFilter(decoded)); - } - if let Ok(decoded) = CommandTemplateInsertedFilter::decode_log(log) { - return Ok(EmailAuthEvents::CommandTemplateInsertedFilter(decoded)); - } - if let Ok(decoded) = CommandTemplateUpdatedFilter::decode_log(log) { - return Ok(EmailAuthEvents::CommandTemplateUpdatedFilter(decoded)); - } - if let Ok(decoded) = DkimregistryUpdatedFilter::decode_log(log) { - return Ok(EmailAuthEvents::DkimregistryUpdatedFilter(decoded)); - } - if let Ok(decoded) = EmailAuthedFilter::decode_log(log) { - return Ok(EmailAuthEvents::EmailAuthedFilter(decoded)); - } - if let Ok(decoded) = InitializedFilter::decode_log(log) { - return Ok(EmailAuthEvents::InitializedFilter(decoded)); - } - if let Ok(decoded) = OwnershipTransferredFilter::decode_log(log) { - return Ok(EmailAuthEvents::OwnershipTransferredFilter(decoded)); - } - if let Ok(decoded) = TimestampCheckEnabledFilter::decode_log(log) { - return Ok(EmailAuthEvents::TimestampCheckEnabledFilter(decoded)); - } - if let Ok(decoded) = UpgradedFilter::decode_log(log) { - return Ok(EmailAuthEvents::UpgradedFilter(decoded)); - } - if let Ok(decoded) = VerifierUpdatedFilter::decode_log(log) { - return Ok(EmailAuthEvents::VerifierUpdatedFilter(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData) - } - } - impl ::core::fmt::Display for EmailAuthEvents { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::CommandTemplateDeletedFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::CommandTemplateInsertedFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::CommandTemplateUpdatedFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::DkimregistryUpdatedFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::EmailAuthedFilter(element) => ::core::fmt::Display::fmt(element, f), - Self::InitializedFilter(element) => ::core::fmt::Display::fmt(element, f), - Self::OwnershipTransferredFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::TimestampCheckEnabledFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UpgradedFilter(element) => ::core::fmt::Display::fmt(element, f), - Self::VerifierUpdatedFilter(element) => { - ::core::fmt::Display::fmt(element, f) - } - } - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: CommandTemplateDeletedFilter) -> Self { - Self::CommandTemplateDeletedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: CommandTemplateInsertedFilter) -> Self { - Self::CommandTemplateInsertedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: CommandTemplateUpdatedFilter) -> Self { - Self::CommandTemplateUpdatedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: DkimregistryUpdatedFilter) -> Self { - Self::DkimregistryUpdatedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: EmailAuthedFilter) -> Self { - Self::EmailAuthedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: InitializedFilter) -> Self { - Self::InitializedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: OwnershipTransferredFilter) -> Self { - Self::OwnershipTransferredFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: TimestampCheckEnabledFilter) -> Self { - Self::TimestampCheckEnabledFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: UpgradedFilter) -> Self { - Self::UpgradedFilter(value) - } - } - impl ::core::convert::From for EmailAuthEvents { - fn from(value: VerifierUpdatedFilter) -> Self { - Self::VerifierUpdatedFilter(value) - } - } - ///Container type for all input parameters for the `UPGRADE_INTERFACE_VERSION` function with signature `UPGRADE_INTERFACE_VERSION()` and selector `0xad3cb1cc` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "UPGRADE_INTERFACE_VERSION", abi = "UPGRADE_INTERFACE_VERSION()")] - pub struct UpgradeInterfaceVersionCall; - ///Container type for all input parameters for the `accountSalt` function with signature `accountSalt()` and selector `0x6c74921e` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "accountSalt", abi = "accountSalt()")] - pub struct AccountSaltCall; - ///Container type for all input parameters for the `authEmail` function with signature `authEmail((uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)))` and selector `0xad3f5f9b` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "authEmail", - abi = "authEmail((uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)))" - )] - pub struct AuthEmailCall { - pub email_auth_msg: EmailAuthMsg, - } - ///Container type for all input parameters for the `commandTemplates` function with signature `commandTemplates(uint256,uint256)` and selector `0x091c1650` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "commandTemplates", abi = "commandTemplates(uint256,uint256)")] - pub struct CommandTemplatesCall( - pub ::ethers::core::types::U256, - pub ::ethers::core::types::U256, - ); - ///Container type for all input parameters for the `controller` function with signature `controller()` and selector `0xf77c4791` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "controller", abi = "controller()")] - pub struct ControllerCall; - ///Container type for all input parameters for the `deleteCommandTemplate` function with signature `deleteCommandTemplate(uint256)` and selector `0x640e8b69` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "deleteCommandTemplate", abi = "deleteCommandTemplate(uint256)")] - pub struct DeleteCommandTemplateCall { - pub template_id: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `dkimRegistryAddr` function with signature `dkimRegistryAddr()` and selector `0x1bc01b83` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "dkimRegistryAddr", abi = "dkimRegistryAddr()")] - pub struct DkimRegistryAddrCall; - ///Container type for all input parameters for the `getCommandTemplate` function with signature `getCommandTemplate(uint256)` and selector `0x95e33c08` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "getCommandTemplate", abi = "getCommandTemplate(uint256)")] - pub struct GetCommandTemplateCall { - pub template_id: ::ethers::core::types::U256, - } - ///Container type for all input parameters for the `initDKIMRegistry` function with signature `initDKIMRegistry(address)` and selector `0x557cf5ef` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "initDKIMRegistry", abi = "initDKIMRegistry(address)")] - pub struct InitDKIMRegistryCall { - pub dkim_registry_addr: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `initVerifier` function with signature `initVerifier(address)` and selector `0x4141407c` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "initVerifier", abi = "initVerifier(address)")] - pub struct InitVerifierCall { - pub verifier_addr: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `initialize` function with signature `initialize(address,bytes32,address)` and selector `0xd26b3e6e` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "initialize", abi = "initialize(address,bytes32,address)")] - pub struct InitializeCall { - pub initial_owner: ::ethers::core::types::Address, - pub account_salt: [u8; 32], - pub controller: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `insertCommandTemplate` function with signature `insertCommandTemplate(uint256,string[])` and selector `0x8ff3730f` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "insertCommandTemplate", - abi = "insertCommandTemplate(uint256,string[])" - )] - pub struct InsertCommandTemplateCall { - pub template_id: ::ethers::core::types::U256, - pub command_template: ::std::vec::Vec<::std::string::String>, - } - ///Container type for all input parameters for the `lastTimestamp` function with signature `lastTimestamp()` and selector `0x19d8ac61` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "lastTimestamp", abi = "lastTimestamp()")] - pub struct LastTimestampCall; - ///Container type for all input parameters for the `owner` function with signature `owner()` and selector `0x8da5cb5b` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "owner", abi = "owner()")] - pub struct OwnerCall; - ///Container type for all input parameters for the `proxiableUUID` function with signature `proxiableUUID()` and selector `0x52d1902d` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "proxiableUUID", abi = "proxiableUUID()")] - pub struct ProxiableUUIDCall; - ///Container type for all input parameters for the `renounceOwnership` function with signature `renounceOwnership()` and selector `0x715018a6` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "renounceOwnership", abi = "renounceOwnership()")] - pub struct RenounceOwnershipCall; - ///Container type for all input parameters for the `setTimestampCheckEnabled` function with signature `setTimestampCheckEnabled(bool)` and selector `0xe453c0f3` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "setTimestampCheckEnabled", abi = "setTimestampCheckEnabled(bool)")] - pub struct SetTimestampCheckEnabledCall { - pub enabled: bool, - } - ///Container type for all input parameters for the `timestampCheckEnabled` function with signature `timestampCheckEnabled()` and selector `0x3e56f529` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "timestampCheckEnabled", abi = "timestampCheckEnabled()")] - pub struct TimestampCheckEnabledCall; - ///Container type for all input parameters for the `transferOwnership` function with signature `transferOwnership(address)` and selector `0xf2fde38b` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "transferOwnership", abi = "transferOwnership(address)")] - pub struct TransferOwnershipCall { - pub new_owner: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `updateCommandTemplate` function with signature `updateCommandTemplate(uint256,string[])` and selector `0x24e33f11` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall( - name = "updateCommandTemplate", - abi = "updateCommandTemplate(uint256,string[])" - )] - pub struct UpdateCommandTemplateCall { - pub template_id: ::ethers::core::types::U256, - pub command_template: ::std::vec::Vec<::std::string::String>, - } - ///Container type for all input parameters for the `updateDKIMRegistry` function with signature `updateDKIMRegistry(address)` and selector `0xa500125c` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "updateDKIMRegistry", abi = "updateDKIMRegistry(address)")] - pub struct UpdateDKIMRegistryCall { - pub dkim_registry_addr: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `updateVerifier` function with signature `updateVerifier(address)` and selector `0x97fc007c` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "updateVerifier", abi = "updateVerifier(address)")] - pub struct UpdateVerifierCall { - pub verifier_addr: ::ethers::core::types::Address, - } - ///Container type for all input parameters for the `upgradeToAndCall` function with signature `upgradeToAndCall(address,bytes)` and selector `0x4f1ef286` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "upgradeToAndCall", abi = "upgradeToAndCall(address,bytes)")] - pub struct UpgradeToAndCallCall { - pub new_implementation: ::ethers::core::types::Address, - pub data: ::ethers::core::types::Bytes, - } - ///Container type for all input parameters for the `usedNullifiers` function with signature `usedNullifiers(bytes32)` and selector `0x206137aa` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "usedNullifiers", abi = "usedNullifiers(bytes32)")] - pub struct UsedNullifiersCall(pub [u8; 32]); - ///Container type for all input parameters for the `verifierAddr` function with signature `verifierAddr()` and selector `0x663ea2e2` - #[derive( - Clone, - ::ethers::contract::EthCall, - ::ethers::contract::EthDisplay, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - #[ethcall(name = "verifierAddr", abi = "verifierAddr()")] - pub struct VerifierAddrCall; - ///Container type for all of the contract's call - #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] - pub enum EmailAuthCalls { - UpgradeInterfaceVersion(UpgradeInterfaceVersionCall), - AccountSalt(AccountSaltCall), - AuthEmail(AuthEmailCall), - CommandTemplates(CommandTemplatesCall), - Controller(ControllerCall), - DeleteCommandTemplate(DeleteCommandTemplateCall), - DkimRegistryAddr(DkimRegistryAddrCall), - GetCommandTemplate(GetCommandTemplateCall), - InitDKIMRegistry(InitDKIMRegistryCall), - InitVerifier(InitVerifierCall), - Initialize(InitializeCall), - InsertCommandTemplate(InsertCommandTemplateCall), - LastTimestamp(LastTimestampCall), - Owner(OwnerCall), - ProxiableUUID(ProxiableUUIDCall), - RenounceOwnership(RenounceOwnershipCall), - SetTimestampCheckEnabled(SetTimestampCheckEnabledCall), - TimestampCheckEnabled(TimestampCheckEnabledCall), - TransferOwnership(TransferOwnershipCall), - UpdateCommandTemplate(UpdateCommandTemplateCall), - UpdateDKIMRegistry(UpdateDKIMRegistryCall), - UpdateVerifier(UpdateVerifierCall), - UpgradeToAndCall(UpgradeToAndCallCall), - UsedNullifiers(UsedNullifiersCall), - VerifierAddr(VerifierAddrCall), - } - impl ::ethers::core::abi::AbiDecode for EmailAuthCalls { - fn decode( - data: impl AsRef<[u8]>, - ) -> ::core::result::Result { - let data = data.as_ref(); - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpgradeInterfaceVersion(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::AccountSalt(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::AuthEmail(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::CommandTemplates(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Controller(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::DeleteCommandTemplate(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::DkimRegistryAddr(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::GetCommandTemplate(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::InitDKIMRegistry(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::InitVerifier(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Initialize(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::InsertCommandTemplate(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::LastTimestamp(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::Owner(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::ProxiableUUID(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::RenounceOwnership(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::SetTimestampCheckEnabled(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::TimestampCheckEnabled(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::TransferOwnership(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpdateCommandTemplate(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpdateDKIMRegistry(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpdateVerifier(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UpgradeToAndCall(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::UsedNullifiers(decoded)); - } - if let Ok(decoded) = ::decode( - data, - ) { - return Ok(Self::VerifierAddr(decoded)); - } - Err(::ethers::core::abi::Error::InvalidData.into()) - } - } - impl ::ethers::core::abi::AbiEncode for EmailAuthCalls { - fn encode(self) -> Vec { - match self { - Self::UpgradeInterfaceVersion(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::AccountSalt(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::AuthEmail(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::CommandTemplates(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Controller(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::DeleteCommandTemplate(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::DkimRegistryAddr(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::GetCommandTemplate(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::InitDKIMRegistry(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::InitVerifier(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Initialize(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::InsertCommandTemplate(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::LastTimestamp(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::Owner(element) => ::ethers::core::abi::AbiEncode::encode(element), - Self::ProxiableUUID(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::RenounceOwnership(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::SetTimestampCheckEnabled(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::TimestampCheckEnabled(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::TransferOwnership(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UpdateCommandTemplate(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UpdateDKIMRegistry(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UpdateVerifier(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UpgradeToAndCall(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::UsedNullifiers(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - Self::VerifierAddr(element) => { - ::ethers::core::abi::AbiEncode::encode(element) - } - } - } - } - impl ::core::fmt::Display for EmailAuthCalls { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - Self::UpgradeInterfaceVersion(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::AccountSalt(element) => ::core::fmt::Display::fmt(element, f), - Self::AuthEmail(element) => ::core::fmt::Display::fmt(element, f), - Self::CommandTemplates(element) => ::core::fmt::Display::fmt(element, f), - Self::Controller(element) => ::core::fmt::Display::fmt(element, f), - Self::DeleteCommandTemplate(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::DkimRegistryAddr(element) => ::core::fmt::Display::fmt(element, f), - Self::GetCommandTemplate(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::InitDKIMRegistry(element) => ::core::fmt::Display::fmt(element, f), - Self::InitVerifier(element) => ::core::fmt::Display::fmt(element, f), - Self::Initialize(element) => ::core::fmt::Display::fmt(element, f), - Self::InsertCommandTemplate(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::LastTimestamp(element) => ::core::fmt::Display::fmt(element, f), - Self::Owner(element) => ::core::fmt::Display::fmt(element, f), - Self::ProxiableUUID(element) => ::core::fmt::Display::fmt(element, f), - Self::RenounceOwnership(element) => ::core::fmt::Display::fmt(element, f), - Self::SetTimestampCheckEnabled(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::TimestampCheckEnabled(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::TransferOwnership(element) => ::core::fmt::Display::fmt(element, f), - Self::UpdateCommandTemplate(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UpdateDKIMRegistry(element) => { - ::core::fmt::Display::fmt(element, f) - } - Self::UpdateVerifier(element) => ::core::fmt::Display::fmt(element, f), - Self::UpgradeToAndCall(element) => ::core::fmt::Display::fmt(element, f), - Self::UsedNullifiers(element) => ::core::fmt::Display::fmt(element, f), - Self::VerifierAddr(element) => ::core::fmt::Display::fmt(element, f), - } - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: UpgradeInterfaceVersionCall) -> Self { - Self::UpgradeInterfaceVersion(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: AccountSaltCall) -> Self { - Self::AccountSalt(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: AuthEmailCall) -> Self { - Self::AuthEmail(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: CommandTemplatesCall) -> Self { - Self::CommandTemplates(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: ControllerCall) -> Self { - Self::Controller(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: DeleteCommandTemplateCall) -> Self { - Self::DeleteCommandTemplate(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: DkimRegistryAddrCall) -> Self { - Self::DkimRegistryAddr(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: GetCommandTemplateCall) -> Self { - Self::GetCommandTemplate(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: InitDKIMRegistryCall) -> Self { - Self::InitDKIMRegistry(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: InitVerifierCall) -> Self { - Self::InitVerifier(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: InitializeCall) -> Self { - Self::Initialize(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: InsertCommandTemplateCall) -> Self { - Self::InsertCommandTemplate(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: LastTimestampCall) -> Self { - Self::LastTimestamp(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: OwnerCall) -> Self { - Self::Owner(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: ProxiableUUIDCall) -> Self { - Self::ProxiableUUID(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: RenounceOwnershipCall) -> Self { - Self::RenounceOwnership(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: SetTimestampCheckEnabledCall) -> Self { - Self::SetTimestampCheckEnabled(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: TimestampCheckEnabledCall) -> Self { - Self::TimestampCheckEnabled(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: TransferOwnershipCall) -> Self { - Self::TransferOwnership(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: UpdateCommandTemplateCall) -> Self { - Self::UpdateCommandTemplate(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: UpdateDKIMRegistryCall) -> Self { - Self::UpdateDKIMRegistry(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: UpdateVerifierCall) -> Self { - Self::UpdateVerifier(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: UpgradeToAndCallCall) -> Self { - Self::UpgradeToAndCall(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: UsedNullifiersCall) -> Self { - Self::UsedNullifiers(value) - } - } - impl ::core::convert::From for EmailAuthCalls { - fn from(value: VerifierAddrCall) -> Self { - Self::VerifierAddr(value) - } - } - ///Container type for all return fields from the `UPGRADE_INTERFACE_VERSION` function with signature `UPGRADE_INTERFACE_VERSION()` and selector `0xad3cb1cc` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct UpgradeInterfaceVersionReturn(pub ::std::string::String); - ///Container type for all return fields from the `accountSalt` function with signature `accountSalt()` and selector `0x6c74921e` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct AccountSaltReturn(pub [u8; 32]); - ///Container type for all return fields from the `commandTemplates` function with signature `commandTemplates(uint256,uint256)` and selector `0x091c1650` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct CommandTemplatesReturn(pub ::std::string::String); - ///Container type for all return fields from the `controller` function with signature `controller()` and selector `0xf77c4791` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ControllerReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `dkimRegistryAddr` function with signature `dkimRegistryAddr()` and selector `0x1bc01b83` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct DkimRegistryAddrReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `getCommandTemplate` function with signature `getCommandTemplate(uint256)` and selector `0x95e33c08` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct GetCommandTemplateReturn(pub ::std::vec::Vec<::std::string::String>); - ///Container type for all return fields from the `lastTimestamp` function with signature `lastTimestamp()` and selector `0x19d8ac61` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct LastTimestampReturn(pub ::ethers::core::types::U256); - ///Container type for all return fields from the `owner` function with signature `owner()` and selector `0x8da5cb5b` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct OwnerReturn(pub ::ethers::core::types::Address); - ///Container type for all return fields from the `proxiableUUID` function with signature `proxiableUUID()` and selector `0x52d1902d` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct ProxiableUUIDReturn(pub [u8; 32]); - ///Container type for all return fields from the `timestampCheckEnabled` function with signature `timestampCheckEnabled()` and selector `0x3e56f529` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct TimestampCheckEnabledReturn(pub bool); - ///Container type for all return fields from the `usedNullifiers` function with signature `usedNullifiers(bytes32)` and selector `0x206137aa` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct UsedNullifiersReturn(pub bool); - ///Container type for all return fields from the `verifierAddr` function with signature `verifierAddr()` and selector `0x663ea2e2` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct VerifierAddrReturn(pub ::ethers::core::types::Address); - ///`EmailAuthMsg(uint256,bytes[],uint256,(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes))` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct EmailAuthMsg { - pub template_id: ::ethers::core::types::U256, - pub command_params: ::std::vec::Vec<::ethers::core::types::Bytes>, - pub skipped_command_prefix: ::ethers::core::types::U256, - pub proof: EmailProof, - } - ///`EmailProof(string,bytes32,uint256,string,bytes32,bytes32,bool,bytes)` - #[derive( - Clone, - ::ethers::contract::EthAbiType, - ::ethers::contract::EthAbiCodec, - Default, - Debug, - PartialEq, - Eq, - Hash - )] - pub struct EmailProof { - pub domain_name: ::std::string::String, - pub public_key_hash: [u8; 32], - pub timestamp: ::ethers::core::types::U256, - pub masked_command: ::std::string::String, - pub email_nullifier: [u8; 32], - pub account_salt: [u8; 32], - pub is_code_exist: bool, - pub proof: ::ethers::core::types::Bytes, - } -} From f91fc0244eef3559ac3ab3c64c0da137ebd1c53a Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 15 Sep 2024 17:47:07 +0530 Subject: [PATCH 26/53] chore: update github actions and add PR template --- .github/pull_request_template.md | 28 +++++++++++++++++++ .../workflows/{build.yml => build-fmt.yml} | 17 +++++++++-- .github/workflows/clippy.yml | 13 --------- .github/workflows/rustfmt.yml | 13 --------- .github/workflows/unit-tests.yml | 6 ++-- 5 files changed, 45 insertions(+), 32 deletions(-) create mode 100644 .github/pull_request_template.md rename .github/workflows/{build.yml => build-fmt.yml} (77%) delete mode 100644 .github/workflows/clippy.yml delete mode 100644 .github/workflows/rustfmt.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..8b688cb0 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,28 @@ +## Description + + + + +## Type of change + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +## How Has This Been Tested? + + +- [ ] Test A +- [ ] Test B + +## Checklist: + +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published in downstream modules \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build-fmt.yml similarity index 77% rename from .github/workflows/build.yml rename to .github/workflows/build-fmt.yml index 083784e1..df36a2a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build-fmt.yml @@ -1,9 +1,9 @@ -name: Build-Test-Fmt +name: Build and Format on: [push] jobs: - build-test-fmt: + build-and-format: runs-on: ubuntu-latest steps: @@ -11,6 +11,11 @@ jobs: - run: rustup show + - name: Install rustfmt and clippy + run: | + rustup component add rustfmt + rustup component add clippy + - uses: Swatinem/rust-cache@v2 - name: Setup Node.js @@ -27,7 +32,7 @@ jobs: with: version: nightly-0079a1146b79a4aeda58b0258215bedb1f92700b - - name: Run tests + - name: Build contracts working-directory: packages/contracts run: yarn build @@ -49,3 +54,9 @@ jobs: - name: Build and check for warnings run: cargo build --release -D warnings + + - name: Check formatting + run: cargo fmt -- --check + + - name: Run clippy + run: cargo clippy -- -D warnings diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml deleted file mode 100644 index 584a0ff3..00000000 --- a/.github/workflows/clippy.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Clippy Lint Check - -on: [pull_request] - -jobs: - clippy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install clippy - run: rustup component add clippy - - name: Run clippy - run: cargo clippy -- -D warnings diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml deleted file mode 100644 index 9764b118..00000000 --- a/.github/workflows/rustfmt.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Rustfmt Check - -on: [pull_request] - -jobs: - format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install rustfmt - run: rustup component add rustfmt - - name: Check formatting - run: cargo fmt -- --check diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 457f42e1..3d784ba0 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,4 +1,4 @@ -name: unit-tests +name: Unit Tests on: [push] @@ -85,9 +85,9 @@ jobs: with: version: nightly-0079a1146b79a4aeda58b0258215bedb1f92700b - - name: Forge Build + - name: Build contracts working-directory: packages/contracts - run: forge build + run: yarn build - name: Run tests working-directory: packages/relayer From b4e547ad84327bbda7048aa1dd19a673e2cbc387 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 15 Sep 2024 18:02:39 +0530 Subject: [PATCH 27/53] fix: github action --- .github/workflows/build-fmt.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-fmt.yml b/.github/workflows/build-fmt.yml index df36a2a9..0cb1b536 100644 --- a/.github/workflows/build-fmt.yml +++ b/.github/workflows/build-fmt.yml @@ -53,7 +53,9 @@ jobs: swap-storage: true - name: Build and check for warnings - run: cargo build --release -D warnings + env: + RUSTFLAGS: "-D warnings" + run: cargo build --release - name: Check formatting run: cargo fmt -- --check From f036aaca1ce2440d05ca183fbb133aced1a9e808 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Mon, 16 Sep 2024 13:42:28 +0700 Subject: [PATCH 28/53] Remove hard-coded file_paths; Fix clippy warnings --- packages/relayer/.env.example | 2 + packages/relayer/src/abis/mod.rs | 1 + packages/relayer/src/chain.rs | 43 +++++++++---------- packages/relayer/src/core.rs | 32 +++++++------- packages/relayer/src/modules/dkim.rs | 28 ++++++------ packages/relayer/src/modules/mail.rs | 6 +-- .../relayer/src/modules/web_server/mod.rs | 4 +- .../{errors.rs => relayer_errors.rs} | 0 .../src/modules/web_server/rest_api.rs | 6 +-- packages/relayer/src/utils/mod.rs | 3 ++ packages/relayer/src/utils/strings.rs | 2 + .../relayer/src/utils/subject_templates.rs | 16 ++----- packages/relayer/src/utils/utils.rs | 4 +- rustfmt.toml | 8 ++++ 14 files changed, 79 insertions(+), 76 deletions(-) rename packages/relayer/src/modules/web_server/{errors.rs => relayer_errors.rs} (100%) create mode 100644 rustfmt.toml diff --git a/packages/relayer/.env.example b/packages/relayer/.env.example index 12957976..34721015 100644 --- a/packages/relayer/.env.example +++ b/packages/relayer/.env.example @@ -13,6 +13,8 @@ RELAYER_EMAIL_ADDR= WEB_SERVER_ADDRESS="127.0.0.1:4500" CIRCUITS_DIR_PATH= #Path to email-wallet/packages/circuits EMAIL_TEMPLATES_PATH= #Path to email templates, e.g. ./packages/relayer/eml_templates/ +SELECTOR_DEF_PATH="./src/regex_json/selector_def.json" +REQUEST_DEF_PATH="./src/regex_json/request_def.json" CANISTER_ID="q7eci-dyaaa-aaaak-qdbia-cai" PEM_PATH="./.ic.pem" diff --git a/packages/relayer/src/abis/mod.rs b/packages/relayer/src/abis/mod.rs index 5fb44ddb..6a38feb0 100644 --- a/packages/relayer/src/abis/mod.rs +++ b/packages/relayer/src/abis/mod.rs @@ -1,3 +1,4 @@ +#![allow(clippy::all)] pub mod ecdsa_owned_dkim_registry; pub mod email_account_recovery; pub mod email_auth; diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index 8de83d4e..27127ca4 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -66,7 +66,7 @@ impl ChainClient { pub async fn get_dkim_from_wallet( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, ) -> Result, anyhow::Error> { let controller_eth_addr: H160 = controller_eth_addr.parse()?; let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); @@ -76,7 +76,7 @@ impl ChainClient { pub async fn get_dkim_from_email_auth( &self, - email_auth_addr: &String, + email_auth_addr: &str, ) -> Result, anyhow::Error> { let email_auth_address: H160 = email_auth_addr.parse()?; let contract = EmailAuth::new(email_auth_address, self.client.clone()); @@ -87,9 +87,9 @@ impl ChainClient { pub async fn get_email_auth_addr_from_wallet( &self, - controller_eth_addr: &String, - wallet_addr: &String, - account_salt: &String, + controller_eth_addr: &str, + wallet_addr: &str, + account_salt: &str, ) -> Result { let controller_eth_addr: H160 = controller_eth_addr.parse()?; let wallet_address: H160 = wallet_addr.parse()?; @@ -107,7 +107,7 @@ impl ChainClient { Ok(email_auth_addr) } - pub async fn is_wallet_deployed(&self, wallet_addr_str: &String) -> Result { + pub async fn is_wallet_deployed(&self, wallet_addr_str: &str) -> Result { let wallet_addr: H160 = wallet_addr_str.parse().map_err(ChainError::HexError)?; match self.client.get_code(wallet_addr, None).await { Ok(code) => Ok(!code.is_empty()), @@ -123,7 +123,7 @@ impl ChainClient { pub async fn get_acceptance_command_templates( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, template_idx: u64, ) -> Result, ChainError> { let controller_eth_addr: H160 = @@ -141,7 +141,7 @@ impl ChainClient { pub async fn get_recovery_command_templates( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, template_idx: u64, ) -> Result, ChainError> { let controller_eth_addr: H160 = @@ -159,9 +159,9 @@ impl ChainClient { pub async fn complete_recovery( &self, - controller_eth_addr: &String, - account_eth_addr: &String, - complete_calldata: &String, + controller_eth_addr: &str, + account_eth_addr: &str, + complete_calldata: &str, ) -> Result { println!("doing complete recovery"); let controller_eth_addr: H160 = @@ -170,7 +170,7 @@ impl ChainClient { let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); let decoded_calldata = - hex::decode(&complete_calldata.trim_start_matches("0x")).expect("Decoding failed"); + hex::decode(complete_calldata.trim_start_matches("0x")).expect("Decoding failed"); println!("decoded_calldata : {:?}", decoded_calldata); let account_eth_addr = account_eth_addr @@ -208,7 +208,7 @@ impl ChainClient { pub async fn handle_acceptance( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, email_auth_msg: EmailAuthMsg, template_idx: u64, ) -> std::result::Result { @@ -239,7 +239,7 @@ impl ChainClient { pub async fn handle_recovery( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, email_auth_msg: EmailAuthMsg, template_idx: u64, ) -> std::result::Result { @@ -265,10 +265,7 @@ impl ChainClient { .unwrap_or(false)) } - pub async fn get_bytecode( - &self, - wallet_addr: &String, - ) -> std::result::Result { + pub async fn get_bytecode(&self, wallet_addr: &str) -> std::result::Result { let wallet_address: H160 = wallet_addr.parse().map_err(ChainError::HexError)?; let client_code = self .client @@ -280,7 +277,7 @@ impl ChainClient { pub async fn get_storage_at( &self, - wallet_addr: &String, + wallet_addr: &str, slot: u64, ) -> Result { let wallet_address: H160 = wallet_addr.parse()?; @@ -292,7 +289,7 @@ impl ChainClient { pub async fn get_recovered_account_from_acceptance_command( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, command_params: Vec, template_idx: u64, ) -> Result { @@ -324,7 +321,7 @@ impl ChainClient { pub async fn get_recovered_account_from_recovery_command( &self, - controller_eth_addr: &String, + controller_eth_addr: &str, command_params: Vec, template_idx: u64, ) -> Result { @@ -357,8 +354,8 @@ impl ChainClient { pub async fn get_is_activated( &self, - controller_eth_addr: &String, - account_eth_addr: &String, + controller_eth_addr: &str, + account_eth_addr: &str, ) -> Result { let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 7af369ae..f1b1926f 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -1,6 +1,8 @@ #![allow(clippy::upper_case_acronyms)] #![allow(clippy::identity_op)] +use std::fs; + use crate::abis::email_account_recovery::{EmailAuthMsg, EmailProof}; use crate::*; @@ -22,9 +24,12 @@ pub async fn handle_email(email: String) -> Result { trace!(LOG, "From address: {}", guardian_email_addr); let email_body = parsed_email.get_cleaned_body()?; - let request_decomposed_def = - serde_json::from_str(include_str!("./regex_json/request_def.json")) - .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; + let request_def_path = env::var(REQUEST_DEF_PATH_KEY) + .map_err(|_| anyhow!("ENV var {} not set", REQUEST_DEF_PATH_KEY))?; + let request_def_contents = fs::read_to_string(&request_def_path) + .map_err(|e| anyhow!("Failed to read file {}: {}", request_def_path, e))?; + let request_decomposed_def = serde_json::from_str(&request_def_contents) + .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; let request_idxes = extract_substr_idxes(&email, &request_decomposed_def)?; if request_idxes.is_empty() { return Err(EmailError::Body(WRONG_COMMAND_FORMAT.to_string())); @@ -221,15 +226,13 @@ async fn recover(params: EmailRequestContext) -> Result, start_idx: usize) -> Result { // Gather signals from start_idx to start_idx + COMMAND_FIELDS - let mut command_bytes = Vec::new(); - for i in start_idx..start_idx + COMMAND_FIELDS { - let signal = public_signals[i as usize]; - if signal == U256::zero() { - break; - } - let bytes = u256_to_bytes32_little(&signal); - command_bytes.extend_from_slice(&bytes); - } + let command_bytes: Vec = public_signals + .iter() + .skip(start_idx) + .take(COMMAND_FIELDS) + .take_while(|&signal| *signal != U256::zero()) + .flat_map(u256_to_bytes32_little) + .collect(); // Bytes to string, removing null bytes let command = String::from_utf8(command_bytes.into_iter().filter(|&b| b != 0u8).collect()) @@ -257,7 +260,7 @@ async fn update_request( account_salt: Some(bytes32_to_hex(&account_salt)), }; - let update_request_result = DB.update_request(&updated_request).await?; + DB.update_request(&updated_request).await?; Ok(()) } @@ -313,8 +316,7 @@ fn get_template_id(params: &EmailRequestContext) -> [u8; 32] { Token::Uint(params.request.template_idx.into()), ]; - let template_id = keccak256(encode(&tokens)); - template_id + keccak256(encode(&tokens)) } async fn get_encoded_command_params( diff --git a/packages/relayer/src/modules/dkim.rs b/packages/relayer/src/modules/dkim.rs index 82e9f912..b1d29c26 100644 --- a/packages/relayer/src/modules/dkim.rs +++ b/packages/relayer/src/modules/dkim.rs @@ -1,3 +1,5 @@ +use std::fs; + use anyhow::anyhow; use relayer_utils::extract_substr_idxes; use relayer_utils::LOG; @@ -41,7 +43,7 @@ impl<'a> DkimOracleClient<'a> { pub fn new(canister_id: &str, agent: &'a Agent) -> anyhow::Result { let canister = CanisterBuilder::new() .with_canister_id(canister_id) - .with_agent(&agent) + .with_agent(agent) .build()?; Ok(Self { canister }) } @@ -78,22 +80,16 @@ pub async fn check_and_update_dkim( info!(LOG, "public_key_hash {:?}", public_key_hash); let domain = parsed_email.get_email_domain()?; info!(LOG, "domain {:?}", domain); - if CLIENT.get_bytecode(&wallet_addr.to_string()).await? == Bytes::from(vec![0u8; 20]) { + if CLIENT.get_bytecode(wallet_addr).await? == Bytes::from_static(&[0u8; 20]) { info!(LOG, "wallet not deployed"); return Ok(()); } let email_auth_addr = CLIENT - .get_email_auth_addr_from_wallet( - &controller_eth_addr.to_string(), - &wallet_addr.to_string(), - &account_salt.to_string(), - ) + .get_email_auth_addr_from_wallet(controller_eth_addr, wallet_addr, account_salt) .await?; let email_auth_addr = format!("0x{:x}", email_auth_addr); - let mut dkim = CLIENT - .get_dkim_from_wallet(&controller_eth_addr.to_string()) - .await?; - if CLIENT.get_bytecode(&email_auth_addr).await? != Bytes::from(vec![]) { + let mut dkim = CLIENT.get_dkim_from_wallet(controller_eth_addr).await?; + if CLIENT.get_bytecode(&email_auth_addr).await? != Bytes::new() { dkim = CLIENT.get_dkim_from_email_auth(&email_auth_addr).await?; } info!(LOG, "dkim {:?}", dkim); @@ -108,13 +104,15 @@ pub async fn check_and_update_dkim( info!(LOG, "public key registered"); return Ok(()); } - let selector_decomposed_def = - serde_json::from_str(include_str!("../regex_json/selector_def.json")).unwrap(); + let selector_def_path = env::var(SELECTOR_DEF_PATH_KEY) + .map_err(|_| anyhow!("ENV var {} not set", SELECTOR_DEF_PATH_KEY))?; + let selector_def_contents = fs::read_to_string(&selector_def_path) + .map_err(|e| anyhow!("Failed to read file {}: {}", selector_def_path, e))?; + let selector_decomposed_def = serde_json::from_str(&selector_def_path).unwrap(); let selector = { let idxes = extract_substr_idxes(&parsed_email.canonicalized_header, &selector_decomposed_def)?[0]; - let str = parsed_email.canonicalized_header[idxes.0..idxes.1].to_string(); - str + parsed_email.canonicalized_header[idxes.0..idxes.1].to_string() }; info!(LOG, "selector {}", selector); let ic_agent = DkimOracleClient::gen_agent( diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index dfb237dc..ffc15d8e 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -100,7 +100,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, command, account_code, request_id ); - let subject = format!("Email Recovery: Acceptance Request"); + let subject = "Email Recovery: Acceptance Request".to_string(); let render_data = serde_json::json!({ "userEmailAddr": guardian_email_addr, @@ -197,7 +197,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, request_id ); - let subject = format!("Email Recovery: Recovery Request"); + let subject = "Email Recovery: Recovery Request".to_string(); let render_data = serde_json::json!({ "userEmailAddr": guardian_email_addr, @@ -408,7 +408,7 @@ pub fn parse_error(error: String) -> Result> { let revert_bytes = hex::decode(revert_data) .unwrap() .into_iter() - .filter(|&b| b >= 0x20 && b <= 0x7E) + .filter(|&b| (0x20..=0x7E).contains(&b)) .collect(); error = String::from_utf8(revert_bytes).unwrap().trim().to_string(); } diff --git a/packages/relayer/src/modules/web_server/mod.rs b/packages/relayer/src/modules/web_server/mod.rs index 14a44e7b..35ed632a 100644 --- a/packages/relayer/src/modules/web_server/mod.rs +++ b/packages/relayer/src/modules/web_server/mod.rs @@ -1,7 +1,7 @@ -pub mod errors; +pub mod relayer_errors; pub mod rest_api; pub mod server; -pub use errors::*; +pub use relayer_errors::*; pub use rest_api::*; pub use server::*; diff --git a/packages/relayer/src/modules/web_server/errors.rs b/packages/relayer/src/modules/web_server/relayer_errors.rs similarity index 100% rename from packages/relayer/src/modules/web_server/errors.rs rename to packages/relayer/src/modules/web_server/relayer_errors.rs diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 823eb6e0..454bf088 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -122,7 +122,7 @@ pub async fn handle_acceptance_request( let account_salt = calculate_account_salt(&payload.guardian_email_addr, &payload.account_code); DB.insert_request(&Request { - request_id: request_id.clone(), + request_id, account_eth_addr: account_eth_addr.clone(), controller_eth_addr: payload.controller_eth_addr.clone(), guardian_email_addr: payload.guardian_email_addr.clone(), @@ -310,7 +310,7 @@ pub async fn handle_recovery_request( { println!("email and wallet are not registered"); DB.insert_request(&Request { - request_id: request_id.clone(), + request_id, account_eth_addr: account_eth_addr.clone(), controller_eth_addr: payload.controller_eth_addr.clone(), guardian_email_addr: payload.guardian_email_addr.clone(), @@ -338,7 +338,7 @@ pub async fn handle_recovery_request( } DB.insert_request(&Request { - request_id: request_id.clone(), + request_id, account_eth_addr: account_eth_addr.clone(), controller_eth_addr: payload.controller_eth_addr.clone(), guardian_email_addr: payload.guardian_email_addr.clone(), diff --git a/packages/relayer/src/utils/mod.rs b/packages/relayer/src/utils/mod.rs index 361a451a..92b1cf5b 100644 --- a/packages/relayer/src/utils/mod.rs +++ b/packages/relayer/src/utils/mod.rs @@ -1,3 +1,6 @@ +// TODO: Remove this once we remove the utils +#![allow(clippy::module_inception)] + pub mod strings; pub mod subject_templates; pub mod utils; diff --git a/packages/relayer/src/utils/strings.rs b/packages/relayer/src/utils/strings.rs index c33a1e7f..51b610ac 100644 --- a/packages/relayer/src/utils/strings.rs +++ b/packages/relayer/src/utils/strings.rs @@ -11,6 +11,8 @@ pub const PRIVATE_KEY_KEY: &str = "PRIVATE_KEY"; pub const CHAIN_ID_KEY: &str = "CHAIN_ID"; pub const EMAIL_ACCOUNT_RECOVERY_VERSION_ID_KEY: &str = "EMAIL_ACCOUNT_RECOVERY_VERSION_ID"; pub const EMAIL_TEMPLATES_PATH_KEY: &str = "EMAIL_TEMPLATES_PATH"; +pub const SELECTOR_DEF_PATH_KEY: &str = "SELECTOR_DEF_PATH"; +pub const REQUEST_DEF_PATH_KEY: &str = "REQUEST_DEF_PATH"; // Log strings pub const JSON_LOGGER_KEY: &str = "JSON_LOGGER"; diff --git a/packages/relayer/src/utils/subject_templates.rs b/packages/relayer/src/utils/subject_templates.rs index e8ccd734..f2fe37a1 100644 --- a/packages/relayer/src/utils/subject_templates.rs +++ b/packages/relayer/src/utils/subject_templates.rs @@ -24,7 +24,7 @@ impl TemplateValue { Self::Uint(uint) => Ok(Bytes::from(abi::encode(&[Token::Uint(*uint)]))), Self::Int(int) => Ok(Bytes::from(abi::encode(&[Token::Int(int.into_raw())]))), Self::Decimals(string) => Ok(Bytes::from(abi::encode(&[Token::Uint( - Self::decimals_str_to_uint(&string, decimal_size.unwrap_or(18)), + Self::decimals_str_to_uint(string, decimal_size.unwrap_or(18)), )]))), Self::EthAddr(address) => Ok(Bytes::from(abi::encode(&[Token::Address(*address)]))), Self::Fixed(string) => Err(anyhow!("Fixed value must not be passed to abi_encode")), @@ -76,10 +76,7 @@ pub fn extract_template_vals_from_command( // Extract the values based on the matched pattern let current_input = &input[skipped_bytes..]; - match extract_template_vals(current_input, templates) { - Ok(vals) => Ok(vals), - Err(e) => Err(e), - } + extract_template_vals(current_input, templates) } else { // If there's no match, return an error indicating no match was found Err(anyhow!("Unable to match templates with input")) @@ -89,13 +86,8 @@ pub fn extract_template_vals_from_command( pub fn extract_template_vals(input: &str, templates: Vec) -> Result> { let input_decomposed: Vec<&str> = input.split_whitespace().collect(); let mut template_vals = Vec::new(); - let mut input_idx = 0; - - for template in templates.iter() { - if input_idx >= input_decomposed.len() { - break; // Prevents index out of bounds if input is shorter than template - } + for (input_idx, template) in templates.iter().enumerate() { match template.as_str() { "{string}" => { let string_match = Regex::new(STRING_REGEX) @@ -171,8 +163,6 @@ pub fn extract_template_vals(input: &str, templates: Vec) -> Result {} // Skip unknown placeholders } - - input_idx += 1; // Move to the next piece of input } Ok(template_vals) diff --git a/packages/relayer/src/utils/utils.rs b/packages/relayer/src/utils/utils.rs index 948c83fe..80bbc4dc 100644 --- a/packages/relayer/src/utils/utils.rs +++ b/packages/relayer/src/utils/utils.rs @@ -81,9 +81,9 @@ pub fn calculate_default_hash(input: &str) -> String { } pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> String { - let padded_email_addr = PaddedEmailAddr::from_email_addr(&email_addr); + let padded_email_addr = PaddedEmailAddr::from_email_addr(email_addr); let account_code = if account_code.starts_with("0x") { - hex_to_field(&account_code).unwrap() + hex_to_field(account_code).unwrap() } else { hex_to_field(&format!("0x{}", account_code)).unwrap() }; diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..a8f43d10 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,8 @@ +max_width = 100 +indent_style = "Block" +use_small_heuristics = "Default" +imports_layout = "Mixed" +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +reorder_imports = true +reorder_modules = true From deba9f3e3aa0eb19089ef62eb8f436adf01b3a7d Mon Sep 17 00:00:00 2001 From: Dimitri Date: Mon, 16 Sep 2024 15:35:41 +0700 Subject: [PATCH 29/53] Move util files from ether-email-auth to utils repo --- Cargo.lock | 4 +- packages/relayer/Cargo.toml | 3 +- packages/relayer/src/chain.rs | 1 + packages/relayer/src/core.rs | 5 +- packages/relayer/src/lib.rs | 4 +- .../src/modules/web_server/rest_api.rs | 2 +- packages/relayer/src/{utils => }/strings.rs | 0 packages/relayer/src/utils/mod.rs | 10 - .../relayer/src/utils/subject_templates.rs | 236 ------------------ packages/relayer/src/utils/utils.rs | 94 ------- 10 files changed, 12 insertions(+), 347 deletions(-) rename packages/relayer/src/{utils => }/strings.rs (100%) delete mode 100644 packages/relayer/src/utils/mod.rs delete mode 100644 packages/relayer/src/utils/subject_templates.rs delete mode 100644 packages/relayer/src/utils/utils.rs diff --git a/Cargo.lock b/Cargo.lock index fa7bc496..ac64a597 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4141,7 +4141,6 @@ dependencies = [ [[package]] name = "relayer-utils" version = "0.3.7" -source = "git+https://github.com/zkemail/relayer-utils.git#c9371a327fecb422f5e0f015ebca9199a06b658f" dependencies = [ "anyhow", "base64 0.21.7", @@ -4160,6 +4159,7 @@ dependencies = [ "poseidon-rs", "rand_core", "regex", + "reqwest 0.11.27", "rsa", "serde", "serde_json", @@ -6555,7 +6555,7 @@ dependencies = [ [[package]] name = "zk-regex-apis" version = "2.1.1" -source = "git+https://github.com/zkemail/zk-regex.git#3b626316b07081378ffdca0d36ed2bec6df5b55a" +source = "git+https://github.com/zkemail/zk-regex.git#531575345558ba938675d725bd54df45c866ef74" dependencies = [ "fancy-regex", "itertools 0.13.0", diff --git a/packages/relayer/Cargo.toml b/packages/relayer/Cargo.toml index c55e95bf..505b5a52 100644 --- a/packages/relayer/Cargo.toml +++ b/packages/relayer/Cargo.toml @@ -24,7 +24,8 @@ serde_json = "1.0.68" tiny_http = "0.12.0" lettre = { version = "0.10.4", features = ["tokio1", "tokio1-native-tls"] } ethers = { version = "2.0.10", features = ["abigen"] } -relayer-utils = { version = "0.3.7", git = "https://github.com/zkemail/relayer-utils.git" } +# relayer-utils = { version = "0.3.7", git = "https://github.com/zkemail/relayer-utils.git" } +relayer-utils = { path = "../../../relayer-utils" } futures = "0.3.28" sqlx = { version = "=0.7.3", features = ["postgres", "runtime-tokio"] } regex = "1.10.2" diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index 27127ca4..0cffe7f0 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -4,6 +4,7 @@ use ethers::middleware::Middleware; use ethers::prelude::*; use ethers::signers::Signer; use relayer_utils::converters::u64_to_u8_array_32; +use relayer_utils::TemplateValue; const CONFIRMATIONS: usize = 1; diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index f1b1926f..fd4e16ae 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -10,7 +10,10 @@ use ethers::{ abi::{encode, Token}, utils::keccak256, }; -use relayer_utils::{extract_substr_idxes, generate_email_circuit_input, EmailCircuitParams, LOG}; +use relayer_utils::{ + extract_substr_idxes, extract_template_vals_from_command, generate_email_circuit_input, + generate_proof, EmailCircuitParams, LOG, +}; const DOMAIN_FIELDS: usize = 9; const COMMAND_FIELDS: usize = 20; diff --git a/packages/relayer/src/lib.rs b/packages/relayer/src/lib.rs index c9c8a781..5cc01621 100644 --- a/packages/relayer/src/lib.rs +++ b/packages/relayer/src/lib.rs @@ -8,7 +8,7 @@ pub mod config; pub mod core; pub mod database; pub mod modules; -pub mod utils; +pub mod strings; pub use abis::*; pub use chain::*; @@ -17,7 +17,7 @@ pub use core::*; pub use database::*; pub use modules::*; use relayer_utils::LOG; -pub use utils::*; +pub use strings::*; use tokio::sync::Mutex; diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 454bf088..1f520ce7 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -3,7 +3,7 @@ use anyhow::Result; use axum::Json; use hex::decode; use rand::Rng; -use relayer_utils::LOG; +use relayer_utils::{calculate_account_salt, extract_template_vals, TemplateValue, LOG}; use serde::{Deserialize, Serialize}; use std::str; diff --git a/packages/relayer/src/utils/strings.rs b/packages/relayer/src/strings.rs similarity index 100% rename from packages/relayer/src/utils/strings.rs rename to packages/relayer/src/strings.rs diff --git a/packages/relayer/src/utils/mod.rs b/packages/relayer/src/utils/mod.rs deleted file mode 100644 index 92b1cf5b..00000000 --- a/packages/relayer/src/utils/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -// TODO: Remove this once we remove the utils -#![allow(clippy::module_inception)] - -pub mod strings; -pub mod subject_templates; -pub mod utils; - -pub use strings::*; -pub use subject_templates::*; -pub use utils::*; diff --git a/packages/relayer/src/utils/subject_templates.rs b/packages/relayer/src/utils/subject_templates.rs deleted file mode 100644 index f2fe37a1..00000000 --- a/packages/relayer/src/utils/subject_templates.rs +++ /dev/null @@ -1,236 +0,0 @@ -#![allow(clippy::upper_case_acronyms)] - -use crate::*; - -use ethers::abi::{self, Token}; -use ethers::types::{Address, Bytes, I256, U256}; -use regex::Regex; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum TemplateValue { - String(String), - Uint(U256), - Int(I256), - Decimals(String), - EthAddr(Address), - Fixed(String), -} - -impl TemplateValue { - pub fn abi_encode(&self, decimal_size: Option) -> Result { - match self { - Self::String(string) => Ok(Bytes::from(abi::encode(&[Token::String(string.clone())]))), - Self::Uint(uint) => Ok(Bytes::from(abi::encode(&[Token::Uint(*uint)]))), - Self::Int(int) => Ok(Bytes::from(abi::encode(&[Token::Int(int.into_raw())]))), - Self::Decimals(string) => Ok(Bytes::from(abi::encode(&[Token::Uint( - Self::decimals_str_to_uint(string, decimal_size.unwrap_or(18)), - )]))), - Self::EthAddr(address) => Ok(Bytes::from(abi::encode(&[Token::Address(*address)]))), - Self::Fixed(string) => Err(anyhow!("Fixed value must not be passed to abi_encode")), - } - } - - pub fn decimals_str_to_uint(str: &str, decimal_size: u8) -> U256 { - let decimal_size = decimal_size as usize; - let dot = Regex::new("\\.").unwrap().find(str); - let (before_dot_str, mut after_dot_str) = match dot { - Some(dot_match) => ( - str[0..dot_match.start()].to_string(), - str[dot_match.end()..].to_string(), - ), - None => (str.to_string(), "".to_string()), - }; - assert!(after_dot_str.len() <= decimal_size); - let num_leading_zeros = decimal_size - after_dot_str.len(); - after_dot_str.push_str(&"0".repeat(num_leading_zeros)); - U256::from_dec_str(&(before_dot_str + &after_dot_str)) - .expect("composed amount string is not valid decimal") - } -} - -pub fn extract_template_vals_from_command( - input: &str, - templates: Vec, -) -> Result, anyhow::Error> { - // Convert the template to a regex pattern, escaping necessary characters and replacing placeholders - let pattern = templates - .iter() - .map(|template| match template.as_str() { - "{string}" => STRING_REGEX.to_string(), - "{uint}" => UINT_REGEX.to_string(), - "{int}" => INT_REGEX.to_string(), - "{decimals}" => DECIMALS_REGEX.to_string(), - "{ethAddr}" => ETH_ADDR_REGEX.to_string(), - _ => regex::escape(template), - }) - .collect::>() - .join("\\s+"); - - let regex = Regex::new(&pattern).map_err(|e| anyhow!("Regex compilation failed: {}", e))?; - - // Attempt to find the pattern in the input - if let Some(matched) = regex.find(input) { - // Calculate the number of bytes to skip before the match - let skipped_bytes = matched.start(); - - // Extract the values based on the matched pattern - let current_input = &input[skipped_bytes..]; - extract_template_vals(current_input, templates) - } else { - // If there's no match, return an error indicating no match was found - Err(anyhow!("Unable to match templates with input")) - } -} - -pub fn extract_template_vals(input: &str, templates: Vec) -> Result> { - let input_decomposed: Vec<&str> = input.split_whitespace().collect(); - let mut template_vals = Vec::new(); - - for (input_idx, template) in templates.iter().enumerate() { - match template.as_str() { - "{string}" => { - let string_match = Regex::new(STRING_REGEX) - .unwrap() - .find(input_decomposed[input_idx]) - .ok_or(anyhow!("No string found"))?; - if string_match.start() != 0 { - return Err(anyhow!("String must be the whole word")); - } - let mut string = string_match.as_str().to_string(); - if string.contains("") { - string = string.split("").collect::>()[0].to_string(); - } - template_vals.push(TemplateValue::String(string)); - } - "{uint}" => { - let uint_match = Regex::new(UINT_REGEX) - .unwrap() - .find(input_decomposed[input_idx]) - .ok_or(anyhow!("No uint found"))?; - if uint_match.start() != 0 || uint_match.end() != input_decomposed[input_idx].len() - { - return Err(anyhow!("Uint must be the whole word")); - } - let mut uint_match = uint_match.as_str(); - if uint_match.contains("") { - uint_match = uint_match.split("").collect::>()[0]; - } - let uint = U256::from_dec_str(uint_match).unwrap(); - template_vals.push(TemplateValue::Uint(uint)); - } - "{int}" => { - let int_match = Regex::new(INT_REGEX) - .unwrap() - .find(input_decomposed[input_idx]) - .ok_or(anyhow!("No int found"))?; - if int_match.start() != 0 || int_match.end() != input_decomposed[input_idx].len() { - return Err(anyhow!("Int must be the whole word")); - } - let mut int_match = int_match.as_str(); - if int_match.contains("") { - int_match = int_match.split("").collect::>()[0]; - } - let int = I256::from_dec_str(int_match).unwrap(); - template_vals.push(TemplateValue::Int(int)); - } - "{decimals}" => { - let decimals_match = Regex::new(DECIMALS_REGEX) - .unwrap() - .find(input_decomposed[input_idx]) - .ok_or(anyhow!("No decimals found"))?; - if decimals_match.start() != 0 - || decimals_match.end() != input_decomposed[input_idx].len() - { - return Err(anyhow!("Decimals must be the whole word")); - } - let mut decimals = decimals_match.as_str().to_string(); - if decimals.contains("") { - decimals = decimals.split("").collect::>()[0].to_string(); - } - template_vals.push(TemplateValue::Decimals(decimals)); - } - "{ethAddr}" => { - let address_match = Regex::new(ETH_ADDR_REGEX) - .unwrap() - .find(input_decomposed[input_idx]) - .ok_or(anyhow!("No address found"))?; - if address_match.start() != 0 { - return Err(anyhow!("Address must be the whole word")); - } - let address = address_match.as_str().parse::
().unwrap(); - template_vals.push(TemplateValue::EthAddr(address)); - } - _ => {} // Skip unknown placeholders - } - } - - Ok(template_vals) -} - -// Generated by Github Copilot! -pub fn uint_to_decimal_string(uint: u128, decimal: usize) -> String { - // Convert amount to string in wei format (no decimals) - let uint_str = uint.to_string(); - let uint_length = uint_str.len(); - - // Create result vector with max length - // If less than 18 decimals, then 2 extra for "0.", otherwise one extra for "." - let mut result = vec![ - '0'; - if uint_length > decimal { - uint_length + 1 - } else { - decimal + 2 - } - ]; - let result_length = result.len(); - - // Difference between result and amount array index when copying - // If more than 18, then 1 index diff for ".", otherwise actual diff in length - let mut delta = if uint_length > decimal { - 1 - } else { - result_length - uint_length - }; - - // Boolean to indicate if we found a non-zero digit when scanning from last to first index - let mut found_non_zero_decimal = false; - - let mut actual_result_len = 0; - - // In each iteration we fill one index of result array (starting from end) - for i in (0..result_length).rev() { - // Check if we have reached the index where we need to add decimal point - if i == result_length - decimal - 1 { - // No need to add "." if there was no value in decimal places - if found_non_zero_decimal { - result[i] = '.'; - actual_result_len += 1; - } - // Set delta to 0, as we have already added decimal point (only for amount_length > 18) - delta = 0; - } - // If amountLength < 18 and we have copied everything, fill zeros - else if uint_length <= decimal && i < result_length - uint_length { - result[i] = '0'; - actual_result_len += 1; - } - // If non-zero decimal is found, or decimal point inserted (delta == 0), copy from amount array - else if found_non_zero_decimal || delta == 0 { - result[i] = uint_str.chars().nth(i - delta).unwrap(); - actual_result_len += 1; - } - // If we find non-zero decimal for the first time (trailing zeros are skipped) - else if uint_str.chars().nth(i - delta).unwrap() != '0' { - result[i] = uint_str.chars().nth(i - delta).unwrap(); - actual_result_len += 1; - found_non_zero_decimal = true; - } - } - - // Create final result string with correct length - let compact_result: String = result.into_iter().take(actual_result_len).collect(); - - compact_result -} diff --git a/packages/relayer/src/utils/utils.rs b/packages/relayer/src/utils/utils.rs deleted file mode 100644 index 80bbc4dc..00000000 --- a/packages/relayer/src/utils/utils.rs +++ /dev/null @@ -1,94 +0,0 @@ -#![allow(clippy::upper_case_acronyms)] -#![allow(clippy::identity_op)] - -use crate::*; -use ethers::abi::Token; -use ethers::types::{Bytes, U256}; - -use ::serde::Deserialize; - -use relayer_utils::*; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; - -#[derive(Debug, Clone, Deserialize)] -pub struct ProverRes { - proof: ProofJson, - pub_signals: Vec, -} - -#[derive(Debug, Clone, Deserialize)] -pub struct ProofJson { - pi_a: Vec, - pi_b: Vec>, - pi_c: Vec, -} - -impl ProofJson { - pub fn to_eth_bytes(&self) -> Result { - let pi_a = Token::FixedArray(vec![ - Token::Uint(U256::from_dec_str(self.pi_a[0].as_str())?), - Token::Uint(U256::from_dec_str(self.pi_a[1].as_str())?), - ]); - let pi_b = Token::FixedArray(vec![ - Token::FixedArray(vec![ - Token::Uint(U256::from_dec_str(self.pi_b[0][1].as_str())?), - Token::Uint(U256::from_dec_str(self.pi_b[0][0].as_str())?), - ]), - Token::FixedArray(vec![ - Token::Uint(U256::from_dec_str(self.pi_b[1][1].as_str())?), - Token::Uint(U256::from_dec_str(self.pi_b[1][0].as_str())?), - ]), - ]); - let pi_c = Token::FixedArray(vec![ - Token::Uint(U256::from_dec_str(self.pi_c[0].as_str())?), - Token::Uint(U256::from_dec_str(self.pi_c[1].as_str())?), - ]); - Ok(Bytes::from(abi::encode(&[pi_a, pi_b, pi_c]))) - } -} - -pub async fn generate_proof( - input: &str, - request: &str, - address: &str, -) -> Result<(Bytes, Vec)> { - let client = reqwest::Client::new(); - info!(LOG, "prover input {}", input); - let res = client - .post(format!("{}/prove/{}", address, request)) - .json(&serde_json::json!({ "input": input })) - .send() - .await? - .error_for_status()?; - let res_json = res.json::().await?; - info!(LOG, "prover response {:?}", res_json); - let proof = res_json.proof.to_eth_bytes()?; - let pub_signals = res_json - .pub_signals - .into_iter() - .map(|str| U256::from_dec_str(&str).expect("pub signal should be u256")) - .collect(); - Ok((proof, pub_signals)) -} - -pub fn calculate_default_hash(input: &str) -> String { - let mut hasher = DefaultHasher::new(); - input.hash(&mut hasher); - let hash_code = hasher.finish(); - - hash_code.to_string() -} - -pub fn calculate_account_salt(email_addr: &str, account_code: &str) -> String { - let padded_email_addr = PaddedEmailAddr::from_email_addr(email_addr); - let account_code = if account_code.starts_with("0x") { - hex_to_field(account_code).unwrap() - } else { - hex_to_field(&format!("0x{}", account_code)).unwrap() - }; - let account_code = AccountCode::from(account_code); - let account_salt = AccountSalt::new(&padded_email_addr, account_code).unwrap(); - - field_to_hex(&account_salt.0) -} From 2d3347a2d5d3e615cdd4ad8cb7103e971bb4b6ae Mon Sep 17 00:00:00 2001 From: Dimitri Date: Mon, 16 Sep 2024 16:19:30 +0700 Subject: [PATCH 30/53] Fix relayer-utils version to refactor commit --- packages/relayer/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relayer/Cargo.toml b/packages/relayer/Cargo.toml index 505b5a52..2240108a 100644 --- a/packages/relayer/Cargo.toml +++ b/packages/relayer/Cargo.toml @@ -25,7 +25,7 @@ tiny_http = "0.12.0" lettre = { version = "0.10.4", features = ["tokio1", "tokio1-native-tls"] } ethers = { version = "2.0.10", features = ["abigen"] } # relayer-utils = { version = "0.3.7", git = "https://github.com/zkemail/relayer-utils.git" } -relayer-utils = { path = "../../../relayer-utils" } +relayer-utils = { rev = "94d78d6", git = "https://github.com/zkemail/relayer-utils.git" } futures = "0.3.28" sqlx = { version = "=0.7.3", features = ["postgres", "runtime-tokio"] } regex = "1.10.2" From 19bd27e045279c1075ff583fd60b6758acf3ec39 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Tue, 17 Sep 2024 15:41:17 +0700 Subject: [PATCH 31/53] Force db initialization on startup --- Cargo.lock | 1 + packages/relayer/src/database.rs | 25 ++++++++++++++- packages/relayer/src/lib.rs | 32 ++++++++++++------- .../relayer/src/modules/web_server/server.rs | 17 ++++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac64a597..212f8687 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4141,6 +4141,7 @@ dependencies = [ [[package]] name = "relayer-utils" version = "0.3.7" +source = "git+https://github.com/zkemail/relayer-utils.git?rev=94d78d6#94d78d67862b6d6c15bebac66d184c7557f6aff5" dependencies = [ "anyhow", "base64 0.21.7", diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index 5dd0fbb9..1af6a220 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -73,6 +73,28 @@ impl Database { Ok(()) } + pub(crate) async fn test_db_connection(&self) -> Result<()> { + // Try up to 3 times + for i in 1..4 { + match sqlx::query("SELECT 1").execute(&self.db).await { + Ok(_) => { + info!(LOG, "Connected successfully to database"); + return Ok(()); + } + Err(e) => { + error!( + LOG, + "Failed to initialize connection to the database: {:?}. Retrying...", e + ); + tokio::time::sleep(Duration::from_secs(i * i)).await; + } + } + } + Err(anyhow::anyhow!( + "Failed to initialize database connection after 3 attempts" + )) + } + pub(crate) async fn get_credentials(&self, account_code: &str) -> Result> { let row = sqlx::query("SELECT * FROM credentials WHERE account_code = $1") .bind(account_code) @@ -326,6 +348,7 @@ impl Database { &self, row: &Request, ) -> std::result::Result<(), DatabaseError> { + let request_id = row.request_id; let row = sqlx::query( "INSERT INTO requests (request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, is_for_recovery, template_idx, is_processed, is_success, email_nullifier, account_salt) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *", ) @@ -342,7 +365,7 @@ impl Database { .fetch_one(&self.db) .await .map_err(|e| DatabaseError::new("Failed to insert request", e))?; - info!(LOG, "Request inserted"); + info!(LOG, "Request inserted with request_id: {}", request_id); Ok(()) } } diff --git a/packages/relayer/src/lib.rs b/packages/relayer/src/lib.rs index 5cc01621..42348138 100644 --- a/packages/relayer/src/lib.rs +++ b/packages/relayer/src/lib.rs @@ -19,7 +19,7 @@ pub use modules::*; use relayer_utils::LOG; pub use strings::*; -use tokio::sync::Mutex; +use tokio::sync::{Mutex, OnceCell}; use anyhow::{anyhow, Result}; use dotenv::dotenv; @@ -44,17 +44,27 @@ pub static EMAIL_TEMPLATES: OnceLock = OnceLock::new(); pub static RELAYER_EMAIL_ADDRESS: OnceLock = OnceLock::new(); pub static SMTP_SERVER: OnceLock = OnceLock::new(); +static DB_CELL: OnceCell> = OnceCell::const_new(); + +struct DBWrapper; + +impl DBWrapper { + fn get() -> &'static Arc { + DB_CELL.get().expect("Database not initialized") + } +} + +impl std::ops::Deref for DBWrapper { + type Target = Database; + + fn deref(&self) -> &Self::Target { + &**Self::get() + } +} + +static DB: DBWrapper = DBWrapper; + lazy_static! { - pub static ref DB: Arc = { - dotenv().ok(); - let db = tokio::task::block_in_place(|| { - tokio::runtime::Runtime::new() - .unwrap() - .block_on(Database::open(&env::var(DATABASE_PATH_KEY).unwrap())) - }) - .unwrap(); - Arc::new(db) - }; pub static ref CLIENT: Arc = { dotenv().ok(); let client = tokio::task::block_in_place(|| { diff --git a/packages/relayer/src/modules/web_server/server.rs b/packages/relayer/src/modules/web_server/server.rs index fbf85e77..f96afb12 100644 --- a/packages/relayer/src/modules/web_server/server.rs +++ b/packages/relayer/src/modules/web_server/server.rs @@ -6,6 +6,23 @@ use tower_http::cors::{AllowHeaders, AllowMethods, Any, CorsLayer}; pub async fn run_server() -> Result<()> { let addr = WEB_SERVER_ADDRESS.get().unwrap(); + DB_CELL + .get_or_init(|| async { + dotenv::dotenv().ok(); + let db = Database::open(&std::env::var("DATABASE_URL").unwrap()) + .await + .unwrap(); + Arc::new(db) + }) + .await; + + info!(LOG, "Testing connection to database"); + if let Err(e) = DB.test_db_connection().await { + error!(LOG, "Failed to initialize db with e: {}", e); + panic!("Forcing panic, since connection to DB could not be established"); + }; + info!(LOG, "Testing connection to database successfull"); + let mut app = Router::new() .route( "/api/echo", From adcefd6e504b1de4d84961653e63b14b5b09879d Mon Sep 17 00:00:00 2001 From: Dimitri Date: Wed, 18 Sep 2024 11:29:01 +0700 Subject: [PATCH 32/53] AI generated doc comments --- packages/relayer/src/chain.rs | 171 ++++++++++++++++++ packages/relayer/src/core.rs | 9 + packages/relayer/src/database.rs | 24 +++ packages/relayer/src/modules/dkim.rs | 43 +++++ packages/relayer/src/modules/mail.rs | 37 ++++ .../relayer/src/modules/web_server/mod.rs | 2 + .../src/modules/web_server/rest_api.rs | 64 ++++++- .../relayer/src/modules/web_server/server.rs | 5 + 8 files changed, 354 insertions(+), 1 deletion(-) diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index 0cffe7f0..d3df1e62 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -16,6 +16,11 @@ pub struct ChainClient { } impl ChainClient { + /// Sets up a new ChainClient. + /// + /// # Returns + /// + /// A `Result` containing the new `ChainClient` if successful, or an error if not. pub async fn setup() -> Result { let wallet: LocalWallet = PRIVATE_KEY.get().unwrap().parse()?; let provider = Provider::::try_from(CHAIN_RPC_PROVIDER.get().unwrap())?; @@ -28,6 +33,19 @@ impl ChainClient { Ok(Self { client }) } + /// Sets the DKIM public key hash. + /// + /// # Arguments + /// + /// * `selector` - The selector string. + /// * `domain_name` - The domain name. + /// * `public_key_hash` - The public key hash as a 32-byte array. + /// * `signature` - The signature as Bytes. + /// * `dkim` - The ECDSA Owned DKIM Registry. + /// + /// # Returns + /// + /// A `Result` containing the transaction hash as a String if successful, or an error if not. pub async fn set_dkim_public_key_hash( &self, selector: String, @@ -52,6 +70,17 @@ impl ChainClient { Ok(tx_hash) } + /// Checks if a DKIM public key hash is valid. + /// + /// # Arguments + /// + /// * `domain_name` - The domain name. + /// * `public_key_hash` - The public key hash as a 32-byte array. + /// * `dkim` - The ECDSA Owned DKIM Registry. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the hash is valid. pub async fn check_if_dkim_public_key_hash_valid( &self, domain_name: ::std::string::String, @@ -65,6 +94,15 @@ impl ChainClient { Ok(is_valid) } + /// Gets the DKIM from a wallet. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// + /// # Returns + /// + /// A `Result` containing the ECDSA Owned DKIM Registry if successful, or an error if not. pub async fn get_dkim_from_wallet( &self, controller_eth_addr: &str, @@ -75,6 +113,15 @@ impl ChainClient { Ok(ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone())) } + /// Gets the DKIM from an email auth address. + /// + /// # Arguments + /// + /// * `email_auth_addr` - The email auth address as a string. + /// + /// # Returns + /// + /// A `Result` containing the ECDSA Owned DKIM Registry if successful, or an error if not. pub async fn get_dkim_from_email_auth( &self, email_auth_addr: &str, @@ -86,6 +133,17 @@ impl ChainClient { Ok(ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone())) } + /// Gets the email auth address from a wallet. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `wallet_addr` - The wallet address as a string. + /// * `account_salt` - The account salt as a string. + /// + /// # Returns + /// + /// A `Result` containing the email auth address as H160 if successful, or an error if not. pub async fn get_email_auth_addr_from_wallet( &self, controller_eth_addr: &str, @@ -108,6 +166,15 @@ impl ChainClient { Ok(email_auth_addr) } + /// Checks if a wallet is deployed. + /// + /// # Arguments + /// + /// * `wallet_addr_str` - The wallet address as a string. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the wallet is deployed. pub async fn is_wallet_deployed(&self, wallet_addr_str: &str) -> Result { let wallet_addr: H160 = wallet_addr_str.parse().map_err(ChainError::HexError)?; match self.client.get_code(wallet_addr, None).await { @@ -122,6 +189,16 @@ impl ChainClient { } } + /// Gets the acceptance command templates. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `template_idx` - The template index. + /// + /// # Returns + /// + /// A `Result` containing a vector of acceptance command templates. pub async fn get_acceptance_command_templates( &self, controller_eth_addr: &str, @@ -140,6 +217,16 @@ impl ChainClient { Ok(templates[template_idx as usize].clone()) } + /// Gets the recovery command templates. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `template_idx` - The template index. + /// + /// # Returns + /// + /// A `Result` containing a vector of recovery command templates. pub async fn get_recovery_command_templates( &self, controller_eth_addr: &str, @@ -158,6 +245,17 @@ impl ChainClient { Ok(templates[template_idx as usize].clone()) } + /// Completes the recovery process. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `account_eth_addr` - The account Ethereum address as a string. + /// * `complete_calldata` - The complete calldata as a string. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the recovery was successful. pub async fn complete_recovery( &self, controller_eth_addr: &str, @@ -207,6 +305,17 @@ impl ChainClient { .unwrap_or(false)) } + /// Handles the acceptance process. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `email_auth_msg` - The email authentication message. + /// * `template_idx` - The template index. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the acceptance was successful. pub async fn handle_acceptance( &self, controller_eth_addr: &str, @@ -238,6 +347,17 @@ impl ChainClient { .unwrap_or(false)) } + /// Handles the recovery process. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `email_auth_msg` - The email authentication message. + /// * `template_idx` - The template index. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the recovery was successful. pub async fn handle_recovery( &self, controller_eth_addr: &str, @@ -266,6 +386,15 @@ impl ChainClient { .unwrap_or(false)) } + /// Gets the bytecode of a wallet. + /// + /// # Arguments + /// + /// * `wallet_addr` - The wallet address as a string. + /// + /// # Returns + /// + /// A `Result` containing the bytecode as Bytes. pub async fn get_bytecode(&self, wallet_addr: &str) -> std::result::Result { let wallet_address: H160 = wallet_addr.parse().map_err(ChainError::HexError)?; let client_code = self @@ -276,6 +405,16 @@ impl ChainClient { Ok(client_code) } + /// Gets the storage at a specific slot for a wallet. + /// + /// # Arguments + /// + /// * `wallet_addr` - The wallet address as a string. + /// * `slot` - The storage slot. + /// + /// # Returns + /// + /// A `Result` containing the storage value as H256. pub async fn get_storage_at( &self, wallet_addr: &str, @@ -288,6 +427,17 @@ impl ChainClient { .await?) } + /// Gets the recovered account from an acceptance command. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `command_params` - The command parameters. + /// * `template_idx` - The template index. + /// + /// # Returns + /// + /// A `Result` containing the recovered account address as H160. pub async fn get_recovered_account_from_acceptance_command( &self, controller_eth_addr: &str, @@ -320,6 +470,17 @@ impl ChainClient { Ok(recovered_account) } + /// Gets the recovered account from a recovery command. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `command_params` - The command parameters. + /// * `template_idx` - The template index. + /// + /// # Returns + /// + /// A `Result` containing the recovered account address as H160. pub async fn get_recovered_account_from_recovery_command( &self, controller_eth_addr: &str, @@ -353,6 +514,16 @@ impl ChainClient { Ok(recovered_account) } + /// Checks if an account is activated. + /// + /// # Arguments + /// + /// * `controller_eth_addr` - The controller Ethereum address as a string. + /// * `account_eth_addr` - The account Ethereum address as a string. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the account is activated. pub async fn get_is_activated( &self, controller_eth_addr: &str, diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index fd4e16ae..43986c63 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -19,6 +19,15 @@ const DOMAIN_FIELDS: usize = 9; const COMMAND_FIELDS: usize = 20; const EMAIL_ADDR_FIELDS: usize = 9; +/// Handles an incoming email for authentication or recovery. +/// +/// # Arguments +/// +/// * `email` - The raw email string to be processed. +/// +/// # Returns +/// +/// A `Result` containing an `EmailAuthEvent` on success, or an `EmailError` on failure. pub async fn handle_email(email: String) -> Result { let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; trace!(LOG, "email: {}", email); diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index 1af6a220..59984139 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -30,6 +30,15 @@ pub struct Database { } impl Database { + /// Opens a new database connection. + /// + /// # Arguments + /// + /// * `path` - The connection string for the database. + /// + /// # Returns + /// + /// A `Result` containing the `Database` struct if successful, or an error if the connection fails. pub async fn open(path: &str) -> Result { let res = Self { db: PgPool::connect(path) @@ -42,6 +51,11 @@ impl Database { Ok(res) } + /// Sets up the database by creating necessary tables if they don't exist. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the setup process. pub async fn setup_database(&self) -> Result<()> { sqlx::query( "CREATE TABLE IF NOT EXISTS credentials ( @@ -208,6 +222,16 @@ impl Database { Ok(()) } + /// Checks if a guardian is set for a given account and email address. + /// + /// # Arguments + /// + /// * `account_eth_addr` - The Ethereum address of the account. + /// * `guardian_email_addr` - The email address of the guardian. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating whether the guardian is set. pub async fn is_guardian_set( &self, account_eth_addr: &str, diff --git a/packages/relayer/src/modules/dkim.rs b/packages/relayer/src/modules/dkim.rs index b1d29c26..21ae7d30 100644 --- a/packages/relayer/src/modules/dkim.rs +++ b/packages/relayer/src/modules/dkim.rs @@ -30,6 +30,16 @@ pub struct SignedDkimPublicKey { } impl<'a> DkimOracleClient<'a> { + /// Generates an agent for the DKIM Oracle Client. + /// + /// # Arguments + /// + /// * `pem_path` - The path to the PEM file. + /// * `replica_url` - The URL of the replica. + /// + /// # Returns + /// + /// An `anyhow::Result`. pub fn gen_agent(pem_path: &str, replica_url: &str) -> anyhow::Result { let identity = Secp256k1Identity::from_pem_file(pem_path)?; let transport = ReqwestTransport::create(replica_url)?; @@ -40,6 +50,16 @@ impl<'a> DkimOracleClient<'a> { Ok(agent) } + /// Creates a new DkimOracleClient. + /// + /// # Arguments + /// + /// * `canister_id` - The ID of the canister. + /// * `agent` - The agent to use for communication. + /// + /// # Returns + /// + /// An `anyhow::Result`. pub fn new(canister_id: &str, agent: &'a Agent) -> anyhow::Result { let canister = CanisterBuilder::new() .with_canister_id(canister_id) @@ -48,6 +68,16 @@ impl<'a> DkimOracleClient<'a> { Ok(Self { canister }) } + /// Requests a signature for a DKIM public key. + /// + /// # Arguments + /// + /// * `selector` - The selector for the DKIM key. + /// * `domain` - The domain for the DKIM key. + /// + /// # Returns + /// + /// An `anyhow::Result`. pub async fn request_signature( &self, selector: &str, @@ -67,6 +97,19 @@ impl<'a> DkimOracleClient<'a> { } } +/// Checks and updates the DKIM for a given email. +/// +/// # Arguments +/// +/// * `email` - The email address. +/// * `parsed_email` - The parsed email data. +/// * `controller_eth_addr` - The Ethereum address of the controller. +/// * `wallet_addr` - The address of the wallet. +/// * `account_salt` - The salt for the account. +/// +/// # Returns +/// +/// A `Result<()>`. pub async fn check_and_update_dkim( email: &str, parsed_email: &ParsedEmail, diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index ffc15d8e..c90b6d87 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -80,6 +80,15 @@ pub struct EmailAttachment { pub contents: Vec, } +/// Handles all possible email events and requests. +/// +/// # Arguments +/// +/// * `event` - The `EmailAuthEvent` to be handled. +/// +/// # Returns +/// +/// A `Result` indicating success or an `EmailError`. pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> { match event { EmailAuthEvent::AcceptanceRequest { @@ -378,6 +387,16 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> Ok(()) } +/// Renders an HTML template with the given data. +/// +/// # Arguments +/// +/// * `template_name` - The name of the template file. +/// * `render_data` - The data to be used in rendering the template. +/// +/// # Returns +/// +/// A `Result` containing the rendered HTML string or an `EmailError`. pub async fn render_html(template_name: &str, render_data: Value) -> Result { let email_template_filename = PathBuf::new() .join(EMAIL_TEMPLATES.get().unwrap()) @@ -397,6 +416,15 @@ pub async fn render_html(template_name: &str, render_data: Value) -> Result` with the parsed error message. pub fn parse_error(error: String) -> Result> { let mut error = error; if error.contains("Contract call reverted with data: ") { @@ -420,6 +448,15 @@ pub fn parse_error(error: String) -> Result> { } } +/// Sends an email using the configured SMTP server. +/// +/// # Arguments +/// +/// * `email` - The `EmailMessage` to be sent. +/// +/// # Returns +/// +/// A `Result` indicating success or an `EmailError`. pub async fn send_email(email: EmailMessage) -> Result<(), EmailError> { let smtp_server = SMTP_SERVER.get().unwrap(); diff --git a/packages/relayer/src/modules/web_server/mod.rs b/packages/relayer/src/modules/web_server/mod.rs index 35ed632a..3a48beb6 100644 --- a/packages/relayer/src/modules/web_server/mod.rs +++ b/packages/relayer/src/modules/web_server/mod.rs @@ -1,3 +1,5 @@ +//! This module contains the axum web server and its routes and custom errors. + pub mod relayer_errors; pub mod rest_api; pub mod server; diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 1f520ce7..df9bce37 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -7,7 +7,15 @@ use relayer_utils::{calculate_account_salt, extract_template_vals, TemplateValue use serde::{Deserialize, Serialize}; use std::str; -// Create request status API +/// Retrieves the status of a request. +/// +/// # Arguments +/// +/// * `payload` - A JSON payload containing the request ID. +/// +/// # Returns +/// +/// A `Result` containing a JSON `RequestStatusResponse` or an `ApiError`. pub async fn request_status_api( Json(payload): Json, ) -> Result, ApiError> { @@ -33,6 +41,15 @@ pub async fn request_status_api( })) } +/// Handles an acceptance request for a wallet. +/// +/// # Arguments +/// +/// * `payload` - A JSON payload containing the acceptance request details. +/// +/// # Returns +/// +/// A `Result` containing a JSON `AcceptanceResponse` or an `ApiError`. pub async fn handle_acceptance_request( Json(payload): Json, ) -> Result, ApiError> { @@ -193,6 +210,15 @@ pub async fn handle_acceptance_request( })) } +/// Handles a recovery request for a wallet. +/// +/// # Arguments +/// +/// * `payload` - A JSON payload containing the recovery request details. +/// +/// # Returns +/// +/// A `Result` containing a JSON `RecoveryResponse` or an `ApiError`. pub async fn handle_recovery_request( Json(payload): Json, ) -> Result, ApiError> { @@ -386,6 +412,15 @@ pub async fn handle_recovery_request( })) } +/// Handles the completion of a recovery request. +/// +/// # Arguments +/// +/// * `payload` - A JSON payload containing the complete recovery request details. +/// +/// # Returns +/// +/// A `Result` containing a `String` message or an `ApiError`. pub async fn handle_complete_recovery_request( Json(payload): Json, ) -> Result { @@ -425,6 +460,15 @@ pub async fn handle_complete_recovery_request( } } +/// Retrieves the account salt for a given email address and account code. +/// +/// # Arguments +/// +/// * `payload` - A JSON payload containing the email address and account code. +/// +/// # Returns +/// +/// A `Result` containing the account salt as a `String` or an `ApiError`. pub async fn get_account_salt( Json(payload): Json, ) -> Result { @@ -433,6 +477,15 @@ pub async fn get_account_salt( Ok(account_salt) } +/// Marks a guardian as inactive for a given wallet. +/// +/// # Arguments +/// +/// * `payload` - A JSON payload containing the account and controller Ethereum addresses. +/// +/// # Returns +/// +/// A `Result` containing a `String` message or an `ApiError`. pub async fn inactive_guardian( Json(payload): Json, ) -> Result { @@ -472,6 +525,15 @@ fn parse_error_message(error_data: String) -> String { format!("Failed to parse contract error: {}", error_data) } +/// Receives and processes an email. +/// +/// # Arguments +/// +/// * `email` - The raw email as a `String`. +/// +/// # Returns +/// +/// A `Result` containing `()` or an `ApiError`. pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { println!("receive_email_api_fn"); let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; diff --git a/packages/relayer/src/modules/web_server/server.rs b/packages/relayer/src/modules/web_server/server.rs index f96afb12..594ee4c5 100644 --- a/packages/relayer/src/modules/web_server/server.rs +++ b/packages/relayer/src/modules/web_server/server.rs @@ -3,6 +3,11 @@ use axum::{routing::post, Router}; use relayer_utils::LOG; use tower_http::cors::{AllowHeaders, AllowMethods, Any, CorsLayer}; +/// Runs the server and sets up the API routes. +/// +/// # Returns +/// +/// A `Result` indicating success or failure. pub async fn run_server() -> Result<()> { let addr = WEB_SERVER_ADDRESS.get().unwrap(); From 69d7b3cb8d70d4e54eb49b36b8aa4bf1a805194a Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 19 Sep 2024 12:44:44 +0700 Subject: [PATCH 33/53] Prevent duplicates by checking if it is a valid reply --- Cargo.lock | 2 +- packages/relayer/Cargo.toml | 3 +- packages/relayer/src/database.rs | 48 ++++++++++++ packages/relayer/src/modules/mail.rs | 74 ++++++++++++++++--- .../src/modules/web_server/rest_api.rs | 41 ++-------- 5 files changed, 120 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 212f8687..b060b89f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4141,7 +4141,6 @@ dependencies = [ [[package]] name = "relayer-utils" version = "0.3.7" -source = "git+https://github.com/zkemail/relayer-utils.git?rev=94d78d6#94d78d67862b6d6c15bebac66d184c7557f6aff5" dependencies = [ "anyhow", "base64 0.21.7", @@ -4153,6 +4152,7 @@ dependencies = [ "hmac-sha256", "itertools 0.10.5", "lazy_static", + "mailparse", "neon", "num-bigint", "num-traits", diff --git a/packages/relayer/Cargo.toml b/packages/relayer/Cargo.toml index 2240108a..30d0bb2b 100644 --- a/packages/relayer/Cargo.toml +++ b/packages/relayer/Cargo.toml @@ -25,7 +25,8 @@ tiny_http = "0.12.0" lettre = { version = "0.10.4", features = ["tokio1", "tokio1-native-tls"] } ethers = { version = "2.0.10", features = ["abigen"] } # relayer-utils = { version = "0.3.7", git = "https://github.com/zkemail/relayer-utils.git" } -relayer-utils = { rev = "94d78d6", git = "https://github.com/zkemail/relayer-utils.git" } +# relayer-utils = { rev = "94d78d6", git = "https://github.com/zkemail/relayer-utils.git" } +relayer-utils = { path = "../../../relayer-utils" } futures = "0.3.28" sqlx = { version = "=0.7.3", features = ["postgres", "runtime-tokio"] } regex = "1.10.2" diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index 59984139..93de8ee1 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -84,6 +84,17 @@ impl Database { ) .execute(&self.db) .await?; + + sqlx::query( + "CREATE TABLE IF NOT EXISTS expected_replies ( + message_id VARCHAR(255) PRIMARY KEY, + request_id VARCHAR(255), + has_reply BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT (NOW() AT TIME ZONE 'UTC') + );", + ) + .execute(&self.db) + .await?; Ok(()) } @@ -392,4 +403,41 @@ impl Database { info!(LOG, "Request inserted with request_id: {}", request_id); Ok(()) } + + pub(crate) async fn add_expected_reply( + &self, + message_id: &str, + request_id: Option, + ) -> Result<(), DatabaseError> { + let query = " + INSERT INTO expected_replies (message_id, request_id) + VALUES ($1, $2); + "; + sqlx::query(query) + .bind(message_id) + .bind(request_id) + .execute(&self.db) + .await + .map_err(|e| DatabaseError::new("Failed to insert expected_reply", e))?; + Ok(()) + } + + // Checks if the given message_id corresponds to a valid reply. + // This function updates the `has_reply` field to true if the message_id exists and hasn't been replied to yet. + // Returns true if the update was successful (i.e., a valid reply was recorded), false otherwise, + // also if no record exists to be updated. + pub(crate) async fn is_valid_reply(&self, message_id: &str) -> Result { + let query = " + UPDATE expected_replies + SET has_reply = true + WHERE message_id = $1 AND has_reply = false + RETURNING *; + "; + let result = sqlx::query(query) + .bind(message_id) + .execute(&self.db) + .await + .map_err(|e| DatabaseError::new("Failed to validate reply", e))?; + Ok(result.rows_affected() > 0) + } } diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index c90b6d87..d0fd85f7 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -129,7 +129,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, Some(ExpectsReply::new(request_id))).await?; } EmailAuthEvent::Error { email_addr, @@ -161,7 +161,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, None).await?; } EmailAuthEvent::GuardianAlreadyExists { account_eth_addr, @@ -190,7 +190,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, None).await?; } EmailAuthEvent::RecoveryRequest { account_eth_addr, @@ -226,7 +226,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, Some(ExpectsReply::new(request_id))).await?; } EmailAuthEvent::AcceptanceSuccess { account_eth_addr, @@ -259,7 +259,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, None).await?; } EmailAuthEvent::RecoverySuccess { account_eth_addr, @@ -292,7 +292,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, None).await?; } EmailAuthEvent::GuardianNotSet { account_eth_addr, @@ -317,7 +317,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, None).await?; } EmailAuthEvent::GuardianNotRegistered { account_eth_addr, @@ -355,7 +355,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> body_attachments: None, }; - send_email(email).await?; + send_email(email, Some(ExpectsReply::new(request_id))).await?; } EmailAuthEvent::Ack { email_addr, @@ -379,7 +379,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> reply_to: original_message_id, body_attachments: None, }; - send_email(email).await?; + send_email(email, None).await?; } EmailAuthEvent::NoOp => {} } @@ -457,7 +457,10 @@ pub fn parse_error(error: String) -> Result> { /// # Returns /// /// A `Result` indicating success or an `EmailError`. -pub async fn send_email(email: EmailMessage) -> Result<(), EmailError> { +pub async fn send_email( + email: EmailMessage, + expects_reply: Option, +) -> Result<(), EmailError> { let smtp_server = SMTP_SERVER.get().unwrap(); // Send POST request to email server @@ -476,5 +479,56 @@ pub async fn send_email(email: EmailMessage) -> Result<(), EmailError> { ))); } + if let Some(expects_reply) = expects_reply { + let response_body: EmailResponse = response + .json() + .await + .map_err(|e| EmailError::Parse(format!("Failed to parse response JSON: {}", e)))?; + + let message_id = response_body.message_id; + DB.add_expected_reply(&message_id, expects_reply.request_id) + .await?; + } + Ok(()) } + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct EmailResponse { + status: String, + message_id: String, +} + +pub struct ExpectsReply { + request_id: Option, +} + +impl ExpectsReply { + fn new(request_id: u32) -> Self { + Self { + request_id: Some(request_id.to_string()), + } + } + + fn new_no_request_id() -> Self { + Self { request_id: None } + } +} + +/// Checks if the email is a reply to a command that expects a reply. +/// Will return false for duplicate replies. +/// Will return true if the email is not a reply. +pub async fn check_is_valid_request(email: &ParsedEmail) -> Result { + let reply_message_id = match email + .headers + .get_header("In-Reply-To") + .and_then(|v| v.first().cloned()) + { + Some(id) => id, + // Email is not a reply + None => return Ok(true), + }; + + let is_valid = DB.is_valid_reply(&reply_message_id).await?; + Ok(is_valid) +} diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index df9bce37..add61e88 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -19,7 +19,6 @@ use std::str; pub async fn request_status_api( Json(payload): Json, ) -> Result, ApiError> { - println!("requesting status"); let row = DB.get_request(payload.request_id).await?; let status = if let Some(ref row) = row { if row.is_processed { @@ -53,7 +52,6 @@ pub async fn request_status_api( pub async fn handle_acceptance_request( Json(payload): Json, ) -> Result, ApiError> { - println!("handle_acceptance_request"); let command_template = CLIENT .get_acceptance_command_templates(&payload.controller_eth_addr, payload.template_idx) .await?; @@ -222,15 +220,12 @@ pub async fn handle_acceptance_request( pub async fn handle_recovery_request( Json(payload): Json, ) -> Result, ApiError> { - println!("handle_recovery_request: {:?}", payload); let command_template = CLIENT .get_recovery_command_templates(&payload.controller_eth_addr, payload.template_idx) .await?; - println!("command_template: {:?}", command_template); let command_params = extract_template_vals(&payload.command, command_template) .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; - println!("command_params"); let account_eth_addr = CLIENT .get_recovered_account_from_recovery_command( @@ -240,22 +235,15 @@ pub async fn handle_recovery_request( ) .await?; - println!("account_eth_addr"); - let account_eth_addr = format!("0x{:x}", account_eth_addr); - println!("account_eth_addr"); if !CLIENT.is_wallet_deployed(&account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } - println!("wallet is deployed"); - // Check if hash of bytecode of proxy contract is equal or not let bytecode = CLIENT.get_bytecode(&account_eth_addr).await?; - println!("bytecode"); let bytecode_hash = format!("0x{}", hex::encode(keccak256(bytecode.as_ref()))); - println!("bytecode_hash"); // let permitted_wallets: Vec = // serde_json::from_str(include_str!("../../permitted_wallets.json")).unwrap(); @@ -304,37 +292,24 @@ pub async fn handle_recovery_request( // } let mut request_id = rand::thread_rng().gen::(); - println!("got request_id"); while let Ok(Some(request)) = DB.get_request(request_id).await { request_id = rand::thread_rng().gen::(); } - println!("got request: {:?}", request_id); - println!("account_eth_addr: {:?}", account_eth_addr); - println!( - "payload.guardian_email_addr: {:?}", - payload.guardian_email_addr - ); - let account = DB .get_credentials_from_wallet_and_email(&account_eth_addr, &payload.guardian_email_addr) .await?; - println!("got account: {:?}", account); - let account_salt = if let Some(account_details) = account { calculate_account_salt(&payload.guardian_email_addr, &account_details.account_code) } else { return Err(ApiError::Validation("Wallet not deployed".to_string())); }; - println!("got account_salt"); - if !DB .is_wallet_and_email_registered(&account_eth_addr, &payload.guardian_email_addr) .await? { - println!("email and wallet are not registered"); DB.insert_request(&Request { request_id, account_eth_addr: account_eth_addr.clone(), @@ -377,13 +352,10 @@ pub async fn handle_recovery_request( }) .await?; - println!("inserted request"); - if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) .await? { - println!("guardian is set"); handle_email_event(EmailAuthEvent::RecoveryRequest { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -394,7 +366,6 @@ pub async fn handle_recovery_request( // TODO: Add custom error for handle_email_event .expect("Failed to send Recovery event"); } else { - println!("guardian is not set"); handle_email_event(EmailAuthEvent::GuardianNotSet { account_eth_addr, guardian_email_addr: payload.guardian_email_addr.clone(), @@ -404,8 +375,6 @@ pub async fn handle_recovery_request( .expect("Failed to send Recovery event"); } - println!("all done"); - Ok(Json(RecoveryResponse { request_id, command_params, @@ -424,11 +393,9 @@ pub async fn handle_recovery_request( pub async fn handle_complete_recovery_request( Json(payload): Json, ) -> Result { - println!("handle_complete_recovery_request"); if !CLIENT.is_wallet_deployed(&payload.account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } - println!("wallet is deployed"); match CLIENT .complete_recovery( @@ -472,7 +439,6 @@ pub async fn handle_complete_recovery_request( pub async fn get_account_salt( Json(payload): Json, ) -> Result { - println!("get_account_salt"); let account_salt = calculate_account_salt(&payload.email_addr, &payload.account_code); Ok(account_salt) } @@ -489,7 +455,6 @@ pub async fn get_account_salt( pub async fn inactive_guardian( Json(payload): Json, ) -> Result { - println!("inactive_guardian"); let is_activated = CLIENT .get_is_activated(&payload.controller_eth_addr, &payload.account_eth_addr) .await?; @@ -535,11 +500,15 @@ fn parse_error_message(error_data: String) -> String { /// /// A `Result` containing `()` or an `ApiError`. pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { - println!("receive_email_api_fn"); let parsed_email = ParsedEmail::new_from_raw_email(&email).await?; let from_addr = parsed_email.get_from_addr()?; let original_subject = parsed_email.get_subject_all()?; tokio::spawn(async move { + if !check_is_valid_request(&parsed_email).await.unwrap() { + trace!(LOG, "Got a non valid email request. Ignoring."); + return; + } + match handle_email_event(EmailAuthEvent::Ack { email_addr: from_addr.clone(), command: parsed_email.get_command(false).unwrap_or_default(), From 719dc4a56740d9eeee5c54c0548a7eefad2315ac Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 19 Sep 2024 13:26:48 +0700 Subject: [PATCH 34/53] Add AI generated comments --- Cargo.lock | 1 + packages/relayer/Cargo.toml | 3 +- packages/relayer/src/chain.rs | 110 +++++++++-- packages/relayer/src/config.rs | 21 ++ packages/relayer/src/core.rs | 95 +++++++++ packages/relayer/src/database.rs | 180 +++++++++++++++-- packages/relayer/src/lib.rs | 28 ++- packages/relayer/src/modules/dkim.rs | 38 ++++ packages/relayer/src/modules/mail.rs | 59 +++++- packages/relayer/src/modules/mod.rs | 2 + .../src/modules/web_server/relayer_errors.rs | 7 + .../src/modules/web_server/rest_api.rs | 186 ++++++++---------- .../relayer/src/modules/web_server/server.rs | 3 + 13 files changed, 590 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b060b89f..8c4df7ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4141,6 +4141,7 @@ dependencies = [ [[package]] name = "relayer-utils" version = "0.3.7" +source = "git+https://github.com/zkemail/relayer-utils.git?rev=0c19631#0c196312b6ce7ce2c282d11e6c736e958b8df77a" dependencies = [ "anyhow", "base64 0.21.7", diff --git a/packages/relayer/Cargo.toml b/packages/relayer/Cargo.toml index 30d0bb2b..4ccd237d 100644 --- a/packages/relayer/Cargo.toml +++ b/packages/relayer/Cargo.toml @@ -25,8 +25,7 @@ tiny_http = "0.12.0" lettre = { version = "0.10.4", features = ["tokio1", "tokio1-native-tls"] } ethers = { version = "2.0.10", features = ["abigen"] } # relayer-utils = { version = "0.3.7", git = "https://github.com/zkemail/relayer-utils.git" } -# relayer-utils = { rev = "94d78d6", git = "https://github.com/zkemail/relayer-utils.git" } -relayer-utils = { path = "../../../relayer-utils" } +relayer-utils = { rev = "0c19631", git = "https://github.com/zkemail/relayer-utils.git" } futures = "0.3.28" sqlx = { version = "=0.7.3", features = ["postgres", "runtime-tokio"] } regex = "1.10.2" diff --git a/packages/relayer/src/chain.rs b/packages/relayer/src/chain.rs index d3df1e62..30e362b4 100644 --- a/packages/relayer/src/chain.rs +++ b/packages/relayer/src/chain.rs @@ -10,6 +10,7 @@ const CONFIRMATIONS: usize = 1; type SignerM = SignerMiddleware, LocalWallet>; +/// Represents a client for interacting with the blockchain. #[derive(Debug, Clone)] pub struct ChainClient { pub client: Arc, @@ -25,6 +26,7 @@ impl ChainClient { let wallet: LocalWallet = PRIVATE_KEY.get().unwrap().parse()?; let provider = Provider::::try_from(CHAIN_RPC_PROVIDER.get().unwrap())?; + // Create a new SignerMiddleware with the provider and wallet let client = Arc::new(SignerMiddleware::new( provider, wallet.with_chain_id(*CHAIN_ID.get().unwrap()), @@ -58,13 +60,18 @@ impl ChainClient { let mut mutex = SHARED_MUTEX.lock().await; *mutex += 1; + // Call the contract method let call = dkim.set_dkim_public_key_hash(selector, domain_name, public_key_hash, signature); let tx = call.send().await?; + + // Wait for the transaction to be confirmed let receipt = tx .log() .confirmations(CONFIRMATIONS) .await? .ok_or(anyhow!("No receipt"))?; + + // Format the transaction hash let tx_hash = receipt.transaction_hash; let tx_hash = format!("0x{}", hex::encode(tx_hash.as_bytes())); Ok(tx_hash) @@ -87,6 +94,7 @@ impl ChainClient { public_key_hash: [u8; 32], dkim: ECDSAOwnedDKIMRegistry, ) -> Result { + // Call the contract method to check if the hash is valid let is_valid = dkim .is_dkim_public_key_hash_valid(domain_name, public_key_hash) .call() @@ -107,9 +115,16 @@ impl ChainClient { &self, controller_eth_addr: &str, ) -> Result, anyhow::Error> { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse()?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Call the dkim method to get the DKIM registry address let dkim = contract.dkim().call().await?; + + // Create and return a new ECDSAOwnedDKIMRegistry instance Ok(ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone())) } @@ -126,10 +141,16 @@ impl ChainClient { &self, email_auth_addr: &str, ) -> Result, anyhow::Error> { + // Parse the email auth address let email_auth_address: H160 = email_auth_addr.parse()?; + + // Create a new EmailAuth contract instance let contract = EmailAuth::new(email_auth_address, self.client.clone()); + + // Call the dkim_registry_addr method to get the DKIM registry address let dkim = contract.dkim_registry_addr().call().await?; + // Create and return a new ECDSAOwnedDKIMRegistry instance Ok(ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone())) } @@ -150,11 +171,18 @@ impl ChainClient { wallet_addr: &str, account_salt: &str, ) -> Result { + // Parse the controller and wallet Ethereum addresses let controller_eth_addr: H160 = controller_eth_addr.parse()?; let wallet_address: H160 = wallet_addr.parse()?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Decode the account salt let account_salt_bytes = hex::decode(account_salt.trim_start_matches("0x")) .map_err(|e| anyhow!("Failed to decode account_salt: {}", e))?; + + // Compute the email auth address let email_auth_addr = contract .compute_email_auth_address( wallet_address, @@ -176,7 +204,10 @@ impl ChainClient { /// /// A `Result` containing a boolean indicating if the wallet is deployed. pub async fn is_wallet_deployed(&self, wallet_addr_str: &str) -> Result { + // Parse the wallet address let wallet_addr: H160 = wallet_addr_str.parse().map_err(ChainError::HexError)?; + + // Get the bytecode at the wallet address match self.client.get_code(wallet_addr, None).await { Ok(code) => Ok(!code.is_empty()), Err(e) => { @@ -204,9 +235,14 @@ impl ChainClient { controller_eth_addr: &str, template_idx: u64, ) -> Result, ChainError> { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Get the acceptance command templates let templates = contract .acceptance_command_templates() .call() @@ -232,9 +268,14 @@ impl ChainClient { controller_eth_addr: &str, template_idx: u64, ) -> Result, ChainError> { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Get the recovery command templates let templates = contract .recovery_command_templates() .call() @@ -262,30 +303,30 @@ impl ChainClient { account_eth_addr: &str, complete_calldata: &str, ) -> Result { - println!("doing complete recovery"); + // Parse the controller and account Ethereum addresses let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; - println!("controller_eth_addr: {:?}", controller_eth_addr); + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Decode the complete calldata let decoded_calldata = hex::decode(complete_calldata.trim_start_matches("0x")).expect("Decoding failed"); - println!("decoded_calldata : {:?}", decoded_calldata); let account_eth_addr = account_eth_addr .parse::() .map_err(ChainError::HexError)?; - println!("account_eth_addr : {:?}", account_eth_addr); + // Call the complete_recovery method let call = contract.complete_recovery(account_eth_addr, Bytes::from(decoded_calldata)); - println!("call: {:?}", call); let tx = call .send() .await .map_err(|e| ChainError::contract_error("Failed to call complete_recovery", e))?; - println!("tx: {:?}", tx); - // If the transaction is successful, the function will return true and false otherwise. + + // Wait for the transaction to be confirmed let receipt = tx .log() .confirmations(CONFIRMATIONS) @@ -297,8 +338,8 @@ impl ChainClient { ) })? .ok_or(anyhow!("No receipt"))?; - println!("receipt : {:?}", receipt); + // Check if the transaction was successful Ok(receipt .status .map(|status| status == U64::from(1)) @@ -322,14 +363,20 @@ impl ChainClient { email_auth_msg: EmailAuthMsg, template_idx: u64, ) -> std::result::Result { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse()?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Call the handle_acceptance method let call = contract.handle_acceptance(email_auth_msg, template_idx.into()); let tx = call .send() .await .map_err(|e| ChainError::contract_error("Failed to call handle_acceptance", e))?; - // If the transaction is successful, the function will return true and false otherwise. + + // Wait for the transaction to be confirmed let receipt = tx .log() .confirmations(CONFIRMATIONS) @@ -341,6 +388,8 @@ impl ChainClient { ) })? .ok_or(anyhow!("No receipt"))?; + + // Check if the transaction was successful Ok(receipt .status .map(|status| status == U64::from(1)) @@ -364,14 +413,20 @@ impl ChainClient { email_auth_msg: EmailAuthMsg, template_idx: u64, ) -> std::result::Result { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse()?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Call the handle_recovery method let call = contract.handle_recovery(email_auth_msg, template_idx.into()); let tx = call .send() .await .map_err(|e| ChainError::contract_error("Failed to call handle_recovery", e))?; - // If the transaction is successful, the function will return true and false otherwise. + + // Wait for the transaction to be confirmed let receipt = tx .log() .confirmations(CONFIRMATIONS) @@ -380,6 +435,8 @@ impl ChainClient { ChainError::provider_error("Failed to get receipt after calling handle_recovery", e) })? .ok_or(anyhow!("No receipt"))?; + + // Check if the transaction was successful Ok(receipt .status .map(|status| status == U64::from(1)) @@ -396,7 +453,10 @@ impl ChainClient { /// /// A `Result` containing the bytecode as Bytes. pub async fn get_bytecode(&self, wallet_addr: &str) -> std::result::Result { + // Parse the wallet address let wallet_address: H160 = wallet_addr.parse().map_err(ChainError::HexError)?; + + // Get the bytecode at the wallet address let client_code = self .client .get_code(wallet_address, None) @@ -420,7 +480,10 @@ impl ChainClient { wallet_addr: &str, slot: u64, ) -> Result { + // Parse the wallet address let wallet_address: H160 = wallet_addr.parse()?; + + // Get the storage at the specified slot Ok(self .client .get_storage_at(wallet_address, u64_to_u8_array_32(slot).into(), None) @@ -444,16 +507,23 @@ impl ChainClient { command_params: Vec, template_idx: u64, ) -> Result { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Encode the command parameters let command_params_bytes = command_params - .iter() // Change here: use iter() instead of map() directly on Vec + .iter() .map(|s| { - s.abi_encode(None) // Assuming decimal_size is not needed or can be None + s.abi_encode(None) .unwrap_or_else(|_| Bytes::from("Error encoding".as_bytes().to_vec())) - }) // Error handling + }) .collect::>(); + + // Call the extract_recovered_account_from_acceptance_command method let recovered_account = contract .extract_recovered_account_from_acceptance_command( command_params_bytes, @@ -487,17 +557,24 @@ impl ChainClient { command_params: Vec, template_idx: u64, ) -> Result { + // Parse the controller Ethereum address let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Encode the command parameters let command_params_bytes = command_params - .iter() // Change here: use iter() instead of map() directly on Vec + .iter() .map(|s| { s.abi_encode(None).map_err(|_| { ChainError::Validation("Error encoding subject parameters".to_string()) }) }) .collect::, ChainError>>()?; + + // Call the extract_recovered_account_from_recovery_command method let recovered_account = contract .extract_recovered_account_from_recovery_command( command_params_bytes, @@ -529,10 +606,15 @@ impl ChainClient { controller_eth_addr: &str, account_eth_addr: &str, ) -> Result { + // Parse the controller and account Ethereum addresses let controller_eth_addr: H160 = controller_eth_addr.parse().map_err(ChainError::HexError)?; let account_eth_addr: H160 = account_eth_addr.parse().map_err(ChainError::HexError)?; + + // Create a new EmailAccountRecovery contract instance let contract = EmailAccountRecovery::new(controller_eth_addr, self.client.clone()); + + // Call the is_activated method let is_activated = contract .is_activated(account_eth_addr) .call() diff --git a/packages/relayer/src/config.rs b/packages/relayer/src/config.rs index bed30ff4..2e5a9095 100644 --- a/packages/relayer/src/config.rs +++ b/packages/relayer/src/config.rs @@ -4,6 +4,10 @@ use std::{env, path::PathBuf}; use dotenv::dotenv; +/// Configuration struct for the Relayer service. +/// +/// This struct holds various configuration parameters needed for the Relayer service, +/// including SMTP settings, database path, web server address, and blockchain-related information. #[derive(Clone)] pub struct RelayerConfig { pub smtp_server: String, @@ -21,9 +25,19 @@ pub struct RelayerConfig { } impl RelayerConfig { + /// Creates a new instance of RelayerConfig. + /// + /// This function loads environment variables using dotenv and populates + /// the RelayerConfig struct with the values. + /// + /// # Returns + /// + /// A new instance of RelayerConfig. pub fn new() -> Self { + // Load environment variables from .env file dotenv().ok(); + // Construct and return the RelayerConfig instance Self { smtp_server: env::var(SMTP_SERVER_KEY).unwrap(), relayer_email_addr: env::var(RELAYER_EMAIL_ADDR_KEY).unwrap(), @@ -45,6 +59,13 @@ impl RelayerConfig { } impl Default for RelayerConfig { + /// Provides a default instance of RelayerConfig. + /// + /// This implementation simply calls the `new()` method to create a default instance. + /// + /// # Returns + /// + /// A default instance of RelayerConfig. fn default() -> Self { Self::new() } diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index 43986c63..f9c10165 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -104,6 +104,16 @@ pub async fn handle_email(email: String) -> Result { handle_email_request(params, invitation_code).await } +/// Handles the email request based on the presence of an invitation code and whether it's for recovery. +/// +/// # Arguments +/// +/// * `params` - The `EmailRequestContext` containing request details. +/// * `invitation_code` - An optional invitation code. +/// +/// # Returns +/// +/// A `Result` containing an `EmailAuthEvent` or an `EmailError`. async fn handle_email_request( params: EmailRequestContext, invitation_code: Option, @@ -141,6 +151,16 @@ async fn handle_email_request( } } +/// Handles the acceptance of an email authentication request. +/// +/// # Arguments +/// +/// * `params` - The `EmailRequestContext` containing request details. +/// * `invitation_code` - The invitation code from the email. +/// +/// # Returns +/// +/// A `Result` containing an `EmailAuthEvent` or an `EmailError`. async fn accept( params: EmailRequestContext, invitation_code: String, @@ -150,6 +170,7 @@ async fn accept( info!(LOG, "Email Auth Msg: {:?}", email_auth_msg); info!(LOG, "Request: {:?}", params.request); + // Handle the acceptance with the client let is_accepted = CLIENT .handle_acceptance( ¶ms.request.controller_eth_addr, @@ -194,12 +215,22 @@ async fn accept( } } +/// Handles the recovery process for an email authentication request. +/// +/// # Arguments +/// +/// * `params` - The `EmailRequestContext` containing request details. +/// +/// # Returns +/// +/// A `Result` containing an `EmailAuthEvent` or an `EmailError`. async fn recover(params: EmailRequestContext) -> Result { let (email_auth_msg, email_proof, account_salt) = get_email_auth_msg(¶ms).await?; info!(LOG, "Email Auth Msg: {:?}", email_auth_msg); info!(LOG, "Request: {:?}", params.request); + // Handle the recovery with the client let is_success = CLIENT .handle_recovery( ¶ms.request.controller_eth_addr, @@ -236,6 +267,16 @@ async fn recover(params: EmailRequestContext) -> Result, start_idx: usize) -> Result { // Gather signals from start_idx to start_idx + COMMAND_FIELDS let command_bytes: Vec = public_signals @@ -253,6 +294,18 @@ fn get_masked_command(public_signals: Vec, start_idx: usize) -> Result Result<(EmailProof, [u8; 32]), EmailError> { @@ -314,6 +376,15 @@ async fn generate_email_proof( Ok((email_proof, account_salt)) } +/// Generates the template ID for the email authentication request. +/// +/// # Arguments +/// +/// * `params` - The `EmailRequestContext` containing request details. +/// +/// # Returns +/// +/// A 32-byte array representing the template ID. fn get_template_id(params: &EmailRequestContext) -> [u8; 32] { let action = if params.request.is_for_recovery { "RECOVERY".to_string() @@ -331,6 +402,15 @@ fn get_template_id(params: &EmailRequestContext) -> [u8; 32] { keccak256(encode(&tokens)) } +/// Retrieves and encodes the command parameters for the email authentication request. +/// +/// # Arguments +/// +/// * `params` - The `EmailRequestContext` containing request details. +/// +/// # Returns +/// +/// A `Result` containing a vector of encoded command parameters or an `EmailError`. async fn get_encoded_command_params( params: &EmailRequestContext, ) -> Result, EmailError> { @@ -365,6 +445,15 @@ async fn get_encoded_command_params( Ok(command_params_encoded) } +/// Generates the email authentication message. +/// +/// # Arguments +/// +/// * `params` - The `EmailRequestContext` containing request details. +/// +/// # Returns +/// +/// A `Result` containing the `EmailAuthMsg`, `EmailProof`, and account salt, or an `EmailError`. async fn get_email_auth_msg( params: &EmailRequestContext, ) -> Result<(EmailAuthMsg, EmailProof, [u8; 32]), EmailError> { @@ -380,11 +469,17 @@ async fn get_email_auth_msg( Ok((email_auth_msg, email_proof, account_salt)) } +/// Represents the context for an email authentication request. #[derive(Debug, Clone)] struct EmailRequestContext { + /// The request details. request: Request, + /// The body of the email. email_body: String, + /// The account code as a string. account_code_str: String, + /// The full raw email. email: String, + /// The parsed email. parsed_email: ParsedEmail, } diff --git a/packages/relayer/src/database.rs b/packages/relayer/src/database.rs index 93de8ee1..29729903 100644 --- a/packages/relayer/src/database.rs +++ b/packages/relayer/src/database.rs @@ -3,28 +3,45 @@ use crate::*; use relayer_utils::LOG; use sqlx::{postgres::PgPool, Row}; +/// Represents the credentials for a user account. #[derive(Debug, Clone)] pub struct Credentials { + /// The unique code associated with the account. pub account_code: String, + /// The Ethereum address of the account. pub account_eth_addr: String, + /// The email address of the guardian. pub guardian_email_addr: String, + /// Indicates whether the credentials are set. pub is_set: bool, } +/// Represents a request in the system. #[derive(Debug, Clone)] pub struct Request { + /// The unique identifier for the request. pub request_id: u32, + /// The Ethereum address of the account. pub account_eth_addr: String, + /// The Ethereum address of the controller. pub controller_eth_addr: String, + /// The email address of the guardian. pub guardian_email_addr: String, + /// Indicates whether the request is for recovery. pub is_for_recovery: bool, + /// The index of the template used for the request. pub template_idx: u64, + /// Indicates whether the request has been processed. pub is_processed: bool, + /// Indicates the success status of the request, if available. pub is_success: Option, + /// The nullifier for the email, if available. pub email_nullifier: Option, + /// The salt for the account, if available. pub account_salt: Option, } +/// Represents the database connection and operations. pub struct Database { db: PgPool, } @@ -57,6 +74,7 @@ impl Database { /// /// A `Result` indicating success or failure of the setup process. pub async fn setup_database(&self) -> Result<()> { + // Create credentials table sqlx::query( "CREATE TABLE IF NOT EXISTS credentials ( account_code TEXT PRIMARY KEY, @@ -68,6 +86,7 @@ impl Database { .execute(&self.db) .await?; + // Create requests table sqlx::query( "CREATE TABLE IF NOT EXISTS requests ( request_id BIGINT PRIMARY KEY, @@ -85,6 +104,7 @@ impl Database { .execute(&self.db) .await?; + // Create expected_replies table sqlx::query( "CREATE TABLE IF NOT EXISTS expected_replies ( message_id VARCHAR(255) PRIMARY KEY, @@ -98,6 +118,11 @@ impl Database { Ok(()) } + /// Tests the database connection by attempting to execute a simple query. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the connection test. pub(crate) async fn test_db_connection(&self) -> Result<()> { // Try up to 3 times for i in 1..4 { @@ -120,6 +145,15 @@ impl Database { )) } + /// Retrieves credentials for a given account code. + /// + /// # Arguments + /// + /// * `account_code` - The unique code associated with the account. + /// + /// # Returns + /// + /// A `Result` containing an `Option` if successful, or an error if the query fails. pub(crate) async fn get_credentials(&self, account_code: &str) -> Result> { let row = sqlx::query("SELECT * FROM credentials WHERE account_code = $1") .bind(account_code) @@ -128,6 +162,7 @@ impl Database { match row { Some(row) => { + // Extract values from the row let account_code: String = row.get("account_code"); let account_eth_addr: String = row.get("account_eth_addr"); let guardian_email_addr: String = row.get("guardian_email_addr"); @@ -145,6 +180,16 @@ impl Database { } } + /// Checks if a wallet and email combination is registered in the database. + /// + /// # Arguments + /// + /// * `account_eth_addr` - The Ethereum address of the account. + /// * `email_addr` - The email address to check. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the combination is registered. pub(crate) async fn is_wallet_and_email_registered( &self, account_eth_addr: &str, @@ -159,17 +204,23 @@ impl Database { .await .map_err(|e| DatabaseError::new("Failed to check if wallet and email are registered", e))?; - match row { - Some(_) => Ok(true), - None => Ok(false), - } + Ok(row.is_some()) } + /// Updates the credentials for a given account code. + /// + /// # Arguments + /// + /// * `row` - The `Credentials` struct containing the updated information. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the update operation. pub(crate) async fn update_credentials_of_account_code( &self, row: &Credentials, ) -> std::result::Result<(), DatabaseError> { - let res = sqlx::query("UPDATE credentials SET account_eth_addr = $1, guardian_email_addr = $2, is_set = $3 WHERE account_code = $4") + sqlx::query("UPDATE credentials SET account_eth_addr = $1, guardian_email_addr = $2, is_set = $3 WHERE account_code = $4") .bind(&row.account_eth_addr) .bind(&row.guardian_email_addr) .bind(row.is_set) @@ -182,11 +233,20 @@ impl Database { Ok(()) } + /// Updates the credentials for a given wallet and email combination. + /// + /// # Arguments + /// + /// * `row` - The `Credentials` struct containing the updated information. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the update operation. pub(crate) async fn update_credentials_of_wallet_and_email( &self, row: &Credentials, ) -> std::result::Result<(), DatabaseError> { - let res = sqlx::query("UPDATE credentials SET account_code = $1, is_set = $2 WHERE account_eth_addr = $3 AND guardian_email_addr = $4") + sqlx::query("UPDATE credentials SET account_code = $1, is_set = $2 WHERE account_eth_addr = $3 AND guardian_email_addr = $4") .bind(&row.account_code) .bind(row.is_set) .bind(&row.account_eth_addr) @@ -199,12 +259,22 @@ impl Database { Ok(()) } + /// Updates the credentials of an inactive guardian. + /// + /// # Arguments + /// + /// * `is_set` - The new value for the `is_set` field. + /// * `account_eth_addr` - The Ethereum address of the account. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the update operation. pub(crate) async fn update_credentials_of_inactive_guardian( &self, is_set: bool, account_eth_addr: &str, ) -> std::result::Result<(), DatabaseError> { - let res = sqlx::query( + sqlx::query( "UPDATE credentials SET is_set = $1 WHERE account_eth_addr = $2 AND is_set = true", ) .bind(is_set) @@ -215,11 +285,20 @@ impl Database { Ok(()) } + /// Inserts new credentials into the database. + /// + /// # Arguments + /// + /// * `row` - The `Credentials` struct containing the new information. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the insert operation. pub(crate) async fn insert_credentials( &self, row: &Credentials, ) -> std::result::Result<(), DatabaseError> { - let row = sqlx::query( + sqlx::query( "INSERT INTO credentials (account_code, account_eth_addr, guardian_email_addr, is_set) VALUES ($1, $2, $3, $4) RETURNING *", ) .bind(&row.account_code) @@ -229,7 +308,7 @@ impl Database { .fetch_one(&self.db) .await .map_err(|e| DatabaseError::new("Failed to insert credentials", e))?; - info!(LOG, "Credentials inserted",); + info!(LOG, "Credentials inserted"); Ok(()) } @@ -255,12 +334,18 @@ impl Database { .await .map_err(|e| DatabaseError::new("Failed to check if guardian is set", e))?; - match row { - Some(_) => Ok(true), - None => Ok(false), - } + Ok(row.is_some()) } + /// Retrieves a request from the database based on the request ID. + /// + /// # Arguments + /// + /// * `request_id` - The unique identifier of the request. + /// + /// # Returns + /// + /// A `Result` containing an `Option` if successful, or an error if the query fails. pub(crate) async fn get_request( &self, request_id: u32, @@ -273,6 +358,7 @@ impl Database { match row { Some(row) => { + // Extract values from the row let request_id: i64 = row.get("request_id"); let account_eth_addr: String = row.get("account_eth_addr"); let controller_eth_addr: String = row.get("controller_eth_addr"); @@ -302,11 +388,20 @@ impl Database { } } + /// Updates an existing request in the database. + /// + /// # Arguments + /// + /// * `row` - The `Request` struct containing the updated information. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the update operation. pub(crate) async fn update_request( &self, row: &Request, ) -> std::result::Result<(), DatabaseError> { - let res = sqlx::query("UPDATE requests SET account_eth_addr = $1, controller_eth_addr = $2, guardian_email_addr = $3, is_for_recovery = $4, template_idx = $5, is_processed = $6, is_success = $7, email_nullifier = $8, account_salt = $9 WHERE request_id = $10") + sqlx::query("UPDATE requests SET account_eth_addr = $1, controller_eth_addr = $2, guardian_email_addr = $3, is_for_recovery = $4, template_idx = $5, is_processed = $6, is_success = $7, email_nullifier = $8, account_salt = $9 WHERE request_id = $10") .bind(&row.account_eth_addr) .bind(&row.controller_eth_addr) .bind(&row.guardian_email_addr) @@ -323,6 +418,16 @@ impl Database { Ok(()) } + /// Retrieves the account code for a given wallet and email combination. + /// + /// # Arguments + /// + /// * `account_eth_addr` - The Ethereum address of the account. + /// * `email_addr` - The email address associated with the account. + /// + /// # Returns + /// + /// A `Result` containing an `Option` with the account code if found, or an error if the query fails. pub(crate) async fn get_account_code_from_wallet_and_email( &self, account_eth_addr: &str, @@ -346,6 +451,16 @@ impl Database { } } + /// Retrieves the credentials for a given wallet and email combination. + /// + /// # Arguments + /// + /// * `account_eth_addr` - The Ethereum address of the account. + /// * `email_addr` - The email address associated with the account. + /// + /// # Returns + /// + /// A `Result` containing an `Option` if found, or an error if the query fails. pub(crate) async fn get_credentials_from_wallet_and_email( &self, account_eth_addr: &str, @@ -362,6 +477,7 @@ impl Database { match row { Some(row) => { + // Extract values from the row let account_code: String = row.get("account_code"); let account_eth_addr: String = row.get("account_eth_addr"); let guardian_email_addr: String = row.get("guardian_email_addr"); @@ -379,12 +495,21 @@ impl Database { } } + /// Inserts a new request into the database. + /// + /// # Arguments + /// + /// * `row` - The `Request` struct containing the new request information. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the insert operation. pub(crate) async fn insert_request( &self, row: &Request, ) -> std::result::Result<(), DatabaseError> { let request_id = row.request_id; - let row = sqlx::query( + sqlx::query( "INSERT INTO requests (request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, is_for_recovery, template_idx, is_processed, is_success, email_nullifier, account_salt) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *", ) .bind(row.request_id as i64) @@ -404,6 +529,16 @@ impl Database { Ok(()) } + /// Adds an expected reply to the database. + /// + /// # Arguments + /// + /// * `message_id` - The unique identifier of the message. + /// * `request_id` - An optional request ID associated with the reply. + /// + /// # Returns + /// + /// A `Result` indicating success or failure of the insert operation. pub(crate) async fn add_expected_reply( &self, message_id: &str, @@ -422,10 +557,17 @@ impl Database { Ok(()) } - // Checks if the given message_id corresponds to a valid reply. - // This function updates the `has_reply` field to true if the message_id exists and hasn't been replied to yet. - // Returns true if the update was successful (i.e., a valid reply was recorded), false otherwise, - // also if no record exists to be updated. + /// Checks if the given message_id corresponds to a valid reply. + /// + /// This function updates the `has_reply` field to true if the message_id exists and hasn't been replied to yet. + /// + /// # Arguments + /// + /// * `message_id` - The unique identifier of the message. + /// + /// # Returns + /// + /// A `Result` containing a boolean indicating if the reply is valid (true if the update was successful). pub(crate) async fn is_valid_reply(&self, message_id: &str) -> Result { let query = " UPDATE expected_replies diff --git a/packages/relayer/src/lib.rs b/packages/relayer/src/lib.rs index 42348138..c4d1adb6 100644 --- a/packages/relayer/src/lib.rs +++ b/packages/relayer/src/lib.rs @@ -46,9 +46,19 @@ pub static SMTP_SERVER: OnceLock = OnceLock::new(); static DB_CELL: OnceCell> = OnceCell::const_new(); +/// Wrapper struct for database access struct DBWrapper; impl DBWrapper { + /// Retrieves the database instance. + /// + /// # Returns + /// + /// A reference to the `Arc`. + /// + /// # Panics + /// + /// Panics if the database is not initialized. fn get() -> &'static Arc { DB_CELL.get().expect("Database not initialized") } @@ -58,13 +68,14 @@ impl std::ops::Deref for DBWrapper { type Target = Database; fn deref(&self) -> &Self::Target { - &**Self::get() + Self::get() } } static DB: DBWrapper = DBWrapper; lazy_static! { + /// Shared instance of the `ChainClient`. pub static ref CLIENT: Arc = { dotenv().ok(); let client = tokio::task::block_in_place(|| { @@ -75,12 +86,23 @@ lazy_static! { .unwrap(); Arc::new(client) }; + /// Shared mutex for synchronization. pub static ref SHARED_MUTEX: Arc> = Arc::new(Mutex::new(0)); } +/// Runs the relayer with the given configuration. +/// +/// # Arguments +/// +/// * `config` - The configuration for the relayer. +/// +/// # Returns +/// +/// A `Result` indicating success or failure. pub async fn run(config: RelayerConfig) -> Result<()> { info!(LOG, "Starting relayer"); + // Initialize global configuration CIRCUITS_DIR_PATH.set(config.circuits_dir_path).unwrap(); WEB_SERVER_ADDRESS.set(config.web_server_address).unwrap(); PROVER_ADDRESS.set(config.prover_address).unwrap(); @@ -97,6 +119,7 @@ pub async fn run(config: RelayerConfig) -> Result<()> { .unwrap(); SMTP_SERVER.set(config.smtp_server).unwrap(); + // Spawn the API server task let api_server_task = tokio::task::spawn(async move { loop { match run_server().await { @@ -106,13 +129,14 @@ pub async fn run(config: RelayerConfig) -> Result<()> { } Err(err) => { error!(LOG, "Error api server: {}", err); - // Optionally, add a delay before restarting + // Add a delay before restarting to prevent rapid restart loops tokio::time::sleep(Duration::from_secs(5)).await; } } } }); + // Wait for the API server task to complete let _ = tokio::join!(api_server_task); Ok(()) diff --git a/packages/relayer/src/modules/dkim.rs b/packages/relayer/src/modules/dkim.rs index 21ae7d30..fe91ee7c 100644 --- a/packages/relayer/src/modules/dkim.rs +++ b/packages/relayer/src/modules/dkim.rs @@ -15,17 +15,25 @@ use ic_utils::canister::*; use serde::Deserialize; +/// Represents a client for interacting with the DKIM Oracle. #[derive(Debug, Clone)] pub struct DkimOracleClient<'a> { + /// The canister used for communication pub canister: Canister<'a>, } +/// Represents a signed DKIM public key. #[derive(Default, CandidType, Deserialize, Debug, Clone)] pub struct SignedDkimPublicKey { + /// The selector for the DKIM key pub selector: String, + /// The domain for the DKIM key pub domain: String, + /// The signature of the DKIM key pub signature: String, + /// The public key pub public_key: String, + /// The hash of the public key pub public_key_hash: String, } @@ -41,8 +49,13 @@ impl<'a> DkimOracleClient<'a> { /// /// An `anyhow::Result`. pub fn gen_agent(pem_path: &str, replica_url: &str) -> anyhow::Result { + // Create identity from PEM file let identity = Secp256k1Identity::from_pem_file(pem_path)?; + + // Create transport using the replica URL let transport = ReqwestTransport::create(replica_url)?; + + // Build and return the agent let agent = AgentBuilder::default() .with_identity(identity) .with_transport(transport) @@ -61,6 +74,7 @@ impl<'a> DkimOracleClient<'a> { /// /// An `anyhow::Result`. pub fn new(canister_id: &str, agent: &'a Agent) -> anyhow::Result { + // Build the canister using the provided ID and agent let canister = CanisterBuilder::new() .with_canister_id(canister_id) .with_agent(agent) @@ -83,11 +97,14 @@ impl<'a> DkimOracleClient<'a> { selector: &str, domain: &str, ) -> anyhow::Result { + // Build the request to sign the DKIM public key let request = self .canister .update("sign_dkim_public_key") .with_args((selector, domain)) .build::<(Result,)>(); + + // Call the canister and wait for the response let response = request .call_and_wait_one::>() .await? @@ -117,25 +134,36 @@ pub async fn check_and_update_dkim( wallet_addr: &str, account_salt: &str, ) -> Result<()> { + // Generate public key hash let mut public_key_n = parsed_email.public_key.clone(); public_key_n.reverse(); let public_key_hash = public_key_hash(&public_key_n)?; info!(LOG, "public_key_hash {:?}", public_key_hash); + + // Get email domain let domain = parsed_email.get_email_domain()?; info!(LOG, "domain {:?}", domain); + + // Check if wallet is deployed if CLIENT.get_bytecode(wallet_addr).await? == Bytes::from_static(&[0u8; 20]) { info!(LOG, "wallet not deployed"); return Ok(()); } + + // Get email auth address let email_auth_addr = CLIENT .get_email_auth_addr_from_wallet(controller_eth_addr, wallet_addr, account_salt) .await?; let email_auth_addr = format!("0x{:x}", email_auth_addr); + + // Get DKIM from wallet or email auth let mut dkim = CLIENT.get_dkim_from_wallet(controller_eth_addr).await?; if CLIENT.get_bytecode(&email_auth_addr).await? != Bytes::new() { dkim = CLIENT.get_dkim_from_email_auth(&email_auth_addr).await?; } info!(LOG, "dkim {:?}", dkim); + + // Check if DKIM public key hash is valid if CLIENT .check_if_dkim_public_key_hash_valid( domain.clone(), @@ -147,6 +175,8 @@ pub async fn check_and_update_dkim( info!(LOG, "public key registered"); return Ok(()); } + + // Get selector let selector_def_path = env::var(SELECTOR_DEF_PATH_KEY) .map_err(|_| anyhow!("ENV var {} not set", SELECTOR_DEF_PATH_KEY))?; let selector_def_contents = fs::read_to_string(&selector_def_path) @@ -158,17 +188,25 @@ pub async fn check_and_update_dkim( parsed_email.canonicalized_header[idxes.0..idxes.1].to_string() }; info!(LOG, "selector {}", selector); + + // Generate IC agent and create oracle client let ic_agent = DkimOracleClient::gen_agent( &env::var(PEM_PATH_KEY).unwrap(), &env::var(IC_REPLICA_URL_KEY).unwrap(), )?; let oracle_client = DkimOracleClient::new(&env::var(CANISTER_ID_KEY).unwrap(), &ic_agent)?; + + // Request signature from oracle let oracle_result = oracle_client.request_signature(&selector, &domain).await?; info!(LOG, "DKIM oracle result {:?}", oracle_result); + + // Process oracle response let public_key_hash = hex::decode(&oracle_result.public_key_hash[2..])?; info!(LOG, "public_key_hash from oracle {:?}", public_key_hash); let signature = Bytes::from_hex(&oracle_result.signature[2..])?; info!(LOG, "signature {:?}", signature); + + // Set DKIM public key hash let tx_hash = CLIENT .set_dkim_public_key_hash( selector, diff --git a/packages/relayer/src/modules/mail.rs b/packages/relayer/src/modules/mail.rs index d0fd85f7..5fbc5d9a 100644 --- a/packages/relayer/src/modules/mail.rs +++ b/packages/relayer/src/modules/mail.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::fs::read_to_string; +/// Represents different types of email authentication events. #[derive(Debug, Clone)] pub enum EmailAuthEvent { AcceptanceRequest { @@ -62,6 +63,7 @@ pub enum EmailAuthEvent { NoOp, } +/// Represents an email message to be sent. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct EmailMessage { pub to: String, @@ -73,6 +75,7 @@ pub struct EmailMessage { pub body_attachments: Option>, } +/// Represents an attachment in an email message. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct EmailAttachment { pub inline_id: String, @@ -98,8 +101,10 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> command, account_code, } => { + // Prepare the command with the account code let command = format!("{} Code {}", command, account_code); + // Create the plain text body let body_plain = format!( "You have received an guardian request from the wallet address {}. \ {} Code {}. \ @@ -111,6 +116,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let subject = "Email Recovery: Acceptance Request".to_string(); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "userEmailAddr": guardian_email_addr, "walletAddress": account_eth_addr, @@ -119,6 +125,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> }); let body_html = render_html("acceptance_request.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject, @@ -145,12 +152,14 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> error ); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "error": error, "userEmailAddr": email_addr, }); let body_html = render_html("error.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: email_addr, subject, @@ -174,12 +183,14 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> guardian_email_addr, account_eth_addr ); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "walletAddress": account_eth_addr, "userEmailAddr": guardian_email_addr, }); let body_html = render_html("guardian_already_exists.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject: subject.to_string(), @@ -208,6 +219,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let subject = "Email Recovery: Recovery Request".to_string(); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "userEmailAddr": guardian_email_addr, "walletAddress": account_eth_addr, @@ -216,6 +228,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> }); let body_html = render_html("recovery_request.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject, @@ -242,6 +255,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, request_id ); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "walletAddress": account_eth_addr, "userEmailAddr": guardian_email_addr, @@ -249,6 +263,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> }); let body_html = render_html("acceptance_success.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject: subject.to_string(), @@ -275,6 +290,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, request_id ); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "walletAddress": account_eth_addr, "userEmailAddr": guardian_email_addr, @@ -282,6 +298,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> }); let body_html = render_html("recovery_success.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject: subject.to_string(), @@ -301,12 +318,14 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let subject = "Guardian Not Set"; let body_plain = format!("Guardian not set for wallet address {}", account_eth_addr); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "walletAddress": account_eth_addr, "userEmailAddr": guardian_email_addr, }); let body_html = render_html("guardian_not_set.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject: subject.to_string(), @@ -335,6 +354,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> account_eth_addr, request_id ); + // Prepare data for HTML rendering let render_data = serde_json::json!({ "userEmailAddr": guardian_email_addr, "walletAddress": account_eth_addr, @@ -345,6 +365,7 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> let subject = "Guardian Not Registered".to_string(); let body_html = render_html("credential_not_present.html", render_data).await?; + // Create and send the email let email = EmailMessage { to: guardian_email_addr, subject, @@ -367,9 +388,11 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> "Hi {}!\nYour email with the command {} is received.", email_addr, command ); + // Prepare data for HTML rendering let render_data = serde_json::json!({"userEmailAddr": email_addr, "request": command}); let body_html = render_html("acknowledgement.html", render_data).await?; let subject = format!("Re: {}", original_subject); + // Create and send the email let email = EmailMessage { to: email_addr, subject, @@ -397,10 +420,13 @@ pub async fn handle_email_event(event: EmailAuthEvent) -> Result<(), EmailError> /// # Returns /// /// A `Result` containing the rendered HTML string or an `EmailError`. -pub async fn render_html(template_name: &str, render_data: Value) -> Result { +async fn render_html(template_name: &str, render_data: Value) -> Result { + // Construct the full path to the email template let email_template_filename = PathBuf::new() .join(EMAIL_TEMPLATES.get().unwrap()) .join(template_name); + + // Read the email template file let email_template = read_to_string(&email_template_filename) .await .map_err(|e| { @@ -410,8 +436,10 @@ pub async fn render_html(template_name: &str, render_data: Value) -> Result Result` with the parsed error message. -pub fn parse_error(error: String) -> Result> { +fn parse_error(error: String) -> Result> { let mut error = error; if error.contains("Contract call reverted with data: ") { + // Extract and decode the revert data let revert_data = error .replace("Contract call reverted with data: ", "") .split_at(10) @@ -441,6 +470,7 @@ pub fn parse_error(error: String) -> Result> { error = String::from_utf8(revert_bytes).unwrap().trim().to_string(); } + // Match known error messages and provide user-friendly responses match error.as_str() { "Account is already created" => Ok(Some(error)), "insufficient balance" => Ok(Some("You don't have sufficient balance".to_string())), @@ -453,11 +483,12 @@ pub fn parse_error(error: String) -> Result> { /// # Arguments /// /// * `email` - The `EmailMessage` to be sent. +/// * `expects_reply` - An optional `ExpectsReply` struct indicating if a reply is expected. /// /// # Returns /// /// A `Result` indicating success or an `EmailError`. -pub async fn send_email( +async fn send_email( email: EmailMessage, expects_reply: Option, ) -> Result<(), EmailError> { @@ -472,6 +503,7 @@ pub async fn send_email( .await .map_err(|e| EmailError::Send(format!("Failed to send email: {}", e)))?; + // Check if the email was sent successfully if !response.status().is_success() { return Err(EmailError::Send(format!( "Failed to send email: {}", @@ -479,6 +511,7 @@ pub async fn send_email( ))); } + // Handle expected reply if necessary if let Some(expects_reply) = expects_reply { let response_body: EmailResponse = response .json() @@ -493,23 +526,31 @@ pub async fn send_email( Ok(()) } +/// Represents the response from the email server after sending an email. #[derive(Debug, Clone, Serialize, Deserialize)] struct EmailResponse { status: String, message_id: String, } +/// Represents an expectation of a reply to an email. pub struct ExpectsReply { request_id: Option, } impl ExpectsReply { + /// Creates a new `ExpectsReply` instance with a request ID. + /// + /// # Arguments + /// + /// * `request_id` - The ID of the request expecting a reply. fn new(request_id: u32) -> Self { Self { request_id: Some(request_id.to_string()), } } + /// Creates a new `ExpectsReply` instance without a request ID. fn new_no_request_id() -> Self { Self { request_id: None } } @@ -518,17 +559,27 @@ impl ExpectsReply { /// Checks if the email is a reply to a command that expects a reply. /// Will return false for duplicate replies. /// Will return true if the email is not a reply. +/// +/// # Arguments +/// +/// * `email` - The `ParsedEmail` to be checked. +/// +/// # Returns +/// +/// A `Result` containing a boolean indicating if the request is valid. pub async fn check_is_valid_request(email: &ParsedEmail) -> Result { + // Check if the email is a reply by looking for the "In-Reply-To" header let reply_message_id = match email .headers .get_header("In-Reply-To") .and_then(|v| v.first().cloned()) { Some(id) => id, - // Email is not a reply + // Email is not a reply, so it's valid None => return Ok(true), }; + // Check if the reply is valid (not a duplicate) using the database let is_valid = DB.is_valid_reply(&reply_message_id).await?; Ok(is_valid) } diff --git a/packages/relayer/src/modules/mod.rs b/packages/relayer/src/modules/mod.rs index 5ace1b92..eaf1adc5 100644 --- a/packages/relayer/src/modules/mod.rs +++ b/packages/relayer/src/modules/mod.rs @@ -1,3 +1,5 @@ +//! This module contains the dkim, mail and web_server modules. + pub mod dkim; pub mod mail; pub mod web_server; diff --git a/packages/relayer/src/modules/web_server/relayer_errors.rs b/packages/relayer/src/modules/web_server/relayer_errors.rs index 10959c21..8b49462a 100644 --- a/packages/relayer/src/modules/web_server/relayer_errors.rs +++ b/packages/relayer/src/modules/web_server/relayer_errors.rs @@ -10,6 +10,7 @@ use rustc_hex::FromHexError; use serde_json::json; use thiserror::Error; +/// Custom error type for API-related errors #[derive(Error, Debug)] pub enum ApiError { #[error("Database error: {0}")] @@ -30,6 +31,7 @@ pub enum ApiError { Email(#[from] EmailError), } +/// Custom error type for email-related errors #[derive(Error, Debug)] pub enum EmailError { #[error("Email body error: {0}")] @@ -65,6 +67,7 @@ pub enum EmailError { Anyhow(#[from] anyhow::Error), } +/// Custom error type for blockchain-related errors #[derive(Error, Debug)] pub enum ChainError { #[error("Contract error: {0}")] @@ -98,6 +101,7 @@ impl ChainError { } } +/// Custom error type for database-related errors #[derive(Debug, thiserror::Error)] #[error("{msg}: {source}")] pub struct DatabaseError { @@ -115,6 +119,7 @@ impl DatabaseError { } } +/// Wrapper for contract-related errors #[derive(Debug)] pub struct ContractErrorWrapper { msg: String, @@ -136,6 +141,7 @@ impl ContractErrorWrapper { } } +/// Wrapper for signer middleware-related errors #[derive(Debug)] pub struct SignerMiddlewareErrorWrapper { msg: String, @@ -160,6 +166,7 @@ impl SignerMiddlewareErrorWrapper { } } +/// Wrapper for provider-related errors #[derive(Debug)] pub struct ProviderErrorWrapper { msg: String, diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index add61e88..8b0093d0 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -20,6 +20,8 @@ pub async fn request_status_api( Json(payload): Json, ) -> Result, ApiError> { let row = DB.get_request(payload.request_id).await?; + + // Determine the status based on the retrieved row let status = if let Some(ref row) = row { if row.is_processed { RequestStatus::Processed @@ -29,6 +31,7 @@ pub async fn request_status_api( } else { RequestStatus::NotExist }; + Ok(Json(RequestStatusResponse { request_id: payload.request_id, status, @@ -56,9 +59,11 @@ pub async fn handle_acceptance_request( .get_acceptance_command_templates(&payload.controller_eth_addr, payload.template_idx) .await?; + // Extract and validate command parameters let command_params = extract_template_vals(&payload.command, command_template) .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; + // Recover the account address let account_eth_addr = CLIENT .get_recovered_account_from_acceptance_command( &payload.controller_eth_addr, @@ -69,66 +74,19 @@ pub async fn handle_acceptance_request( let account_eth_addr = format!("0x{:x}", account_eth_addr); + // Check if the wallet is deployed if !CLIENT.is_wallet_deployed(&account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } - // Check if hash of bytecode of proxy contract is equal or not - let bytecode = CLIENT.get_bytecode(&account_eth_addr).await?; - let bytecode_hash = format!("0x{}", hex::encode(keccak256(bytecode.as_ref()))); - - // let permitted_wallets: Vec = - // serde_json::from_str(include_str!("../../permitted_wallets.json")).unwrap(); - // let permitted_wallet = permitted_wallets - // .iter() - // .find(|w| w.hash_of_bytecode_of_proxy == bytecode_hash); - - // if let Some(permitted_wallet) = permitted_wallet { - // let slot_location = permitted_wallet.slot_location.parse::().unwrap(); - // let impl_contract_from_proxy = { - // let raw_hex = hex::encode( - // CLIENT - // .get_storage_at(&account_eth_addr, slot_location) - // .await - // .unwrap(), - // ); - // format!("0x{}", &raw_hex[24..]) - // }; - - // if !permitted_wallet - // .impl_contract_address - // .eq_ignore_ascii_case(&impl_contract_from_proxy) - // { - // return Response::builder() - // .status(StatusCode::BAD_REQUEST) - // .body(Body::from( - // "Invalid bytecode, impl contract address mismatch", - // )) - // .unwrap(); - // } - - // if !permitted_wallet - // .controller_eth_addr - // .eq_ignore_ascii_case(&payload.controller_eth_addr) - // { - // return Response::builder() - // .status(StatusCode::BAD_REQUEST) - // .body(Body::from("Invalid controller eth addr")) - // .unwrap(); - // } - // } else { - // return Response::builder() - // .status(StatusCode::BAD_REQUEST) - // .body(Body::from("Wallet not permitted")) - // .unwrap(); - // } - + // Check if the account code is already used if let Ok(Some(creds)) = DB.get_credentials(&payload.account_code).await { return Err(ApiError::Validation( "Account code already used".to_string(), )); } + // Generate a unique request ID let mut request_id = rand::thread_rng().gen::(); while let Ok(Some(request)) = DB.get_request(request_id).await { request_id = rand::thread_rng().gen::(); @@ -150,6 +108,7 @@ pub async fn handle_acceptance_request( }) .await?; + // Handle different scenarios based on guardian status if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) .await? @@ -165,8 +124,7 @@ pub async fn handle_acceptance_request( .is_wallet_and_email_registered(&account_eth_addr, &payload.guardian_email_addr) .await? { - // In this case, the relayer sent a request email to the same guardian before, but it has not been replied yet. - // Therefore, the relayer will send an email to the guardian again with a fresh account code. + // Update credentials and send acceptance request email DB.update_credentials_of_wallet_and_email(&Credentials { account_code: payload.account_code.clone(), account_eth_addr: account_eth_addr.clone(), @@ -184,6 +142,7 @@ pub async fn handle_acceptance_request( }) .await?; } else { + // Insert new credentials and send acceptance request email DB.insert_credentials(&Credentials { account_code: payload.account_code.clone(), account_eth_addr: account_eth_addr.clone(), @@ -220,13 +179,16 @@ pub async fn handle_acceptance_request( pub async fn handle_recovery_request( Json(payload): Json, ) -> Result, ApiError> { + // Fetch the command template let command_template = CLIENT .get_recovery_command_templates(&payload.controller_eth_addr, payload.template_idx) .await?; + // Extract and validate command parameters let command_params = extract_template_vals(&payload.command, command_template) .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; + // Recover the account address let account_eth_addr = CLIENT .get_recovered_account_from_recovery_command( &payload.controller_eth_addr, @@ -237,65 +199,18 @@ pub async fn handle_recovery_request( let account_eth_addr = format!("0x{:x}", account_eth_addr); + // Check if the wallet is deployed if !CLIENT.is_wallet_deployed(&account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } - // Check if hash of bytecode of proxy contract is equal or not - let bytecode = CLIENT.get_bytecode(&account_eth_addr).await?; - let bytecode_hash = format!("0x{}", hex::encode(keccak256(bytecode.as_ref()))); - - // let permitted_wallets: Vec = - // serde_json::from_str(include_str!("../../permitted_wallets.json")).unwrap(); - // let permitted_wallet = permitted_wallets - // .iter() - // .find(|w| w.hash_of_bytecode_of_proxy == bytecode_hash); - - // if let Some(permitted_wallet) = permitted_wallet { - // let slot_location = permitted_wallet.slot_location.parse::().unwrap(); - // let impl_contract_from_proxy = { - // let raw_hex = hex::encode( - // CLIENT - // .get_storage_at(&account_eth_addr, slot_location) - // .await - // .unwrap(), - // ); - // format!("0x{}", &raw_hex[24..]) - // }; - - // if !permitted_wallet - // .impl_contract_address - // .eq_ignore_ascii_case(&impl_contract_from_proxy) - // { - // return Response::builder() - // .status(StatusCode::BAD_REQUEST) - // .body(Body::from( - // "Invalid bytecode, impl contract address mismatch", - // )) - // .unwrap(); - // } - - // if !permitted_wallet - // .controller_eth_addr - // .eq_ignore_ascii_case(&payload.controller_eth_addr) - // { - // return Response::builder() - // .status(StatusCode::BAD_REQUEST) - // .body(Body::from("Invalid controller eth addr")) - // .unwrap(); - // } - // } else { - // return Response::builder() - // .status(StatusCode::BAD_REQUEST) - // .body(Body::from("Wallet not permitted")) - // .unwrap(); - // } - + // Generate a unique request ID let mut request_id = rand::thread_rng().gen::(); while let Ok(Some(request)) = DB.get_request(request_id).await { request_id = rand::thread_rng().gen::(); } + // Fetch account details and calculate account salt let account = DB .get_credentials_from_wallet_and_email(&account_eth_addr, &payload.guardian_email_addr) .await?; @@ -306,6 +221,7 @@ pub async fn handle_recovery_request( return Err(ApiError::Validation("Wallet not deployed".to_string())); }; + // Handle the case when wallet and email are not registered if !DB .is_wallet_and_email_registered(&account_eth_addr, &payload.guardian_email_addr) .await? @@ -338,6 +254,7 @@ pub async fn handle_recovery_request( })); } + // Insert the recovery request DB.insert_request(&Request { request_id, account_eth_addr: account_eth_addr.clone(), @@ -352,6 +269,7 @@ pub async fn handle_recovery_request( }) .await?; + // Handle different scenarios based on guardian status if DB .is_guardian_set(&account_eth_addr, &payload.guardian_email_addr) .await? @@ -393,10 +311,12 @@ pub async fn handle_recovery_request( pub async fn handle_complete_recovery_request( Json(payload): Json, ) -> Result { + // Check if the wallet is deployed if !CLIENT.is_wallet_deployed(&payload.account_eth_addr).await? { return Err(ApiError::Validation("Wallet not deployed".to_string())); } + // Attempt to complete the recovery match CLIENT .complete_recovery( &payload.controller_eth_addr, @@ -455,6 +375,7 @@ pub async fn get_account_salt( pub async fn inactive_guardian( Json(payload): Json, ) -> Result { + // Check if the wallet is activated let is_activated = CLIENT .get_is_activated(&payload.controller_eth_addr, &payload.account_eth_addr) .await?; @@ -464,18 +385,31 @@ pub async fn inactive_guardian( } trace!(LOG, "Inactive guardian"; "is_activated" => is_activated); + + // Parse and format the account Ethereum address let account_eth_addr: Address = payload .account_eth_addr .parse() .map_err(|e| ApiError::Validation(format!("Failed to parse account_eth_addr: {}", e)))?; let account_eth_addr = format!("0x{:x}", &account_eth_addr); trace!(LOG, "Inactive guardian"; "account_eth_addr" => &account_eth_addr); + + // Update the credentials of the inactive guardian DB.update_credentials_of_inactive_guardian(false, &account_eth_addr) .await?; Ok("Guardian inactivated".to_string()) } +/// Parses an error message from contract call data. +/// +/// # Arguments +/// +/// * `error_data` - The error data as a `String`. +/// +/// # Returns +/// +/// A `String` containing the parsed error message or a default error message. fn parse_error_message(error_data: String) -> String { // Attempt to extract and decode the error message if let Some(hex_error) = error_data.split(" ").last() { @@ -509,6 +443,7 @@ pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { return; } + // Send acknowledgment email match handle_email_event(EmailAuthEvent::Ack { email_addr: from_addr.clone(), command: parsed_email.get_command(false).unwrap_or_default(), @@ -524,6 +459,8 @@ pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { error!(LOG, "Error handling email event: {:?}", e); } } + + // Process the email match handle_email(email.clone()).await { Ok(event) => match handle_email_event(event).await { Ok(_) => {} @@ -555,80 +492,125 @@ pub async fn receive_email_api_fn(email: String) -> Result<(), ApiError> { Ok(()) } +/// Request status request structure. #[derive(Serialize, Deserialize)] pub struct RequestStatusRequest { + /// The unique identifier for the request. pub request_id: u32, } +/// Enum representing the possible statuses of a request. #[derive(Serialize, Deserialize)] pub enum RequestStatus { + /// The request does not exist. NotExist = 0, + /// The request is pending processing. Pending = 1, + /// The request has been processed. Processed = 2, } +/// Response structure for a request status query. #[derive(Serialize, Deserialize)] pub struct RequestStatusResponse { + /// The unique identifier for the request. pub request_id: u32, + /// The current status of the request. pub status: RequestStatus, + /// Indicates whether the request was successful. pub is_success: bool, + /// The email nullifier, if available. pub email_nullifier: Option, + /// The account salt, if available. pub account_salt: Option, } +/// Request structure for an acceptance request. #[derive(Serialize, Deserialize)] pub struct AcceptanceRequest { + /// The Ethereum address of the controller. pub controller_eth_addr: String, + /// The email address of the guardian. pub guardian_email_addr: String, + /// The unique account code. pub account_code: String, + /// The index of the template to use. pub template_idx: u64, + /// The command to execute. pub command: String, } +/// Response structure for an acceptance request. #[derive(Serialize, Deserialize)] pub struct AcceptanceResponse { + /// The unique identifier for the request. pub request_id: u32, + /// The parameters extracted from the command. pub command_params: Vec, } +/// Request structure for a recovery request. #[derive(Serialize, Deserialize, Debug)] pub struct RecoveryRequest { + /// The Ethereum address of the controller. pub controller_eth_addr: String, + /// The email address of the guardian. pub guardian_email_addr: String, + /// The index of the template to use. pub template_idx: u64, + /// The command to execute. pub command: String, } +/// Response structure for a recovery request. #[derive(Serialize, Deserialize)] pub struct RecoveryResponse { + /// The unique identifier for the request. pub request_id: u32, + /// The parameters extracted from the command. pub command_params: Vec, } +/// Request structure for completing a recovery. #[derive(Serialize, Deserialize)] pub struct CompleteRecoveryRequest { + /// The Ethereum address of the account to recover. pub account_eth_addr: String, + /// The Ethereum address of the controller. pub controller_eth_addr: String, + /// The calldata to complete the recovery. pub complete_calldata: String, } +/// Request structure for retrieving an account salt. #[derive(Serialize, Deserialize)] pub struct GetAccountSaltRequest { + /// The unique account code. pub account_code: String, + /// The email address associated with the account. pub email_addr: String, } +/// Structure representing a permitted wallet. #[derive(Deserialize)] struct PermittedWallet { + /// The name of the wallet. wallet_name: String, + /// The Ethereum address of the controller. controller_eth_addr: String, + /// The hash of the bytecode of the proxy contract. hash_of_bytecode_of_proxy: String, + /// The address of the implementation contract. impl_contract_address: String, + /// The slot location in storage. slot_location: String, } +/// Request structure for marking a guardian as inactive. #[derive(Serialize, Deserialize)] pub struct InactiveGuardianRequest { + /// The Ethereum address of the account. pub account_eth_addr: String, + /// The Ethereum address of the controller. pub controller_eth_addr: String, } diff --git a/packages/relayer/src/modules/web_server/server.rs b/packages/relayer/src/modules/web_server/server.rs index 594ee4c5..b8f371c3 100644 --- a/packages/relayer/src/modules/web_server/server.rs +++ b/packages/relayer/src/modules/web_server/server.rs @@ -11,6 +11,7 @@ use tower_http::cors::{AllowHeaders, AllowMethods, Any, CorsLayer}; pub async fn run_server() -> Result<()> { let addr = WEB_SERVER_ADDRESS.get().unwrap(); + // Initialize the global DB ref before starting the server DB_CELL .get_or_init(|| async { dotenv::dotenv().ok(); @@ -28,6 +29,7 @@ pub async fn run_server() -> Result<()> { }; info!(LOG, "Testing connection to database successfull"); + // Initialize the API routes let mut app = Router::new() .route( "/api/echo", @@ -51,6 +53,7 @@ pub async fn run_server() -> Result<()> { .allow_origin(Any), ); + // Start the server trace!(LOG, "Listening API at {}", addr); axum::Server::bind(&addr.parse()?) .serve(app.into_make_service()) From 4c179e5c56552b315da99c59460ac89e9b0f8e2d Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 19 Sep 2024 14:14:03 +0700 Subject: [PATCH 35/53] Rename func to extract_template_vals_from_command --- packages/relayer/src/modules/web_server/rest_api.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/relayer/src/modules/web_server/rest_api.rs b/packages/relayer/src/modules/web_server/rest_api.rs index 8b0093d0..e17988fe 100644 --- a/packages/relayer/src/modules/web_server/rest_api.rs +++ b/packages/relayer/src/modules/web_server/rest_api.rs @@ -3,7 +3,9 @@ use anyhow::Result; use axum::Json; use hex::decode; use rand::Rng; -use relayer_utils::{calculate_account_salt, extract_template_vals, TemplateValue, LOG}; +use relayer_utils::{ + calculate_account_salt, extract_template_vals_from_command, TemplateValue, LOG, +}; use serde::{Deserialize, Serialize}; use std::str; @@ -60,7 +62,7 @@ pub async fn handle_acceptance_request( .await?; // Extract and validate command parameters - let command_params = extract_template_vals(&payload.command, command_template) + let command_params = extract_template_vals_from_command(&payload.command, command_template) .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; // Recover the account address @@ -185,7 +187,7 @@ pub async fn handle_recovery_request( .await?; // Extract and validate command parameters - let command_params = extract_template_vals(&payload.command, command_template) + let command_params = extract_template_vals_from_command(&payload.command, command_template) .map_err(|_| ApiError::Validation("Invalid command".to_string()))?; // Recover the account address From 9cf423cf6f15ba656eea51891243dd708d195003 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 19 Sep 2024 14:31:21 +0700 Subject: [PATCH 36/53] Exclude abi folder as workspace member --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9fd16a34..fc094365 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,4 @@ [workspace] members = ["packages/relayer"] -exclude = ["node_modules/*"] +exclude = ["node_modules/*", "packages/relayer/src/abis"] resolver = "2" From cf12f6d4482163dc7c20c5217336ff9e86f55c38 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 19 Sep 2024 17:10:30 +0700 Subject: [PATCH 37/53] Ignore abis for fmt --- Cargo.lock | 2 +- packages/relayer/Cargo.toml | 3 ++- packages/relayer/src/abis/mod.rs | 7 +++++++ rust-toolchain | 2 +- rustfmt.toml | 4 ---- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c4df7ba..18223391 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4141,7 +4141,7 @@ dependencies = [ [[package]] name = "relayer-utils" version = "0.3.7" -source = "git+https://github.com/zkemail/relayer-utils.git?rev=0c19631#0c196312b6ce7ce2c282d11e6c736e958b8df77a" +source = "git+https://github.com/zkemail/relayer-utils.git?rev=6fb85e6#6fb85e6b867165a5deb2fe877bc81827b6bf001e" dependencies = [ "anyhow", "base64 0.21.7", diff --git a/packages/relayer/Cargo.toml b/packages/relayer/Cargo.toml index 4ccd237d..ef4a199d 100644 --- a/packages/relayer/Cargo.toml +++ b/packages/relayer/Cargo.toml @@ -25,7 +25,8 @@ tiny_http = "0.12.0" lettre = { version = "0.10.4", features = ["tokio1", "tokio1-native-tls"] } ethers = { version = "2.0.10", features = ["abigen"] } # relayer-utils = { version = "0.3.7", git = "https://github.com/zkemail/relayer-utils.git" } -relayer-utils = { rev = "0c19631", git = "https://github.com/zkemail/relayer-utils.git" } +relayer-utils = { rev = "6fb85e6", git = "https://github.com/zkemail/relayer-utils.git" } +# relayer-utils = { path="../../../relayer-utils" } futures = "0.3.28" sqlx = { version = "=0.7.3", features = ["postgres", "runtime-tokio"] } regex = "1.10.2" diff --git a/packages/relayer/src/abis/mod.rs b/packages/relayer/src/abis/mod.rs index 6a38feb0..27a4c209 100644 --- a/packages/relayer/src/abis/mod.rs +++ b/packages/relayer/src/abis/mod.rs @@ -1,6 +1,13 @@ #![allow(clippy::all)] + + +#[cfg_attr(rustfmt, rustfmt::skip)] pub mod ecdsa_owned_dkim_registry; + +#[cfg_attr(rustfmt, rustfmt::skip)] pub mod email_account_recovery; + +#[cfg_attr(rustfmt, rustfmt::skip)] pub mod email_auth; pub use ecdsa_owned_dkim_registry::ECDSAOwnedDKIMRegistry; diff --git a/rust-toolchain b/rust-toolchain index 4fa580ba..97e98527 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.80.1 \ No newline at end of file +1.80.1 diff --git a/rustfmt.toml b/rustfmt.toml index a8f43d10..b8116019 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,8 +1,4 @@ max_width = 100 -indent_style = "Block" use_small_heuristics = "Default" -imports_layout = "Mixed" -imports_granularity = "Crate" -group_imports = "StdExternalCrate" reorder_imports = true reorder_modules = true From d5771ded6c2debc53326cbdb4f98c6d7871c5038 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 20 Sep 2024 14:03:17 +0700 Subject: [PATCH 38/53] Add github actions to build docker image --- .github/workflows/build-img.yml | 51 +++++++++++++++++++++++++ Full.Dockerfile | 66 +++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 .github/workflows/build-img.yml create mode 100644 Full.Dockerfile diff --git a/.github/workflows/build-img.yml b/.github/workflows/build-img.yml new file mode 100644 index 00000000..2e578f91 --- /dev/null +++ b/.github/workflows/build-img.yml @@ -0,0 +1,51 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - refactor + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=sha,prefix= + type=raw,value=latest + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: ./Full.Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Full.Dockerfile b/Full.Dockerfile new file mode 100644 index 00000000..bb07d4e7 --- /dev/null +++ b/Full.Dockerfile @@ -0,0 +1,66 @@ +# Use the latest official Rust image as the base +FROM rust:latest + +# Use bash as the shell +SHELL ["/bin/bash", "-c"] + +# Install NVM, Node.js, and Yarn +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash \ + && . $HOME/.nvm/nvm.sh \ + && nvm install 18 \ + && nvm alias default 18 \ + && nvm use default \ + && npm install -g yarn + +# Set the working directory +WORKDIR /relayer + +# Pre-configure Git to avoid common issues and increase clone verbosity +RUN git config --global advice.detachedHead false \ + && git config --global core.compression 0 \ + && git config --global protocol.version 2 \ + && git config --global http.postBuffer 1048576000 \ + && git config --global fetch.verbose true + +# Copy project files +COPY . . + +# Remove the packages/relayer directory +RUN rm -rf packages/relayer + +# Install Yarn dependencies with retry mechanism +RUN . $HOME/.nvm/nvm.sh && nvm use default && yarn || \ + (sleep 5 && yarn) || \ + (sleep 10 && yarn) + +# Install Foundry +RUN curl -L https://foundry.paradigm.xyz | bash \ + && source $HOME/.bashrc \ + && foundryup + +# Verify Foundry installation +RUN source $HOME/.bashrc && forge --version + +# Set the working directory for contracts +WORKDIR /relayer/packages/contracts + +# Install Yarn dependencies for contracts +RUN source $HOME/.nvm/nvm.sh && nvm use default && yarn + +# Build the contracts using Foundry +RUN source $HOME/.bashrc && forge build + +# Copy the project files +COPY packages/relayer /relayer/packages/relayer + +# Set the working directory for the Rust project +WORKDIR /relayer/packages/relayer + +# Build the Rust project with caching +RUN cargo build + +# Expose port +EXPOSE 4500 + +# Set the default command +CMD ["cargo", "run"] From 58ed8fb9a1aa3e4631a257d73fd05ddf9323bc51 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sat, 28 Sep 2024 06:25:26 +0530 Subject: [PATCH 39/53] ui: Update email template UI - powered by zk email is odd that theyre different sizes - the social icons at the bottom look squished - Update the email template from The Zk team Aayush to The ZK Email Team - Check vertical padding in the mail --- .../relayer/eml_templates/acceptance_request.html | 11 ++++++----- .../relayer/eml_templates/acceptance_success.html | 11 ++++++----- packages/relayer/eml_templates/acknowledgement.html | 11 ++++++----- .../relayer/eml_templates/credential_not_present.html | 11 ++++++----- .../eml_templates/guardian_already_exists.html | 11 ++++++----- packages/relayer/eml_templates/guardian_not_set.html | 11 ++++++----- packages/relayer/eml_templates/recovery_request.html | 11 ++++++----- packages/relayer/eml_templates/recovery_success.html | 11 ++++++----- 8 files changed, 48 insertions(+), 40 deletions(-) diff --git a/packages/relayer/eml_templates/acceptance_request.html b/packages/relayer/eml_templates/acceptance_request.html index 6950b8c8..5b536f0d 100644 --- a/packages/relayer/eml_templates/acceptance_request.html +++ b/packages/relayer/eml_templates/acceptance_request.html @@ -79,7 +79,6 @@ margin: 0; padding: 0; font-size: 16px; - height: 100vh; font-family: 'Space Grotesk', sans-serif; " > @@ -150,9 +149,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -174,7 +171,7 @@ Powered by ZK Email

@@ -190,6 +187,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -145,9 +144,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -169,7 +166,7 @@ Powered by ZK Email

@@ -185,6 +182,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -144,9 +143,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -168,7 +165,7 @@ Powered by ZK Email

@@ -184,6 +181,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -149,9 +148,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -173,7 +170,7 @@ Powered by ZK Email

@@ -189,6 +186,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -146,9 +145,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -170,7 +167,7 @@ Powered by ZK Email

@@ -186,6 +183,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -144,9 +143,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -168,7 +165,7 @@ Powered by ZK Email

@@ -184,6 +181,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -149,9 +148,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -173,7 +170,7 @@ Powered by ZK Email

@@ -189,6 +186,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > @@ -145,9 +144,7 @@

- Cheers,
The Zk team
Aayush + Cheers,
The ZK Email Team

@@ -169,7 +166,7 @@ Powered by ZK Email

@@ -185,6 +182,7 @@ height: 24px; width: 24px; text-align: center; + line-height: 24px; display: block" > Date: Sat, 28 Sep 2024 22:51:22 +0530 Subject: [PATCH 40/53] feat: GPU prover (#66) * feat: use GPU for proving * chore: update Dockerfile * chore: cleanup * chore: update params.zip * chore: update circom_proofgen.sh * chore: update --- Relayer.Dockerfile | 2 +- libs/rapidsnark.Dockerfile | 22 ----------- packages/prover/Dockerfile | 61 +++++++++++++++++++----------- packages/prover/circom_proofgen.sh | 26 ++++--------- packages/prover/core.py | 28 +++++++++----- packages/prover/local_setup.sh | 7 +--- packages/prover/modal_server.py | 13 ++++--- 7 files changed, 74 insertions(+), 85 deletions(-) delete mode 100644 libs/rapidsnark.Dockerfile diff --git a/Relayer.Dockerfile b/Relayer.Dockerfile index cd99b0ff..1dafb15e 100644 --- a/Relayer.Dockerfile +++ b/Relayer.Dockerfile @@ -1,5 +1,5 @@ # Use the base image -FROM us-central1-docker.pkg.dev/zkairdrop/ether-email-auth/relayer-base:v1 +FROM bisht13/relayer-base # Copy the project files COPY packages/relayer /relayer/packages/relayer diff --git a/libs/rapidsnark.Dockerfile b/libs/rapidsnark.Dockerfile deleted file mode 100644 index b1c3f656..00000000 --- a/libs/rapidsnark.Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ - -FROM ubuntu:20.04 - -ARG DEBIAN_FRONTEND=noninteractive - -# Install Node.js, Yarn and required dependencies -RUN apt-get update \ - && apt-get install -y curl git gnupg build-essential cmake libgmp-dev libsodium-dev nasm \ - && curl --silent --location https://deb.nodesource.com/setup_12.x | bash - \ - && apt-get install -y nodejs - -RUN git clone https://github.com/iden3/rapidsnark.git /rapidsnark -WORKDIR /rapidsnark -RUN npm install -RUN git submodule init -RUN git submodule update -RUN npx task createFieldSources -RUN npx task buildPistache -RUN apt-get install -y -RUN npx task buildProver - -ENTRYPOINT ["/rapidsnark/build/prover"] diff --git a/packages/prover/Dockerfile b/packages/prover/Dockerfile index bec65c85..d7fe17bc 100644 --- a/packages/prover/Dockerfile +++ b/packages/prover/Dockerfile @@ -1,49 +1,66 @@ -FROM python:3.10 +FROM nvidia/cuda:12.4.0-devel-ubuntu22.04 RUN apt-get update && apt-get upgrade -y # Update the package list and install necessary dependencies RUN apt-get update && \ - apt install -y cmake build-essential pkg-config libssl-dev libgmp-dev libsodium-dev nasm git awscli gcc nodejs npm + DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends \ + cmake \ + build-essential \ + pkg-config \ + libssl-dev \ + libgmp-dev \ + libffi-dev \ + libsodium-dev \ + nasm \ + git \ + awscli \ + gcc \ + nodejs \ + npm \ + curl \ + m4 \ + python3 \ + python3-pip \ + python3-dev \ + wget \ + software-properties-common \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +# Set Python 3 as the default python version +RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1 \ + && update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 # Node install RUN npm install -g n -RUN n 18 +RUN n 22 RUN npm install -g yarn snarkjs -RUN git clone -b feat/body-parsing-circuit https://github.com/zkemail/ether-email-auth.git + +RUN git clone -b feat/gpu https://github.com/zkemail/ether-email-auth.git WORKDIR /ether-email-auth/packages/prover RUN pip install -r requirements.txt RUN cp ./circom_proofgen.sh /root WORKDIR /root RUN ls /root -# RUN mkdir params -# RUN cp /email-wallet/packages/prover/params/account_creation.wasm /root/params -# RUN cp /email-wallet/packages/prover/params/account_init.wasm /root/params -# RUN cp /email-wallet/packages/prover/params/account_transport.wasm /root/params -# RUN cp /email-wallet/packages/prover/params/claim.wasm /root/params -# RUN cp /email-wallet/packages/prover/params/email_sender.wasm /root/params RUN mkdir params WORKDIR /root/params -RUN gdown "https://drive.google.com/uc?id=1XDPFIL5YK8JzLGoTjmHLXO9zMDjSQcJH" +RUN gdown "https://drive.google.com/uc?id=1l3mNqFYv-YZc2efFlphFUkoaCnGCxFtE" RUN unzip params.zip RUN mv params/* /root/params WORKDIR /root RUN ls params -# RUN mv build params -# RUN curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-account-creation/contributions/emailwallet-account-creation_00019.zkey --output ./params/account_creation.zkey -# RUN curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-account-init/contributions/emailwallet-account-init_00007.zkey --output ./params/account_init.zkey -# RUN curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-account-transport/contributions/emailwallet-account-transport_00005.zkey --output ./params/account_transport.zkey -# RUN curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-claim/contributions/emailwallet-claim_00006.zkey --output ./params/claim.zkey -# RUN curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-email-sender/contributions/emailwallet-email-sender_00006.zkey --output ./params/email_sender.zkey RUN chmod +x circom_proofgen.sh RUN mkdir build -RUN git clone https://github.com/iden3/rapidsnark-old.git rapidsnark +RUN git clone https://github.com/Orbiter-Finance/rapidsnark.git rapidsnark WORKDIR /root/rapidsnark RUN yarn RUN git submodule init RUN git submodule update -RUN npx task createFieldSources -RUN npx task buildPistache -RUN npx task buildProver -RUN chmod +x build/prover +RUN ./build_gmp.sh host +RUN mkdir build_prover +WORKDIR /root/rapidsnark/build_prover +RUN cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package -DNVML_LIBRARY=/usr/local/cuda-12.4/targets/x86_64-linux/lib/stubs/libnvidia-ml.so +RUN make -j$(nproc) && make install +RUN chmod +x ../package/bin/prover_cuda WORKDIR /root \ No newline at end of file diff --git a/packages/prover/circom_proofgen.sh b/packages/prover/circom_proofgen.sh index 738f2e2c..18ac8162 100755 --- a/packages/prover/circom_proofgen.sh +++ b/packages/prover/circom_proofgen.sh @@ -21,21 +21,9 @@ public_path="${buildDir}/rapidsnark_public_${circuitName}_${nonce}.json" cd "${SCRIPT_DIR}" echo "entered zk email path: ${SCRIPT_DIR}" -echo "NODE_OPTIONS='--max-old-space-size=644000' snarkjs wc "${paramsDir}/${circuitName}.wasm" "${input_path}" "${witness_path}"" -NODE_OPTIONS='--max-old-space-size=644000' snarkjs wc "${paramsDir}/${circuitName}.wasm" "${input_path}" "${witness_path}" | tee /dev/stderr +${paramsDir}/${circuitName}_cpp/${circuitName} "${input_path}" "${witness_path}" | tee /dev/stderr status_jswitgen=$? -echo "✓ Finished witness generation with js! ${status_jswitgen}" - -# TODO: Get C-based witness gen to work -# echo "/${build_dir}/${CIRCUIT_NAME}_cpp/${CIRCUIT_NAME} ${input_wallet_path} ${witness_path}" -# "/${build_dir}/${CIRCUIT_NAME}_cpp/${CIRCUIT_NAME}" "${input_wallet_path}" "${witness_path}" -# status_c_wit=$? - -# echo "Finished C witness gen! Status: ${status_c_wit}" -# if [ $status_c_wit -ne 0 ]; then -# echo "C based witness gen failed with status (might be on machine specs diff than compilation): ${status_c_wit}" -# exit 1 -# fi +echo "✓ Finished witness generation with cpp! ${status_jswitgen}" if [ $isLocal = 1 ]; then # DEFAULT SNARKJS PROVER (SLOW) @@ -43,14 +31,14 @@ if [ $isLocal = 1 ]; then status_prover=$? echo "✓ Finished slow proofgen! Status: ${status_prover}" else - # RAPIDSNARK PROVER (10x FASTER) - echo "ldd ${SCRIPT_DIR}/rapidsnark/build/prover" - ldd "${SCRIPT_DIR}/rapidsnark/build/prover" + # RAPIDSNARK PROVER GPU + echo "ldd ${SCRIPT_DIR}/rapidsnark/package/bin/prover_cuda" + ldd "${SCRIPT_DIR}/rapidsnark/package/bin/prover_cuda" status_lld=$? echo "✓ lld prover dependencies present! ${status_lld}" - echo "${SCRIPT_DIR}/rapidsnark/build/prover ${paramsDir}/${circuitName}.zkey ${witness_path} ${proof_path} ${public_path}" - "${SCRIPT_DIR}/rapidsnark/build/prover" "${paramsDir}/${circuitName}.zkey" "${witness_path}" "${proof_path}" "${public_path}" | tee /dev/stderr + echo "${SCRIPT_DIR}/rapidsnark/package/bin/prover_cuda ${paramsDir}/${circuitName}.zkey ${witness_path} ${proof_path} ${public_path}" + "${SCRIPT_DIR}/rapidsnark/package/bin/prover_cuda" "${paramsDir}/${circuitName}.zkey" "${witness_path}" "${proof_path}" "${public_path}" | tee /dev/stderr status_prover=$? echo "✓ Finished rapid proofgen! Status: ${status_prover}" fi diff --git a/packages/prover/core.py b/packages/prover/core.py index 194fd9f0..eb4c1f74 100644 --- a/packages/prover/core.py +++ b/packages/prover/core.py @@ -3,7 +3,7 @@ import json import logging -logger = logging.getLogger(__name__) +# logger = logging.getLogger(__name__) def gen_email_auth_proof(nonce: str, is_local: bool, input: dict) -> dict: @@ -19,18 +19,28 @@ def gen_email_auth_proof(nonce: str, is_local: bool, input: dict) -> dict: def store_input(circuit_name: str, nonce: str, json_data: dict): + print("Storing input") cur_dir = get_cur_dir() + print(f"Current dir: {cur_dir}") build_dir = os.path.join(cur_dir, "build") # check if build_dir exists if not os.path.exists(build_dir): os.makedirs(build_dir) + print(f"Build dir: {build_dir}") json_file_path = os.path.join( build_dir, "input_" + circuit_name + "_" + nonce + ".json" ) - logger.info(f"Store user input to {json_file_path}") + print(f"Json file path: {json_file_path}") + print(f"Json data: {json_data}") + print(f"Json data type: {type(json_data)}") + # logger.info(f"Store user input to {json_file_path}") with open(json_file_path, "w") as json_file: json_file.write(json_data) + # Read the file back + with open(json_file_path, "r") as json_file: + print(json_file.read()) + print("Stored input") def load_proof(circuit_name: str, nonce: str) -> dict: @@ -39,7 +49,7 @@ def load_proof(circuit_name: str, nonce: str) -> dict: json_file_path = os.path.join( build_dir, "rapidsnark_proof_" + circuit_name + "_" + nonce + ".json" ) - logger.info(f"Loading proof from {json_file_path}") + # logger.info(f"Loading proof from {json_file_path}") with open(json_file_path, "r") as json_file: return json.loads(json_file.read()) @@ -50,7 +60,7 @@ def load_pub_signals(circuit_name: str, nonce: str) -> dict: json_file_path = os.path.join( build_dir, "rapidsnark_public_" + circuit_name + "_" + nonce + ".json" ) - logger.info(f"Loading public signals from {json_file_path}") + # logger.info(f"Loading public signals from {json_file_path}") with open(json_file_path, "r") as json_file: return json.loads(json_file.read()) @@ -59,9 +69,9 @@ def gen_proof(circuit_name: str, nonce: str, is_local: bool): is_local_int: int = 1 if is_local else 0 cur_dir = get_cur_dir() params_dir = os.path.join(cur_dir, "params") - logger.info(f"Params dir: {params_dir}") + # logger.info(f"Params dir: {params_dir}") build_dir = os.path.join(cur_dir, "build") - logger.info(f"Build dir: {build_dir}") + # logger.info(f"Build dir: {build_dir}") result = subprocess.run( [ os.path.join(cur_dir, "circom_proofgen.sh"), @@ -72,9 +82,9 @@ def gen_proof(circuit_name: str, nonce: str, is_local: bool): str(is_local_int), ] ) - logger.info(f"Proof generation result: {result.returncode}") - if result.stderr is not None: - logger.error(result.stderr) + # logger.info(f"Proof generation result: {result.returncode}") + # if result.stderr is not None: + # logger.error(result.stderr) print(result.stdout) print(result.stderr) diff --git a/packages/prover/local_setup.sh b/packages/prover/local_setup.sh index 77bd4eb6..026f0cfb 100755 --- a/packages/prover/local_setup.sh +++ b/packages/prover/local_setup.sh @@ -6,11 +6,6 @@ mkdir -p build npm install -g snarkjs@latest pip install -r requirements.txt mkdir build && cd build -gdown "https://drive.google.com/uc?id=1XDPFIL5YK8JzLGoTjmHLXO9zMDjSQcJH" +gdown "https://drive.google.com/uc?id=1l3mNqFYv-YZc2efFlphFUkoaCnGCxFtE" unzip params.zip -# curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-account-creation/contributions/emailwallet-account-creation_00019.zkey --output /root/params/account_creation.zkey -# curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-account-init/contributions/emailwallet-account-init_00007.zkey --output /root/params/account_init.zkey -# curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-account-transport/contributions/emailwallet-account-transport_00005.zkey --output /root/params/account_transport.zkey -# curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-claim/contributions/emailwallet-claim_00006.zkey --output /root/params/claim.zkey -# curl https://email-wallet-trusted-setup-ceremony-pse-p0tion-production.s3.eu-central-1.amazonaws.com/circuits/emailwallet-email-sender/contributions/emailwallet-email-sender_00006.zkey --output /root/params/email_sender.zkey chmod +x circom_proofgen.sh diff --git a/packages/prover/modal_server.py b/packages/prover/modal_server.py index e59c239f..567ae3b3 100644 --- a/packages/prover/modal_server.py +++ b/packages/prover/modal_server.py @@ -5,7 +5,7 @@ from google.cloud.logging_v2.handlers import setup_logging from google.oauth2 import service_account -app = modal.App("email-auth-prover-v1.3.0") +app = modal.App("email-auth-prover-v1.4.0") image = modal.Image.from_dockerfile("Dockerfile") @@ -15,7 +15,8 @@ mounts=[ modal.Mount.from_local_python_packages("core"), ], - cpu=14, + cpu=16, + gpu="any", secrets=[modal.Secret.from_name("gc-ether-email-auth-prover")], ) @modal.wsgi_app() @@ -45,17 +46,17 @@ def prove_email_auth(): print("prove_email_auth") req = request.get_json() input = req["input"] - logger = logging.getLogger(__name__) - logger.info(req) + # logger = logging.getLogger(__name__) + # logger.info(req) print(req) nonce = random.randint( 0, sys.maxsize, ) - logger.info(nonce) + # logger.info(nonce) print(nonce) proof = gen_email_auth_proof(str(nonce), False, input) - logger.info(proof) + # logger.info(proof) print(proof) return jsonify(proof) From d81c86e7bf3ff335cfd414e584093bcf36351421 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 29 Sep 2024 17:16:19 -0700 Subject: [PATCH 41/53] fix: regex json path --- packages/relayer/.env.example | 4 +--- packages/relayer/README.md | 1 - packages/relayer/src/config.rs | 4 ++-- packages/relayer/src/core.rs | 13 +++++++++---- packages/relayer/src/lib.rs | 4 ++-- packages/relayer/src/modules/dkim.rs | 17 +++++++++++++---- packages/relayer/src/strings.rs | 4 +--- 7 files changed, 28 insertions(+), 19 deletions(-) diff --git a/packages/relayer/.env.example b/packages/relayer/.env.example index 34721015..5a0c88a9 100644 --- a/packages/relayer/.env.example +++ b/packages/relayer/.env.example @@ -11,10 +11,8 @@ PROVER_ADDRESS="https://zkemail--email-auth-prover-v1-3-0-flask-app.modal.run" DATABASE_URL= "postgres://test@localhost/emailauth_test" RELAYER_EMAIL_ADDR= WEB_SERVER_ADDRESS="127.0.0.1:4500" -CIRCUITS_DIR_PATH= #Path to email-wallet/packages/circuits EMAIL_TEMPLATES_PATH= #Path to email templates, e.g. ./packages/relayer/eml_templates/ -SELECTOR_DEF_PATH="./src/regex_json/selector_def.json" -REQUEST_DEF_PATH="./src/regex_json/request_def.json" +REGEX_JSON_DIR_PATH= CANISTER_ID="q7eci-dyaaa-aaaak-qdbia-cai" PEM_PATH="./.ic.pem" diff --git a/packages/relayer/README.md b/packages/relayer/README.md index d4f8a333..4689b36b 100644 --- a/packages/relayer/README.md +++ b/packages/relayer/README.md @@ -51,7 +51,6 @@ You can run the relayer either on your local environments or cloud instances (we DATABASE_URL= "postgres://new_user:my_secure_password@localhost/my_new_database" WEB_SERVER_ADDRESS="127.0.0.1:4500" - CIRCUITS_DIR_PATH= # Absolute path to packages/circuits EMAIL_TEMPLATES_PATH= # Absolute path to packages/relayer/eml_templates CANISTER_ID="q7eci-dyaaa-aaaak-qdbia-cai" diff --git a/packages/relayer/src/config.rs b/packages/relayer/src/config.rs index 2e5a9095..6615cca5 100644 --- a/packages/relayer/src/config.rs +++ b/packages/relayer/src/config.rs @@ -14,7 +14,7 @@ pub struct RelayerConfig { pub relayer_email_addr: String, pub db_path: String, pub web_server_address: String, - pub circuits_dir_path: PathBuf, + pub regex_json_dir_path: PathBuf, pub prover_address: String, pub chain_rpc_provider: String, pub chain_rpc_explorer: String, @@ -43,7 +43,7 @@ impl RelayerConfig { relayer_email_addr: env::var(RELAYER_EMAIL_ADDR_KEY).unwrap(), db_path: env::var(DATABASE_PATH_KEY).unwrap(), web_server_address: env::var(WEB_SERVER_ADDRESS_KEY).unwrap(), - circuits_dir_path: env::var(CIRCUITS_DIR_PATH_KEY).unwrap().into(), + regex_json_dir_path: env::var(REGEX_JSON_DIR_PATH_KEY).unwrap().into(), prover_address: env::var(PROVER_ADDRESS_KEY).unwrap(), chain_rpc_provider: env::var(CHAIN_RPC_PROVIDER_KEY).unwrap(), chain_rpc_explorer: env::var(CHAIN_RPC_EXPLORER_KEY).unwrap(), diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index f9c10165..a06a6324 100644 --- a/packages/relayer/src/core.rs +++ b/packages/relayer/src/core.rs @@ -36,10 +36,15 @@ pub async fn handle_email(email: String) -> Result { trace!(LOG, "From address: {}", guardian_email_addr); let email_body = parsed_email.get_cleaned_body()?; - let request_def_path = env::var(REQUEST_DEF_PATH_KEY) - .map_err(|_| anyhow!("ENV var {} not set", REQUEST_DEF_PATH_KEY))?; - let request_def_contents = fs::read_to_string(&request_def_path) - .map_err(|e| anyhow!("Failed to read file {}: {}", request_def_path, e))?; + let request_def_path = + PathBuf::from(REGEX_JSON_DIR_PATH.get().unwrap()).join("request_def.json"); + let request_def_contents = fs::read_to_string(&request_def_path).map_err(|e| { + anyhow!( + "Failed to read file {:?}: {}", + request_def_path.display(), + e + ) + })?; let request_decomposed_def = serde_json::from_str(&request_def_contents) .map_err(|e| EmailError::Parse(format!("Failed to parse request_def.json: {}", e)))?; let request_idxes = extract_substr_idxes(&email, &request_decomposed_def)?; diff --git a/packages/relayer/src/lib.rs b/packages/relayer/src/lib.rs index c4d1adb6..d0b83379 100644 --- a/packages/relayer/src/lib.rs +++ b/packages/relayer/src/lib.rs @@ -32,7 +32,7 @@ use std::path::PathBuf; use std::sync::{Arc, OnceLock}; use tokio::time::Duration; -pub static CIRCUITS_DIR_PATH: OnceLock = OnceLock::new(); +pub static REGEX_JSON_DIR_PATH: OnceLock = OnceLock::new(); pub static WEB_SERVER_ADDRESS: OnceLock = OnceLock::new(); pub static PROVER_ADDRESS: OnceLock = OnceLock::new(); pub static PRIVATE_KEY: OnceLock = OnceLock::new(); @@ -103,7 +103,7 @@ pub async fn run(config: RelayerConfig) -> Result<()> { info!(LOG, "Starting relayer"); // Initialize global configuration - CIRCUITS_DIR_PATH.set(config.circuits_dir_path).unwrap(); + REGEX_JSON_DIR_PATH.set(config.regex_json_dir_path).unwrap(); WEB_SERVER_ADDRESS.set(config.web_server_address).unwrap(); PROVER_ADDRESS.set(config.prover_address).unwrap(); PRIVATE_KEY.set(config.private_key).unwrap(); diff --git a/packages/relayer/src/modules/dkim.rs b/packages/relayer/src/modules/dkim.rs index fe91ee7c..369f063b 100644 --- a/packages/relayer/src/modules/dkim.rs +++ b/packages/relayer/src/modules/dkim.rs @@ -2,6 +2,7 @@ use std::fs; use anyhow::anyhow; use relayer_utils::extract_substr_idxes; +use relayer_utils::DecomposedRegexConfig; use relayer_utils::LOG; use crate::*; @@ -177,16 +178,24 @@ pub async fn check_and_update_dkim( } // Get selector - let selector_def_path = env::var(SELECTOR_DEF_PATH_KEY) - .map_err(|_| anyhow!("ENV var {} not set", SELECTOR_DEF_PATH_KEY))?; + let selector_def_path = + PathBuf::from(env::var(REGEX_JSON_DIR_PATH_KEY).unwrap()).join("selector_def.json"); let selector_def_contents = fs::read_to_string(&selector_def_path) - .map_err(|e| anyhow!("Failed to read file {}: {}", selector_def_path, e))?; - let selector_decomposed_def = serde_json::from_str(&selector_def_path).unwrap(); + .map_err(|e| anyhow!("Failed to read file {}: {}", selector_def_path.display(), e))?; + let selector_decomposed_def: DecomposedRegexConfig = + serde_json::from_str(&selector_def_contents).map_err(|e| { + anyhow!( + "Failed to parse JSON from file {}: {}", + selector_def_path.display(), + e + ) + })?; let selector = { let idxes = extract_substr_idxes(&parsed_email.canonicalized_header, &selector_decomposed_def)?[0]; parsed_email.canonicalized_header[idxes.0..idxes.1].to_string() }; + info!(LOG, "selector {}", selector); // Generate IC agent and create oracle client diff --git a/packages/relayer/src/strings.rs b/packages/relayer/src/strings.rs index 51b610ac..b9db6720 100644 --- a/packages/relayer/src/strings.rs +++ b/packages/relayer/src/strings.rs @@ -3,7 +3,6 @@ pub const SMTP_SERVER_KEY: &str = "SMTP_SERVER"; pub const RELAYER_EMAIL_ADDR_KEY: &str = "RELAYER_EMAIL_ADDR"; pub const DATABASE_PATH_KEY: &str = "DATABASE_URL"; pub const WEB_SERVER_ADDRESS_KEY: &str = "WEB_SERVER_ADDRESS"; -pub const CIRCUITS_DIR_PATH_KEY: &str = "CIRCUITS_DIR_PATH"; pub const PROVER_ADDRESS_KEY: &str = "PROVER_ADDRESS"; pub const CHAIN_RPC_PROVIDER_KEY: &str = "CHAIN_RPC_PROVIDER"; pub const CHAIN_RPC_EXPLORER_KEY: &str = "CHAIN_RPC_EXPLORER"; @@ -11,8 +10,7 @@ pub const PRIVATE_KEY_KEY: &str = "PRIVATE_KEY"; pub const CHAIN_ID_KEY: &str = "CHAIN_ID"; pub const EMAIL_ACCOUNT_RECOVERY_VERSION_ID_KEY: &str = "EMAIL_ACCOUNT_RECOVERY_VERSION_ID"; pub const EMAIL_TEMPLATES_PATH_KEY: &str = "EMAIL_TEMPLATES_PATH"; -pub const SELECTOR_DEF_PATH_KEY: &str = "SELECTOR_DEF_PATH"; -pub const REQUEST_DEF_PATH_KEY: &str = "REQUEST_DEF_PATH"; +pub const REGEX_JSON_DIR_PATH_KEY: &str = "REGEX_JSON_DIR_PATH"; // Log strings pub const JSON_LOGGER_KEY: &str = "JSON_LOGGER"; From 6b8bf54e8582526a25f9ec6007ffb9e583734414 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 29 Sep 2024 17:17:30 -0700 Subject: [PATCH 42/53] chore: update k8s manifest --- kubernetes/relayer.staging.yml | 30 +++++++++++++++--------------- kubernetes/relayer.yml | 30 +++++++++++++++--------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/kubernetes/relayer.staging.yml b/kubernetes/relayer.staging.yml index 2c9855bd..cf985be4 100644 --- a/kubernetes/relayer.staging.yml +++ b/kubernetes/relayer.staging.yml @@ -6,18 +6,18 @@ metadata: labels: app: relayer data: - EMAIL_ACCOUNT_RECOVERY_VERSION_ID: '' - CHAIN_RPC_PROVIDER: '' - CHAIN_RPC_EXPLORER: '' - CHAIN_ID: '' - WEB_SERVER_ADDRESS: '' - CIRCUITS_DIR_PATH: '' - EMAIL_TEMPLATES_PATH: '' - CANISTER_ID: '' - IC_REPLICA_URL: '' - JSON_LOGGER: '' - PEM_PATH: '' - SMTP_SERVER: '' + EMAIL_ACCOUNT_RECOVERY_VERSION_ID: "" + CHAIN_RPC_PROVIDER: "" + CHAIN_RPC_EXPLORER: "" + CHAIN_ID: "" + WEB_SERVER_ADDRESS: "" + REGEX_JSON_DIR_PATH: "" + EMAIL_TEMPLATES_PATH: "" + CANISTER_ID: "" + IC_REPLICA_URL: "" + JSON_LOGGER: "" + PEM_PATH: "" + SMTP_SERVER: "" --- apiVersion: v1 @@ -111,8 +111,8 @@ spec: periodSeconds: 30 volumeMounts: - name: pem-volume - mountPath: '/relayer/packages/relayer/.ic.pem' - subPath: '.ic.pem' + mountPath: "/relayer/packages/relayer/.ic.pem" + subPath: ".ic.pem" - name: smtp-container image: bisht13/relayer-smtp-new:latest ports: @@ -131,7 +131,7 @@ spec: secretName: relayer-secret-email-auth items: - key: ICPEM - path: '.ic.pem' + path: ".ic.pem" --- apiVersion: v1 kind: Service diff --git a/kubernetes/relayer.yml b/kubernetes/relayer.yml index 83c3da5f..08854dca 100644 --- a/kubernetes/relayer.yml +++ b/kubernetes/relayer.yml @@ -6,18 +6,18 @@ metadata: labels: app: relayer data: - EMAIL_ACCOUNT_RECOVERY_VERSION_ID: '' - CHAIN_RPC_PROVIDER: '' - CHAIN_RPC_EXPLORER: '' - CHAIN_ID: '' - WEB_SERVER_ADDRESS: '' - CIRCUITS_DIR_PATH: '' - EMAIL_TEMPLATES_PATH: '' - CANISTER_ID: '' - IC_REPLICA_URL: '' - JSON_LOGGER: '' - PEM_PATH: '' - SMTP_SERVER: '' + EMAIL_ACCOUNT_RECOVERY_VERSION_ID: "" + CHAIN_RPC_PROVIDER: "" + CHAIN_RPC_EXPLORER: "" + CHAIN_ID: "" + WEB_SERVER_ADDRESS: "" + REGEX_JSON_DIR_PATH: "" + EMAIL_TEMPLATES_PATH: "" + CANISTER_ID: "" + IC_REPLICA_URL: "" + JSON_LOGGER: "" + PEM_PATH: "" + SMTP_SERVER: "" --- apiVersion: v1 @@ -111,8 +111,8 @@ spec: periodSeconds: 30 volumeMounts: - name: pem-volume - mountPath: '/relayer/packages/relayer/.ic.pem' - subPath: '.ic.pem' + mountPath: "/relayer/packages/relayer/.ic.pem" + subPath: ".ic.pem" - name: smtp-container image: bisht13/relayer-smtp-new:latest ports: @@ -131,7 +131,7 @@ spec: secretName: relayer-secret-email-auth items: - key: ICPEM - path: '.ic.pem' + path: ".ic.pem" --- apiVersion: v1 From 14659787868927db1087ce500fa77f41290d6d99 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Tue, 24 Sep 2024 22:13:15 +0000 Subject: [PATCH 43/53] feat: use GPU for proving --- libs/rapidsnark.Dockerfile | 20 ++++++++++++++++++++ packages/prover/Dockerfile | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 libs/rapidsnark.Dockerfile diff --git a/libs/rapidsnark.Dockerfile b/libs/rapidsnark.Dockerfile new file mode 100644 index 00000000..1a8cf1f7 --- /dev/null +++ b/libs/rapidsnark.Dockerfile @@ -0,0 +1,20 @@ +FROM ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive + +# Install Node.js, Yarn and required dependencies +RUN apt-get update \ + && apt-get install -y curl git gnupg build-essential cmake libgmp-dev libsodium-dev nasm curl m4 \ + && curl --silent --location https://deb.nodesource.com/setup_12.x | bash - \ + && apt-get install -y nodejs + +RUN git clone https://github.com/Orbiter-Finance/rapidsnark.git /rapidsnark +WORKDIR /rapidsnark +RUN git submodule init +RUN git submodule update +./build_gmp.sh host +mkdir build_prover && cd build_prover +cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package +make -j$(nproc) && make install + +ENTRYPOINT ["/rapidsnark/package/build/prover_cuda"] diff --git a/packages/prover/Dockerfile b/packages/prover/Dockerfile index d7fe17bc..2007b8b8 100644 --- a/packages/prover/Dockerfile +++ b/packages/prover/Dockerfile @@ -36,10 +36,11 @@ RUN npm install -g n RUN n 22 RUN npm install -g yarn snarkjs -RUN git clone -b feat/gpu https://github.com/zkemail/ether-email-auth.git +RUN git clone -b refactor https://github.com/zkemail/ether-email-auth.git WORKDIR /ether-email-auth/packages/prover RUN pip install -r requirements.txt RUN cp ./circom_proofgen.sh /root +RUN cp ./email_auth_with_body_parsing_with_qp_encoding /root WORKDIR /root RUN ls /root RUN mkdir params From e1080aaf7eb2845976879d6b993434399d4e1f60 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Sun, 29 Sep 2024 19:36:32 -0700 Subject: [PATCH 44/53] chore: add comment in example env --- packages/contracts/{.env.sample => .env.example} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename packages/contracts/{.env.sample => .env.example} (90%) diff --git a/packages/contracts/.env.sample b/packages/contracts/.env.example similarity index 90% rename from packages/contracts/.env.sample rename to packages/contracts/.env.example index 132381ec..8e28ffb5 100644 --- a/packages/contracts/.env.sample +++ b/packages/contracts/.env.example @@ -10,6 +10,6 @@ PRIVATE_KEY= CHAIN_ID=84532 RPC_URL="https://sepolia.base.org" -SIGNER=0x69bec2dd161d6bbcc91ec32aa44d9333ebc864c0 # Signer for the dkim oracle on IC +SIGNER=0x69bec2dd161d6bbcc91ec32aa44d9333ebc864c0 # Signer for the dkim oracle on IC (Don't change this) ETHERSCAN_API_KEY= # CHAIN_NAME="base_sepolia" From 987575fd9a6407292a22c4940c60f87b38174ed5 Mon Sep 17 00:00:00 2001 From: Aditya Bisht Date: Mon, 30 Sep 2024 02:42:26 -0700 Subject: [PATCH 45/53] feat: keep modal warm --- packages/prover/modal_server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/prover/modal_server.py b/packages/prover/modal_server.py index 567ae3b3..44d95f58 100644 --- a/packages/prover/modal_server.py +++ b/packages/prover/modal_server.py @@ -18,6 +18,7 @@ cpu=16, gpu="any", secrets=[modal.Secret.from_name("gc-ether-email-auth-prover")], + keep_warm=True ) @modal.wsgi_app() def flask_app(): From 7bd653409620ad6cd2acd3afe6036afa4439775d Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 30 Sep 2024 18:16:27 +0530 Subject: [PATCH 46/53] ui: update email template design --- .../eml_templates/acceptance_request.html | 85 +++--- .../eml_templates/acceptance_success.html | 85 +++--- .../eml_templates/acknowledgement.html | 85 +++--- .../eml_templates/credential_not_present.html | 85 +++--- packages/relayer/eml_templates/error.html | 252 +++++++++++++++++- .../guardian_already_exists.html | 85 +++--- .../eml_templates/guardian_not_set.html | 73 +++-- .../eml_templates/recovery_request.html | 85 +++--- .../eml_templates/recovery_success.html | 85 +++--- 9 files changed, 573 insertions(+), 347 deletions(-) diff --git a/packages/relayer/eml_templates/acceptance_request.html b/packages/relayer/eml_templates/acceptance_request.html index 5b536f0d..853efc6f 100644 --- a/packages/relayer/eml_templates/acceptance_request.html +++ b/packages/relayer/eml_templates/acceptance_request.html @@ -2,23 +2,23 @@ + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + +
+ Hi, {{userEmailAddr}}! +
+ An error occurred while processing your request.
+ Error: {{error}} +
+

+ Cheers,
The ZK Email Team +

+
+ + + + + + +
+

+ Powered by + ZK Email +

+ + + + + + + +
+ + + + + + + +
+
+
+ + diff --git a/packages/relayer/eml_templates/guardian_already_exists.html b/packages/relayer/eml_templates/guardian_already_exists.html index 469c5d01..00a0192b 100644 --- a/packages/relayer/eml_templates/guardian_already_exists.html +++ b/packages/relayer/eml_templates/guardian_already_exists.html @@ -2,23 +2,23 @@