158 lines
5.5 KiB
Rust
158 lines
5.5 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use sdk_client::api::{
|
|
create_device_from_sp_wallet, create_process_from_template, create_process_init_transaction, get_address, get_outputs, pair_device, reset_device, setup
|
|
};
|
|
use sdk_client::lock_processes;
|
|
use sdk_common::network::CachedMessage;
|
|
use sdk_common::pcd::{Member, Pcd};
|
|
use sdk_common::prd::Prd;
|
|
use sdk_common::sp_client::bitcoin::OutPoint;
|
|
use sdk_common::sp_client::spclient::OwnedOutput;
|
|
use sdk_common::uuid::Uuid;
|
|
use sdk_common::log::debug;
|
|
use serde_json::{self, 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
|
|
reset_device().unwrap();
|
|
create_device_from_sp_wallet(ALICE_LOGIN_WALLET.to_owned()).unwrap();
|
|
|
|
// we get our own address
|
|
let device_address = get_address().unwrap();
|
|
|
|
// we scan the qr code or get the address by any other means
|
|
let paired_device = helper_get_bob_address();
|
|
|
|
// Alice creates the new member with Bob address
|
|
let new_member = Member::new(
|
|
vec![
|
|
device_address.as_str().try_into().unwrap(),
|
|
paired_device.as_str().try_into().unwrap(),
|
|
]
|
|
).unwrap();
|
|
|
|
// We get the template for the pairing
|
|
// We don't really care how we get it, we can even imagine user writing it himself
|
|
// It just have to respect the basic Process struct, i.e. have all the fields below and the right type for the value
|
|
let pairing_template = json!({
|
|
"uuid": "",
|
|
"html": "",
|
|
"script": "",
|
|
"style": "",
|
|
"init_state": {
|
|
"roles": {
|
|
"owner": {
|
|
"members":
|
|
[
|
|
new_member
|
|
],
|
|
"validation_rules":
|
|
[
|
|
{
|
|
"quorum": 0.0,
|
|
"fields": [
|
|
"roles",
|
|
"pairing_tx"
|
|
],
|
|
"min_sig_member": 0.0
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"pairing_tx": "",
|
|
},
|
|
"commited_in": OutPoint::null()
|
|
});
|
|
|
|
let new_process = create_process_from_template(pairing_template.to_string()).unwrap();
|
|
|
|
// we can update our local device now
|
|
pair_device(new_process.uuid.clone(), vec![helper_get_bob_address()]).unwrap();
|
|
|
|
debug!("Alice sends a transaction commiting to an init prd to Bob");
|
|
let alice_pairing_return = create_process_init_transaction(new_process, 1).unwrap();
|
|
|
|
let get_outputs_result = get_outputs().unwrap();
|
|
|
|
let alice_outputs: HashMap<OutPoint, OwnedOutput> = get_outputs_result.into_serde().unwrap();
|
|
|
|
let alice_pairing_tweak_data =
|
|
helper_get_tweak_data(&alice_pairing_return.transaction, alice_outputs);
|
|
|
|
// Alice parse her own transaction
|
|
helper_parse_transaction(&alice_pairing_return.transaction, &alice_pairing_tweak_data).id;
|
|
|
|
// Notify user that we're waiting for confirmation from the other device
|
|
|
|
// ======================= Bob
|
|
reset_device().unwrap();
|
|
create_device_from_sp_wallet(BOB_LOGIN_WALLET.to_owned()).unwrap();
|
|
|
|
// Bob receives Alice pairing transaction
|
|
debug!("Bob parses Alice pairing transaction");
|
|
helper_parse_transaction(&alice_pairing_return.transaction, &alice_pairing_tweak_data);
|
|
|
|
debug!("Bob receives the prd");
|
|
let mut bob_retrieved_prd = CachedMessage::default();
|
|
for message in alice_pairing_return.new_messages.iter() {
|
|
for cipher in message.cipher.iter() {
|
|
match helper_parse_cipher(cipher.clone()) {
|
|
Ok(res) => bob_retrieved_prd = res,
|
|
Err(_) => continue
|
|
}
|
|
}
|
|
}
|
|
|
|
if bob_retrieved_prd == CachedMessage::default() {
|
|
panic!("Bob failed to retrieve Alice message");
|
|
}
|
|
|
|
debug!("Bob receives the pcd");
|
|
let mut bob_retrieved_pcd = CachedMessage::default();
|
|
for message in alice_pairing_return.new_messages {
|
|
for cipher in message.cipher {
|
|
match helper_parse_cipher(cipher) {
|
|
Ok(res) => bob_retrieved_pcd = res,
|
|
Err(_) => continue
|
|
}
|
|
}
|
|
}
|
|
|
|
if bob_retrieved_pcd == CachedMessage::default() {
|
|
panic!("Bob failed to retrieve Alice message");
|
|
}
|
|
|
|
// At this point, user must validate the pairing proposal received from Alice
|
|
|
|
debug!("Bob pairs device with Alice");
|
|
let process = lock_processes().unwrap();
|
|
let prd: Prd = serde_json::from_str(&bob_retrieved_prd.prd.unwrap()).unwrap();
|
|
let relevant_process = process.get(&Uuid::parse_str(&prd.process_uuid).unwrap()).unwrap();
|
|
// decrypt the pcd and update bob device
|
|
if let Some(initial_state) = relevant_process.get_status_at(0) {
|
|
let keys = initial_state.keys;
|
|
let mut pcd = initial_state.encrypted_pcd;
|
|
pcd.decrypt_fields(&keys).unwrap();
|
|
pair_device(relevant_process.get_process().uuid, vec![device_address]).unwrap();
|
|
}
|
|
|
|
// To make the pairing effective, alice and bob must now spend their respective output into a new transaction
|
|
// login();
|
|
|
|
// Once we know this tx id, we can commit to the relay
|
|
}
|