diff --git a/packages/relayer/src/core.rs b/packages/relayer/src/core.rs index fc49ae57..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,328 +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(), - }; - - 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, @@ -662,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))