main.rs 26 KB

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