From b41bb427db833b1601c7906942fb187898bbff45 Mon Sep 17 00:00:00 2001 From: Dev43 Date: Sun, 18 Sep 2022 04:08:56 +0200 Subject: [PATCH] add eth addresses --- fhe_contract/Cargo.toml | 4 ++ fhe_contract/src/arweave.rs | 85 ++++++++++++++++++++++++++++-------- fhe_contract/src/cli.rs | 28 +++++++----- fhe_contract/src/ethereum.rs | 66 ++++++++++++++++++++++++++++ fhe_contract/src/lib.rs | 2 + 5 files changed, 156 insertions(+), 29 deletions(-) create mode 100644 fhe_contract/src/ethereum.rs diff --git a/fhe_contract/Cargo.toml b/fhe_contract/Cargo.toml index a6c1b0c..6274824 100644 --- a/fhe_contract/Cargo.toml +++ b/fhe_contract/Cargo.toml @@ -21,6 +21,10 @@ tokio = { version = "1", features = ["full"] } url = "2.2.2" ring = "0.16.20" futures = "0.3" +walletconnect = { git = "https://github.com/Dev43/walletconnect-rs", branch = "feat/ethberlin", features = [ + "web3", + "qr", +] } [dev-dependencies] tokio-test = "*" diff --git a/fhe_contract/src/arweave.rs b/fhe_contract/src/arweave.rs index 5af2208..80db5a1 100644 --- a/fhe_contract/src/arweave.rs +++ b/fhe_contract/src/arweave.rs @@ -5,9 +5,11 @@ use arloader::{ Arweave, }; // use futures::{stream, StreamExt}; +use crate::ethereum::EthClient; use reqwest; use ring::digest::{Context, SHA256}; use serde_json::{json, Value}; +use std::fmt::Write; use std::str::FromStr; use std::time::Duration; use std::time::SystemTime; @@ -60,9 +62,18 @@ impl Ar { let contract_id = Base64(sha_256(id_data.as_bytes()).to_vec()).to_string(); - let action = r#"{"action":"deploy", arguments: [], validity_proof:"ID_OF_VALIDITY_PROOF"}"#; + let action = r#"{"action":"deploy", arguments: []}"#; - let tags = self.create_tags(&contract_id, &unix_timestamp, action, ContractType::Source); + let (account, sig) = get_eth_metadata(&contract_data.as_bytes().to_vec()).await?; + + let tags = self.create_tags( + &contract_id, + &unix_timestamp, + action, + ContractType::Source, + &account, + &sig, + ); let mut tx = self .client @@ -92,10 +103,18 @@ impl Ar { let unix_timestamp = get_unix_timestamp(); // contract id is only the hash of the data and a unix timestamp -- this is only a POC - not secure as someone can change the unix timestamp - let action = - r#"{"action":"zk_snark", arguments: [], validity_proof:"ID_OF_VALIDITY_PROOF"}"#; + let action = r#"{"action":"zk_snark", arguments: []}"#; + + let (account, sig) = get_eth_metadata(&contract_data).await?; - let tags = self.create_tags(&contract_id, &unix_timestamp, action, ContractType::ZkSnark); + let tags = self.create_tags( + &contract_id, + &unix_timestamp, + action, + ContractType::ZkSnark, + &account, + &sig, + ); let mut tx = self .client @@ -123,6 +142,8 @@ impl Ar { unix_timestamp: &str, action: &str, contract_type: ContractType, + eth_address: &str, + eth_sig: &str, ) -> Vec> { let app = get_app_name(contract_type); vec![ @@ -135,15 +156,8 @@ impl Ar { .unwrap(), Tag::::from_utf8_strs("Unix-Time", &unix_timestamp).unwrap(), Tag::::from_utf8_strs("Input", &action).unwrap(), - // Tag::::from_utf8_strs( - // "Eth-Address", - // "0x...", - // ).unwrap(), - // Tag::::from_utf8_strs( - // "Eth-Signature", - // "0x...", - // ) - // .unwrap(), + Tag::::from_utf8_strs("Eth-Address", eth_address).unwrap(), + Tag::::from_utf8_strs("Eth-Signature", eth_sig).unwrap(), ] } @@ -154,13 +168,16 @@ impl Ar { ) -> Result<(String, String), Box> { let unix_timestamp = get_unix_timestamp(); - let action = - r#"{"action":"init_state", arguments: [], validity_proof:"ID_OF_VALIDITY_PROOF"}"#; + let action = r#"{"action":"init_state", arguments: []}"#; + let (account, sig) = get_eth_metadata(&initial_state.as_bytes().to_vec()).await?; + let tags = self.create_tags( &contract_id, &unix_timestamp, action, ContractType::Interaction, + &account, + &sig, ); let mut tx = self @@ -193,12 +210,16 @@ impl Ar { let unix_timestamp = get_unix_timestamp(); // todo, currently we don't send out multiple votes, so no arguments of last votes - let action = r#"{"action":"vote", arguments: [], validity_proof:"ID_OF_VALIDITY_PROOF"}"#; + let action = r#"{"action":"vote", arguments: []}"#; + let (account, sig) = get_eth_metadata(&vote_data.as_bytes().to_vec()).await?; + let tags = self.create_tags( &contract_id, &unix_timestamp, action, ContractType::Interaction, + &account, + &sig, ); let mut tx = self @@ -436,3 +457,33 @@ mod tests { Ok(()) } } + +pub fn encode_hex(bytes: &[u8]) -> String { + let mut s = String::with_capacity(bytes.len() * 2); + for &b in bytes { + write!(&mut s, "{:02x}", b).unwrap(); + } + s +} + +pub async fn get_eth_metadata( + data: &Vec, +) -> Result<(String, String), Box> { + // to show you own your ethereum address, you need to sign a message + // the message is the concatenation of your address + hash of the data being deployed + + // we get the hash + let hash = sha_256(&data); + + let c = EthClient::new().await?; + + let account = c.account(); + let account_b = account.as_bytes(); + + let mut iter = account_b.into_iter().chain(&hash); + let result = [(); 74].map(|_| iter.next().unwrap().to_owned()); + + let hashed_message = encode_hex(&sha_256(&result)); + + c.get_sig(&hashed_message).await +} diff --git a/fhe_contract/src/cli.rs b/fhe_contract/src/cli.rs index f132236..470076c 100644 --- a/fhe_contract/src/cli.rs +++ b/fhe_contract/src/cli.rs @@ -6,7 +6,6 @@ use sunscreen::{Application, Ciphertext, PrivateKey, PublicKey, Runtime}; use crate::calculator::{calculate, decrypt, get_initial_state}; use crate::compiler::compile; use crate::snarkjs::{generate_proof, generate_witness, verify_snark_proof}; -use futures::{future, FutureExt}; use serde_json::{json, Value}; use std::fs::{self, File}; use std::io::prelude::*; @@ -259,7 +258,7 @@ async fn compute_latest() -> Result<(), Box> { happens when serde_json::from_value(intx["data"].clone()).unwrap(); */ - + // todo add verifying eth sig // this bit does the calculations #[allow(unused_assignments)] let mut t_s = String::from(""); @@ -386,6 +385,7 @@ async fn vote(id: &String, index: &usize) -> Result<(), Box Result<(), Box> { // deploy contract to arweave let contract_id = deploy().await?; - let futures = vec![ - // initialize the zk states - init_zk(&contract_id).boxed(), - // init the state - init_state(&contract_id).boxed(), - ]; - let results = future::join_all(futures).await; + init_zk(&contract_id).await?; + + init_state(&contract_id).await?; + + // let futures = vec![ + // // initialize the zk states + // init_zk(&contract_id).boxed(), + // // init the state + // init_state(&contract_id).boxed(), + // ]; + // let results = future::join_all(futures).await; // we unwrap all ensuring no erro - for r in results { - r.unwrap(); - } + // for r in results { + // r.unwrap(); + // } // fetch the zk info to populate our cache fetch_zk(&contract_id).await?; diff --git a/fhe_contract/src/ethereum.rs b/fhe_contract/src/ethereum.rs new file mode 100644 index 0000000..44a167c --- /dev/null +++ b/fhe_contract/src/ethereum.rs @@ -0,0 +1,66 @@ +use std::error::Error; +use walletconnect::{qr, Client, Metadata}; + +pub struct EthClient { + client: Client, + account: String, +} + +impl EthClient { + pub async fn new() -> Result> { + let c = Client::new( + "ethberlin", + Metadata { + description: "Ethberlin WallectConnect for harpocrates".into(), + url: "https://github.com/nlordell/walletconnect-rs".parse()?, + icons: vec!["https://avatars0.githubusercontent.com/u/4210206".parse()?], + name: "EthBerlin WallectConnect for harpocrates".into(), + }, + )?; + + let (accounts, _) = c.ensure_session(qr::print_with_url).await?; + + // println!("Connected accounts:"); + let main_account = format!("{:?}", accounts[0]); + Ok(EthClient { + client: c, + account: main_account, + }) + } + + pub fn account(&self) -> String { + self.account.clone() + } + pub async fn get_sig(&self, to_sign: &str) -> Result<(String, String), Box> { + let sig = self.client.personal_sign(&[to_sign, &self.account]).await?; + Ok((self.account.to_string(), format!("{}", sig))) + } +} + +#[allow(unused)] +fn verify_sig(message: &str, sig: &[u8]) -> Result> { + let addr = walletconnect::client::verify_sig(message, sig)?; + Ok(addr) +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[tokio::test] + async fn it_runs() -> Result<(), Box> { + let msg = "hello"; + let h = keccak256(msg.as_bytes()); + let message_hash = hex::encode(&h); + println!("hash {}", message_hash); + + let c = EthClient::new().await.unwrap(); + let (acc, sig) = c.get_sig(msg).await.unwrap(); + println!("{}", acc); + println!("{}", sig); + + verify_sig(&message_hash, sig.as_bytes())?; + Ok(()) + } +} diff --git a/fhe_contract/src/lib.rs b/fhe_contract/src/lib.rs index 095d951..576ebff 100644 --- a/fhe_contract/src/lib.rs +++ b/fhe_contract/src/lib.rs @@ -9,3 +9,5 @@ pub mod cli; pub mod arweave; pub mod snarkjs; + +pub mod ethereum;