Преглед изворни кода

sepreate state object from Client

ghassmo пре 4 година
родитељ
комит
a73da61ec0
3 измењених фајлова са 171 додато и 156 уклоњено
  1. 47 18
      src/bin/cashierd.rs
  2. 91 77
      src/bin/darkfid.rs
  3. 33 61
      src/client.rs

+ 47 - 18
src/bin/cashierd.rs

@@ -1,4 +1,4 @@
-use async_std::sync::Arc;
+use async_std::sync::{Arc, Mutex};
 use async_trait::async_trait;
 use async_trait::async_trait;
 use clap::clap_app;
 use clap::clap_app;
 use ff::Field;
 use ff::Field;
@@ -11,9 +11,12 @@ use std::path::PathBuf;
 use std::str::FromStr;
 use std::str::FromStr;
 
 
 use drk::{
 use drk::{
-    blockchain::Rocks,
+    blockchain::{rocks::columns, Rocks, RocksColumn},
     cli::{CashierdConfig, Config},
     cli::{CashierdConfig, Config},
-    client::Client,
+    client::{Client, State},
+    crypto::{
+        load_params, merkle::CommitmentTree, save_params, setup_mint_prover, setup_spend_prover,
+    },
     rpc::{
     rpc::{
         jsonrpc::{error as jsonerr, response as jsonresp},
         jsonrpc::{error as jsonerr, response as jsonresp},
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
@@ -452,6 +455,7 @@ impl Cashierd {
     async fn start(
     async fn start(
         &mut self,
         &mut self,
         mut client: Client,
         mut client: Client,
+        state: Arc<Mutex<State>>,
     ) -> Result<(
     ) -> Result<(
         smol::Task<Result<()>>,
         smol::Task<Result<()>>,
         smol::Task<Result<()>>,
         smol::Task<Result<()>>,
@@ -543,7 +547,7 @@ impl Cashierd {
         let (notify, recv_coin) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
         let (notify, recv_coin) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
 
 
         client
         client
-            .connect_to_subscriber_from_cashier(self.cashier_wallet.clone(), notify.clone())
+            .connect_to_subscriber_from_cashier(state, self.cashier_wallet.clone(), notify.clone())
             .await?;
             .await?;
 
 
         let cashier_wallet = self.cashier_wallet.clone();
         let cashier_wallet = self.cashier_wallet.clone();
@@ -625,29 +629,54 @@ async fn main() -> Result<()> {
     let rocks = Rocks::new(expand_path(&cashierd.config.database_path.clone())?.as_path())?;
     let rocks = Rocks::new(expand_path(&cashierd.config.database_path.clone())?.as_path())?;
 
 
     // this is just an empty vector
     // this is just an empty vector
-    let mut cashier_public_key: Vec<jubjub::SubgroupPoint> = Vec::new();
+    let mut cashier_public_keys: Vec<jubjub::SubgroupPoint> = Vec::new();
+
+    let params_paths = (
+        expand_path(&cashierd.config.mint_params_path.clone())?,
+        expand_path(&cashierd.config.spend_params_path.clone())?,
+    );
+
+    let mint_params_path = params_paths.0.to_str().unwrap_or("mint.params");
+    let spend_params_path = params_paths.1.to_str().unwrap_or("spend.params");
+    // Auto create trusted ceremony parameters if they don't exist
+    if !params_paths.0.exists() {
+        let params = setup_mint_prover();
+        save_params(mint_params_path, &params)?;
+    }
+    if !params_paths.1.exists() {
+        let params = setup_spend_prover();
+        save_params(spend_params_path, &params)?;
+    }
+
+    // Load trusted setup parameters
+    let (mint_params, mint_pvk) = load_params(mint_params_path)?;
+    let (spend_params, spend_pvk) = load_params(spend_params_path)?;
 
 
     let client = Client::new(
     let client = Client::new(
-        rocks,
+        rocks.clone(),
         (
         (
             cashierd.config.gateway_protocol_url.parse()?,
             cashierd.config.gateway_protocol_url.parse()?,
             cashierd.config.gateway_publisher_url.parse()?,
             cashierd.config.gateway_publisher_url.parse()?,
         ),
         ),
-        (
-            expand_path(&cashierd.config.mint_params_path.clone())?,
-            expand_path(&cashierd.config.spend_params_path.clone())?,
-        ),
         client_wallet.clone(),
         client_wallet.clone(),
-        cashier_public_key.clone(),
+        mint_params,
+        spend_params,
     )
     )
     .await?;
     .await?;
 
 
-    // must add cashier public key to the client wallet, which in this case it's the same
-    // as main_keypair
-    if cashier_public_key.clone().is_empty() {
-        cashier_public_key.push(client.main_keypair.public);
-        client_wallet.put_cashier_pub(&client.main_keypair.public)?;
-    }
+    let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
+    let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
+
+    cashier_public_keys.push(client.main_keypair.public);
+
+    let state = Arc::new(Mutex::new(State {
+        tree: CommitmentTree::empty(),
+        merkle_roots,
+        nullifiers,
+        mint_pvk,
+        spend_pvk,
+        public_keys: cashier_public_keys,
+    }));
 
 
     if args.is_present("ADDRESS") {
     if args.is_present("ADDRESS") {
         let cashier_public = client.main_keypair.public;
         let cashier_public = client.main_keypair.public;
@@ -663,7 +692,7 @@ async fn main() -> Result<()> {
         identity_pass: cashierd.config.tls_identity_password.clone(),
         identity_pass: cashierd.config.tls_identity_password.clone(),
     };
     };
 
 
-    let (t1, t2, t3) = cashierd.start(client).await?;
+    let (t1, t2, t3) = cashierd.start(client, state).await?;
     listen_and_serve(cfg, Arc::new(cashierd)).await?;
     listen_and_serve(cfg, Arc::new(cashierd)).await?;
 
 
     t1.cancel().await;
     t1.cancel().await;

+ 91 - 77
src/bin/darkfid.rs

@@ -1,7 +1,10 @@
 use drk::{
 use drk::{
-    blockchain::Rocks,
+    blockchain::{rocks::columns, Rocks, RocksColumn},
     cli::{Config, DarkfidConfig},
     cli::{Config, DarkfidConfig},
-    client::Client,
+    client::{Client, State},
+    crypto::{
+        load_params, merkle::CommitmentTree, save_params, setup_mint_prover, setup_spend_prover,
+    },
     rpc::{
     rpc::{
         jsonrpc::{error as jsonerr, request as jsonreq, response as jsonresp, send_request},
         jsonrpc::{error as jsonerr, request as jsonreq, response as jsonresp, send_request},
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
@@ -33,14 +36,6 @@ pub struct Cashier {
     pub public_key: jubjub::SubgroupPoint,
     pub public_key: jubjub::SubgroupPoint,
 }
 }
 
 
-struct Darkfid {
-    config: DarkfidConfig,
-    client: Arc<Mutex<Client>>,
-    sol_tokenlist: SolTokenList,
-    drk_tokenlist: DrkTokenList,
-    cashiers: Vec<Cashier>,
-}
-
 #[async_trait]
 #[async_trait]
 impl RequestHandler for Darkfid {
 impl RequestHandler for Darkfid {
     async fn handle_request(&self, req: JsonRequest) -> JsonResult {
     async fn handle_request(&self, req: JsonRequest) -> JsonResult {
@@ -66,58 +61,19 @@ impl RequestHandler for Darkfid {
     }
     }
 }
 }
 
 
-impl Darkfid {
-    async fn new(config: DarkfidConfig, wallet: Arc<WalletDb>) -> Result<Self> {
-        debug!(target: "DARKFID", "INIT WALLET WITH PATH {}", config.wallet_path);
-
-        let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
-
-        let mut cashiers = Vec::new();
-        let mut cashier_keys = Vec::new();
-
-        // If is empty, warn!
-        for cashier in config.clone().cashiers {
-            if cashier.public_key.is_empty() {
-                // TODO: this is just a random error, need proper error
-                debug!(target: "DARKFID", "Public key field is empty");
-                return Err(Error::PathNotFound);
-            }
-            debug!(target: "DARKFID", "Found public key");
-            let cashier_public: jubjub::SubgroupPoint =
-                deserialize(&bs58::decode(cashier.public_key).into_vec()?)?;
-            debug!(target: "DARKFID", "push to Cashier");
-            cashiers.push(Cashier {
-                name: cashier.name,
-                rpc_url: cashier.rpc_url,
-                public_key: cashier_public,
-            });
-            debug!(target: "DARKFID", "push cashier_public to cashier_keys");
-            cashier_keys.push(cashier_public);
-            debug!(target: "DARKFID", "CASHIER KEYS {:?}", cashier_keys);
-        }
-
-        let client = Client::new(
-            rocks,
-            (
-                config.gateway_protocol_url.parse()?,
-                config.gateway_publisher_url.parse()?,
-            ),
-            (
-                expand_path(&config.mint_params_path.clone())?,
-                expand_path(&config.spend_params_path.clone())?,
-            ),
-            wallet.clone(),
-            cashier_keys,
-        )
-        .await?;
-
-        let client = Arc::new(Mutex::new(client));
+struct Darkfid {
+    client: Arc<Mutex<Client>>,
+    sol_tokenlist: SolTokenList,
+    drk_tokenlist: DrkTokenList,
+    cashiers: Vec<Cashier>,
+}
 
 
+impl Darkfid {
+    async fn new(client: Arc<Mutex<Client>>, cashiers: Vec<Cashier>) -> Result<Self> {
         let sol_tokenlist = SolTokenList::new()?;
         let sol_tokenlist = SolTokenList::new()?;
         let drk_tokenlist = DrkTokenList::new(sol_tokenlist.clone())?;
         let drk_tokenlist = DrkTokenList::new(sol_tokenlist.clone())?;
 
 
         Ok(Self {
         Ok(Self {
-            config,
             client,
             client,
             sol_tokenlist,
             sol_tokenlist,
             drk_tokenlist,
             drk_tokenlist,
@@ -125,9 +81,13 @@ impl Darkfid {
         })
         })
     }
     }
 
 
-    async fn start(&mut self) -> Result<()> {
+    async fn start(&mut self, state: Arc<Mutex<State>>) -> Result<()> {
         self.client.lock().await.start().await?;
         self.client.lock().await.start().await?;
-        self.client.lock().await.connect_to_subscriber().await?;
+        self.client
+            .lock()
+            .await
+            .connect_to_subscriber(state)
+            .await?;
 
 
         Ok(())
         Ok(())
     }
     }
@@ -573,26 +533,80 @@ async fn main() -> Result<()> {
         config.wallet_password.clone(),
         config.wallet_password.clone(),
     )?;
     )?;
 
 
-    //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(());
-    //    }
+    let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
+
+    let mut cashiers = Vec::new();
+    let mut cashier_keys = Vec::new();
+
+    // If is empty, warn!
+    for cashier in config.clone().cashiers {
+        if cashier.public_key.is_empty() {
+            // TODO: this is just a random error, need proper error
+            debug!(target: "DARKFID", "Public key field is empty");
+            return Err(Error::PathNotFound);
+        }
+        debug!(target: "DARKFID", "Found public key");
+        let cashier_public: jubjub::SubgroupPoint =
+            deserialize(&bs58::decode(cashier.public_key).into_vec()?)?;
+        debug!(target: "DARKFID", "push to Cashier");
+        cashiers.push(Cashier {
+            name: cashier.name,
+            rpc_url: cashier.rpc_url,
+            public_key: cashier_public,
+        });
+        debug!(target: "DARKFID", "push cashier_public to cashier_keys");
+        cashier_keys.push(cashier_public);
+        debug!(target: "DARKFID", "CASHIER KEYS {:?}", cashier_keys);
+    }
+
+    let params_paths = (
+        expand_path(&config.mint_params_path.clone())?,
+        expand_path(&config.spend_params_path.clone())?,
+    );
+
+    let mint_params_path = params_paths.0.to_str().unwrap_or("mint.params");
+    let spend_params_path = params_paths.1.to_str().unwrap_or("spend.params");
+    // Auto create trusted ceremony parameters if they don't exist
+    if !params_paths.0.exists() {
+        let params = setup_mint_prover();
+        save_params(mint_params_path, &params)?;
+    }
+    if !params_paths.1.exists() {
+        let params = setup_spend_prover();
+        save_params(spend_params_path, &params)?;
+    }
+
+    // Load trusted setup parameters
+    let (mint_params, mint_pvk) = load_params(mint_params_path)?;
+    let (spend_params, spend_pvk) = load_params(spend_params_path)?;
+
+    let client = Client::new(
+        rocks.clone(),
+        (
+            config.gateway_protocol_url.parse()?,
+            config.gateway_publisher_url.parse()?,
+        ),
+        wallet.clone(),
+        mint_params,
+        spend_params,
+    )
+    .await?;
+
+    let client = Arc::new(Mutex::new(client));
 
 
-    //    if matches.is_present("SETCASHIERKEY") {
-    //        let cashier_public = matches.value_of("SETCASHIERKEY").unwrap();
+    let mut darkfid = Darkfid::new(client, cashiers).await?;
 
 
-    //        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 merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
+    let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
 
 
-    let mut darkfid = Darkfid::new(config.clone(), wallet.clone()).await?;
+    let state = Arc::new(Mutex::new(State {
+        tree: CommitmentTree::empty(),
+        merkle_roots,
+        nullifiers,
+        mint_pvk,
+        spend_pvk,
+        public_keys: cashier_keys,
+    }));
 
 
     let server_config = RpcServerConfig {
     let server_config = RpcServerConfig {
         socket_addr: config.rpc_listen_address.clone(),
         socket_addr: config.rpc_listen_address.clone(),
@@ -601,6 +615,6 @@ async fn main() -> Result<()> {
         identity_pass: config.tls_identity_password.clone(),
         identity_pass: config.tls_identity_password.clone(),
     };
     };
 
 
-    darkfid.start().await?;
+    darkfid.start(state).await?;
     listen_and_serve(server_config, Arc::new(darkfid)).await
     listen_and_serve(server_config, Arc::new(darkfid)).await
 }
 }

+ 33 - 61
src/client.rs

@@ -5,17 +5,15 @@ use log::*;
 
 
 use std::collections::HashMap;
 use std::collections::HashMap;
 use std::net::SocketAddr;
 use std::net::SocketAddr;
-use std::path::PathBuf;
 
 
 use crate::{
 use crate::{
     blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
     blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
     crypto::{
     crypto::{
-        load_params,
         merkle::{CommitmentTree, IncrementalWitness},
         merkle::{CommitmentTree, IncrementalWitness},
         merkle_node::MerkleNode,
         merkle_node::MerkleNode,
         note::{EncryptedNote, Note},
         note::{EncryptedNote, Note},
         nullifier::Nullifier,
         nullifier::Nullifier,
-        save_params, setup_mint_prover, setup_spend_prover, OwnCoin,
+        OwnCoin,
     },
     },
     serial::{serialize, Decodable, Encodable},
     serial::{serialize, Decodable, Encodable},
     service::{GatewayClient, GatewaySlabsSubscriber},
     service::{GatewayClient, GatewaySlabsSubscriber},
@@ -41,31 +39,21 @@ pub enum ClientFailed {
 }
 }
 
 
 pub struct Client {
 pub struct Client {
-    pub state: Arc<Mutex<State>>,
     mint_params: bellman::groth16::Parameters<Bls12>,
     mint_params: bellman::groth16::Parameters<Bls12>,
     spend_params: bellman::groth16::Parameters<Bls12>,
     spend_params: bellman::groth16::Parameters<Bls12>,
     gateway: GatewayClient,
     gateway: GatewayClient,
+    wallet: WalletPtr,
     pub main_keypair: Keypair,
     pub main_keypair: Keypair,
-    pub cashier_keys: Vec<jubjub::SubgroupPoint>,
 }
 }
 
 
 impl Client {
 impl Client {
     pub async fn new(
     pub async fn new(
         rocks: Arc<Rocks>,
         rocks: Arc<Rocks>,
         gateway_addrs: (SocketAddr, SocketAddr),
         gateway_addrs: (SocketAddr, SocketAddr),
-        params_paths: (PathBuf, PathBuf),
         wallet: WalletPtr,
         wallet: WalletPtr,
-        cashier_keys: Vec<jubjub::SubgroupPoint>,
+        mint_params: bellman::groth16::Parameters<Bls12>,
+        spend_params: bellman::groth16::Parameters<Bls12>,
     ) -> Result<Self> {
     ) -> Result<Self> {
-        let slabstore = RocksColumn::<columns::Slabs>::new(rocks.clone());
-        let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
-        let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
-
-        let mint_params_path = params_paths.0.to_str().unwrap_or("mint.params");
-        let spend_params_path = params_paths.1.to_str().unwrap_or("spend.params");
-
-        let public_keys = cashier_keys.clone();
-
         wallet.init_db().await?;
         wallet.init_db().await?;
 
 
         if wallet.get_keypairs()?.is_empty() {
         if wallet.get_keypairs()?.is_empty() {
@@ -75,45 +63,22 @@ impl Client {
         let main_keypair = wallet.get_keypairs()?[0].clone();
         let main_keypair = wallet.get_keypairs()?[0].clone();
 
 
         info!(
         info!(
-        target: "CLIENT", "Main Keypair: {}",
-        bs58::encode(&serialize(&main_keypair.public)).into_string()
+            target: "CLIENT", "Main Keypair: {}",
+            bs58::encode(&serialize(&main_keypair.public)).into_string()
         );
         );
 
 
-        // Auto create trusted ceremony parameters if they don't exist
-        if !params_paths.0.exists() {
-            let params = setup_mint_prover();
-            save_params(mint_params_path, &params)?;
-        }
-        if !params_paths.1.exists() {
-            let params = setup_spend_prover();
-            save_params(spend_params_path, &params)?;
-        }
-
-        // Load trusted setup parameters
-        let (mint_params, mint_pvk) = load_params(mint_params_path)?;
-        let (spend_params, spend_pvk) = load_params(spend_params_path)?;
-
-        let state = Arc::new(Mutex::new(State {
-            tree: CommitmentTree::empty(),
-            merkle_roots,
-            nullifiers,
-            mint_pvk,
-            spend_pvk,
-            wallet,
-            public_keys,
-        }));
+        let slabstore = RocksColumn::<columns::Slabs>::new(rocks.clone());
 
 
         // create gateway client
         // create gateway client
         debug!(target: "CLIENT", "Creating GatewayClient");
         debug!(target: "CLIENT", "Creating GatewayClient");
         let gateway = GatewayClient::new(gateway_addrs.0, gateway_addrs.1, slabstore)?;
         let gateway = GatewayClient::new(gateway_addrs.0, gateway_addrs.1, slabstore)?;
 
 
         Ok(Self {
         Ok(Self {
-            state,
             mint_params,
             mint_params,
             spend_params,
             spend_params,
+            wallet,
             gateway,
             gateway,
             main_keypair,
             main_keypair,
-            cashier_keys,
         })
         })
     }
     }
 
 
@@ -130,7 +95,7 @@ impl Client {
     ) -> ClientResult<()> {
     ) -> ClientResult<()> {
         debug!(target: "CLIENT", "Start transfer {}", amount);
         debug!(target: "CLIENT", "Start transfer {}", amount);
 
 
-        let token_id_exists = self.state.lock().await.wallet.token_id_exists(&token_id)?;
+        let token_id_exists = self.wallet.token_id_exists(&token_id)?;
 
 
         if token_id_exists {
         if token_id_exists {
             self.send(pub_key, amount, token_id, false).await?;
             self.send(pub_key, amount, token_id, false).await?;
@@ -228,13 +193,13 @@ impl Client {
         let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
         let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
         let mut inputs_value: u64 = 0;
         let mut inputs_value: u64 = 0;
 
 
-        let own_coins = self.state.lock().await.wallet.get_own_coins()?;
+        let own_coins = self.wallet.get_own_coins()?;
 
 
         for (coin_id, own_coin) in own_coins.iter() {
         for (coin_id, own_coin) in own_coins.iter() {
             if inputs_value >= amount {
             if inputs_value >= amount {
                 break;
                 break;
             }
             }
-            self.state.lock().await.wallet.confirm_spend_coin(coin_id)?;
+            self.wallet.confirm_spend_coin(coin_id)?;
             let witness = &own_coin.witness;
             let witness = &own_coin.witness;
             let merkle_path = witness.path().unwrap();
             let merkle_path = witness.path().unwrap();
             inputs_value += own_coin.note.value;
             inputs_value += own_coin.note.value;
@@ -268,6 +233,7 @@ impl Client {
 
 
     pub async fn connect_to_subscriber_from_cashier(
     pub async fn connect_to_subscriber_from_cashier(
         &self,
         &self,
+        state: Arc<Mutex<State>>,
         cashier_wallet: CashierDbPtr,
         cashier_wallet: CashierDbPtr,
         notify: async_channel::Sender<(jubjub::SubgroupPoint, u64)>,
         notify: async_channel::Sender<(jubjub::SubgroupPoint, u64)>,
     ) -> Result<()> {
     ) -> Result<()> {
@@ -276,7 +242,7 @@ impl Client {
         let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
         let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
 
 
         let secret_key = self.main_keypair.private;
         let secret_key = self.main_keypair.private;
-        let state = self.state.clone();
+        let wallet = self.wallet.clone();
 
 
         let task: smol::Task<Result<()>> = smol::spawn(async move {
         let task: smol::Task<Result<()>> = smol::spawn(async move {
             loop {
             loop {
@@ -306,7 +272,12 @@ impl Client {
                 secret_keys.append(&mut withdraw_keys);
                 secret_keys.append(&mut withdraw_keys);
 
 
                 let state_apply = state
                 let state_apply = state
-                    .apply(update?, secret_keys.clone(), Some(notify.clone()))
+                    .apply(
+                        update?,
+                        secret_keys.clone(),
+                        Some(notify.clone()),
+                        wallet.clone(),
+                    )
                     .await;
                     .await;
 
 
                 if let Err(e) = state_apply {
                 if let Err(e) = state_apply {
@@ -321,13 +292,13 @@ impl Client {
         Ok(())
         Ok(())
     }
     }
 
 
-    pub async fn connect_to_subscriber(&self) -> Result<()> {
+    pub async fn connect_to_subscriber(&self, state: Arc<Mutex<State>>) -> Result<()> {
         // start subscribing
         // start subscribing
         debug!(target: "CLIENT", "Start subscriber");
         debug!(target: "CLIENT", "Start subscriber");
         let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
         let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
 
 
         let secret_key = self.main_keypair.private;
         let secret_key = self.main_keypair.private;
-        let state = self.state.clone();
+        let wallet = self.wallet.clone();
 
 
         let task: smol::Task<Result<()>> = smol::spawn(async move {
         let task: smol::Task<Result<()>> = smol::spawn(async move {
             loop {
             loop {
@@ -355,7 +326,9 @@ impl Client {
 
 
                 let secret_keys: Vec<jubjub::Fr> = vec![secret_key];
                 let secret_keys: Vec<jubjub::Fr> = vec![secret_key];
 
 
-                let state_apply = state.apply(update?, secret_keys.clone(), None).await;
+                let state_apply = state
+                    .apply(update?, secret_keys.clone(), None, wallet.clone())
+                    .await;
 
 
                 if let Err(e) = state_apply {
                 if let Err(e) = state_apply {
                     warn!("apply state: {}", e.to_string());
                     warn!("apply state: {}", e.to_string());
@@ -370,23 +343,23 @@ impl Client {
     }
     }
 
 
     pub async fn init_db(&self) -> Result<()> {
     pub async fn init_db(&self) -> Result<()> {
-        self.state.lock().await.wallet.init_db().await
+        self.wallet.init_db().await
     }
     }
 
 
     pub async fn key_gen(&self) -> Result<()> {
     pub async fn key_gen(&self) -> Result<()> {
-        self.state.lock().await.wallet.key_gen()
+        self.wallet.key_gen()
     }
     }
 
 
     pub async fn get_balances(&self) -> Result<HashMap<Vec<u8>, u64>> {
     pub async fn get_balances(&self) -> Result<HashMap<Vec<u8>, u64>> {
-        self.state.lock().await.wallet.get_balances()
+        self.wallet.get_balances()
     }
     }
 
 
     pub async fn token_id_exists(&self, token_id: &jubjub::Fr) -> Result<bool> {
     pub async fn token_id_exists(&self, token_id: &jubjub::Fr) -> Result<bool> {
-        self.state.lock().await.wallet.token_id_exists(token_id)
+        self.wallet.token_id_exists(token_id)
     }
     }
 
 
     pub async fn get_token_id(&self) -> Result<Vec<jubjub::Fr>> {
     pub async fn get_token_id(&self) -> Result<Vec<jubjub::Fr>> {
-        self.state.lock().await.wallet.get_token_id()
+        self.wallet.get_token_id()
     }
     }
 }
 }
 
 
@@ -402,8 +375,6 @@ pub struct State {
     pub mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
     pub mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
     // Spend verifying key used by ZK
     // Spend verifying key used by ZK
     pub spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
     pub spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
-    // Pointer to sql database
-    pub wallet: WalletPtr,
     // List of cashier public keys
     // List of cashier public keys
     pub public_keys: Vec<jubjub::SubgroupPoint>,
     pub public_keys: Vec<jubjub::SubgroupPoint>,
 }
 }
@@ -454,6 +425,7 @@ impl State {
         update: StateUpdate,
         update: StateUpdate,
         secret_keys: Vec<jubjub::Fr>,
         secret_keys: Vec<jubjub::Fr>,
         notify: Option<async_channel::Sender<(jubjub::SubgroupPoint, u64)>>,
         notify: Option<async_channel::Sender<(jubjub::SubgroupPoint, u64)>>,
+        wallet: WalletPtr,
     ) -> Result<()> {
     ) -> Result<()> {
         // Extend our list of nullifiers with the ones from the update
         // Extend our list of nullifiers with the ones from the update
 
 
@@ -477,9 +449,9 @@ impl State {
             debug!(target: "CLIENT STATE", "Update witness");
             debug!(target: "CLIENT STATE", "Update witness");
 
 
             // Also update all the coin witnesses
             // Also update all the coin witnesses
-            for (coin_id, witness) in self.wallet.get_witnesses()?.iter_mut() {
+            for (coin_id, witness) in wallet.get_witnesses()?.iter_mut() {
                 witness.append(node).expect("Append to witness");
                 witness.append(node).expect("Append to witness");
-                self.wallet.update_witness(*coin_id, witness.clone())?;
+                wallet.update_witness(*coin_id, witness.clone())?;
             }
             }
 
 
             debug!(target: "CLIENT STATE", "iterate over secret_keys to decrypt note");
             debug!(target: "CLIENT STATE", "iterate over secret_keys to decrypt note");
@@ -505,7 +477,7 @@ impl State {
                         witness: witness.clone(),
                         witness: witness.clone(),
                     };
                     };
 
 
-                    self.wallet.put_own_coins(own_coin)?;
+                    wallet.put_own_coins(own_coin)?;
                     let pub_key = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
                     let pub_key = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
 
 
                     debug!(target: "CLIENT STATE", "Received a coin: amount {} ", note.value);
                     debug!(target: "CLIENT STATE", "Received a coin: amount {} ", note.value);