main.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. use std::{collections::HashMap, 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 num_bigint::BigUint;
  9. use serde_json::{json, Value};
  10. use simplelog::{ColorChoice, LevelFilter, TermLogger, TerminalMode};
  11. use url::Url;
  12. use darkfi::{
  13. blockchain::{rocks::columns, Rocks, RocksColumn},
  14. cli::{cli_config::spawn_config, CliDarkfid, Config, DarkfidConfig},
  15. crypto::{
  16. address::Address,
  17. keypair::{Keypair, PublicKey, SecretKey},
  18. proof::VerifyingKey,
  19. token_list::{assign_id, DrkTokenList, TokenList},
  20. types::DrkTokenId,
  21. },
  22. node::{
  23. client::Client,
  24. state::{ProgramState, State},
  25. wallet::walletdb::WalletDb,
  26. },
  27. rpc::{
  28. jsonrpc::{
  29. error as jsonerr, request as jsonreq, response as jsonresp, send_request, ErrorCode::*,
  30. JsonRequest, JsonResult,
  31. },
  32. rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
  33. },
  34. util::{decode_base10, encode_base10, expand_path, join_config_path, NetworkName},
  35. zk::circuit::{MintContract, SpendContract},
  36. Error, Result,
  37. };
  38. const CONFIG_FILE_CONTENTS: &[u8] = include_bytes!("../darkfid_config.toml");
  39. pub const ETH_NATIVE_TOKEN_ID: &str = "0x0000000000000000000000000000000000000000";
  40. #[derive(Clone, Debug)]
  41. pub struct Cashier {
  42. pub name: String,
  43. pub rpc_url: String,
  44. pub public_key: PublicKey,
  45. }
  46. struct Darkfid {
  47. client: Arc<Mutex<Client>>,
  48. state: Arc<Mutex<State>>,
  49. sol_tokenlist: TokenList,
  50. eth_tokenlist: TokenList,
  51. btc_tokenlist: TokenList,
  52. drk_tokenlist: DrkTokenList,
  53. cashiers: Vec<Cashier>,
  54. }
  55. #[async_trait]
  56. impl RequestHandler for Darkfid {
  57. async fn handle_request(&self, req: JsonRequest, _executor: Arc<Executor<'_>>) -> JsonResult {
  58. if req.params.as_array().is_none() {
  59. return JsonResult::Err(jsonerr(InvalidParams, None, req.id))
  60. }
  61. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  62. if self.update_balances().await.is_err() {
  63. return JsonResult::Err(jsonerr(
  64. InternalError,
  65. Some("Unable to update balances".into()),
  66. req.id,
  67. ))
  68. }
  69. match req.method.as_str() {
  70. Some("say_hello") => return self.say_hello(req.id, req.params).await,
  71. Some("create_wallet") => return self.create_wallet(req.id, req.params).await,
  72. Some("key_gen") => return self.key_gen(req.id, req.params).await,
  73. Some("get_key") => return self.get_key(req.id, req.params).await,
  74. Some("get_keys") => return self.get_keys(req.id, req.params).await,
  75. Some("export_keypair") => return self.export_keypair(req.id, req.params).await,
  76. Some("import_keypair") => return self.import_keypair(req.id, req.params).await,
  77. Some("set_default_address") => {
  78. return self.set_default_address(req.id, req.params).await
  79. }
  80. Some("get_balances") => return self.get_balances(req.id, req.params).await,
  81. Some("get_token_id") => return self.get_token_id(req.id, req.params).await,
  82. Some("features") => return self.features(req.id, req.params).await,
  83. Some("deposit") => return self.deposit(req.id, req.params).await,
  84. Some("withdraw") => return self.withdraw(req.id, req.params).await,
  85. Some("transfer") => return self.transfer(req.id, req.params).await,
  86. Some(_) | None => return JsonResult::Err(jsonerr(MethodNotFound, None, req.id)),
  87. };
  88. }
  89. }
  90. impl Darkfid {
  91. async fn new(
  92. client: Arc<Mutex<Client>>,
  93. state: Arc<Mutex<State>>,
  94. cashiers: Vec<Cashier>,
  95. ) -> Result<Self> {
  96. let sol_tokenlist =
  97. TokenList::new(include_bytes!("../../../contrib/token/solana_token_list.json"))?;
  98. let eth_tokenlist =
  99. TokenList::new(include_bytes!("../../../contrib/token/erc20_token_list.json"))?;
  100. let btc_tokenlist =
  101. TokenList::new(include_bytes!("../../../contrib/token/bitcoin_token_list.json"))?;
  102. let drk_tokenlist = DrkTokenList::new(&sol_tokenlist, &eth_tokenlist, &btc_tokenlist)?;
  103. Ok(Self {
  104. client,
  105. state,
  106. sol_tokenlist,
  107. eth_tokenlist,
  108. btc_tokenlist,
  109. drk_tokenlist,
  110. cashiers,
  111. })
  112. }
  113. async fn start(&mut self, executor: Arc<Executor<'_>>) -> Result<()> {
  114. self.client.lock().await.start().await?;
  115. self.client.lock().await.connect_to_subscriber(self.state.clone(), executor).await?;
  116. Ok(())
  117. }
  118. async fn update_balances(&self) -> Result<()> {
  119. let own_coins = self.client.lock().await.get_own_coins().await?;
  120. for own_coin in own_coins.iter() {
  121. let nullifier_exists = self.state.lock().await.nullifier_exists(&own_coin.nullifier);
  122. if nullifier_exists {
  123. self.client.lock().await.confirm_spend_coin(&own_coin.coin).await?;
  124. }
  125. }
  126. Ok(())
  127. }
  128. // RPCAPI:
  129. // Returns a `helloworld` string.
  130. // --> {"method": "say_hello", "params": []}
  131. // <-- {"result": "helloworld"}
  132. async fn say_hello(&self, id: Value, _params: Value) -> JsonResult {
  133. JsonResult::Resp(jsonresp(json!("hello world"), id))
  134. }
  135. // RPCAPI:
  136. // Attempts to initialize a wallet, and returns `true` upon success.
  137. // --> {"method": "create_wallet", "params": []}
  138. // <-- {"result": true}
  139. async fn create_wallet(&self, id: Value, _params: Value) -> JsonResult {
  140. match self.client.lock().await.init_db().await {
  141. Ok(()) => JsonResult::Resp(jsonresp(json!(true), id)),
  142. Err(e) => JsonResult::Err(jsonerr(ServerError(-32001), Some(e.to_string()), id)),
  143. }
  144. }
  145. // RPCAPI:
  146. // Attempts to generate a new keypair and returns `true` upon success.
  147. // --> {"method": "key_gen", "params": []}
  148. // <-- {"result": true}
  149. async fn key_gen(&self, id: Value, _params: Value) -> JsonResult {
  150. let client = self.client.lock().await;
  151. match client.key_gen().await {
  152. Ok(()) => JsonResult::Resp(jsonresp(json!(true), id)),
  153. Err(e) => JsonResult::Err(jsonerr(ServerError(-32002), Some(e.to_string()), id)),
  154. }
  155. }
  156. // RPCAPI:
  157. // Fetches the main keypair from the wallet and returns it
  158. // in an encoded format.
  159. // --> {"method": "get_key", "params": []}
  160. // <-- {"result": "vdNS7oBj7KvsMWWmo9r96SV4SqATLrGsH2a3PGpCfJC"}
  161. async fn get_key(&self, id: Value, _params: Value) -> JsonResult {
  162. let pk = self.client.lock().await.main_keypair.public;
  163. let addr = Address::from(pk).to_string();
  164. JsonResult::Resp(jsonresp(json!(addr), id))
  165. }
  166. // RPCAPI:
  167. // Fetches all keypairs from the wallet and returns a list of them
  168. // in an encoded format.
  169. // The first one in the list is the default selected keypair.
  170. // --> {"method": "get_keys", "params": []}
  171. // <-- {"result": "[vdNS7oBj7KvsMWWmo9r96SV4SqATLrGsH2a3PGpCfJC,...]"}
  172. async fn get_keys(&self, id: Value, _params: Value) -> JsonResult {
  173. let result: Result<Vec<String>> = async {
  174. let keypairs = self.client.lock().await.get_keypairs().await?;
  175. let default_keypair = self.client.lock().await.main_keypair;
  176. let mut addresses: Vec<String> = keypairs
  177. .iter()
  178. .filter_map(|k| {
  179. if *k == default_keypair {
  180. return None
  181. }
  182. Some(Address::from(k.public).to_string())
  183. })
  184. .collect();
  185. addresses.insert(0, Address::from(default_keypair.public).to_string());
  186. Ok(addresses)
  187. }
  188. .await;
  189. match result {
  190. Ok(addresses) => JsonResult::Resp(jsonresp(json!(addresses), id)),
  191. Err(err) => JsonResult::Err(jsonerr(ServerError(-32003), Some(err.to_string()), id)),
  192. }
  193. }
  194. // RPCAPI:
  195. // Imports a keypair into the wallet with a given path on the filesystem.
  196. // Returns `true` upon success.
  197. // --> {"method": "import_keypair", "params": [path]}
  198. // <-- {"result": true}
  199. async fn import_keypair(&self, id: Value, params: Value) -> JsonResult {
  200. let args = params.as_array();
  201. if args.is_none() {
  202. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  203. }
  204. let arg = args.unwrap()[0].clone();
  205. if arg.as_str().is_none() &&
  206. expand_path(arg.as_str().unwrap()).is_ok() &&
  207. expand_path(arg.as_str().unwrap()).unwrap().to_str().is_some()
  208. {
  209. return JsonResult::Err(jsonerr(InvalidParams, Some("invalid path".into()), id))
  210. }
  211. let path = expand_path(arg.as_str().unwrap()).unwrap();
  212. let path = path.to_str().unwrap();
  213. let result: Result<()> = async {
  214. let keypair_str: String = std::fs::read_to_string(path)?;
  215. let mut bytes = [0u8; 32];
  216. let bytes_vec: Vec<u8> = serde_json::from_str(&keypair_str)?;
  217. bytes.copy_from_slice(bytes_vec.as_slice());
  218. let secret: SecretKey = SecretKey::from_bytes(&bytes)?;
  219. let public: PublicKey = PublicKey::from_secret(secret);
  220. self.client.lock().await.put_keypair(&Keypair { secret, public }).await?;
  221. Ok(())
  222. }
  223. .await;
  224. match result {
  225. Ok(_) => JsonResult::Resp(jsonresp(json!(true), id)),
  226. Err(err) => JsonResult::Err(jsonerr(ServerError(-32004), Some(err.to_string()), id)),
  227. }
  228. }
  229. // RPCAPI:
  230. // Exports the default selected keypair to a given path on the filesystem.
  231. // Returns `true` upon success.
  232. // --> {"method": "export_keypair", "params": [path]}
  233. // <-- {"result": true}
  234. async fn export_keypair(&self, id: Value, params: Value) -> JsonResult {
  235. let args = params.as_array();
  236. if args.is_none() {
  237. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  238. }
  239. let arg = args.unwrap()[0].clone();
  240. if arg.as_str().is_none() &&
  241. expand_path(arg.as_str().unwrap()).is_ok() &&
  242. expand_path(arg.as_str().unwrap()).unwrap().to_str().is_some()
  243. {
  244. return JsonResult::Err(jsonerr(InvalidParams, Some("invalid path".into()), id))
  245. }
  246. let path = expand_path(arg.as_str().unwrap()).unwrap();
  247. let path = path.to_str().unwrap();
  248. let result: Result<()> = async {
  249. let keypair: String =
  250. serde_json::to_string(&self.client.lock().await.main_keypair.secret.to_bytes())?;
  251. std::fs::write(path, &keypair)?;
  252. Ok(())
  253. }
  254. .await;
  255. match result {
  256. Ok(_) => JsonResult::Resp(jsonresp(json!(true), id)),
  257. Err(err) => JsonResult::Err(jsonerr(ServerError(-32004), Some(err.to_string()), id)),
  258. }
  259. }
  260. // RPCAPI:
  261. // Sets the default wallet address to the given parameter.
  262. // Returns true upon success.
  263. // --> {"method": "set_default_address", "params": [vdNS7oBj7KvsMWWmo9r96SV4SqATLrGsH2a3PGpCfJC]}
  264. // <-- {"result": true}
  265. async fn set_default_address(&self, id: Value, params: Value) -> JsonResult {
  266. let args = params.as_array();
  267. if args.is_none() && args.unwrap()[0].as_str().is_none() {
  268. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  269. }
  270. let addr_str = args.unwrap()[0].as_str().unwrap();
  271. let result: Result<()> = async {
  272. let public = PublicKey::try_from(Address::from_str(addr_str)?)?;
  273. self.client.lock().await.set_default_keypair(&public).await?;
  274. Ok(())
  275. }
  276. .await;
  277. match result {
  278. Ok(_) => JsonResult::Resp(jsonresp(json!(true), id)),
  279. Err(err) => JsonResult::Err(jsonerr(ServerError(-32005), Some(err.to_string()), id)),
  280. }
  281. }
  282. // RPCAPI:
  283. // Fetches the known balances from the wallet.
  284. // Returns a map of balances, indexed by `network`, and token ID.
  285. // --> {"method": "get_balances", "params": []}
  286. // <-- {"result": "[{"btc":(value,network)},...]"}
  287. async fn get_balances(&self, id: Value, _params: Value) -> JsonResult {
  288. let result: Result<HashMap<String, (String, String)>> = async {
  289. let balances = self.client.lock().await.get_balances().await?;
  290. let mut symbols: HashMap<String, (String, String)> = HashMap::new();
  291. for b in balances.list.iter() {
  292. let network: String;
  293. let symbol: String;
  294. let mut amount = BigUint::from(b.value);
  295. if let Some((net, sym)) = self.drk_tokenlist.symbol_from_id(&b.token_id)? {
  296. network = net.to_string();
  297. symbol = sym;
  298. } else {
  299. // TODO: SQL needs to have the mint address for show, not the internal hash.
  300. // TODO: SQL needs to have the nework name
  301. network = String::from("UNKNOWN");
  302. symbol = format!("{:?}", b.token_id);
  303. }
  304. if let Some(prev) = symbols.get(&symbol) {
  305. let prev_amnt = decode_base10(&prev.0, 8, true)?;
  306. amount += prev_amnt;
  307. }
  308. let amount = encode_base10(amount, 8);
  309. symbols.insert(symbol, (amount, network));
  310. }
  311. Ok(symbols)
  312. }
  313. .await;
  314. match result {
  315. Ok(res) => JsonResult::Resp(jsonresp(json!(res), id)),
  316. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  317. }
  318. }
  319. // RPCAPI:
  320. // Generates the internal token ID for a given `network` and token ticker or address.
  321. // Returns the internal representation of the token ID.
  322. // --> {"method": "get_token_id", "params": [network,token]}
  323. // <-- {"result": "Ht5G1RhkcKnpLVLMhqJc5aqZ4wYUEbxbtZwGCVbgU7DL"}
  324. async fn get_token_id(&self, id: Value, params: Value) -> JsonResult {
  325. let args = params.as_array();
  326. if args.is_none() {
  327. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  328. }
  329. let args = args.unwrap();
  330. if args.len() != 2 {
  331. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  332. }
  333. let network: &str;
  334. let symbol: &str;
  335. match (args[0].as_str(), args[1].as_str()) {
  336. (Some(net), Some(sym)) => {
  337. network = net;
  338. symbol = sym;
  339. }
  340. (None, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  341. (_, None) => return JsonResult::Err(jsonerr(InvalidSymbolParam, None, id)),
  342. }
  343. let result: Result<Value> = async {
  344. let network = NetworkName::from_str(network)?;
  345. match network {
  346. NetworkName::Solana => {
  347. if let Some(tkn) = self.sol_tokenlist.search_id(symbol)? {
  348. Ok(json!(tkn))
  349. } else {
  350. Err(Error::NotSupportedToken)
  351. }
  352. }
  353. NetworkName::Bitcoin => {
  354. if let Some(tkn) = self.btc_tokenlist.search_id(symbol)? {
  355. Ok(json!(tkn))
  356. } else {
  357. Err(Error::NotSupportedToken)
  358. }
  359. }
  360. NetworkName::Ethereum => {
  361. if symbol.to_lowercase() == "eth" {
  362. Ok(json!(ETH_NATIVE_TOKEN_ID.to_string()))
  363. } else if let Some(tkn) = self.eth_tokenlist.search_id(symbol)? {
  364. Ok(json!(tkn))
  365. } else {
  366. Err(Error::NotSupportedToken)
  367. }
  368. }
  369. _ => Err(Error::NotSupportedNetwork),
  370. }
  371. }
  372. .await;
  373. match result {
  374. Ok(res) => JsonResult::Resp(jsonresp(json!(res), id)),
  375. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  376. }
  377. }
  378. // RPCAPI:
  379. // Asks the configured cashier for their supported features.
  380. // Returns a map of features received from the requested cashier.
  381. // --> {"method": "features", "params": []}
  382. // <-- {"result": {"network":["btc","sol"]}}
  383. async fn features(&self, id: Value, _params: Value) -> JsonResult {
  384. let req = jsonreq(json!("features"), json!([]));
  385. let rep: JsonResult =
  386. // NOTE: this just selects the first cashier in the list
  387. match send_request(&self.cashiers[0].rpc_url, json!(req)).await {
  388. Ok(v) => v,
  389. Err(e) => return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id)),
  390. };
  391. match rep {
  392. JsonResult::Resp(r) => JsonResult::Resp(r),
  393. JsonResult::Err(e) => JsonResult::Err(e),
  394. JsonResult::Notif(_) => JsonResult::Err(jsonerr(InternalError, None, id)),
  395. }
  396. }
  397. // RPCAPI:
  398. // Initializes a DarkFi deposit request for a given `network`, `token`,
  399. // and `publickey`.
  400. // The public key send here is used so the cashier can know where to send
  401. // the newly minted tokens once the deposit is received.
  402. // Returns an address to which the caller is supposed to deposit funds.
  403. // --> {"method": "deposit", "params": [network,token,publickey]}
  404. // <-- {"result": "Ht5G1RhkcKnpLVLMhqJc5aqZ4wYUEbxbtZwGCVbgU7DL"}
  405. async fn deposit(&self, id: Value, params: Value) -> JsonResult {
  406. let args = params.as_array();
  407. if args.is_none() {
  408. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  409. }
  410. let args = args.unwrap();
  411. if args.len() != 2 {
  412. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  413. }
  414. let network: NetworkName;
  415. let token: &str;
  416. match (args[0].as_str(), args[1].as_str()) {
  417. (Some(net), Some(tkn)) => {
  418. if NetworkName::from_str(net).is_err() {
  419. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  420. }
  421. network = NetworkName::from_str(net).unwrap();
  422. token = tkn;
  423. }
  424. (None, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  425. (_, None) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  426. }
  427. let token_id = match assign_id(
  428. &network,
  429. token,
  430. &self.sol_tokenlist,
  431. &self.eth_tokenlist,
  432. &self.btc_tokenlist,
  433. ) {
  434. Ok(t) => t,
  435. Err(e) => return JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id)),
  436. };
  437. let pk = self.client.lock().await.main_keypair.public;
  438. let pubkey = Address::from(pk).to_string();
  439. // Send request to cashier. If the cashier supports the requested network
  440. // (and token), it shall return a valid address where tokens can be deposited.
  441. // If not, an error is returned, and forwarded to the method caller.
  442. let req = jsonreq(json!("deposit"), json!([network, token_id, pubkey]));
  443. let rep: JsonResult = match send_request(&self.cashiers[0].rpc_url, json!(req)).await {
  444. Ok(v) => v,
  445. Err(e) => {
  446. debug!(target: "DARKFID", "REQUEST IS ERR");
  447. return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id))
  448. }
  449. };
  450. match rep {
  451. JsonResult::Resp(r) => JsonResult::Resp(r),
  452. JsonResult::Err(e) => JsonResult::Err(e),
  453. JsonResult::Notif(_n) => JsonResult::Err(jsonerr(InternalError, None, id)),
  454. }
  455. }
  456. // RPCAPI:
  457. // Initializes a withdraw request for a given `network`, `token`, `publickey`,
  458. // and `amount`.
  459. // The publickey send here is the address where the caller wants to receive
  460. // the tokens they plan to withdraw.
  461. // On request, sends a request to a cashier to get a deposit address, and
  462. // then transfers wrapped DarkFitokens to the cashier's wallet. Following that,
  463. // the cashier should return a transaction ID of them sending the funds that
  464. // are requested for withdrawal.
  465. // --> {"method": "withdraw", "params": [network,token,publickey,amount]}
  466. // <-- {"result": "txID"}
  467. async fn withdraw(&self, id: Value, params: Value) -> JsonResult {
  468. let args = params.as_array();
  469. if args.is_none() {
  470. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  471. }
  472. let args = args.unwrap();
  473. if args.len() != 4 {
  474. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  475. }
  476. let network: NetworkName;
  477. let token: &str;
  478. let address: &str;
  479. let amount: &str;
  480. match (args[0].as_str(), args[1].as_str(), args[2].as_str(), args[3].as_str()) {
  481. (Some(net), Some(tkn), Some(addr), Some(val)) => {
  482. if NetworkName::from_str(net).is_err() {
  483. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  484. }
  485. network = NetworkName::from_str(net).unwrap();
  486. token = tkn;
  487. address = addr;
  488. amount = val;
  489. }
  490. (None, _, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  491. (_, None, _, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  492. (_, _, None, _) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  493. (_, _, _, None) => return JsonResult::Err(jsonerr(InvalidAmountParam, None, id)),
  494. }
  495. let amount_in_apo = match decode_base10(amount, 8, true) {
  496. Ok(a) => a,
  497. Err(e) => return JsonResult::Err(jsonerr(InvalidAmountParam, Some(e.to_string()), id)),
  498. };
  499. let token_id = match assign_id(
  500. &network,
  501. token,
  502. &self.sol_tokenlist,
  503. &self.eth_tokenlist,
  504. &self.btc_tokenlist,
  505. ) {
  506. Ok(t) => t,
  507. Err(e) => return JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id)),
  508. };
  509. let req = jsonreq(json!("withdraw"), json!([network, token_id, address, amount_in_apo]));
  510. let mut rep: JsonResult = match send_request(&self.cashiers[0].rpc_url, json!(req)).await {
  511. Ok(v) => v,
  512. Err(e) => return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id)),
  513. };
  514. let token_id: &DrkTokenId;
  515. if let Some(tk_id) = self.drk_tokenlist.tokens[&network].get(&token.to_uppercase()) {
  516. token_id = tk_id;
  517. } else {
  518. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id))
  519. }
  520. // send drk to cashier_public
  521. if let JsonResult::Resp(cashier_public) = &rep {
  522. let result: Result<()> = async {
  523. let cashier_public = cashier_public.result.as_str().unwrap();
  524. let cashier_public: PublicKey =
  525. PublicKey::try_from(Address::from_str(cashier_public)?)?;
  526. self.client
  527. .lock()
  528. .await
  529. .transfer(
  530. *token_id,
  531. cashier_public,
  532. amount_in_apo.try_into()?,
  533. self.state.clone(),
  534. )
  535. .await?;
  536. Ok(())
  537. }
  538. .await;
  539. match result {
  540. Err(e) => {
  541. rep = JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id.clone()))
  542. }
  543. Ok(_) => {
  544. rep = JsonResult::Resp(jsonresp(
  545. json!(format!(
  546. "Sent request to withdraw {} amount of {:?}",
  547. amount, token_id
  548. )),
  549. id.clone(),
  550. ))
  551. }
  552. }
  553. };
  554. match rep {
  555. JsonResult::Resp(r) => JsonResult::Resp(r),
  556. JsonResult::Err(e) => JsonResult::Err(e),
  557. JsonResult::Notif(_n) => JsonResult::Err(jsonerr(InternalError, None, id)),
  558. }
  559. }
  560. // RPCAPI:
  561. // Transfer a given wrapped DarkFi token amount to the given address.
  562. // Returns the transaction ID of the transfer.
  563. // --> {"method": "transfer", "params": [network,dToken,address,amount]}
  564. // <-- {"result": "txID"}
  565. async fn transfer(&self, id: Value, params: Value) -> JsonResult {
  566. let args = params.as_array();
  567. if args.is_none() {
  568. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  569. }
  570. let args = args.unwrap();
  571. if args.len() != 4 {
  572. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  573. }
  574. let network: NetworkName;
  575. let token: &str;
  576. let address: &str;
  577. let amount: &str;
  578. match (args[0].as_str(), args[1].as_str(), args[2].as_str(), args[3].as_str()) {
  579. (Some(net), Some(tkn), Some(addr), Some(val)) => {
  580. if NetworkName::from_str(net).is_err() {
  581. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  582. }
  583. network = NetworkName::from_str(net).unwrap();
  584. token = tkn;
  585. address = addr;
  586. amount = val;
  587. }
  588. (None, _, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  589. (_, None, _, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  590. (_, _, None, _) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  591. (_, _, _, None) => return JsonResult::Err(jsonerr(InvalidAmountParam, None, id)),
  592. }
  593. let token_id: &DrkTokenId;
  594. // get the id for the token
  595. if let Some(tk_id) = self.drk_tokenlist.tokens[&network].get(&token.to_uppercase()) {
  596. token_id = tk_id;
  597. } else {
  598. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id))
  599. }
  600. let result: Result<()> = async {
  601. let drk_address: PublicKey = PublicKey::try_from(Address::from_str(address)?)?;
  602. let decimals: usize = 8;
  603. let amount = decode_base10(amount, decimals, true)?;
  604. self.client
  605. .lock()
  606. .await
  607. .transfer(*token_id, drk_address, amount.try_into()?, self.state.clone())
  608. .await?;
  609. Ok(())
  610. }
  611. .await;
  612. match result {
  613. Ok(_) => JsonResult::Resp(jsonresp(json!("Success"), id)),
  614. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  615. }
  616. }
  617. }
  618. async fn start(
  619. executor: Arc<Executor<'_>>,
  620. local_cashier: Option<String>,
  621. config: &DarkfidConfig,
  622. ) -> Result<()> {
  623. let wallet_path = format!("sqlite://{}", expand_path(&config.wallet_path)?.to_str().unwrap());
  624. let wallet = WalletDb::new(&wallet_path, &config.wallet_password).await?;
  625. let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
  626. let mut cashiers = Vec::new();
  627. let mut cashier_keys = Vec::new();
  628. if let Some(cpub) = local_cashier {
  629. let cashier_public: PublicKey = PublicKey::try_from(Address::from_str(&cpub)?)?;
  630. cashiers.push(Cashier {
  631. name: "localCashier".into(),
  632. rpc_url: "tcp://127.0.0.1:9000".into(),
  633. public_key: cashier_public,
  634. });
  635. cashier_keys.push(cashier_public);
  636. } else {
  637. for cashier in config.clone().cashiers {
  638. if cashier.public_key.is_empty() {
  639. return Err(Error::CashierKeysNotFound)
  640. }
  641. let cashier_public: PublicKey =
  642. PublicKey::try_from(Address::from_str(&cashier.public_key)?)?;
  643. cashiers.push(Cashier {
  644. name: cashier.name,
  645. rpc_url: cashier.rpc_url,
  646. public_key: cashier_public,
  647. });
  648. cashier_keys.push(cashier_public);
  649. }
  650. }
  651. let client = Client::new(
  652. rocks.clone(),
  653. (Url::parse(&config.gateway_protocol_url)?, Url::parse(&config.gateway_publisher_url)?),
  654. wallet.clone(),
  655. )
  656. .await?;
  657. let client = Arc::new(Mutex::new(client));
  658. let tree = client.lock().await.get_tree().await?;
  659. let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
  660. let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
  661. info!("Building verifying key for the mint contract...");
  662. let mint_vk = VerifyingKey::build(11, MintContract::default());
  663. info!("Building verifying key for the spend contract...");
  664. let spend_vk = VerifyingKey::build(11, SpendContract::default());
  665. let state = Arc::new(Mutex::new(State {
  666. tree,
  667. merkle_roots,
  668. nullifiers,
  669. mint_vk,
  670. spend_vk,
  671. public_keys: cashier_keys,
  672. }));
  673. let mut darkfid = Darkfid::new(client, state, cashiers).await?;
  674. let server_config = RpcServerConfig {
  675. socket_addr: config.rpc_listen_address,
  676. use_tls: config.serve_tls,
  677. identity_path: expand_path(&config.tls_identity_path.clone())?,
  678. identity_pass: config.tls_identity_password.clone(),
  679. };
  680. darkfid.start(executor.clone()).await?;
  681. listen_and_serve(server_config, Arc::new(darkfid), executor).await
  682. }
  683. #[async_std::main]
  684. async fn main() -> Result<()> {
  685. let args = CliDarkfid::parse();
  686. let matches = CliDarkfid::into_app().get_matches();
  687. let config_path = if args.config.is_some() {
  688. expand_path(&args.config.unwrap())?
  689. } else {
  690. join_config_path(&PathBuf::from("darkfid.toml"))?
  691. };
  692. // Spawn config file if it's not in place already.
  693. spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
  694. let mut verbosity_level = 0;
  695. verbosity_level += matches.occurrences_of("verbose");
  696. let loglevel = match verbosity_level {
  697. 0 => LevelFilter::Info,
  698. 1 => LevelFilter::Debug,
  699. _ => LevelFilter::Trace,
  700. };
  701. TermLogger::init(
  702. loglevel,
  703. simplelog::Config::default(),
  704. TerminalMode::Mixed,
  705. ColorChoice::Auto,
  706. )?;
  707. let config: DarkfidConfig = Config::<DarkfidConfig>::load(config_path)?;
  708. if args.refresh {
  709. info!(target: "DARKFI DAEMON", "Refresh the wallet and the database");
  710. let wallet_path =
  711. format!("sqlite://{}", expand_path(&config.wallet_path)?.to_str().unwrap());
  712. let wallet = WalletDb::new(&wallet_path, &config.wallet_password).await?;
  713. wallet.remove_own_coins().await?;
  714. if let Some(path) = expand_path(&config.database_path)?.to_str() {
  715. info!(target: "DARKFI DAEMON", "Remove database: {}", path);
  716. std::fs::remove_dir_all(path)?;
  717. }
  718. info!("Wallet updated successfully.");
  719. return Ok(())
  720. }
  721. let ex = Arc::new(Executor::new());
  722. let (signal, shutdown) = async_channel::unbounded::<()>();
  723. let ex2 = ex.clone();
  724. let nthreads = num_cpus::get();
  725. debug!(target: "DARKFI DAEMON", "Run {} executor threads", nthreads);
  726. let (_, result) = Parallel::new()
  727. .each(0..nthreads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  728. // Run the main future on the current thread.
  729. .finish(|| {
  730. smol::future::block_on(async move {
  731. start(ex2, args.cashier, &config).await?;
  732. drop(signal);
  733. Ok::<(), darkfi::Error>(())
  734. })
  735. });
  736. result
  737. }