Просмотр исходного кода

Merge branch 'cashier_public_keys'

ghassmo 4 лет назад
Родитель
Сommit
7b01ea9bea
8 измененных файлов с 235 добавлено и 357 удалено
  1. 14 4
      example/config/darkfid.toml
  2. 0 4
      sql/schema.sql
  3. 0 179
      src/bin/build_tx.rs
  4. 50 16
      src/bin/cashierd.rs
  5. 106 57
      src/bin/darkfid.rs
  6. 12 2
      src/cli/cli_config.rs
  7. 40 61
      src/client.rs
  8. 13 34
      src/wallet/walletdb.rs

+ 14 - 4
example/config/darkfid.toml

@@ -17,10 +17,6 @@ tls_identity_path = "~/.config/darkfi/darkfid_identity.pfx"
 # Password for the created TLS identity. (Unused if serve_tls=false)
 tls_identity_password = "FOOBAR"
 
-# The RPC endpoint for a selected cashier
-cashier_rpc_url = "tcp://127.0.0.1:9000"
-#cashier_rpc_url = "tls://127.0.0.1:9000"
-
 # The endpoint to a gatewayd protocol API
 gateway_protocol_url = "127.0.0.1:3333"
 
@@ -41,3 +37,17 @@ wallet_path = "~/.config/darkfi/darkfid_wallet.db"
 
 # The wallet password
 wallet_password = "TEST_PASSWORD"
+
+# The configured cashiers to use.
+[[cashiers]]
+
+# Cashier name
+name = "cashier.dark.fi"
+
+# The RPC endpoint for a selected cashier
+rpc_url = "tcp://127.0.0.1:9000"
+#cashier_rpc_url = "tls://127.0.0.1:9000"
+
+# The selected cashier public key
+public_key = ""
+

+ 0 - 4
sql/schema.sql

@@ -16,7 +16,3 @@ CREATE TABLE IF NOT EXISTS coins(
    	secret BLOB NOT NULL,
 	is_spent BLOB NOT NULL
 );
-CREATE TABLE IF NOT EXISTS cashier(
-    key_id INTEGER PRIMARY KEY NOT NULL,
-    key_public BLOB NOT NULL
-);

+ 0 - 179
src/bin/build_tx.rs

@@ -1,179 +0,0 @@
-use drk::{
-    blockchain::{rocks::columns, Rocks, RocksColumn},
-    cli::{CashierdConfig, Config, DarkfidConfig},
-    client::State,
-    crypto::{
-        load_params, merkle::CommitmentTree, save_params, setup_mint_prover, setup_spend_prover,
-    },
-    state::state_transition,
-    tx,
-    util::{expand_path, join_config_path},
-    wallet::WalletDb,
-    Result,
-};
-
-use std::path::PathBuf;
-
-use async_std;
-use async_std::sync::{Arc, Mutex};
-use ff::Field;
-use rand::rngs::OsRng;
-
-#[async_std::main]
-async fn main() -> Result<()> {
-    let config: DarkfidConfig =
-        Config::<DarkfidConfig>::load(join_config_path(&PathBuf::from("darkfid.toml"))?)?;
-
-    let config_cashier: CashierdConfig =
-        Config::<CashierdConfig>::load(join_config_path(&PathBuf::from("cashierd.toml"))?)?;
-
-    let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
-
-    let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
-    let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
-
-    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");
-
-    let cashier_params_paths = (
-        expand_path(&config_cashier.mint_params_path.clone())?,
-        expand_path(&config_cashier.spend_params_path.clone())?,
-    );
-
-    let cashier_mint_params_path = &cashier_params_paths
-        .0
-        .to_str()
-        .unwrap_or("cash_mint.params");
-    let cashier_spend_params_path = &cashier_params_paths
-        .1
-        .to_str()
-        .unwrap_or("cash_spend.params");
-
-    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)?;
-    }
-
-    if !cashier_params_paths.0.exists() {
-        let params = setup_mint_prover();
-        save_params(cashier_mint_params_path, &params)?;
-    }
-    if !cashier_params_paths.1.exists() {
-        let params = setup_spend_prover();
-        save_params(cashier_spend_params_path, &params)?;
-    }
-
-    let cashier_wallet = WalletDb::new(
-        expand_path(&config_cashier.client_wallet_path.clone())?.as_path(),
-        config.wallet_password.clone(),
-    )?;
-
-    let wallet = WalletDb::new(
-        expand_path(&config.wallet_path.clone())?.as_path(),
-        config.wallet_password.clone(),
-    )?;
-
-    wallet.init_db().await?;
-
-    if wallet.get_keypairs()?.is_empty() {
-        wallet.key_gen()?;
-    }
-
-    cashier_wallet.init_db().await?;
-
-    if cashier_wallet.get_keypairs()?.is_empty() {
-        cashier_wallet.key_gen()?;
-    }
-
-    let user_main_keypair = wallet.get_keypairs()?[0].clone();
-
-    let cashier_main_keypair = cashier_wallet.get_keypairs()?[0].clone();
-
-    wallet.put_cashier_pub(&cashier_main_keypair.public)?;
-
-    // Load trusted setup parameters
-    let (_, mint_pvk) = load_params(mint_params_path)?;
-    let (_, spend_pvk) = load_params(spend_params_path)?;
-
-    // Load trusted setup parameters
-    let (cashier_mint_params, _) = load_params(cashier_mint_params_path)?;
-    let (cashier_spend_params, _) = load_params(cashier_spend_params_path)?;
-
-    //
-    //
-    //
-    // user's state
-    //
-    //
-    //
-    let state = Arc::new(Mutex::new(State {
-        tree: CommitmentTree::empty(),
-        merkle_roots,
-        nullifiers,
-        mint_pvk,
-        spend_pvk,
-        wallet,
-    }));
-
-    //
-    //
-    //
-    // cashier buid tx
-    //
-    //
-    //
-    let mut clear_inputs: Vec<tx::TransactionBuilderClearInputInfo> = vec![];
-    let inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
-    let mut outputs: Vec<tx::TransactionBuilderOutputInfo> = vec![];
-
-    let token_id = jubjub::Fr::random(&mut OsRng);
-    let value = 10;
-
-    let signature_secret = cashier_main_keypair.private;
-    let input = tx::TransactionBuilderClearInputInfo {
-        value,
-        token_id,
-        signature_secret,
-    };
-
-    clear_inputs.push(input);
-
-    outputs.push(tx::TransactionBuilderOutputInfo {
-        value,
-        token_id,
-        public: user_main_keypair.public,
-    });
-
-    let builder = tx::TransactionBuilder {
-        clear_inputs,
-        inputs,
-        outputs,
-    };
-
-    let tx = builder.build(&cashier_mint_params, &cashier_spend_params);
-
-    //
-    //
-    //
-    // user get the tx
-    //
-    //
-    //
-    let state = state.lock().await;
-    let update = state_transition(&state, tx);
-
-    if let Err(e) = update {
-        println!("state transition error: {}", e.to_string());
-    }
-
-    Ok(())
-}

+ 50 - 16
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 clap::clap_app;
 use ff::Field;
@@ -6,14 +6,17 @@ use log::debug;
 use rand::rngs::OsRng;
 use serde_json::{json, Value};
 use std::collections::HashMap;
+use std::iter::FromIterator;
 use std::path::PathBuf;
 use std::str::FromStr;
-use std::iter::FromIterator;
 
 use drk::{
-    blockchain::Rocks,
+    blockchain::{rocks::columns, Rocks, RocksColumn},
     cli::{CashierdConfig, Config},
-    client::Client,
+    client::{Client, State},
+    crypto::{
+        load_params, merkle::CommitmentTree, save_params, setup_mint_prover, setup_spend_prover,
+    },
     rpc::{
         jsonrpc::{error as jsonerr, response as jsonresp},
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
@@ -452,6 +455,7 @@ impl Cashierd {
     async fn start(
         &mut self,
         mut client: Client,
+        state: Arc<Mutex<State>>,
     ) -> Result<(
         smol::Task<Result<()>>,
         smol::Task<Result<()>>,
@@ -543,7 +547,7 @@ impl Cashierd {
         let (notify, recv_coin) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
 
         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?;
 
         let cashier_wallet = self.cashier_wallet.clone();
@@ -624,25 +628,55 @@ async fn main() -> Result<()> {
 
     let rocks = Rocks::new(expand_path(&cashierd.config.database_path.clone())?.as_path())?;
 
+    // this is just an empty vector
+    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(
-        rocks,
+        rocks.clone(),
         (
             cashierd.config.gateway_protocol_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(),
+        mint_params,
+        spend_params,
     )
     .await?;
 
-    // must add cashier public key to the client wallet, which in this case it's the same
-    // as main_keypair
-    if client_wallet.get_cashier_public_keys()?.is_empty() {
-        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") {
         let cashier_public = client.main_keypair.public;
@@ -658,7 +692,7 @@ async fn main() -> Result<()> {
         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?;
 
     t1.cancel().await;

+ 106 - 57
src/bin/darkfid.rs

@@ -1,7 +1,10 @@
 use drk::{
-    blockchain::Rocks,
+    blockchain::{rocks::columns, Rocks, RocksColumn},
     cli::{Config, DarkfidConfig},
-    client::Client,
+    client::{Client, State},
+    crypto::{
+        load_params, merkle::CommitmentTree, save_params, setup_mint_prover, setup_spend_prover,
+    },
     rpc::{
         jsonrpc::{error as jsonerr, request as jsonreq, response as jsonresp, send_request},
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
@@ -26,11 +29,11 @@ use std::collections::HashMap;
 use std::path::PathBuf;
 use std::str::FromStr;
 
-struct Darkfid {
-    config: DarkfidConfig,
-    client: Arc<Mutex<Client>>,
-    sol_tokenlist: SolTokenList,
-    drk_tokenlist: DrkTokenList,
+#[derive(Clone, Debug)]
+pub struct Cashier {
+    pub name: String,
+    pub rpc_url: String,
+    pub public_key: jubjub::SubgroupPoint,
 }
 
 #[async_trait]
@@ -58,42 +61,33 @@ 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 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(),
-        )
-        .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 drk_tokenlist = DrkTokenList::new(sol_tokenlist.clone())?;
 
         Ok(Self {
-            config,
             client,
             sol_tokenlist,
             drk_tokenlist,
+            cashiers,
         })
     }
 
-    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.connect_to_subscriber().await?;
+        self.client
+            .lock()
+            .await
+            .connect_to_subscriber(state)
+            .await?;
 
         Ok(())
     }
@@ -217,7 +211,8 @@ impl Darkfid {
     async fn features(&self, id: Value, _params: Value) -> JsonResult {
         let req = jsonreq(json!("features"), json!([]));
         let rep: JsonResult;
-        match send_request(&self.config.cashier_rpc_url, json!(req)).await {
+        // TODO: this just selects the first cashier in the list
+        match send_request(&self.cashiers[0].rpc_url, json!(req)).await {
             Ok(v) => rep = v,
             Err(e) => {
                 return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id))
@@ -279,7 +274,7 @@ impl Darkfid {
         // If not, an error is returned, and forwarded to the method caller.
         let req = jsonreq(json!("deposit"), json!([network, token_id, pubkey]));
         let rep: JsonResult;
-        match send_request(&self.config.cashier_rpc_url, json!(req)).await {
+        match send_request(&self.cashiers[0].rpc_url, json!(req)).await {
             Ok(v) => rep = v,
             Err(e) => {
                 debug!(target: "DARKFID", "REQUEST IS ERR");
@@ -356,7 +351,7 @@ impl Darkfid {
             json!([network, token_id, address, amount_in_apo]),
         );
         let mut rep: JsonResult;
-        match send_request(&self.config.cashier_rpc_url, json!(req)).await {
+        match send_request(&self.cashiers[0].rpc_url, json!(req)).await {
             Ok(v) => rep = v,
             Err(e) => {
                 return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id));
@@ -484,11 +479,11 @@ async fn main() -> Result<()> {
     let args = clap_app!(darkfid =>
         (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
         (@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")
-        )
+        //(@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();
 
@@ -513,26 +508,80 @@ async fn main() -> Result<()> {
         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(());
-        }
-
-        if matches.is_present("SETCASHIERKEY") {
-            let cashier_public = matches.value_of("SETCASHIERKEY").unwrap();
+    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 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 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)?;
     }
 
-    let mut darkfid = Darkfid::new(config.clone(), wallet.clone()).await?;
+    // 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));
+
+    let mut darkfid = Darkfid::new(client, cashiers).await?;
+
+    let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
+    let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
+
+    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 {
         socket_addr: config.rpc_listen_address.clone(),
@@ -541,6 +590,6 @@ async fn main() -> Result<()> {
         identity_pass: config.tls_identity_password.clone(),
     };
 
-    darkfid.start().await?;
+    darkfid.start(state).await?;
     listen_and_serve(server_config, Arc::new(darkfid)).await
 }

+ 12 - 2
src/cli/cli_config.rs

@@ -48,6 +48,16 @@ pub struct DrkConfig {
     pub darkfid_rpc_url: String,
 }
 
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct Cashier {
+    /// Cashier name
+    pub name: String,
+    /// The RPC endpoint for a selected cashier
+    pub rpc_url: String,
+    /// The selected cashier public key
+    pub public_key: String,
+}
+
 /// The configuration for darkfid
 #[derive(Clone, Serialize, Deserialize, Debug)]
 pub struct DarkfidConfig {
@@ -59,8 +69,6 @@ pub struct DarkfidConfig {
     pub tls_identity_path: String,
     /// Password for the TLS identity. (Unused if serve_tls=false)
     pub tls_identity_password: String,
-    /// The RPC endpoint for a selected cashier
-    pub cashier_rpc_url: String,
     /// The endpoint to a gatewayd protocol API
     pub gateway_protocol_url: String,
     /// The endpoint to a gatewayd publisher API
@@ -75,6 +83,8 @@ pub struct DarkfidConfig {
     pub wallet_path: String,
     /// The wallet password
     pub wallet_password: String,
+    /// The configured cashiers to use
+    pub cashiers: Vec<Cashier>,
 }
 
 /// The configuration for gatewayd

+ 40 - 61
src/client.rs

@@ -5,17 +5,15 @@ use log::*;
 
 use std::collections::HashMap;
 use std::net::SocketAddr;
-use std::path::PathBuf;
 
 use crate::{
     blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
     crypto::{
-        load_params,
         merkle::{CommitmentTree, IncrementalWitness},
         merkle_node::MerkleNode,
         note::{EncryptedNote, Note},
         nullifier::Nullifier,
-        save_params, setup_mint_prover, setup_spend_prover, OwnCoin,
+        OwnCoin,
     },
     serial::{serialize, Decodable, Encodable},
     service::{GatewayClient, GatewaySlabsSubscriber},
@@ -41,10 +39,10 @@ pub enum ClientFailed {
 }
 
 pub struct Client {
-    pub state: Arc<Mutex<State>>,
     mint_params: bellman::groth16::Parameters<Bls12>,
     spend_params: bellman::groth16::Parameters<Bls12>,
     gateway: GatewayClient,
+    wallet: WalletPtr,
     pub main_keypair: Keypair,
 }
 
@@ -52,16 +50,10 @@ impl Client {
     pub async fn new(
         rocks: Arc<Rocks>,
         gateway_addrs: (SocketAddr, SocketAddr),
-        params_paths: (PathBuf, PathBuf),
         wallet: WalletPtr,
+        mint_params: bellman::groth16::Parameters<Bls12>,
+        spend_params: bellman::groth16::Parameters<Bls12>,
     ) -> 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");
-
         wallet.init_db().await?;
 
         if wallet.get_keypairs()?.is_empty() {
@@ -71,41 +63,20 @@ impl Client {
         let main_keypair = wallet.get_keypairs()?[0].clone();
 
         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,
-        }));
+        let slabstore = RocksColumn::<columns::Slabs>::new(rocks.clone());
 
         // create gateway client
         debug!(target: "CLIENT", "Creating GatewayClient");
         let gateway = GatewayClient::new(gateway_addrs.0, gateway_addrs.1, slabstore)?;
 
         Ok(Self {
-            state,
             mint_params,
             spend_params,
+            wallet,
             gateway,
             main_keypair,
         })
@@ -124,7 +95,7 @@ impl Client {
     ) -> ClientResult<()> {
         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 {
             self.send(pub_key, amount, token_id, false).await?;
@@ -222,13 +193,13 @@ impl Client {
         let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
         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() {
             if inputs_value >= amount {
                 break;
             }
-            self.state.lock().await.wallet.confirm_spend_coin(coin_id)?;
+            self.wallet.confirm_spend_coin(coin_id)?;
             let witness = &own_coin.witness;
             let merkle_path = witness.path().unwrap();
             inputs_value += own_coin.note.value;
@@ -262,6 +233,7 @@ impl Client {
 
     pub async fn connect_to_subscriber_from_cashier(
         &self,
+        state: Arc<Mutex<State>>,
         cashier_wallet: CashierDbPtr,
         notify: async_channel::Sender<(jubjub::SubgroupPoint, u64)>,
     ) -> Result<()> {
@@ -270,7 +242,7 @@ impl Client {
         let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
 
         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 {
             loop {
@@ -300,7 +272,12 @@ impl Client {
                 secret_keys.append(&mut withdraw_keys);
 
                 let state_apply = state
-                    .apply(update?, secret_keys.clone(), Some(notify.clone()))
+                    .apply(
+                        update?,
+                        secret_keys.clone(),
+                        Some(notify.clone()),
+                        wallet.clone(),
+                    )
                     .await;
 
                 if let Err(e) = state_apply {
@@ -315,13 +292,13 @@ impl Client {
         Ok(())
     }
 
-    pub async fn connect_to_subscriber(&self) -> Result<()> {
+    pub async fn connect_to_subscriber(&self, state: Arc<Mutex<State>>) -> Result<()> {
         // start subscribing
         debug!(target: "CLIENT", "Start subscriber");
         let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
 
         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 {
             loop {
@@ -349,7 +326,9 @@ impl Client {
 
                 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 {
                     warn!("apply state: {}", e.to_string());
@@ -364,23 +343,23 @@ impl Client {
     }
 
     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<()> {
-        self.state.lock().await.wallet.key_gen()
+        self.wallet.key_gen()
     }
 
     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> {
-        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>> {
-        self.state.lock().await.wallet.get_token_id()
+        self.wallet.get_token_id()
     }
 }
 
@@ -396,21 +375,20 @@ pub struct State {
     pub mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
     // Spend verifying key used by ZK
     pub spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
-    pub wallet: WalletPtr,
+    // List of cashier public keys
+    pub public_keys: Vec<jubjub::SubgroupPoint>,
 }
 
 impl ProgramState for State {
     fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool {
         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);
+        if self.public_keys.is_empty() {
+            error!(target: "State", "No cashier public key");
+            return false;
+        } else {
+            return self.public_keys.contains(public);
         }
-        false
     }
 
     fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
@@ -447,6 +425,7 @@ impl State {
         update: StateUpdate,
         secret_keys: Vec<jubjub::Fr>,
         notify: Option<async_channel::Sender<(jubjub::SubgroupPoint, u64)>>,
+        wallet: WalletPtr,
     ) -> Result<()> {
         // Extend our list of nullifiers with the ones from the update
 
@@ -470,9 +449,9 @@ impl State {
             debug!(target: "CLIENT STATE", "Update witness");
 
             // 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");
-                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");
@@ -498,7 +477,7 @@ impl State {
                         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;
 
                     debug!(target: "CLIENT STATE", "Received a coin: amount {} ", note.value);

+ 13 - 34
src/wallet/walletdb.rs

@@ -303,24 +303,24 @@ impl WalletDb {
         Ok(())
     }
 
-    pub fn get_cashier_public_keys(&self) -> Result<Vec<jubjub::SubgroupPoint>> {
-        debug!(target: "WALLETDB", "Returning Cashier Public key...");
-        let conn = Connection::open(&self.path)?;
-        conn.pragma_update(None, "key", &self.password)?;
+    //pub fn get_cashier_public_keys(&self) -> Result<Vec<jubjub::SubgroupPoint>> {
+    //    debug!(target: "WALLETDB", "Returning Cashier Public key...");
+    //    let conn = Connection::open(&self.path)?;
+    //    conn.pragma_update(None, "key", &self.password)?;
 
-        let mut stmt = conn.prepare("SELECT key_public FROM cashier")?;
+    //    let mut stmt = conn.prepare("SELECT key_public FROM cashier")?;
 
-        let key_iter = stmt.query_map([], |row| row.get(0))?;
+    //    let key_iter = stmt.query_map([], |row| row.get(0))?;
 
-        let mut pub_keys = Vec::new();
+    //    let mut pub_keys = Vec::new();
 
-        for key in key_iter {
-            let public: jubjub::SubgroupPoint = self.get_value_deserialized(&key?)?;
-            pub_keys.push(public);
-        }
+    //    for key in key_iter {
+    //        let public: jubjub::SubgroupPoint = self.get_value_deserialized(&key?)?;
+    //        pub_keys.push(public);
+    //    }
 
-        Ok(pub_keys)
-    }
+    //    Ok(pub_keys)
+    //}
 
     pub fn get_balances(&self) -> Result<HashMap<Vec<u8>, u64>> {
         debug!(target: "WALLETDB", "Get token and balances...");
@@ -675,25 +675,4 @@ mod tests {
         Ok(())
     }
 
-    #[test]
-    pub fn test_put_and_get_cashier_public_key() -> Result<()> {
-        let walletdb_path = join_config_path(&PathBuf::from("test6_wallet.db"))?;
-        let password: String = "darkfi".into();
-        let wallet = WalletDb::new(&walletdb_path, password.clone())?;
-        init_db(&walletdb_path, password)?;
-
-        let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
-        let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
-
-        wallet.put_cashier_pub(&public)?;
-        let cashier_public = wallet.get_cashier_public_keys()?[0];
-
-        assert_eq!(cashier_public, public);
-
-        assert_eq!(wallet.get_cashier_public_keys()?.contains(&public), true);
-
-        std::fs::remove_file(walletdb_path)?;
-
-        Ok(())
-    }
 }