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