use std::collections::HashMap; use log::debug; use sdk_client::api::{ create_login_transaction, create_pairing_transaction, dump_device, dump_message_cache, dump_wallet, get_outputs, login, pair_device, reset_device, restore_device, set_message_cache, setup }; use sdk_common::network::{ CachedMessage, CachedMessageStatus, }; use sdk_common::sp_client::bitcoin::OutPoint; use sdk_common::sp_client::spclient::OwnedOutput; use serde_json; use tsify::JsValueSerdeExt; use wasm_bindgen_test::*; mod utils; use utils::*; wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] fn test_pairing() { setup(); debug!("==============================================\nStarting test_pairing\n=============================================="); // ========================= Alice helper_switch_device(ALICE_LOGIN_WALLET.to_owned()); debug!("Alice sends a pairing transaction to Bob"); let alice_pairing_tx = create_pairing_transaction(helper_get_bob_address(), 1).unwrap(); let get_outputs_result = get_outputs().unwrap(); let alice_outputs: HashMap = get_outputs_result.into_serde().unwrap(); let alice_pairing_tweak_data = helper_get_tweak_data(&alice_pairing_tx.transaction, alice_outputs); // Alice parse her own transaction let alice_msg_id = helper_parse_transaction(&alice_pairing_tx.transaction, &alice_pairing_tweak_data).id; let alice_wallet = dump_wallet().unwrap(); let alice_cache = dump_message_cache().unwrap(); // ======================= Bob reset_device().unwrap(); helper_switch_device(BOB_LOGIN_WALLET.to_owned()); // Bob receives Alice pairing transaction // if he agrees, he must send another pairing transaction to Alice // he can also spend the output that notified him that will become Alice first session key debug!("Bob parses Alice pairing transaction"); helper_parse_transaction(&alice_pairing_tx.transaction, &alice_pairing_tweak_data); debug!("Bob receives the prd"); helper_parse_cipher(alice_pairing_tx.new_network_msg.prd_cipher.unwrap()); debug!("Bob receives the pcd"); let alice_pairing_res = helper_parse_cipher(alice_pairing_tx.new_network_msg.pcd_cipher.unwrap()); assert!(alice_pairing_res.status == CachedMessageStatus::Pairing); // Bob takes the txid of the incoming transaction from Alice, he will need it for pairing let incoming_txid = alice_pairing_res.commited_in.unwrap().txid; // At this point, user must validate the pairing proposal received from Alice debug!("Bob sends a pairing transaction back"); let bob_pairing_tx = create_pairing_transaction(alice_pairing_res.sender.unwrap(), 1).unwrap(); let get_outputs_result = get_outputs().unwrap(); let bob_outputs: HashMap = get_outputs_result.into_serde().unwrap(); let bob_pairing_tweak_data = helper_get_tweak_data(&bob_pairing_tx.transaction, bob_outputs); helper_parse_transaction(&bob_pairing_tx.transaction, &bob_pairing_tweak_data); debug!("Bob pairs device with Alice"); let pairing_process = pair_device(DEFAULT_NYM.to_owned(), bob_pairing_tx.new_network_msg.id, incoming_txid.to_string()).unwrap(); // sign the pairing process // send it to Alice so that she can sign it too // commit it to a transaction to make it public // ======================== Alice reset_device().unwrap(); helper_switch_device(alice_wallet); set_message_cache(alice_cache).unwrap(); // parse Bob's pairing transaction helper_parse_transaction(&bob_pairing_tx.transaction, &bob_pairing_tweak_data); helper_parse_cipher(bob_pairing_tx.new_network_msg.prd_cipher.unwrap()); let bob_pairing_msg = helper_parse_cipher(bob_pairing_tx.new_network_msg.pcd_cipher.unwrap()); assert!(bob_pairing_msg.status == CachedMessageStatus::Pairing); debug!("Alice pairs device"); pair_device(DEFAULT_NYM.to_owned(), alice_msg_id, bob_pairing_tx.txid).unwrap(); } #[wasm_bindgen_test] fn test_first_login() { reset_device().unwrap(); setup(); debug!("==============================================\nStarting test_first_login\n=============================================="); restore_device(BOB_PAIRED_DEVICE.to_owned()).unwrap(); set_message_cache( serde_json::from_str::>(BOB_PAIRING_CACHE) .unwrap() .into_iter() .map(|v| v.to_string()) .collect(), ) .unwrap(); // Bob can now spend the notification output, that will become Alice's first session key debug!("Bob first login"); let bob_first_login_tx = create_login_transaction(1).unwrap(); let get_outputs_result = get_outputs().unwrap(); let bob_outputs: HashMap = get_outputs_result.into_serde().unwrap(); let bob_login_tweak_data = helper_get_tweak_data(&bob_first_login_tx.transaction, bob_outputs); debug!("Bob parses his own login transaction"); helper_parse_transaction(&bob_first_login_tx.transaction, &bob_login_tweak_data); let bob_device = dump_device().unwrap(); let bob_cache = dump_message_cache().unwrap(); // ======================== Alice reset_device().unwrap(); restore_device(ALICE_PAIRED_DEVICE.to_owned()).unwrap(); set_message_cache( serde_json::from_str::>(ALICE_PAIRING_CACHE) .unwrap() .into_iter() .map(|v| v.to_string()) .collect(), ) .unwrap(); debug!("Alice finds out the login demand from Bob"); helper_parse_transaction(&bob_first_login_tx.transaction, &bob_login_tweak_data); helper_parse_cipher(bob_first_login_tx.new_network_msg.prd_cipher.unwrap()); let bob_login_msg = helper_parse_cipher(bob_first_login_tx.new_network_msg.pcd_cipher.unwrap()); // At this point Alice can fire up the revokation output if the login demand is illegitimate // OR she must answer with a login transaction to Bob debug!("Alice first login"); let alice_first_login_tx = create_login_transaction(1).unwrap(); let get_outputs_result = get_outputs().unwrap(); let alice_outputs: HashMap = get_outputs_result.into_serde().unwrap(); let alice_login_tweak_data = helper_get_tweak_data(&alice_first_login_tx.transaction, alice_outputs); helper_parse_transaction(&alice_first_login_tx.transaction, &alice_login_tweak_data); login(bob_login_msg.id, alice_first_login_tx.transaction.clone()).unwrap(); // ======================= Bob reset_device().unwrap(); restore_device(bob_device).unwrap(); set_message_cache(bob_cache).unwrap(); helper_parse_transaction(&alice_first_login_tx.transaction, &alice_login_tweak_data); helper_parse_cipher(alice_first_login_tx.new_network_msg.prd_cipher.unwrap()); let alice_login_msg = helper_parse_cipher(alice_first_login_tx.new_network_msg.pcd_cipher.unwrap()); assert!(alice_login_msg.status == CachedMessageStatus::Login); login(alice_login_msg.id, bob_first_login_tx.transaction).unwrap(); } #[wasm_bindgen_test] fn test_login() { reset_device().unwrap(); setup(); debug!("==============================================\nStarting test_login\n=============================================="); // ======================= Alice restore_device(ALICE_LOGGED_DEVICE.to_owned()).unwrap(); debug!("Alice sends a login transaction to Bob, which creates a new key for him"); let alice_login_tx = create_login_transaction(1).unwrap(); let get_outputs_result = get_outputs().unwrap(); let alice_outputs: HashMap = get_outputs_result.into_serde().unwrap(); let alice_login_tweak_data = helper_get_tweak_data( &alice_login_tx.transaction, alice_outputs ); debug!("Parsing Alice login transaction"); helper_parse_transaction(&alice_login_tx.transaction, &alice_login_tweak_data); let alice_device = dump_device().unwrap(); let alice_cache = dump_message_cache().unwrap(); // ============================== Bob reset_device().unwrap(); restore_device(BOB_LOGGED_DEVICE.to_owned()).unwrap(); debug!("Bob finds out the login demand from Alice"); helper_parse_transaction(&alice_login_tx.transaction, &alice_login_tweak_data); helper_parse_cipher(alice_login_tx.new_network_msg.prd_cipher.unwrap()); let alice_login_msg = helper_parse_cipher(alice_login_tx.new_network_msg.pcd_cipher.unwrap()); // Bob must confirm that he agrees to log in // Boutons "login" ou "Refuser" // At this point Bob can fire up the revokation output if the login demand is illegitimate // revoke_paired_device(1).unwrap(); // OR it must answer with a login transaction to Alice let bob_login_tx = create_login_transaction(1).unwrap(); let get_outputs_result = get_outputs().unwrap(); let bob_outputs: HashMap = get_outputs_result.into_serde().unwrap(); let bob_login_tweak_data = helper_get_tweak_data(&bob_login_tx.transaction, bob_outputs); debug!("Bob parses his own login transaction"); helper_parse_transaction(&bob_login_tx.transaction, &bob_login_tweak_data); login(alice_login_msg.id, alice_login_tx.transaction.clone()).unwrap(); // =================== Alice reset_device().unwrap(); restore_device(alice_device).unwrap(); set_message_cache(alice_cache).unwrap(); helper_parse_transaction(&bob_login_tx.transaction, &bob_login_tweak_data); helper_parse_cipher(bob_login_tx.new_network_msg.prd_cipher.unwrap()); let bob_login_msg = helper_parse_cipher(bob_login_tx.new_network_msg.pcd_cipher.unwrap()); assert!(bob_login_msg.status == CachedMessageStatus::Login); login(bob_login_msg.id, alice_login_tx.transaction).unwrap(); }