main.rs 26 KB

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