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 8.2KB

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