diff --git a/src/bin/darkfid.rs b/src/bin/darkfid.rs index f1eeac187..26d53a9c6 100644 --- a/src/bin/darkfid.rs +++ b/src/bin/darkfid.rs @@ -31,7 +31,7 @@ async fn start(executor: Arc>, config: Arc) -> Resul let mint_params_path = join_config_path(&PathBuf::from("mint.params"))?; let spend_params_path = join_config_path(&PathBuf::from("spend.params"))?; - if let Err(_) = wallet.get_private_keys() { + if let Err(_) = wallet.get_keypairs() { wallet.init_db()?; wallet.key_gen()?; } diff --git a/src/client/client.rs b/src/client/client.rs index 4d4cd52d2..e48cb8e86 100644 --- a/src/client/client.rs +++ b/src/client/client.rs @@ -171,7 +171,7 @@ impl Client { let mut outputs: Vec = vec![]; if clear_input { - let cashier_secret = self.state.wallet.get_private_keys()?[0]; + let cashier_secret = self.state.wallet.get_keypairs()?[0].private; let input = tx::TransactionBuilderClearInputInfo { value: amount, asset_id, @@ -272,7 +272,13 @@ impl Client { let tx = tx::Transaction::decode(&slab.get_payload()[..])?; let mut client = client.lock().await; let update = state_transition(&client.state, tx)?; - let mut secret_keys = client.state.wallet.get_private_keys()?; + let mut secret_keys: Vec = client + .state + .wallet + .get_keypairs()? + .iter() + .map(|k| k.private) + .collect(); let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys()?; secret_keys.append(&mut withdraw_keys); client @@ -309,7 +315,15 @@ impl Client { let tx = tx::Transaction::decode(&slab.get_payload()[..])?; let mut client = client.lock().await; let update = state_transition(&client.state, tx)?; - let secret_keys = client.state.wallet.get_private_keys()?; + + let secret_keys: Vec = client + .state + .wallet + .get_keypairs()? + .iter() + .map(|k| k.private) + .collect(); + client .state .apply(update, secret_keys.clone(), notify.clone()) diff --git a/src/client/mod.rs b/src/client/mod.rs index 90226f0f5..fbd8aa1cd 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -12,8 +12,7 @@ pub enum ClientFailed { UnableToGetDepositAddress, UnableToGetWithdrawAddress, DoNotHaveCashierPublicKey, - DoNotHavePublicKey, - DoNotHavePrivateKey, + DoNotHaveKeypair, EmptyPassword, ClientError(String), } @@ -37,8 +36,7 @@ impl fmt::Display for ClientFailed { f.write_str("Unable to get withdraw address") } ClientFailed::DoNotHaveCashierPublicKey => f.write_str("Don't have cashier public key"), - ClientFailed::DoNotHavePublicKey => f.write_str("Don't have public key"), - ClientFailed::DoNotHavePrivateKey => f.write_str("Don't have private key"), + ClientFailed::DoNotHaveKeypair => f.write_str("Don't have keypair"), ClientFailed::EmptyPassword => f.write_str("Password is empty. Cannot create database"), ClientFailed::ClientError(i) => { write!(f, "ClientError: {}", i) diff --git a/src/rpc/adapter/client_adapter.rs b/src/rpc/adapter/client_adapter.rs index f92789624..b29b4cf41 100644 --- a/src/rpc/adapter/client_adapter.rs +++ b/src/rpc/adapter/client_adapter.rs @@ -67,7 +67,7 @@ impl RpcClientAdapter { } async fn get_key_process(client: Arc>) -> Result { - let key_public = client.lock().await.state.wallet.get_public_keys()?[0]; + let key_public = client.lock().await.state.wallet.get_keypairs()?[0].public; let bs58_address = bs58::encode(serialize(&key_public)).into_string(); Ok(bs58_address) } @@ -150,7 +150,7 @@ impl RpcClientAdapter { T: Decodable + ToString, { let asset_id: jubjub::Fr = deserialize(&asset_id)?; - let deposit_addr = client.lock().await.state.wallet.get_public_keys()?[0]; + let deposit_addr = client.lock().await.state.wallet.get_keypairs()?[0].public; let coin_public = cashier_client .lock() .await diff --git a/src/service/cashier.rs b/src/service/cashier.rs index f85b7089e..73347f5cc 100644 --- a/src/service/cashier.rs +++ b/src/service/cashier.rs @@ -16,6 +16,8 @@ use async_std::sync::{Arc, Mutex}; use std::net::SocketAddr; use std::path::PathBuf; + + #[repr(u8)] enum CashierError { NoError, @@ -42,7 +44,6 @@ impl CashierService { gateway_addrs: (SocketAddr, SocketAddr), params_paths: (PathBuf, PathBuf), ) -> Result { - // Pull address from config later let rocks = Rocks::new(&cashier_database_path)?; @@ -50,6 +51,7 @@ impl CashierService { let client = Arc::new(Mutex::new(client)); + Ok(CashierService { addr, wallet, @@ -59,6 +61,7 @@ impl CashierService { pub async fn start( &mut self, executor: Arc>, + // TODO: the endpoint should be generic according to asset_id btc_endpoint: (bool, String), // TODO: make this a vector of assets asset_id: jubjub::Fr, @@ -76,13 +79,12 @@ impl CashierService { let bridge = bridge::Bridge::new(); - #[cfg(feature = "default")] - let btc_client = super::btc::BtcClient::new(btc_endpoint)?; - #[cfg(feature = "default")] - bridge - .clone() - .add_clients(asset_id, Arc::new(btc_client)) - .await; + cfg_if::cfg_if! { + if #[cfg(feature = "default")]{ + let btc_client = super::btc::BtcClient::new(btc_endpoint)?; + bridge.clone().add_clients(asset_id, Arc::new(btc_client)).await; + } + } let handle_request_task = executor.spawn(Self::handle_request_loop( send.clone(), @@ -129,10 +131,9 @@ impl CashierService { if res.error == 0 { match res.payload { bridge::BridgeResponsePayload::SendResponse => { - // then delete this coin addr from withdraw_keys records // TODO Send the received coins to the main address - wallet.delete_withdraw_key_record(&addr, &serialize(&1) ) - .expect("Delete withdraw key record"); + // wallet.delete_withdraw_key_record(&addr, &serialize(&1) ) + // .expect("Delete withdraw key record"); } _ => {} } @@ -212,7 +213,6 @@ impl CashierService { let (asset_id, dpub): (jubjub::Fr, jubjub::SubgroupPoint) = deserialize(&request.get_payload())?; - //TODO: check if key has already been issued let _check = cashier_wallet.get_deposit_coin_keys_by_dkey_public(&dpub, &serialize(&1)); @@ -252,10 +252,6 @@ impl CashierService { debug!(target: "CASHIER DAEMON", "Received withdraw request"); let (asset_id, coin_address): (jubjub::Fr, Vec) = deserialize(&request.get_payload())?; - //let btc_address: String = deserialize(&btc_address)?; - //let btc_address = bitcoin::util::address::Address::from_str(&btc_address) - // .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?; - // let asset_id = serialize(&asset_id); diff --git a/src/wallet/walletdb.rs b/src/wallet/walletdb.rs index 91a4ecabb..5baf6b557 100644 --- a/src/wallet/walletdb.rs +++ b/src/wallet/walletdb.rs @@ -4,7 +4,6 @@ use crate::crypto::{ merkle::IncrementalWitness, merkle_node::MerkleNode, note::Note, OwnCoin, OwnCoins, }; use crate::serial; -use crate::serial::{deserialize, serialize, Decodable, Encodable}; use crate::{Error, Result}; use async_std::sync::Arc; @@ -17,6 +16,11 @@ use std::path::PathBuf; pub type WalletPtr = Arc; +pub struct Keypair { + pub public: jubjub::SubgroupPoint, + pub private: jubjub::Fr, +} + pub struct WalletDb { pub path: PathBuf, pub password: String, @@ -73,45 +77,31 @@ impl WalletDb { )?; Ok(()) } - pub fn get_public_keys(&self) -> Result> { + pub fn get_keypairs(&self) -> Result> { debug!(target: "WALLETDB", "Returning keys..."); let conn = Connection::open(&self.path)?; conn.pragma_update(None, "key", &self.password)?; - let mut stmt = conn.prepare("SELECT key_public FROM keys")?; + let mut stmt = conn.prepare("SELECT * FROM keys")?; // this just gets the first key. maybe we should randomize this - let key_iter = stmt.query_map([], |row| row.get(0))?; - let mut pub_keys = Vec::new(); + let key_iter = stmt.query_map([], |row| Ok((row.get(1)?, row.get(2)?)))?; + let mut keypairs = Vec::new(); for key in key_iter { + let key = key?; + let public = key.0; + let private = key.1; let public: jubjub::SubgroupPoint = - self.get_value_deserialized::(key?)?; - pub_keys.push(public); + self.get_value_deserialized::(public)?; + let private: jubjub::Fr = self.get_value_deserialized::(private)?; + keypairs.push(Keypair { public, private }); } - if pub_keys.is_empty() { - return Err(Error::from(ClientFailed::DoNotHavePublicKey)); + if keypairs.is_empty() { + return Err(Error::from(ClientFailed::DoNotHaveKeypair)); } - Ok(pub_keys) + Ok(keypairs) } - pub fn get_private_keys(&self) -> Result> { - debug!(target: "WALLETDB", "Returning keys..."); - let conn = Connection::open(&self.path)?; - conn.pragma_update(None, "key", &self.password)?; - let mut stmt = conn.prepare("SELECT key_private FROM keys")?; - let key_iter = stmt.query_map([], |row| row.get(0))?; - let mut keys = Vec::new(); - for key in key_iter { - let private: jubjub::Fr = self.get_value_deserialized(key?)?; - keys.push(private); - } - - if keys.is_empty() { - return Err(Error::from(ClientFailed::DoNotHavePrivateKey)); - } - - Ok(keys) - } pub fn get_own_coins(&self) -> Result { // open connection let conn = Connection::open(&self.path)?; @@ -290,43 +280,6 @@ impl WalletDb { let _rows = stmt.query([])?; Ok(()) } - - fn get_tables_name(&self) -> Result> { - let conn = Connection::open(&self.path)?; - conn.pragma_update(None, "key", &self.password)?; - let mut stmt = conn.prepare("SELECT name FROM sqlite_master WHERE type='table'")?; - let table_iter = stmt.query_map::([], |row| row.get(0))?; - - let mut tables = Vec::new(); - - for table in table_iter { - tables.push(table?); - } - - Ok(tables) - } - - pub fn destroy(&self) -> Result<()> { - let conn = Connection::open(&self.path)?; - conn.pragma_update(None, "key", &self.password)?; - - for table in self.get_tables_name()?.iter() { - let drop_stmt = format!("DROP TABLE IF EXISTS {}", table); - let drop_stmt = drop_stmt.as_str(); - conn.execute(drop_stmt, [])?; - } - - Ok(()) - } - pub fn get_value_serialized(&self, data: &T) -> Result> { - let v = serialize(data); - Ok(v) - } - - pub fn get_value_deserialized(&self, key: Vec) -> Result { - let v: D = deserialize(&key)?; - Ok(v) - } } #[cfg(test)] @@ -350,11 +303,10 @@ mod tests { wallet.put_keypair(key_public, key_private)?; - let public2 = wallet.get_public_keys()?; - let secret2 = wallet.get_private_keys()?; + let keypair = wallet.get_keypairs()?[0]; - assert_eq!(public, public2[0]); - assert_eq!(secret, secret2[0]); + assert_eq!(public, keypair.public); + assert_eq!(secret, keypair.private); wallet.destroy()?;