diff --git a/src/bin/darkfid.rs b/src/bin/darkfid.rs index 2dd91c207..3d12dd34d 100644 --- a/src/bin/darkfid.rs +++ b/src/bin/darkfid.rs @@ -5,7 +5,6 @@ use serde_json::{json, Value}; use async_std::sync::{Arc, Mutex}; use std::path::PathBuf; -use std::str::FromStr; use drk::{ blockchain::Rocks, @@ -18,8 +17,8 @@ use drk::{ }, serial::{deserialize, serialize}, util::{ - assign_id, decimals, decode_base10, expand_path, generate_id, join_config_path, - DrkTokenList, NetworkName, SolTokenList, + assign_id, decimals, decode_base10, expand_path, join_config_path, + DrkTokenList, SolTokenList, }, wallet::WalletDb, Result, @@ -322,24 +321,34 @@ impl Darkfid { } } + let hashmap = self.drk_tokenlist.drk_tokenlist.clone(); + + if hashmap.get(token).is_none() { + return JsonResult::Err(jsonerr(InvalidParams, None, id)); + } + // get the id for the token + let token_id = hashmap.get(token).unwrap(); + // send drk to cashier_public if let JsonResult::Resp(cashier_public) = &rep { let result: Result<()> = async { let cashier_public = cashier_public.result.as_str().unwrap(); - let cashier_public: jubjub::SubgroupPoint = - deserialize(&bs58::decode(cashier_public).into_vec()?)?; + if self.client.lock().await.token_id_exists(token_id).await? == true { + let own_token_id = token_id; - self.client - .lock() - .await - .send( - cashier_public, - amount_in_apo, - generate_id(&token_id, &NetworkName::from_str(network)?)?, - true, - ) - .await?; + let cashier_public: jubjub::SubgroupPoint = + deserialize(&bs58::decode(cashier_public).into_vec()?)?; + + let decimals: usize = 8; + let amount = decode_base10(&amount.to_string(), decimals, true)?; + + self.client + .lock() + .await + .transfer(*own_token_id, cashier_public, amount) + .await?; + } Ok(()) } @@ -446,8 +455,12 @@ impl Darkfid { async fn main() -> Result<()> { let args = clap_app!(darkfid => (@arg CONFIG: -c --config +takes_value "Sets a custom config file") - (@arg CASHIERKEY: --cashier-key +takes_value "Sets cashier public key") (@arg verbose: -v --verbose "Increase verbosity") + (@subcommand cashier => + (about: "Manage cashier public key") + (@arg GETCASHIERKEY: --get "Get cashier public key") + (@arg SETCASHIERKEY: --set +takes_value "Sets cashier public key") + ) ) .get_matches(); @@ -472,12 +485,23 @@ async fn main() -> Result<()> { config.wallet_password.clone(), )?; - if let Some(cashier_public) = args.value_of("CASHIERKEY") { - let cashier_public: jubjub::SubgroupPoint = - deserialize(&bs58::decode(cashier_public).into_vec()?)?; - wallet.put_cashier_pub(&cashier_public)?; - println!("Cashier public key set successfully"); - return Ok(()); + if let Some(matches) = args.subcommand_matches("cashier") { + if matches.is_present("GETCASHIERKEY") { + let cashier_public = wallet.get_cashier_public_keys()?[0]; + let cashier_public = bs58::encode(&serialize(&cashier_public)).into_string(); + println!("Cashier Public Key: {}", cashier_public); + return Ok(()); + } + + if matches.is_present("SETCASHIERKEY") { + let cashier_public = matches.value_of("SETCASHIERKEY").unwrap(); + + let cashier_public: jubjub::SubgroupPoint = + deserialize(&bs58::decode(cashier_public).into_vec()?)?; + wallet.put_cashier_pub(&cashier_public)?; + println!("Cashier public key set successfully"); + return Ok(()); + } } let mut darkfid = Darkfid::new(config.clone(), wallet.clone()).await?; diff --git a/src/client.rs b/src/client.rs index ce49a3c4d..85780cff6 100644 --- a/src/client.rs +++ b/src/client.rs @@ -266,18 +266,30 @@ impl Client { let task: smol::Task> = smol::spawn(async move { loop { let slab = gateway_slabs_sub.recv().await?; - let tx = tx::Transaction::decode(&slab.get_payload()[..])?; + + debug!(target: "CLIENT", "Received new slab"); + + debug!(target: "CLIENT", "Starting build tx from slab"); + let tx = tx::Transaction::decode(&slab.get_payload()[..]); + + if tx.is_err() { + continue; + } let mut state = state.lock().await; - let update = state_transition(&state, tx)?; + let update = state_transition(&state, tx?); + + if update.is_err() { + continue; + } let mut secret_keys: Vec = vec![secret_key]; let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys()?; secret_keys.append(&mut withdraw_keys); state - .apply(update, secret_keys.clone(), notify.clone()) + .apply(update?, secret_keys.clone(), notify.clone()) .await?; } }); @@ -302,16 +314,29 @@ impl Client { let task: smol::Task> = smol::spawn(async move { loop { let slab = gateway_slabs_sub.recv().await?; - let tx = tx::Transaction::decode(&slab.get_payload()[..])?; + + debug!(target: "CLIENT", "Received new slab"); + + debug!(target: "CLIENT", "Starting build tx from slab"); + + let tx = tx::Transaction::decode(&slab.get_payload()[..]); + + if tx.is_err() { + continue; + } let mut state = state.lock().await; - let update = state_transition(&state, tx)?; + let update = state_transition(&state, tx?); + + if update.is_err() { + continue; + } let secret_keys: Vec = vec![secret_key]; state - .apply(update, secret_keys.clone(), notify.clone()) + .apply(update?, secret_keys.clone(), notify.clone()) .await?; } }); @@ -359,22 +384,34 @@ pub struct State { impl ProgramState for State { fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool { - self.wallet - .get_cashier_public_keys() - .expect("Get cashier public keys") - .contains(public) + debug!(target: "CLIENT STATE", "Check if it is valid cashier public key"); + + if let Ok(pub_keys) = self.wallet.get_cashier_public_keys() { + if pub_keys.is_empty() { + error!(target: "State", "No cashier public key"); + return false; + } + return pub_keys.contains(public); + } + false } fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool { - self.merkle_roots - .key_exist(*merkle_root) - .expect("Check if the merkle_root valid") + debug!(target: "CLIENT STATE", "Check if it is valid merkle"); + + if let Ok(mr) = self.merkle_roots.key_exist(*merkle_root) { + return mr; + } + false } fn nullifier_exists(&self, nullifier: &Nullifier) -> bool { - self.nullifiers - .key_exist(nullifier.repr) - .expect("Check if nullifier exists") + debug!(target: "CLIENT STATE", "Check if nullifier exists"); + + if let Ok(nl) = self.nullifiers.key_exist(nullifier.repr) { + return nl; + } + false } // load from disk @@ -408,15 +445,21 @@ impl State { let node = MerkleNode::from_coin(&coin); self.tree.append(node).expect("Append to merkle tree"); + debug!(target: "CLIENT STATE", "Keep track of all merkle roots"); + // Keep track of all merkle roots that have existed self.merkle_roots.put(self.tree.root(), vec![] as Vec)?; + debug!(target: "CLIENT STATE", "Update witness"); + // Also update all the coin witnesses for (coin_id, witness) in self.wallet.get_witnesses()?.iter_mut() { witness.append(node).expect("Append to witness"); self.wallet.update_witness(*coin_id, witness.clone())?; } + debug!(target: "CLIENT STATE", "iterate over secret_keys to decrypt note"); + for secret in secret_keys.iter() { if let Some(note) = Self::try_decrypt_note(enc_note, *secret) { // We need to keep track of the witness for this coin. diff --git a/src/service/gateway.rs b/src/service/gateway.rs index 5933410cf..abe4a09fe 100644 --- a/src/service/gateway.rs +++ b/src/service/gateway.rs @@ -226,6 +226,8 @@ impl GatewayClient { } pub async fn get_slab(&mut self, index: u64) -> Result> { + debug!(target: "GATEWAY CLIENT","Get slab"); + let handle_error = Arc::new(handle_error); let rep = self .protocol @@ -242,10 +244,13 @@ impl GatewayClient { self.slabstore.put(slab.clone())?; return Ok(Some(slab)); } + Ok(None) } pub async fn put_slab(&mut self, mut slab: Slab) -> Result<()> { + debug!(target: "GATEWAY CLIENT","Put slab"); + loop { let last_index = self.sync().await?; slab.set_index(last_index + 1); @@ -266,6 +271,8 @@ impl GatewayClient { } pub async fn get_last_index(&mut self) -> Result { + debug!(target: "GATEWAY CLIENT","Get last index"); + let handle_error = Arc::new(handle_error); let rep = self @@ -283,6 +290,8 @@ impl GatewayClient { } pub async fn start_subscriber(&self) -> Result { + debug!(target: "GATEWAY CLIENT","Start subscriber"); + let mut subscriber = Subscriber::new(self.sub_addr, String::from("GATEWAY CLIENT")); subscriber.start().await?; smol::spawn(Self::subscribe_loop( @@ -299,8 +308,11 @@ impl GatewayClient { slabstore: Arc, gateway_slabs_sub_s: async_channel::Sender, ) -> Result<()> { + debug!(target: "GATEWAY CLIENT","Start subscribe loop"); + loop { let slab = subscriber.fetch::().await?; + debug!(target: "GATEWAY CLIENT","Received new slab"); gateway_slabs_sub_s.send(slab.clone()).await?; slabstore.put(slab)?; } diff --git a/src/state.rs b/src/state.rs index fd78a1266..6c48f8118 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,6 @@ use bellman::groth16; use bls12_381::Bls12; +use log::debug; use std::fmt; use crate::{ @@ -72,14 +73,22 @@ pub fn state_transition( tx: tx::Transaction, ) -> VerifyResult { // Check deposits are legit + + debug!(target: "STATE TRANSITION", "iterate clear_inputs"); + for (i, input) in tx.clear_inputs.iter().enumerate() { // Check the public key in the clear inputs // It should be a valid public key for the cashier + + if !state.is_valid_cashier_public_key(&input.signature_public) { + log::error!(target: "STATE TRANSITION", "Not valid cashier public key"); return Err(VerifyFailed::InvalidCashierKey(i)); } } + debug!(target: "STATE TRANSITION", "iterate inputs"); + for (i, input) in tx.inputs.iter().enumerate() { // Check merkle roots let merkle = &input.revealed.merkle_root; @@ -99,6 +108,7 @@ pub fn state_transition( } } + debug!(target: "STATE TRANSITION", "Check the tx Verifies correctly"); // Check the tx verifies correctly tx.verify(state.mint_pvk(), state.spend_pvk())?; diff --git a/src/wallet/walletdb.rs b/src/wallet/walletdb.rs index 500abd100..b1bdca56a 100644 --- a/src/wallet/walletdb.rs +++ b/src/wallet/walletdb.rs @@ -671,6 +671,8 @@ mod tests { assert_eq!(cashier_public, public); + assert_eq!(wallet.get_cashier_public_keys()?.contains(&public), true); + std::fs::remove_file(walletdb_path)?; Ok(())