You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

integration.rs 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. use common_api::crypto::prelude::*;
  2. use near_primitives_core::{account::id::AccountId, types::Balance};
  3. use near_primitives_light::types::Finality;
  4. use near_rpc::client::{NearClient, Signer};
  5. use rand::{RngCore, SeedableRng};
  6. use rand_chacha::ChaChaRng;
  7. use serde::{Deserialize, Serialize};
  8. use std::str::FromStr;
  9. use url::Url;
  10. use wasm_bindgen::JsValue;
  11. use wasm_bindgen_futures::JsFuture;
  12. use wasm_bindgen_test::*;
  13. use web_client::{KeyProvisioner, ProvisionerConfig};
  14. wasm_bindgen_test_configure!(run_in_browser);
  15. #[derive(Serialize, Deserialize)]
  16. struct ValidatorKey {
  17. account_id: AccountId,
  18. public_key: Ed25519PublicKey,
  19. secret_key: String,
  20. }
  21. fn random_bits() -> [u8; 32] {
  22. let mut chacha = ChaChaRng::from_entropy();
  23. let mut secret_bytes = [0_u8; 32];
  24. chacha.fill_bytes(&mut secret_bytes);
  25. secret_bytes
  26. }
  27. async fn create_account(
  28. client: &NearClient,
  29. validator: &Signer,
  30. account_id_str: &str,
  31. amount: Balance,
  32. ) -> anyhow::Result<Signer> {
  33. let id = AccountId::from_str(account_id_str)?;
  34. let sk = Ed25519SecretKey::try_from_bytes(&random_bits())?;
  35. let pk = Ed25519PublicKey::from(&sk);
  36. client
  37. .create_account(validator, &id, pk, amount)
  38. .commit(Finality::Final)
  39. .await?;
  40. let nonce = Result::from(
  41. client
  42. .view_access_key(&id, &pk, Finality::None)
  43. .await
  44. .unwrap(),
  45. )
  46. .map_err(|err| anyhow::anyhow!(err))?;
  47. Ok(Signer::from_secret(sk, id, nonce))
  48. }
  49. async fn delete_account(
  50. client: &NearClient,
  51. signer: &Signer,
  52. beneficiary_acc_id: &AccountId,
  53. ) -> anyhow::Result<()> {
  54. let id = signer.account().clone();
  55. let pk = signer.public_key();
  56. let nonce = Result::from(client.view_access_key(&id, pk, Finality::Final).await?)
  57. .map_err(|err| anyhow::anyhow!(err))?;
  58. signer.update_nonce(nonce);
  59. client
  60. .delete_account(signer, &id, beneficiary_acc_id)
  61. .commit(Finality::Final)
  62. .await?;
  63. Ok(())
  64. }
  65. async fn validator_key() -> anyhow::Result<ValidatorKey> {
  66. Ok(
  67. reqwest::get("http://sandbox-artifact:3032/validator_key.json")
  68. .await?
  69. .json::<ValidatorKey>()
  70. .await?,
  71. )
  72. }
  73. async fn validator_account(
  74. client: &NearClient,
  75. validator_key: ValidatorKey,
  76. ) -> anyhow::Result<Signer> {
  77. let key_nonce = Result::from(
  78. client
  79. .view_access_key(
  80. &validator_key.account_id,
  81. &validator_key.public_key,
  82. Finality::Final,
  83. )
  84. .await?,
  85. )
  86. .map_err(|err| anyhow::anyhow!(err))?;
  87. let signer = Signer::from_secret_str(
  88. &validator_key.secret_key,
  89. validator_key.account_id.clone(),
  90. key_nonce,
  91. )?;
  92. Ok(signer)
  93. }
  94. async fn meeting_room_contract() -> anyhow::Result<Vec<u8>> {
  95. Ok(
  96. reqwest::get("http://contract-artifact:3033/meeting_room.wasm")
  97. .await?
  98. .bytes()
  99. .await?
  100. .to_vec(),
  101. )
  102. }
  103. #[wasm_bindgen_test]
  104. async fn pass() {
  105. console_log!("Test Passed");
  106. }
  107. #[wasm_bindgen_test]
  108. async fn key_exchange() {
  109. let rpc_url = Url::parse("http://sandbox:3030").unwrap();
  110. let client = NearClient::new(rpc_url).unwrap();
  111. let validator_key = validator_key().await.unwrap();
  112. let validator = validator_account(&client, validator_key).await.unwrap();
  113. // create account for key-exchange
  114. // Alice is an initiator account
  115. let alice_sg = create_account(
  116. &client,
  117. &validator,
  118. "alice.test.near",
  119. near_units::near::parse("10 N").unwrap(),
  120. )
  121. .await
  122. .unwrap();
  123. let bob_sg = create_account(
  124. &client,
  125. &validator,
  126. "bob.test.near",
  127. near_units::near::parse("10 N").unwrap(),
  128. )
  129. .await
  130. .unwrap();
  131. let karl_sg = create_account(
  132. &client,
  133. &validator,
  134. "karl.test.near",
  135. near_units::near::parse("10 N").unwrap(),
  136. )
  137. .await
  138. .unwrap();
  139. let mike_sg = create_account(
  140. &client,
  141. &validator,
  142. "mike.test.near",
  143. near_units::near::parse("10 N").unwrap(),
  144. )
  145. .await
  146. .unwrap();
  147. // Create an contract account
  148. let contract_sg = create_account(
  149. &client,
  150. &validator,
  151. "contract.test.near",
  152. near_units::near::parse("200 N").unwrap(),
  153. )
  154. .await
  155. .unwrap();
  156. // Contract byte code
  157. let contract_wasm = meeting_room_contract().await.unwrap();
  158. let contract_id = contract_sg.account().clone();
  159. client
  160. .deploy_contract(&contract_sg, &contract_id, contract_wasm)
  161. .commit(Finality::Final)
  162. .await
  163. .unwrap();
  164. // config with endpoints
  165. let config = ProvisionerConfig::new(
  166. contract_id.to_string(),
  167. "http://sandbox:3030",
  168. "http://key-exchange:3000",
  169. )
  170. .unwrap();
  171. // Create provisioners for each user
  172. let keypair_str = alice_sg.secret_key().string();
  173. let provisioner = KeyProvisioner::new(
  174. keypair_str,
  175. alice_sg.nonce(),
  176. alice_sg.account().to_string(),
  177. config.clone(),
  178. )
  179. .unwrap();
  180. let arr = JsValue::from(
  181. &[
  182. bob_sg.account().to_string(),
  183. karl_sg.account().to_string(),
  184. mike_sg.account().to_string(),
  185. ]
  186. .into_iter()
  187. .map(|it| JsValue::from_str(&it))
  188. .collect::<js_sys::Array>(),
  189. );
  190. let set = js_sys::Set::new(&arr);
  191. // Init meeting
  192. let meeting_id = JsFuture::from(provisioner.init(set, 3000))
  193. .await
  194. .unwrap()
  195. .as_string()
  196. .unwrap();
  197. // Then each user push own key to blockchain
  198. let keypair_str = bob_sg.secret_key().string();
  199. let provisioner_bob = KeyProvisioner::new(
  200. keypair_str,
  201. bob_sg.nonce(),
  202. bob_sg.account().to_string(),
  203. config.clone(),
  204. )
  205. .unwrap();
  206. let _ = JsFuture::from(provisioner_bob.push_to_near(meeting_id.clone(), 3000))
  207. .await
  208. .unwrap();
  209. let keypair_str = karl_sg.secret_key().string();
  210. let provisioner_karl = KeyProvisioner::new(
  211. keypair_str,
  212. karl_sg.nonce(),
  213. karl_sg.account().to_string(),
  214. config.clone(),
  215. )
  216. .unwrap();
  217. let _ = JsFuture::from(provisioner_karl.push_to_near(meeting_id.clone(), 3000))
  218. .await
  219. .unwrap();
  220. let keypair_str = mike_sg.secret_key().string();
  221. let provisioner_mike = KeyProvisioner::new(
  222. keypair_str,
  223. mike_sg.nonce(),
  224. mike_sg.account().to_string(),
  225. config.clone(),
  226. )
  227. .unwrap();
  228. let _ = JsFuture::from(provisioner_mike.push_to_near(meeting_id.clone(), 3000))
  229. .await
  230. .unwrap();
  231. // Send encrypted keys to participants
  232. // timeout in millis
  233. let alice_key = JsFuture::from(provisioner.send_keys(meeting_id.clone(), 200))
  234. .await
  235. .unwrap()
  236. .as_string()
  237. .unwrap();
  238. // Fetch encrypted keys
  239. let bob_key = JsFuture::from(provisioner_bob.get_key(meeting_id.clone(), 200))
  240. .await
  241. .unwrap()
  242. .as_string()
  243. .unwrap();
  244. let karl_key = JsFuture::from(provisioner_karl.get_key(meeting_id.clone(), 200))
  245. .await
  246. .unwrap()
  247. .as_string()
  248. .unwrap();
  249. let mike_key = JsFuture::from(provisioner_mike.get_key(meeting_id.clone(), 200))
  250. .await
  251. .unwrap()
  252. .as_string()
  253. .unwrap();
  254. assert!(&[mike_key, bob_key, karl_key]
  255. .into_iter()
  256. .all(|key| key == alice_key));
  257. // delete all accounts
  258. delete_account(&client, &contract_sg, validator.account())
  259. .await
  260. .unwrap();
  261. delete_account(&client, &alice_sg, validator.account())
  262. .await
  263. .unwrap();
  264. delete_account(&client, &bob_sg, validator.account())
  265. .await
  266. .unwrap();
  267. delete_account(&client, &karl_sg, validator.account())
  268. .await
  269. .unwrap();
  270. delete_account(&client, &mike_sg, validator.account())
  271. .await
  272. .unwrap();
  273. }
  274. #[wasm_bindgen_test]
  275. async fn sandbox() {}