Skip to content

Commit

Permalink
feat: fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Bisht13 committed Apr 1, 2024
1 parent 87c5467 commit d97eb3f
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 113 deletions.
2 changes: 1 addition & 1 deletion packages/relayer/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
EMAIL_AUTH_ADDRESS= # Address of the deployed wallet contract.
EMAIL_ACCOUNT_RECOVERY_VERSION_ID= # Address of the deployed wallet contract.
PRIVATE_KEY= # Private key for Relayer's account.
CHAIN_RPC_PROVIDER=http://127.0.0.1:8545
CHAIN_RPC_EXPLORER=
Expand Down
51 changes: 28 additions & 23 deletions packages/relayer/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ type SignerM = SignerMiddleware<Provider<Http>, LocalWallet>;
#[derive(Debug, Clone)]
pub struct ChainClient {
pub client: Arc<SignerM>,
pub email_auth: EmailAuth<SignerM>,
pub ecdsa_owned_dkim_registry: ECDSAOwnedDKIMRegistry<SignerM>,
}

impl ChainClient {
Expand All @@ -23,39 +21,43 @@ impl ChainClient {
provider,
wallet.with_chain_id(*CHAIN_ID.get().unwrap()),
));
let email_auth = EmailAuth::new(
EMAIL_AUTH_ADDRESS.get().unwrap().parse::<Address>()?,
client.clone(),
);
let ecdsa_owned_dkim_registry =
ECDSAOwnedDKIMRegistry::new(email_auth.dkim_registry_addr().await?, client.clone());

Ok(Self {
client,
email_auth,
ecdsa_owned_dkim_registry,
})

Ok(Self { client })
}

pub fn self_eth_addr(&self) -> Address {
self.client.address()
}

pub async fn get_email_auth(
&self,
wallet_addr: &String,
account_key: &String,
) -> Result<EmailAuth<SignerM>, anyhow::Error> {
let wallet_address: H160 = wallet_addr.parse()?;
let account_salt: H256 = account_key.parse()?;
let contract = EmailAccountRecovery::new(wallet_address, self.client.clone());
let email_auth = contract
.compute_email_auth_address(account_salt.into())
.call()
.await?;

Ok(EmailAuth::new(email_auth, self.client.clone()))
}

pub async fn set_dkim_public_key_hash(
&self,
selector: String,
domain_name: String,
public_key_hash: [u8; 32],
signature: Bytes,
dkim: H160,
dkim: ECDSAOwnedDKIMRegistry<SignerM>,
) -> Result<String> {
// Mutex is used to prevent nonce conflicts.
let mut mutex = SHARED_MUTEX.lock().await;
*mutex += 1;

let contract = ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone());
let call =
contract.set_dkim_public_key_hash(selector, domain_name, public_key_hash, signature);
let call = dkim.set_dkim_public_key_hash(selector, domain_name, public_key_hash, signature);
let tx = call.send().await?;
let receipt = tx
.log()
Expand All @@ -71,21 +73,24 @@ impl ChainClient {
&self,
domain_name: ::std::string::String,
public_key_hash: [u8; 32],
dkim: H160,
dkim: ECDSAOwnedDKIMRegistry<SignerM>,
) -> Result<bool> {
let contract = ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone());
let is_valid = contract
let is_valid = dkim
.is_dkim_public_key_hash_valid(domain_name, public_key_hash)
.call()
.await?;
Ok(is_valid)
}

pub async fn get_dkim_from_wallet(&self, wallet_addr: &String) -> Result<H160> {
pub async fn get_dkim_from_wallet(
&self,
wallet_addr: &String,
) -> Result<ECDSAOwnedDKIMRegistry<SignerM>, anyhow::Error> {
let wallet_address: H160 = wallet_addr.parse()?;
let contract = EmailAccountRecovery::new(wallet_address, self.client.clone());
let dkim = contract.dkim().call().await?;
Ok(dkim)

Ok(ECDSAOwnedDKIMRegistry::new(dkim, self.client.clone()))
}

pub async fn get_latest_block_number(&self) -> U64 {
Expand Down
7 changes: 5 additions & 2 deletions packages/relayer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct RelayerConfig {
pub chain_rpc_explorer: String,
pub chain_id: u32,
pub private_key: String,
pub email_auth_address: String,
pub email_account_recovery_version_id: u8,
pub input_files_dir: String,
pub email_templates: String,
}
Expand Down Expand Up @@ -68,7 +68,10 @@ impl RelayerConfig {
chain_rpc_explorer: env::var(CHAIN_RPC_EXPLORER_KEY).unwrap(),
chain_id: env::var(CHAIN_ID_KEY).unwrap().parse().unwrap(),
private_key: env::var(PRIVATE_KEY_KEY).unwrap(),
email_auth_address: env::var(EMAIL_AUTH_ADDRESS_KEY).unwrap(),
email_account_recovery_version_id: env::var(EMAIL_ACCOUNT_RECOVERY_VERSION_ID_KEY)
.unwrap()
.parse()
.unwrap(),
input_files_dir,
email_templates: env::var(EMAIL_TEMPLATES_PATH_KEY).unwrap(),
}
Expand Down
96 changes: 51 additions & 45 deletions packages/relayer/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

use crate::*;

use ethers::utils::keccak256;
use ethers::{
abi::{encode, Token},
utils::keccak256,
};
use num_traits::ToBytes;
use relayer_utils::*;

const DOMAIN_FIELDS: usize = 9;
Expand All @@ -23,7 +27,7 @@ pub async fn handle_email<P: EmailsPool>(
let padded_from_addr = PaddedEmailAddr::from_email_addr(&guardian_email_addr);
trace!(LOG, "From address: {}", guardian_email_addr; "func" => function_name!());
let subject = parsed_email.get_subject_all()?;

let account_key_str = db
.get_invitation_code_from_email_addr(&guardian_email_addr)
.await?
Expand Down Expand Up @@ -53,7 +57,13 @@ pub async fn handle_email<P: EmailsPool>(
});
}
let request = request_record.unwrap();
check_and_update_dkim(&email, &parsed_email, &chain_client, &request.wallet_eth_addr).await?;
check_and_update_dkim(
&email,
&parsed_email,
&chain_client,
&request.wallet_eth_addr,
)
.await?;
let subject_template = chain_client
.get_acceptance_subject_templates(&request.wallet_eth_addr, request.template_idx)
.await?;
Expand All @@ -68,19 +78,22 @@ pub async fn handle_email<P: EmailsPool>(
});
}
};

println!("subject_params: {:?}", subject_params);
println!("skipped_subject_prefix: {:?}", skipped_subject_prefix);

let subject_params_encoded: Vec<Bytes> = subject_params
.iter()
.map(|param| param.abi_encode(None).unwrap())
.collect();

if let Ok(invitation_code) = parsed_email.get_invitation_code() {
trace!(LOG, "Email with account code"; "func" => function_name!());
let account_key = AccountKey::from(hex2field(&format!("0x{}", invitation_code))?);
let stored_account_key = db
.get_invitation_code_from_email_addr(&guardian_email_addr)
.await?;
if let Some(stored_account_key) = stored_account_key.as_ref() {
if stored_account_key != &field2hex(&account_key.0) {
if stored_account_key != &invitation_code {
return Err(anyhow!(
"Stored account key is not equal to one in the email: {} != {}",
stored_account_key,
Expand All @@ -89,22 +102,23 @@ pub async fn handle_email<P: EmailsPool>(
}
}
if !request.is_for_recovery {
let template_id = keccak256(
&[
EMAIL_ACCOUNT_RECOVERY_VERSION_ID.as_bytes(),
b"ACCEPTANCE",
request.template_idx.to_string().as_bytes(),
]
.concat(),
);
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_auth_input(&email, &invitation_code).await?;

let (proof, public_signals) =
generate_proof(&circuit_input, "email_auth", PROVER_ADDRESS.get().unwrap()).await?;

let is_code_exist = public_signals[SUBJECT_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into();
let (masked_subject, num_recipient_email_addr_bytes) = get_masked_subject(&subject)?;
let masked_subject = get_masked_subject(public_signals.clone(), DOMAIN_FIELDS + 3)?;

println!("masked_subject: {:?}", masked_subject);

let email_proof = EmailProof {
proof: proof,
Expand Down Expand Up @@ -196,22 +210,21 @@ pub async fn handle_email<P: EmailsPool>(
}
} else {
if request.is_for_recovery {
let template_id = keccak256(
&[
EMAIL_ACCOUNT_RECOVERY_VERSION_ID.as_bytes(),
b"RECOVERY",
request.template_idx.to_string().as_bytes(),
]
.concat(),
);
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_auth_input(&email, &account_key_str).await?;

let (proof, public_signals) =
generate_proof(&circuit_input, "email_auth", PROVER_ADDRESS.get().unwrap()).await?;

let is_code_exist = public_signals[SUBJECT_FIELDS + DOMAIN_FIELDS + 4] == 1u8.into();
let (masked_subject, num_recipient_email_addr_bytes) = get_masked_subject(&subject)?;
let masked_subject = get_masked_subject(public_signals.clone(), DOMAIN_FIELDS + 3)?;

let email_proof = EmailProof {
proof: proof,
Expand Down Expand Up @@ -295,28 +308,21 @@ pub async fn handle_email<P: EmailsPool>(
}
}

#[named]
pub fn get_masked_subject(subject: &str) -> Result<(String, usize)> {
match extract_email_addr_idxes(subject) {
Ok(extracts) => {
if extracts.len() != 1 {
return Err(anyhow!(
"Recipient address in the subject must appear only once."
));
}
let (start, end) = extracts[0];
info!(LOG, "start: {}, end: {}", start, end; "func" => function_name!());
if end == subject.len() {
Ok((subject[0..start].to_string(), 0))
} else {
let mut masked_subject_bytes = subject.as_bytes().to_vec();
masked_subject_bytes[start..end].copy_from_slice(vec![0u8; end - start].as_ref());
Ok((String::from_utf8(masked_subject_bytes)?, end - start))
}
}
Err(err) => {
info!(LOG, "Recipient address not found in the subject: {}", err; "func" => function_name!());
Ok((subject.to_string(), 0))
pub fn get_masked_subject(public_signals: Vec<U256>, start_idx: usize) -> Result<String> {
// 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);
subject_bytes.extend_from_slice(&bytes);
}

// Bytes to string, removing null bytes
let subject = String::from_utf8(subject_bytes.into_iter().filter(|&b| b != 0u8).collect())
.map_err(|e| anyhow!("Failed to convert bytes to string: {}", e))?;

Ok(subject)
}
1 change: 0 additions & 1 deletion packages/relayer/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ impl Database {
&self,
email_addr: &str,
) -> Result<Option<String>> {
println!("email_addr: {}", email_addr);
let row = sqlx::query("SELECT * FROM codes WHERE guardian_email_addr = $1")
.bind(email_addr)
.fetch_optional(&self.db)
Expand Down
6 changes: 4 additions & 2 deletions packages/relayer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub static WEB_SERVER_ADDRESS: OnceLock<String> = OnceLock::new();
pub static PROVER_ADDRESS: OnceLock<String> = OnceLock::new();
pub static PRIVATE_KEY: OnceLock<String> = OnceLock::new();
pub static CHAIN_ID: OnceLock<u32> = OnceLock::new();
pub static EMAIL_AUTH_ADDRESS: OnceLock<String> = OnceLock::new();
pub static EMAIL_ACCOUNT_RECOVERY_VERSION_ID: OnceLock<u8> = OnceLock::new();
pub static CHAIN_RPC_PROVIDER: OnceLock<String> = OnceLock::new();
pub static CHAIN_RPC_EXPLORER: OnceLock<String> = OnceLock::new();
pub static INPUT_FILES_DIR: OnceLock<String> = OnceLock::new();
Expand Down Expand Up @@ -91,7 +91,9 @@ pub async fn run(
CHAIN_ID.set(config.chain_id).unwrap();
CHAIN_RPC_PROVIDER.set(config.chain_rpc_provider).unwrap();
CHAIN_RPC_EXPLORER.set(config.chain_rpc_explorer).unwrap();
EMAIL_AUTH_ADDRESS.set(config.email_auth_address).unwrap();
EMAIL_ACCOUNT_RECOVERY_VERSION_ID
.set(config.email_account_recovery_version_id)
.unwrap();
INPUT_FILES_DIR.set(config.input_files_dir).unwrap();
EMAIL_TEMPLATES.set(config.email_templates).unwrap();
RELAYER_EMAIL_ADDRESS
Expand Down
Loading

0 comments on commit d97eb3f

Please sign in to comment.