main.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. use std::{path::PathBuf, str::FromStr};
  2. use async_executor::Executor;
  3. use async_std::sync::{Arc, Mutex};
  4. use async_trait::async_trait;
  5. use clap::{IntoApp, Parser};
  6. use easy_parallel::Parallel;
  7. use log::{debug, info};
  8. use rand::rngs::OsRng;
  9. use serde_json::{json, Value};
  10. use simplelog::{ColorChoice, LevelFilter, TermLogger, TerminalMode};
  11. use darkfi::{
  12. chain::{rocks::columns, Rocks, RocksColumn},
  13. cli::{CashierdConfig, CliCashierd, Config},
  14. crypto::{
  15. keypair::{PublicKey, SecretKey},
  16. proof::VerifyingKey,
  17. },
  18. node::{
  19. client::Client,
  20. state::State,
  21. wallet::{cashierdb::CashierDb, walletdb::WalletDb},
  22. },
  23. serial::serialize,
  24. types::DrkTokenId,
  25. util::{
  26. expand_path, generate_id2, join_config_path,
  27. parse::truncate,
  28. rpc::{
  29. jsonrpc::{
  30. error as jsonerr, response as jsonresp, ErrorCode::*, JsonRequest, JsonResult,
  31. },
  32. rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
  33. },
  34. Address, NetworkName,
  35. },
  36. zk::circuit::{MintContract, SpendContract},
  37. Error, Result,
  38. };
  39. use cashier::service::{bridge, bridge::Bridge};
  40. fn handle_bridge_error(error_code: u32) -> Result<()> {
  41. match error_code {
  42. 1 => Err(Error::CashierError("Not Supported Client".into())),
  43. 2 => Err(Error::CashierError("Unable to watch the deposit address".into())),
  44. 3 => Err(Error::CashierError("Unable to send the token".into())),
  45. _ => Err(Error::CashierError("Unknown error_code".into())),
  46. }
  47. }
  48. #[derive(Clone, Debug)]
  49. pub struct Network {
  50. pub name: NetworkName,
  51. pub blockchain: String,
  52. pub keypair: String,
  53. }
  54. struct Cashierd {
  55. bridge: Arc<Bridge>,
  56. cashier_wallet: Arc<CashierDb>,
  57. networks: Vec<Network>,
  58. public_key: Address,
  59. config: CashierdConfig,
  60. }
  61. #[async_trait]
  62. impl RequestHandler for Cashierd {
  63. async fn handle_request(&self, req: JsonRequest, executor: Arc<Executor<'_>>) -> JsonResult {
  64. if req.params.as_array().is_none() {
  65. return JsonResult::Err(jsonerr(InvalidParams, None, req.id))
  66. }
  67. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  68. match req.method.as_str() {
  69. Some("deposit") => return self.deposit(req.id, req.params, executor).await,
  70. Some("withdraw") => return self.withdraw(req.id, req.params).await,
  71. Some("features") => return self.features(req.id, req.params).await,
  72. Some(_) => {}
  73. None => {}
  74. };
  75. return JsonResult::Err(jsonerr(MethodNotFound, None, req.id))
  76. }
  77. }
  78. impl Cashierd {
  79. async fn new(config: CashierdConfig, public_key: Address) -> Result<Self> {
  80. debug!(target: "CASHIER DAEMON", "Initialize");
  81. let wallet_path =
  82. format!("sqlite://{}", expand_path(&config.cashier_wallet_path)?.to_str().unwrap());
  83. let cashier_wallet = CashierDb::new(&wallet_path, &config.cashier_wallet_password).await?;
  84. let mut networks = Vec::new();
  85. for network in config.clone().networks {
  86. networks.push(Network {
  87. name: NetworkName::from_str(&network.name)?,
  88. blockchain: network.blockchain,
  89. keypair: network.keypair,
  90. });
  91. }
  92. let bridge = bridge::Bridge::new();
  93. Ok(Self { bridge, cashier_wallet, networks, public_key, config })
  94. }
  95. async fn start(
  96. &mut self,
  97. mut client: Client,
  98. state: Arc<Mutex<State>>,
  99. executor: Arc<Executor<'_>>,
  100. ) -> Result<(smol::Task<Result<()>>, smol::Task<Result<()>>)> {
  101. self.cashier_wallet.init_db().await?;
  102. for network in self.networks.iter() {
  103. match network.name {
  104. #[cfg(feature = "sol")]
  105. NetworkName::Solana => {
  106. debug!(target: "CASHIER DAEMON", "Adding solana network");
  107. use cashier::service::SolClient;
  108. let _bridge = self.bridge.clone();
  109. let sol_client = SolClient::new(
  110. self.cashier_wallet.clone(),
  111. &network.blockchain,
  112. &network.keypair,
  113. )
  114. .await?;
  115. _bridge.add_clients(NetworkName::Solana, sol_client).await?;
  116. }
  117. #[cfg(feature = "eth")]
  118. NetworkName::Ethereum => {
  119. debug!(target: "CASHIER DAEMON", "Adding ethereum network");
  120. use cashier::service::EthClient;
  121. let _bridge = self.bridge.clone();
  122. let passphrase = self.config.geth_passphrase.clone();
  123. let mut eth_client = EthClient::new(
  124. &network.blockchain,
  125. expand_path(&self.config.geth_socket)?.to_str().unwrap(),
  126. &passphrase,
  127. );
  128. eth_client.setup_keypair(self.cashier_wallet.clone(), &network.keypair).await?;
  129. _bridge.add_clients(NetworkName::Ethereum, Arc::new(eth_client)).await?;
  130. }
  131. #[cfg(feature = "btc")]
  132. NetworkName::Bitcoin => {
  133. debug!(target: "CASHIER DAEMON", "Adding bitcoin network");
  134. use cashier::service::btc::BtcClient;
  135. let _bridge = self.bridge.clone();
  136. let btc_client = BtcClient::new(
  137. self.cashier_wallet.clone(),
  138. &network.blockchain,
  139. &network.keypair,
  140. )
  141. .await?;
  142. _bridge.add_clients(NetworkName::Bitcoin, btc_client).await?;
  143. }
  144. _ => {}
  145. }
  146. }
  147. client.start().await?;
  148. let (notify, recv_coin) = async_channel::unbounded::<(PublicKey, u64)>();
  149. client
  150. .connect_to_subscriber_from_cashier(
  151. state.clone(),
  152. self.cashier_wallet.clone(),
  153. notify.clone(),
  154. executor.clone(),
  155. )
  156. .await?;
  157. let cashier_wallet = self.cashier_wallet.clone();
  158. let bridge = self.bridge.clone();
  159. let ex = executor.clone();
  160. let listen_for_receiving_coins_task: smol::Task<Result<()>> = executor.spawn(async move {
  161. let ex2 = ex.clone();
  162. loop {
  163. Self::listen_for_receiving_coins(
  164. bridge.clone(),
  165. cashier_wallet.clone(),
  166. recv_coin.clone(),
  167. ex2.clone(),
  168. )
  169. .await?;
  170. }
  171. });
  172. let bridge2 = self.bridge.clone();
  173. let listen_for_notification_from_bridge_task: smol::Task<Result<()>> =
  174. executor.spawn(async move {
  175. while let Some(token_notification) = bridge2.clone().listen().await {
  176. debug!(target: "CASHIER DAEMON", "Received notification from bridge");
  177. let token_notification = token_notification?;
  178. let received_balance = truncate(
  179. token_notification.received_balance,
  180. 8,
  181. token_notification.decimals,
  182. )?;
  183. client
  184. .send(
  185. token_notification.drk_pub_key,
  186. received_balance,
  187. token_notification.token_id,
  188. true,
  189. state.clone(),
  190. )
  191. .await?;
  192. }
  193. Ok(())
  194. });
  195. Ok((listen_for_receiving_coins_task, listen_for_notification_from_bridge_task))
  196. }
  197. async fn listen_for_receiving_coins(
  198. bridge: Arc<Bridge>,
  199. cashier_wallet: Arc<CashierDb>,
  200. recv_coin: async_channel::Receiver<(PublicKey, u64)>,
  201. executor: Arc<Executor<'_>>,
  202. ) -> Result<()> {
  203. // received drk coin
  204. let (drk_pub_key, amount) = recv_coin.recv().await?;
  205. debug!(target: "CASHIER DAEMON", "Receive coin with amount: {}", amount);
  206. // get public key, and token_id of the token
  207. let token =
  208. cashier_wallet.get_withdraw_token_public_key_by_dkey_public(&drk_pub_key).await?;
  209. // send a request to bridge to send equivalent amount of
  210. // received drk coin to token publickey
  211. if let Some(withdraw_token) = token {
  212. let bridge_subscribtion = bridge
  213. .subscribe(drk_pub_key, Some(withdraw_token.mint_address), executor.clone())
  214. .await;
  215. // send a request to the bridge to send amount of token
  216. // equivalent to the received drk
  217. bridge_subscribtion
  218. .sender
  219. .send(bridge::BridgeRequests {
  220. network: withdraw_token.network.clone(),
  221. payload: bridge::BridgeRequestsPayload::Send(
  222. withdraw_token.token_public_key.clone(),
  223. amount,
  224. ),
  225. })
  226. .await?;
  227. // receive a response
  228. let res = bridge_subscribtion.receiver.recv().await?;
  229. // check the response's error
  230. let error_code = res.error as u32;
  231. if error_code != 0 {
  232. return handle_bridge_error(error_code)
  233. }
  234. match res.payload {
  235. bridge::BridgeResponsePayload::Send => {
  236. cashier_wallet
  237. .confirm_withdraw_key_record(
  238. &withdraw_token.token_public_key,
  239. &withdraw_token.network,
  240. )
  241. .await?;
  242. }
  243. _ => {
  244. return Err(Error::CashierError(
  245. "Receive unknown value from Subscription".into(),
  246. ))
  247. }
  248. }
  249. }
  250. Ok(())
  251. }
  252. fn check_token_id(network: &NetworkName, _token_id: &str) -> Result<Option<String>> {
  253. match network {
  254. #[cfg(feature = "sol")]
  255. NetworkName::Solana => {
  256. use cashier::service::sol::SOL_NATIVE_TOKEN_ID;
  257. if _token_id != SOL_NATIVE_TOKEN_ID {
  258. return Ok(Some(_token_id.to_string()))
  259. }
  260. Ok(None)
  261. }
  262. #[cfg(feature = "eth")]
  263. NetworkName::Ethereum => {
  264. use cashier::service::eth::ETH_NATIVE_TOKEN_ID;
  265. if _token_id != ETH_NATIVE_TOKEN_ID {
  266. return Ok(Some(_token_id.to_string()))
  267. }
  268. Ok(None)
  269. }
  270. #[cfg(feature = "btc")]
  271. NetworkName::Bitcoin => Ok(None),
  272. _ => Err(Error::NotSupportedNetwork),
  273. }
  274. }
  275. async fn deposit(&self, id: Value, params: Value, executor: Arc<Executor<'_>>) -> JsonResult {
  276. info!(target: "CASHIER DAEMON", "Received deposit request");
  277. let args: &Vec<serde_json::Value> = params.as_array().unwrap();
  278. if args.len() != 3 {
  279. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  280. }
  281. let network: NetworkName;
  282. let mut mint_address: &str;
  283. let drk_pub_key: &str;
  284. match (args[0].as_str(), args[1].as_str(), args[2].as_str()) {
  285. (Some(n), Some(m), Some(d)) => {
  286. if NetworkName::from_str(n).is_err() {
  287. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  288. }
  289. network = NetworkName::from_str(n).unwrap();
  290. mint_address = m;
  291. drk_pub_key = d;
  292. }
  293. (None, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  294. (_, None, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  295. (_, _, None) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  296. }
  297. // Check if the features list contains this network
  298. if !self.networks.iter().any(|net| net.name == network) {
  299. return JsonResult::Err(jsonerr(
  300. InvalidParams,
  301. Some(format!("Cashier doesn't support this network: {}", network)),
  302. id,
  303. ))
  304. }
  305. let result: Result<String> = async {
  306. let token_id = generate_id2(mint_address, &network)?;
  307. let mint_address_opt = Self::check_token_id(&network, mint_address)?;
  308. if mint_address_opt.is_none() {
  309. mint_address = "";
  310. }
  311. let drk_pub_key = Address::from_str(drk_pub_key)?;
  312. let drk_pub_key: PublicKey = PublicKey::try_from(drk_pub_key)?;
  313. // check if the drk public key already exist
  314. let check = self
  315. .cashier_wallet
  316. .get_deposit_token_keys_by_dkey_public(&drk_pub_key, &network)
  317. .await?;
  318. // start new subscription from the bridge and then cashierd will
  319. // send a request to the bridge to generate keypair for the desired token
  320. // and start watch this token's keypair
  321. // once a bridge receive an update for this token's address
  322. // cashierd will get notification from bridge.listen() function
  323. //
  324. // The "if statement" check from the cashierdb if the node's drk_pub_key already exist
  325. // in this case it will not generate new keypair but it will
  326. // retrieve the old generated keypair
  327. //
  328. // Once receive a response from the bridge, the cashierd then save a deposit
  329. // record in cashierdb with the network name and token id
  330. let bridge = self.bridge.clone();
  331. let bridge_subscribtion =
  332. bridge.subscribe(drk_pub_key, mint_address_opt, executor).await;
  333. if check.is_empty() {
  334. bridge_subscribtion
  335. .sender
  336. .send(bridge::BridgeRequests {
  337. network: network.clone(),
  338. payload: bridge::BridgeRequestsPayload::Watch(None),
  339. })
  340. .await?;
  341. } else {
  342. let keypair = check[0].clone();
  343. bridge_subscribtion
  344. .sender
  345. .send(bridge::BridgeRequests {
  346. network: network.clone(),
  347. payload: bridge::BridgeRequestsPayload::Watch(Some(keypair)),
  348. })
  349. .await?;
  350. }
  351. let bridge_res = bridge_subscribtion.receiver.recv().await?;
  352. let error_code = bridge_res.error as u32;
  353. if error_code != 0 {
  354. return handle_bridge_error(error_code).map(|_| String::new())
  355. }
  356. match bridge_res.payload {
  357. bridge::BridgeResponsePayload::Watch(token_key) => {
  358. // add pairings to db
  359. self.cashier_wallet
  360. .put_deposit_keys(
  361. &drk_pub_key,
  362. &token_key.private_key,
  363. &serialize(&token_key.public_key),
  364. &network,
  365. &token_id,
  366. mint_address.into(),
  367. )
  368. .await?;
  369. Ok(token_key.public_key)
  370. }
  371. bridge::BridgeResponsePayload::Address(token_pub) => Ok(token_pub),
  372. _ => Err(Error::CashierError("Receive unknown value from Subscription".into())),
  373. }
  374. }
  375. .await;
  376. match result {
  377. Ok(res) => JsonResult::Resp(jsonresp(json!(res), json!(id))),
  378. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  379. }
  380. }
  381. async fn withdraw(&self, id: Value, params: Value) -> JsonResult {
  382. info!(target: "CASHIER DAEMON", "Received withdraw request");
  383. let args: &Vec<serde_json::Value> = params.as_array().unwrap();
  384. if args.len() != 4 {
  385. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  386. }
  387. let network: NetworkName;
  388. let mut mint_address: &str;
  389. let address: &str;
  390. match (args[0].as_str(), args[1].as_str(), args[2].as_str()) {
  391. (Some(n), Some(m), Some(a)) => {
  392. if NetworkName::from_str(n).is_err() {
  393. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  394. }
  395. network = NetworkName::from_str(n).unwrap();
  396. mint_address = m;
  397. address = a;
  398. }
  399. (None, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  400. (_, None, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  401. (_, _, None) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  402. }
  403. // Check if the features list contains this network
  404. if !self.networks.iter().any(|net| net.name == network) {
  405. return JsonResult::Err(jsonerr(
  406. InvalidParams,
  407. Some(format!("Cashier doesn't support this network: {}", network)),
  408. id,
  409. ))
  410. }
  411. let result: Result<String> = async {
  412. let token_id: DrkTokenId = generate_id2(mint_address, &network)?;
  413. let mint_address_opt = Self::check_token_id(&network, mint_address)?;
  414. if mint_address_opt.is_none() {
  415. // empty string
  416. mint_address = "";
  417. }
  418. let address = serialize(&address.to_string());
  419. let cashier_public: PublicKey;
  420. if let Some(addr) = self
  421. .cashier_wallet
  422. .get_withdraw_keys_by_token_public_key(&address, &network)
  423. .await?
  424. {
  425. cashier_public = addr.public;
  426. } else {
  427. let cashier_secret = SecretKey::random(&mut OsRng);
  428. cashier_public = PublicKey::from_secret(cashier_secret);
  429. self.cashier_wallet
  430. .put_withdraw_keys(
  431. &address,
  432. &cashier_public,
  433. &cashier_secret,
  434. &network,
  435. &token_id,
  436. mint_address.into(),
  437. )
  438. .await?;
  439. }
  440. let cashier_public_str = Address::from(cashier_public).to_string();
  441. Ok(cashier_public_str)
  442. }
  443. .await;
  444. match result {
  445. Ok(res) => JsonResult::Resp(jsonresp(json!(res), json!(id))),
  446. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  447. }
  448. }
  449. async fn features(&self, id: Value, _params: Value) -> JsonResult {
  450. let tcp_port: Option<u16>;
  451. let tls_port: Option<u16>;
  452. let onionaddr: Option<String>;
  453. let dnsaddr: Option<String>;
  454. if self.config.serve_tls {
  455. tls_port = Some(self.config.rpc_listen_address.port());
  456. tcp_port = None;
  457. } else {
  458. tcp_port = Some(self.config.rpc_listen_address.port());
  459. tls_port = None;
  460. }
  461. if self.config.dns_addr.ends_with(".onion") {
  462. onionaddr = Some(self.config.dns_addr.clone());
  463. dnsaddr = None;
  464. } else {
  465. dnsaddr = Some(self.config.dns_addr.clone());
  466. onionaddr = None;
  467. }
  468. let mut resp: serde_json::Value = json!(
  469. {
  470. "server_version": env!("CARGO_PKG_VERSION"),
  471. "protocol_version": "1.0",
  472. "public_key": self.public_key.to_string(),
  473. "networks": [],
  474. "hosts": {
  475. "tcp_port": tcp_port,
  476. "tls_port": tls_port,
  477. "onion_addr": onionaddr,
  478. "dns_addr": dnsaddr,
  479. }
  480. }
  481. );
  482. for network in self.networks.iter() {
  483. resp.as_object_mut().unwrap()["networks"].as_array_mut().unwrap().push(json!(
  484. {
  485. network.name.to_string().to_lowercase():
  486. {"chain": network.blockchain.to_lowercase()}
  487. }
  488. ));
  489. }
  490. JsonResult::Resp(jsonresp(resp, id))
  491. }
  492. }
  493. async fn start(
  494. executor: Arc<Executor<'_>>,
  495. config: &CashierdConfig,
  496. get_address_flag: bool,
  497. ) -> Result<()> {
  498. let client_wallet_path =
  499. format!("sqlite://{}", expand_path(&config.client_wallet_path)?.to_str().unwrap());
  500. let client_wallet = WalletDb::new(&client_wallet_path, &config.client_wallet_password).await?;
  501. let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
  502. info!("Building verifying key for the mint contract...");
  503. let mint_vk = VerifyingKey::build(11, MintContract::default());
  504. info!("Building verifying key for the spend contract...");
  505. let spend_vk = VerifyingKey::build(11, SpendContract::default());
  506. // new Client
  507. let gateway_urls =
  508. (config.gateway_protocol_url.parse()?, config.gateway_publisher_url.parse()?);
  509. let client = Client::new(rocks.clone(), gateway_urls, client_wallet.clone()).await?;
  510. let tree = client.get_tree().await?;
  511. let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
  512. let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
  513. // get cashier public key
  514. let cashier_public = client.main_keypair.public;
  515. // new Cashier daemon
  516. let mut cashierd = Cashierd::new(config.clone(), Address::from(cashier_public)).await?;
  517. // this will print the cashier public key and exit
  518. if get_address_flag {
  519. info!("Public Key: {}", cashierd.public_key);
  520. return Ok(())
  521. };
  522. // new State
  523. let public_keys = vec![cashier_public];
  524. let state = Arc::new(Mutex::new(State {
  525. tree,
  526. merkle_roots,
  527. nullifiers,
  528. public_keys,
  529. mint_vk,
  530. spend_vk,
  531. }));
  532. // start cashier
  533. let (t1, t2) = cashierd.start(client, state, executor.clone()).await?;
  534. // config for rpc
  535. let cfg = RpcServerConfig {
  536. socket_addr: config.rpc_listen_address,
  537. use_tls: config.serve_tls,
  538. identity_path: expand_path(&config.clone().tls_identity_path)?,
  539. identity_pass: config.tls_identity_password.clone(),
  540. };
  541. // listen and serve RPC
  542. listen_and_serve(cfg, Arc::new(cashierd), executor).await?;
  543. t1.cancel().await;
  544. t2.cancel().await;
  545. Ok(())
  546. }
  547. #[async_std::main]
  548. async fn main() -> Result<()> {
  549. let args = CliCashierd::parse();
  550. let matches = CliCashierd::into_app().get_matches();
  551. let config_path = if args.config.is_some() {
  552. expand_path(&args.config.unwrap())?
  553. } else {
  554. join_config_path(&PathBuf::from("cashierd.toml"))?
  555. };
  556. let mut verbosity_level = 0;
  557. verbosity_level += matches.occurrences_of("verbose");
  558. let loglevel = match verbosity_level {
  559. 0 => LevelFilter::Info,
  560. 1 => LevelFilter::Debug,
  561. _ => LevelFilter::Trace,
  562. };
  563. TermLogger::init(
  564. loglevel,
  565. simplelog::Config::default(),
  566. TerminalMode::Mixed,
  567. ColorChoice::Auto,
  568. )?;
  569. let config: CashierdConfig = Config::<CashierdConfig>::load(config_path)?;
  570. if args.refresh {
  571. info!(target: "CASHIER DAEMON", "Refresh the wallet and the database");
  572. // refresh cashier's client wallet
  573. let client_wallet_path =
  574. format!("sqlite://{}", expand_path(&config.client_wallet_path)?.to_str().unwrap());
  575. let client_wallet =
  576. WalletDb::new(&client_wallet_path, &config.client_wallet_password).await?;
  577. client_wallet.remove_own_coins().await?;
  578. // refresh cashier wallet
  579. let wallet_path =
  580. format!("sqlite://{}", expand_path(&config.cashier_wallet_path)?.to_str().unwrap());
  581. let wallet = CashierDb::new(&wallet_path, &config.cashier_wallet_password).await?;
  582. wallet.remove_withdraw_and_deposit_keys().await?;
  583. // refresh rocks database
  584. if let Some(path) = expand_path(&config.database_path)?.to_str() {
  585. info!(target: "CASHIER DAEMON", "Remove database: {}", path);
  586. std::fs::remove_dir_all(path)?;
  587. }
  588. info!("Wallet updated successfully.");
  589. return Ok(())
  590. }
  591. let get_address_flag = args.address;
  592. let ex = Arc::new(Executor::new());
  593. let (signal, shutdown) = async_channel::unbounded::<()>();
  594. let ex2 = ex.clone();
  595. let nthreads = num_cpus::get();
  596. debug!(target: "CASHIER DAEMON", "Run {} executor threads", nthreads);
  597. let (_, result) = Parallel::new()
  598. .each(0..nthreads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  599. // Run the main future on the current thread.
  600. .finish(|| {
  601. smol::future::block_on(async move {
  602. start(ex2, &config, get_address_flag).await?;
  603. drop(signal);
  604. Ok::<(), darkfi::Error>(())
  605. })
  606. });
  607. result
  608. }