main.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  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_raw_request,
  30. ErrorCode::*, 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_raw_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_raw_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_raw_request(&self.cashiers[0].rpc_url, json!(req))
  511. .await
  512. {
  513. Ok(v) => v,
  514. Err(e) => return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id)),
  515. };
  516. let token_id: &DrkTokenId;
  517. if let Some(tk_id) = self.drk_tokenlist.tokens[&network].get(&token.to_uppercase()) {
  518. token_id = tk_id;
  519. } else {
  520. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id))
  521. }
  522. // send drk to cashier_public
  523. if let JsonResult::Resp(cashier_public) = &rep {
  524. let result: Result<()> = async {
  525. let cashier_public = cashier_public.result.as_str().unwrap();
  526. let cashier_public: PublicKey =
  527. PublicKey::try_from(Address::from_str(cashier_public)?)?;
  528. self.client
  529. .lock()
  530. .await
  531. .transfer(
  532. *token_id,
  533. cashier_public,
  534. amount_in_apo.try_into()?,
  535. self.state.clone(),
  536. )
  537. .await?;
  538. Ok(())
  539. }
  540. .await;
  541. match result {
  542. Err(e) => {
  543. rep = JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id.clone()))
  544. }
  545. Ok(_) => {
  546. rep = JsonResult::Resp(jsonresp(
  547. json!(format!(
  548. "Sent request to withdraw {} amount of {:?}",
  549. amount, token_id
  550. )),
  551. id.clone(),
  552. ))
  553. }
  554. }
  555. };
  556. match rep {
  557. JsonResult::Resp(r) => JsonResult::Resp(r),
  558. JsonResult::Err(e) => JsonResult::Err(e),
  559. JsonResult::Notif(_n) => JsonResult::Err(jsonerr(InternalError, None, id)),
  560. }
  561. }
  562. // RPCAPI:
  563. // Transfer a given wrapped DarkFi token amount to the given address.
  564. // Returns the transaction ID of the transfer.
  565. // --> {"method": "transfer", "params": [network,dToken,address,amount]}
  566. // <-- {"result": "txID"}
  567. async fn transfer(&self, id: Value, params: Value) -> JsonResult {
  568. let args = params.as_array();
  569. if args.is_none() {
  570. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  571. }
  572. let args = args.unwrap();
  573. if args.len() != 4 {
  574. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  575. }
  576. let network: NetworkName;
  577. let token: &str;
  578. let address: &str;
  579. let amount: &str;
  580. match (args[0].as_str(), args[1].as_str(), args[2].as_str(), args[3].as_str()) {
  581. (Some(net), Some(tkn), Some(addr), Some(val)) => {
  582. if NetworkName::from_str(net).is_err() {
  583. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  584. }
  585. network = NetworkName::from_str(net).unwrap();
  586. token = tkn;
  587. address = addr;
  588. amount = val;
  589. }
  590. (None, _, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  591. (_, None, _, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  592. (_, _, None, _) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  593. (_, _, _, None) => return JsonResult::Err(jsonerr(InvalidAmountParam, None, id)),
  594. }
  595. let token_id: &DrkTokenId;
  596. // get the id for the token
  597. if let Some(tk_id) = self.drk_tokenlist.tokens[&network].get(&token.to_uppercase()) {
  598. token_id = tk_id;
  599. } else {
  600. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id))
  601. }
  602. let result: Result<()> = async {
  603. let drk_address: PublicKey = PublicKey::try_from(Address::from_str(address)?)?;
  604. let decimals: usize = 8;
  605. let amount = decode_base10(amount, decimals, true)?;
  606. self.client
  607. .lock()
  608. .await
  609. .transfer(*token_id, drk_address, amount.try_into()?, self.state.clone())
  610. .await?;
  611. Ok(())
  612. }
  613. .await;
  614. match result {
  615. Ok(_) => JsonResult::Resp(jsonresp(json!("Success"), id)),
  616. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  617. }
  618. }
  619. }
  620. async fn start(
  621. executor: Arc<Executor<'_>>,
  622. local_cashier: Option<String>,
  623. config: &DarkfidConfig,
  624. ) -> Result<()> {
  625. let wallet_path = format!("sqlite://{}", expand_path(&config.wallet_path)?.to_str().unwrap());
  626. let wallet = WalletDb::new(&wallet_path, &config.wallet_password).await?;
  627. let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
  628. let mut cashiers = Vec::new();
  629. let mut cashier_keys = Vec::new();
  630. if let Some(cpub) = local_cashier {
  631. let cashier_public: PublicKey = PublicKey::try_from(Address::from_str(&cpub)?)?;
  632. cashiers.push(Cashier {
  633. name: "localCashier".into(),
  634. rpc_url: "tcp://127.0.0.1:9000".into(),
  635. public_key: cashier_public,
  636. });
  637. cashier_keys.push(cashier_public);
  638. } else {
  639. for cashier in config.clone().cashiers {
  640. if cashier.public_key.is_empty() {
  641. return Err(Error::CashierKeysNotFound)
  642. }
  643. let cashier_public: PublicKey =
  644. PublicKey::try_from(Address::from_str(&cashier.public_key)?)?;
  645. cashiers.push(Cashier {
  646. name: cashier.name,
  647. rpc_url: cashier.rpc_url,
  648. public_key: cashier_public,
  649. });
  650. cashier_keys.push(cashier_public);
  651. }
  652. }
  653. let client = Client::new(
  654. rocks.clone(),
  655. (Url::parse(&config.gateway_protocol_url)?, Url::parse(&config.gateway_publisher_url)?),
  656. wallet.clone(),
  657. )
  658. .await?;
  659. let client = Arc::new(Mutex::new(client));
  660. let tree = client.lock().await.get_tree().await?;
  661. let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
  662. let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
  663. info!("Building verifying key for the mint contract...");
  664. let mint_vk = VerifyingKey::build(11, MintContract::default());
  665. info!("Building verifying key for the spend contract...");
  666. let spend_vk = VerifyingKey::build(11, SpendContract::default());
  667. let state = Arc::new(Mutex::new(State {
  668. tree,
  669. merkle_roots,
  670. nullifiers,
  671. mint_vk,
  672. spend_vk,
  673. public_keys: cashier_keys,
  674. }));
  675. let mut darkfid = Darkfid::new(client, state, cashiers).await?;
  676. let server_config = RpcServerConfig {
  677. socket_addr: config.rpc_listen_address,
  678. use_tls: config.serve_tls,
  679. identity_path: expand_path(&config.tls_identity_path.clone())?,
  680. identity_pass: config.tls_identity_password.clone(),
  681. };
  682. darkfid.start(executor.clone()).await?;
  683. listen_and_serve(server_config, Arc::new(darkfid), executor).await
  684. }
  685. #[async_std::main]
  686. async fn main() -> Result<()> {
  687. let args = CliDarkfid::parse();
  688. let matches = CliDarkfid::into_app().get_matches();
  689. let config_path = if args.config.is_some() {
  690. expand_path(&args.config.unwrap())?
  691. } else {
  692. join_config_path(&PathBuf::from("darkfid.toml"))?
  693. };
  694. // Spawn config file if it's not in place already.
  695. spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
  696. let mut verbosity_level = 0;
  697. verbosity_level += matches.occurrences_of("verbose");
  698. let loglevel = match verbosity_level {
  699. 0 => LevelFilter::Info,
  700. 1 => LevelFilter::Debug,
  701. _ => LevelFilter::Trace,
  702. };
  703. TermLogger::init(
  704. loglevel,
  705. simplelog::Config::default(),
  706. TerminalMode::Mixed,
  707. ColorChoice::Auto,
  708. )?;
  709. let config: DarkfidConfig = Config::<DarkfidConfig>::load(config_path)?;
  710. if args.refresh {
  711. info!(target: "DARKFI DAEMON", "Refresh the wallet and the database");
  712. let wallet_path =
  713. format!("sqlite://{}", expand_path(&config.wallet_path)?.to_str().unwrap());
  714. let wallet = WalletDb::new(&wallet_path, &config.wallet_password).await?;
  715. wallet.remove_own_coins().await?;
  716. if let Some(path) = expand_path(&config.database_path)?.to_str() {
  717. info!(target: "DARKFI DAEMON", "Remove database: {}", path);
  718. std::fs::remove_dir_all(path)?;
  719. }
  720. info!("Wallet updated successfully.");
  721. return Ok(())
  722. }
  723. let ex = Arc::new(Executor::new());
  724. let (signal, shutdown) = async_channel::unbounded::<()>();
  725. let ex2 = ex.clone();
  726. let nthreads = num_cpus::get();
  727. debug!(target: "DARKFI DAEMON", "Run {} executor threads", nthreads);
  728. let (_, result) = Parallel::new()
  729. .each(0..nthreads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  730. // Run the main future on the current thread.
  731. .finish(|| {
  732. smol::future::block_on(async move {
  733. start(ex2, args.cashier, &config).await?;
  734. drop(signal);
  735. Ok::<(), darkfi::Error>(())
  736. })
  737. });
  738. result
  739. }