From 40dbc1b2bafed315bc966262342c70beda62998f Mon Sep 17 00:00:00 2001 From: Sosthene Date: Wed, 11 Dec 2024 23:39:42 +0100 Subject: [PATCH] Update pairing tests --- tests/pairing.rs | 153 +++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 86 deletions(-) diff --git a/tests/pairing.rs b/tests/pairing.rs index 922a117..267b1c7 100644 --- a/tests/pairing.rs +++ b/tests/pairing.rs @@ -2,15 +2,15 @@ use std::collections::HashMap; use std::str::FromStr; use sdk_client::api::{ - create_device_from_sp_wallet, create_new_process, create_response_prd, create_update_message, dump_device, get_address, get_update_proposals, pair_device, parse_cipher, reset_device, restore_device, set_process_cache, set_shared_secrets, setup, validate_state + create_device_from_sp_wallet, create_new_process, create_response_prd, create_update_message, dump_device, get_address, pair_device, parse_cipher, reset_device, restore_device, set_process_cache, set_shared_secrets, setup, update_process_state, validate_state }; use sdk_common::crypto::AnkSharedSecretHash; use sdk_common::log::debug; -use sdk_common::pcd::{Member, Pcd}; -use sdk_common::sp_client::bitcoin::hex::DisplayHex; +use sdk_common::pcd::{Member, Pcd, RoleDefinition}; use sdk_common::secrets::SecretsStore; +use sdk_common::sp_client::bitcoin::hex::FromHex; use sdk_common::sp_client::bitcoin::OutPoint; -use serde_json::{json, Value}; +use serde_json::{json, Map, Value}; use wasm_bindgen_test::*; @@ -97,6 +97,8 @@ fn test_pairing() { let mut bob_process_cache = HashMap::new(); let mut alice_secrets_store = SecretsStore::new(); let mut bob_secrets_store = SecretsStore::new(); + let mut alice_diff_cache = Vec::new(); + let mut bob_diff_cache = Vec::new(); debug!("==============================================\nStarting test_pairing\n=============================================="); @@ -163,6 +165,7 @@ fn test_pairing() { "key_parity": true, // This allows us to use a 32 bytes array in serialization }); + debug!("Alice creates the pairing process"); let create_process_return = create_new_process(pairing_init_state.to_string(), RELAY_ADDRESS.to_owned(), 1).unwrap(); let commit_msg = create_process_return.commit_to_send.unwrap(); @@ -184,12 +187,18 @@ fn test_pairing() { let updated_process = create_process_return.updated_process.unwrap(); alice_process_cache.insert(updated_process.commitment_tx, updated_process.current_process); + // Alice keeps track of the change she needs to validate + let create_process_diffs = updated_process.new_diffs; + + let new_state_id = &create_process_diffs.get(0).unwrap().new_state_merkle_root; + + alice_diff_cache.extend(create_process_diffs.iter()); + // We send the commit_msg to the relay we got the address from // now we create prd update for this new process - debug!("Alice sends an update prd to Bob"); - let root = ::create_merkle_tree(&commit_msg.pcd_commitment).unwrap().root().unwrap(); - let create_update_return = create_update_message(updated_process.commitment_tx.to_string(), root.to_lower_hex_string()).unwrap(); + debug!("Alice creates an update prd to Bob"); + let create_update_return = create_update_message(updated_process.commitment_tx.to_string(), new_state_id.clone()).unwrap(); let updated_process = create_update_return.updated_process.unwrap(); alice_process_cache.insert(updated_process.commitment_tx, updated_process.current_process); @@ -212,11 +221,40 @@ fn test_pairing() { let updated_process = bob_parsed_return.updated_process.unwrap(); + let parsed_prd_diffs = updated_process.new_diffs; + + // debug!("Bob creates process {} with state {}", updated_process.commitment_tx, new_state_id); bob_process_cache.insert(updated_process.commitment_tx, updated_process.current_process); - let prd_confirm_cipher = bob_parsed_return.ciphers_to_send.iter().next().unwrap(); + // Bob also keeps track of changes - debug!("Bob sends a Confirm Prd to Alice"); + bob_diff_cache.extend(parsed_prd_diffs.into_iter()); + + debug!("Bob can now fetch the data from storage using the hashes"); + // We have to cheat here and let Bob access Alice process cache + let process = alice_process_cache.get(&updated_process.commitment_tx).unwrap(); + + let state = process.get_state_for_commitments_root(&new_state_id).unwrap(); + + let hash2values: Map = bob_diff_cache.iter() + .filter(|diff| diff.new_state_merkle_root == *new_state_id) + .map(|diff| { + let encrypted_value = state.encrypted_pcd.as_object().unwrap().get(&diff.field).unwrap(); + (diff.value_commitment.clone(), encrypted_value.clone()) + }) + .collect(); + let update_process_res = update_process_state(updated_process.commitment_tx.to_string(), new_state_id.clone(), serde_json::to_string(&Value::Object(hash2values)).unwrap()).unwrap(); + + let updated_process = update_process_res.updated_process.unwrap(); + + let parsed_prd_diffs = updated_process.new_diffs; + + bob_process_cache.insert(updated_process.commitment_tx, updated_process.current_process); + + bob_diff_cache.extend(parsed_prd_diffs); + + // We can also prune the old diffs from the cache + bob_diff_cache.retain(|diff| diff.new_value != Value::Null); // this is only for testing, as we're playing both parts let bob_device = dump_device().unwrap(); @@ -227,34 +265,23 @@ fn test_pairing() { set_process_cache(serde_json::to_string(&alice_process_cache).unwrap()).unwrap(); set_shared_secrets(serde_json::to_string(&alice_secrets_store).unwrap()).unwrap(); - debug!("Alice receives the Confirm Prd"); - let alice_parsed_confirm = parse_cipher(prd_confirm_cipher.clone()).unwrap(); + let commitment_outpoint = alice_process_cache.keys().next().unwrap(); - debug!( - "Alice parsed Bob's Confirm Prd: {:#?}", - alice_parsed_confirm - ); + debug!("Alice can validate the new state of the process"); + let relevant_process = alice_process_cache.get(&commitment_outpoint).unwrap(); - // Alice simply shoots back the return value in the ws - let bob_received_pcd = alice_parsed_confirm.ciphers_to_send[0].clone(); - let commit_msg = alice_parsed_confirm.commit_to_send.unwrap(); - - // Take the relevant state out of the process - let relevant_process = alice_process_cache.get(&OutPoint::from_str(&commit_msg.init_tx).unwrap()).unwrap(); - - let concurrent_states = relevant_process.get_latest_concurrent_states().unwrap(); - let relevant_state = concurrent_states.into_iter().find(|s| s.pcd_commitment == commit_msg.pcd_commitment).unwrap(); - - let root = ::create_merkle_tree(&relevant_state.pcd_commitment).unwrap().root().unwrap(); + for diff in alice_diff_cache { + debug!("User validate diff: {:#?}", diff); + } // Alice can also sign her response and send it to Bob - let validate_state_return = validate_state(commit_msg.init_tx, root.to_lower_hex_string()).unwrap(); + let validate_state_return = validate_state(commitment_outpoint.to_string(), new_state_id.clone()).unwrap(); let updated_process = validate_state_return.updated_process.unwrap(); alice_process_cache.insert(updated_process.commitment_tx, updated_process.current_process); - let alice_response = create_response_prd(updated_process.commitment_tx.to_string(), root.to_lower_hex_string()).unwrap(); + let alice_response = create_response_prd(updated_process.commitment_tx.to_string(), new_state_id.clone()).unwrap(); // ======================= Bob reset_device().unwrap(); @@ -262,77 +289,31 @@ fn test_pairing() { set_process_cache(serde_json::to_string(&bob_process_cache).unwrap()).unwrap(); set_shared_secrets(serde_json::to_string(&bob_secrets_store).unwrap()).unwrap(); - debug!("Bob parses Alice's pcd"); - let bob_parsed_pcd_return = parse_cipher(bob_received_pcd).unwrap(); - - let updated_process = bob_parsed_pcd_return.updated_process.unwrap(); - - // Here we would update our database - bob_process_cache.insert( - updated_process.commitment_tx, - updated_process.current_process - ); - - // At this point, user must validate the pairing proposal received from Alice - // We decrypt the content of the pcd so that we can display to user what matters - let alice_proposal = get_update_proposals(updated_process.commitment_tx.to_string()).unwrap().decrypted_pcds; - - debug!("Alice proposal: {:#?}", alice_proposal); - - let (pcd_commitment_root, proposal) = alice_proposal.iter().next().unwrap(); - - // debug!("proposal: {:#?}", proposal); - - // get the roles from the proposal - let roles = proposal.extract_roles().unwrap(); - - // we check that the proposal contains only one member - assert!(roles.len() == 1); - assert!(roles["owner"].members.len() == 1); - - // we get all the addresses of the members of the proposal - let proposal_members = roles - .iter() - .flat_map(|(_, members)| members.members.iter().flat_map(|m| m.get_addresses())) - .collect::>(); - - // we can automatically check that a pairing member contains local device address + the one that sent the proposal - assert!(proposal_members.contains(&alice_address)); - assert!(proposal_members.contains(&bob_address)); - assert!(proposal_members.len() == 2); // no free riders - - // We remove the local address, but maybe that's the responsibility of the Member type - let proposal_members = proposal_members - .into_iter() - .filter(|m| m != &bob_address) - .collect::>(); - - debug!("proposal_members: {:?}", proposal_members); - - // we can now show all the addresses to the user on device to prompt confirmation - debug!("Pop-up: User confirmation"); + for diff in &bob_diff_cache { + if diff.need_validation { + debug!("Pop-up: User confirmation"); + debug!("{:#?}", diff); + } + } // If user is ok, we can add our own validation token // Get the whole commitment from the process - let bob_validated_process = validate_state(updated_process.commitment_tx.to_string(), pcd_commitment_root.to_string()).unwrap(); + let bob_validated_process = validate_state(updated_process.commitment_tx.to_string(), new_state_id.clone()).unwrap(); let updated_process = bob_validated_process.updated_process.unwrap(); bob_process_cache.insert(updated_process.commitment_tx, updated_process.current_process); - let bob_response = create_response_prd(updated_process.commitment_tx.to_string(), pcd_commitment_root.to_string()).unwrap(); + let bob_response = create_response_prd(updated_process.commitment_tx.to_string(), new_state_id.clone()).unwrap(); let ciphers = bob_response.ciphers_to_send; // We would send it to Alice to let her know we agree debug!("Bob pairs device with Alice"); - pair_device(updated_process.commitment_tx.to_string(), proposal_members).unwrap(); + let roles: HashMap = serde_json::from_value(bob_diff_cache.iter().find(|diff| diff.field == "roles").unwrap().new_value.clone()).unwrap(); + let owner = roles.get("owner").unwrap(); + let members_to_pair: Vec = owner.members.iter().flat_map(|m| m.get_addresses()).collect(); + pair_device(updated_process.commitment_tx.to_string(), members_to_pair).unwrap(); // We can also check alice response let parsed_alice_response = parse_cipher(alice_response.ciphers_to_send[0].clone()).unwrap(); - - debug!("parsed_alice_response: {:#?}", parsed_alice_response.updated_process.unwrap()); - - // Since we have enough validation we can send it directly to relay for commitment - - // login(); }