diff --git a/src/api.rs b/src/api.rs index 0a7f01c..692dcea 100644 --- a/src/api.rs +++ b/src/api.rs @@ -20,7 +20,7 @@ use anyhow::Error as AnyhowError; use anyhow::Result as AnyhowResult; use sdk_common::aes_gcm::aead::{Aead, Payload}; use sdk_common::crypto::{ - encrypt_with_key, AeadCore, Aes256Gcm, AnkSharedSecretHash, KeyInit, AAD + encrypt_with_key, AeadCore, Aes256Gcm, AnkSharedSecretHash, KeyInit, AAD, }; use sdk_common::process::{lock_processes, Process, ProcessState}; use sdk_common::signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof}; @@ -74,9 +74,7 @@ use sdk_common::sp_client::spclient::{SpWallet, SpendKey}; use crate::user::{lock_local_device, set_new_device, LOCAL_DEVICE}; use crate::wallet::{generate_sp_wallet, lock_freezed_utxos}; -use crate::{ - lock_messages, CACHEDMESSAGES, -}; +use crate::{lock_messages, CACHEDMESSAGES}; #[derive(Debug, PartialEq, Tsify, Serialize, Deserialize, Default)] #[tsify(into_wasm_abi, from_wasm_abi)] @@ -261,30 +259,6 @@ pub fn pair_device(commitment_tx: String, mut sp_addresses: Vec) -> ApiR Ok(()) } -#[wasm_bindgen] -pub fn get_pairing_tx() -> ApiResult { - let device = lock_local_device()?; - - if !device.is_linked() { - return Err(ApiError::new("Device is not linked".to_owned())); - } - - let pairing_commitment= device.get_process_commitment().unwrap(); - - let processes = lock_processes()?; - - let process = processes.get(&OutPoint::new(pairing_commitment, 0)).ok_or(ApiError::new("Pairing process not found".to_owned()))?; - - let state = process.get_latest_state().unwrap(); - - let mut decrypted_pcd = Map::new(); - state.encrypted_pcd.decrypt_fields(&state.keys, &mut decrypted_pcd)?; - - let pairing_tx = decrypted_pcd.get("pairing_tx").unwrap().as_str().unwrap(); - - Ok(pairing_tx.to_owned()) -} - #[wasm_bindgen] pub fn unpair_device() -> ApiResult<()> { let mut local_device = lock_local_device()?; @@ -693,11 +667,7 @@ fn try_decrypt_with_processes( aad: AAD, }, ) { - return Some(( - plain, - address, - *outpoint, - )); + return Some((plain, address, *outpoint)); } } } @@ -705,48 +675,116 @@ fn try_decrypt_with_processes( } #[wasm_bindgen] -pub fn response_prd( +/// Produce a proof and append it to a prd +pub fn add_validation_token_to_prd( root_commitment: String, - prd: String, // The Prd we respond to + prd_commitment: String, approval: bool, ) -> ApiResult { + let prd_hash = AnkPrdHash::from_str(&prd_commitment)?; + let outpoint = OutPoint::from_str(&root_commitment)?; + + // find the prd in the registered process + let mut processes = lock_processes()?; + let process = processes + .get_mut(&outpoint) + .ok_or(ApiError::new("Unknown process".to_owned()))?; + + let prd_ref = process + .get_impending_requests_mut() + .into_iter() + .find(|r| r.create_commitment() == prd_hash) + .ok_or(ApiError::new( + "Failed to find the prd in registered processes".to_owned(), + ))?; + + let local_device = lock_local_device()?; + + let wallet = local_device.get_wallet(); + + let spend_key: SecretKey = wallet.get_client().get_spend_key().try_into()?; + + match prd_ref.prd_type { + PrdType::Update => { + let new_state = Value::from_str(&prd_ref.payload)?; + + let new_state_commitment = new_state.tagged_hash(); + + let message_hash = if approval { + AnkHash::ValidationYes(AnkValidationYesHash::from_commitment(new_state_commitment)) + } else { + AnkHash::ValidationNo(AnkValidationNoHash::from_commitment(new_state_commitment)) + }; + + let proof = Proof::new(message_hash, spend_key); + + prd_ref.validation_tokens.push(proof); + + Ok(ApiReturn { + updated_process: Some((root_commitment, process.clone())), + ..Default::default() + }) + } + _ => return Err(ApiError::new("Can't validate that prd".to_owned())), + } +} + +#[wasm_bindgen] +pub fn response_prd( + root_commitment: String, + prd_commitment: String, // The commitment to the Prd we respond to + approval: bool, +) -> ApiResult { + let prd_hash = AnkPrdHash::from_str(&prd_commitment)?; + let outpoint = OutPoint::from_str(&root_commitment)?; let local_device = lock_local_device()?; let member = local_device .to_member() .ok_or(ApiError::new("Unpaired device".to_owned()))?; - let prd_to_respond = serde_json::from_str::(&prd)?; + // find the prd in the registered process + let mut processes = lock_processes()?; + let process = processes + .get_mut(&outpoint) + .ok_or(ApiError::new("Unknown process".to_owned()))?; - // Probably we should answer differently depending on the type of prd - let message_hash = match prd_to_respond.prd_type { + let prd_ref = process + .get_impending_requests_mut() + .into_iter() + .find(|r| r.create_commitment() == prd_hash) + .ok_or(ApiError::new( + "Failed to find the prd in registered processes".to_owned(), + ))?; + + match prd_ref.prd_type { PrdType::Update => { - let pcd_hash: AnkPcdHash = - AnkPcdHash::from_value(&Value::from_str(&prd_to_respond.payload)?); + let pcd_hash: AnkPcdHash = AnkPcdHash::from_value(&Value::from_str(&prd_ref.payload)?); - let message_hash = if approval { - AnkHash::ValidationYes(AnkValidationYesHash::from_commitment(pcd_hash)) - } else { - AnkHash::ValidationNo(AnkValidationNoHash::from_commitment(pcd_hash)) - }; - - let proof = Proof::new( - message_hash, - local_device - .get_wallet() - .get_client() - .get_spend_key() - .try_into()?, - ); - - let prd = Prd::new_response( + let prd_response = Prd::new_response( OutPoint::from_str(&root_commitment)?, serde_json::to_string(&member)?, - vec![proof], + prd_ref.validation_tokens.clone(), pcd_hash, ); + let prd_msg = prd_response.to_network_msg(local_device.get_wallet())?; + + let mut ciphers = vec![]; + for (sp_address, shared_secret) in process.get_all_secrets() { + if sp_address.to_string() + == local_device + .get_wallet() + .get_client() + .get_receiving_address() + { + continue; + } + let cipher = encrypt_with_key(shared_secret.as_byte_array(), prd_msg.as_bytes())?; + ciphers.push(cipher.to_lower_hex_string()); + } + return Ok(ApiReturn { - ciphers_to_send: vec![prd.to_network_msg(local_device.get_wallet())?.to_string()], + ciphers_to_send: ciphers, ..Default::default() }); } @@ -922,10 +960,7 @@ fn handle_prd( let shared_secret = new_shared_secret .ok_or_else(|| anyhow::Error::msg("Missing shared secret for new process"))?; let mut shared_secrets = HashMap::new(); - shared_secrets.insert( - sp_address, - shared_secret, - ); + shared_secrets.insert(sp_address, shared_secret); entry.insert(Process::new(vec![], shared_secrets, vec![])) } }; @@ -976,7 +1011,7 @@ fn handle_prd( PrdType::Response => { // We must know of a prd update that the response answers to let original_request = relevant_process - .get_impending_requests() + .get_impending_requests_mut() .into_iter() .find(|r| { if r.prd_type != PrdType::Update { @@ -987,7 +1022,16 @@ fn handle_prd( }) .ok_or(anyhow::Error::msg("Original request not found"))?; + // Once we found the prd update, we can add the received proofs as validation tokens + original_request + .validation_tokens + .extend(prd.validation_tokens); + + // We must return an update of the process + let updated_process = (prd.root_commitment, relevant_process.clone()); + return Ok(ApiReturn { + updated_process: Some(updated_process), ..Default::default() }); } @@ -1013,8 +1057,6 @@ fn handle_pcd(plain: Vec, root_commitment: OutPoint) -> AnyhowResult ApiResult { } #[wasm_bindgen] -/// This takes a reference to a process and creates a commit msg for the latest state +/// This takes a reference to a process and creates a commit msg for the latest state pub fn create_commit_message( - init_commitment_outpoint: String, + init_commitment_outpoint: String, relay_address: String, fee_rate: u32, ) -> ApiResult { @@ -1098,7 +1140,7 @@ pub fn create_commit_message( 1 => { // This is a creation let state = process.get_latest_state().unwrap(); - if state.commited_in != OutPoint::null() { + if state.commited_in.vout != u32::MAX { return Err(ApiError::new("Latest state is already commited".to_owned())); } let encrypted_pcd = state.encrypted_pcd.clone(); @@ -1139,7 +1181,9 @@ pub fn create_commit_message( // We're updating an existing process // Check that initial outpoint is not a placeholder and that latest state has a commited_in of null if outpoint.vout != u32::MAX { - return Err(ApiError::new("Initial outpoint is a placeholder".to_owned())); + return Err(ApiError::new( + "Initial outpoint is a placeholder".to_owned(), + )); } let state = process.get_latest_state().unwrap(); if state.commited_in != OutPoint::null() { @@ -1261,7 +1305,12 @@ pub fn create_update_transaction( let mut fields2keys = Map::new(); let mut fields2cipher = Map::new(); let encrypted_pcd = pcd.clone(); - let fields_to_encrypt: Vec = encrypted_pcd.as_object().unwrap().keys().map(|k| k.clone()).collect(); + let fields_to_encrypt: Vec = encrypted_pcd + .as_object() + .unwrap() + .keys() + .map(|k| k.clone()) + .collect(); encrypted_pcd.encrypt_fields(&fields_to_encrypt, &mut fields2keys, &mut fields2cipher); let local_device = lock_local_device()?; @@ -1324,7 +1373,8 @@ pub fn create_update_transaction( let cipher = encrypt_with_key(shared_secret.as_byte_array(), prd_msg.as_bytes())?; ciphers.push(cipher.to_lower_hex_string()); - relevant_process.insert_shared_secret(SilentPaymentAddress::try_from(sp_address)?, shared_secret); + relevant_process + .insert_shared_secret(SilentPaymentAddress::try_from(sp_address)?, shared_secret); } } relevant_process.insert_impending_request(full_prd); @@ -1369,17 +1419,20 @@ pub fn create_faucet_msg() -> ApiResult { } /// Get active update proposals for a given process outpoint -/// Returns a vector with the latest commited state first and all active proposals +/// Returns a vector with the latest commited state first, if any, and all active proposals #[wasm_bindgen] pub fn get_update_proposals(process_outpoint: String) -> ApiResult> { let outpoint = OutPoint::from_str(&process_outpoint)?; let mut processes = lock_processes()?; + // TODO: We clone the process to prevent double borrowing issue, this can certainly be improved let relevant_process = processes .get(&outpoint) .ok_or(ApiError::new("process not found".to_owned()))?; + let mut updated_process = relevant_process.clone(); + let update_proposals: Vec<&Prd> = relevant_process .get_impending_requests() .into_iter() @@ -1395,17 +1448,46 @@ pub fn get_update_proposals(process_outpoint: String) -> ApiResult> let mut res = vec![]; - // If we don't have a latest state, it simply means this update is a creation - if let Some(latest_state) = relevant_process.get_latest_state() { - res.push(serde_json::to_string(&latest_state)?); + // We first push the last commited state, if any + match relevant_process.get_latest_commited_state() { + Some(state) => res.push(serde_json::to_string(state)?), + None => () } + // Maybe that's the right place for adding a new state with what we've got from the prd update + // We should probably iterate on every update proposals and see which one don't have a state yet + let mut update_states = false; for proposal in update_proposals { + // Is there a state that matches this proposal? If not, let's add it let pcd = Value::from_str(&proposal.payload)?; + let pcd_hash = AnkPcdHash::from_value(&pcd); + // We look for a pending state for the exact same state as the one in the proposal + if let None = relevant_process.get_latest_concurrent_states() + .into_iter() + .find(|state| { + AnkPcdHash::from_value(&state.encrypted_pcd) == pcd_hash + }) + { + // If not, we first add a new state + updated_process.insert_state(ProcessState { + commited_in: OutPoint::new(Txid::from_str(&pcd_hash.to_string())?, u32::MAX), + encrypted_pcd: pcd.clone(), + keys: proposal.keys.clone(), + validation_tokens: proposal.validation_tokens.clone() + }); + update_states = true; + } + // We add the decrypted state to our return variable let mut decrypted_pcd = Map::new(); pcd.decrypt_fields(&proposal.keys, &mut decrypted_pcd)?; res.push(serde_json::to_string(&decrypted_pcd)?); } + if update_states { + // We replace the process + processes.insert(outpoint, updated_process); + } + // else we do nothing + Ok(res) } diff --git a/tests/pairing.rs b/tests/pairing.rs index a4917de..15f1dcb 100644 --- a/tests/pairing.rs +++ b/tests/pairing.rs @@ -2,13 +2,13 @@ use std::collections::HashMap; use std::str::FromStr; use sdk_client::api::{ - create_device_from_sp_wallet, create_update_transaction, dump_device, dump_process_cache, - get_address, get_outputs, get_update_proposals, pair_device, parse_cipher, reset_device, - response_prd, restore_device, set_process_cache, setup, ApiReturn, + add_validation_token_to_prd, create_commit_message, create_device_from_sp_wallet, create_update_transaction, dump_device, dump_process_cache, get_address, get_outputs, get_update_proposals, pair_device, parse_cipher, reset_device, response_prd, restore_device, set_process_cache, setup, ApiReturn }; -use sdk_common::log::debug; -use sdk_common::pcd::{Member, Pcd, RoleDefinition}; -use sdk_common::sp_client::bitcoin::OutPoint; +use sdk_common::log::{debug, info}; +use sdk_common::pcd::{Member, RoleDefinition}; +use sdk_common::sp_client::bitcoin::consensus::deserialize; +use sdk_common::sp_client::bitcoin::hex::FromHex; +use sdk_common::sp_client::bitcoin::{OutPoint, Transaction}; use sdk_common::sp_client::spclient::OwnedOutput; use serde_json::{json, Value}; @@ -24,6 +24,9 @@ wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] fn test_pairing() { setup(); + let mut alice_process_cache = HashMap::new(); + let mut bob_process_cache = HashMap::new(); + debug!("==============================================\nStarting test_pairing\n=============================================="); // ========================= Alice @@ -43,10 +46,10 @@ fn test_pairing() { ]) .unwrap(); + let initial_session_privkey = [0u8; 32]; + let initial_session_pubkey = [0u8; 32]; + let pairing_init_state = json!({ - "html": "", - "style": "", - "script": "", "description": "AliceBob", "roles": { "owner": { @@ -59,15 +62,20 @@ fn test_pairing() { { "quorum": 1.0, "fields": [ + "description", "roles", - "pairing_tx" + "session_privkey", + "session_pubkey", + "key_parity" ], "min_sig_member": 1.0 } ] } }, - "pairing_tx": OutPoint::null(), + "session_privkey": initial_session_privkey, + "session_pubkey": initial_session_pubkey, + "key_parity": true, // This allows us to use a 32 bytes array in serialization }); debug!("Alice pairs her device"); @@ -79,57 +87,22 @@ fn test_pairing() { create_update_transaction(None, pairing_init_state.to_string(), 1).unwrap(); let (root_outpoint, alice_init_process) = alice_pairing_return.updated_process.unwrap(); - let alice_pcd_commitment = Value::from_str( - &alice_init_process - .get_impending_requests() - .get(0) - .unwrap() - .payload, - ) - .unwrap() - .tagged_hash(); + alice_process_cache.insert(root_outpoint.clone(), alice_init_process.clone()); - let pairing_tx = alice_pairing_return.new_tx_to_send.unwrap(); + let pairing_tx_msg = alice_pairing_return.new_tx_to_send.unwrap(); // This is only for testing, the relay takes care of that in prod 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(&pairing_tx, alice_outputs); + let alice_pairing_tweak_data = + helper_get_tweak_data(&pairing_tx_msg.transaction, alice_outputs); // End of the test only part // Alice parses her own transaction - helper_parse_transaction(&pairing_tx, &alice_pairing_tweak_data); - - // Notify user that we're waiting for confirmation from the other device - // We can update the local device with the actual pairing outpoint - pair_device( - OutPoint::new(pairing_tx.txid(), 0).to_string(), - vec![helper_get_bob_address()], - ) - .unwrap(); - - // TODO unpair device - - // We can produce the prd response now even if we can't use it yet - let alice_prd_response = response_prd( - root_outpoint, - alice_init_process - .get_impending_requests() - .get(0) - .unwrap() - .to_string(), - true, - ) - .unwrap() - .ciphers_to_send - .get(0) - .unwrap() - .clone(); - - // We can also create the first login transaction and sign it + helper_parse_transaction(&pairing_tx_msg.transaction, &alice_pairing_tweak_data); // this is only for testing, as we're playing both parts let alice_device = dump_device().unwrap(); @@ -141,7 +114,7 @@ fn test_pairing() { // Bob receives Alice pairing transaction debug!("Bob parses Alice pairing transaction"); - helper_parse_transaction(&pairing_tx, &alice_pairing_tweak_data); + helper_parse_transaction(&pairing_tx_msg.transaction, &alice_pairing_tweak_data); debug!("Bob receives the prd"); let mut bob_retrieved_prd: ApiReturn = ApiReturn::default(); @@ -162,12 +135,9 @@ fn test_pairing() { debug!("Bob retrieved prd: {:#?}", bob_retrieved_prd); let (root_commitment, relevant_process) = bob_retrieved_prd.updated_process.unwrap(); - let pcd_commitment = relevant_process - .get_impending_requests() - .get(0) - .unwrap() - .payload - .clone(); + + bob_process_cache.insert(root_commitment.clone(), relevant_process); + let prd_confirm_cipher = bob_retrieved_prd.ciphers_to_send.iter().next().unwrap(); debug!("Bob sends a Confirm Prd to Alice"); @@ -182,9 +152,37 @@ fn test_pairing() { set_process_cache(alice_processes).unwrap(); debug!("Alice receives the Confirm Prd"); - let alice_parsed_prd = parse_cipher(prd_confirm_cipher.clone()).unwrap(); + let alice_parsed_confirm = parse_cipher(prd_confirm_cipher.clone()).unwrap(); - debug!("Alice parsed Bob's Confirm Prd: {:#?}", alice_parsed_prd); + debug!( + "Alice parsed Bob's Confirm Prd: {:#?}", + alice_parsed_confirm + ); + + // Alice simply shoots back the return value in the ws + let bob_received_pcd = alice_parsed_confirm.ciphers_to_send[0].clone(); + + // Now that we're sure that bob got the prd udpate we also produce the prd response and shoot it + let alice_prd_update_commitment = alice_init_process + .get_impending_requests() + .get(0) + .unwrap() + .create_commitment(); + let (_, alice_validated_prd) = add_validation_token_to_prd( + root_outpoint.clone(), + alice_prd_update_commitment.to_string(), + true, + ) + .unwrap() + .updated_process + .unwrap(); + + alice_process_cache.insert(root_outpoint.clone(), alice_validated_prd); + + let alice_prd_response = + response_prd(root_outpoint, alice_prd_update_commitment.to_string(), true).unwrap(); + + let bob_received_response = alice_prd_response.ciphers_to_send.get(0).unwrap().clone(); // ======================= Bob reset_device().unwrap(); @@ -192,29 +190,39 @@ fn test_pairing() { set_process_cache(bob_processes).unwrap(); debug!("Bob parses Alice's pcd"); - let bob_parsed_pcd_return = parse_cipher(alice_parsed_prd.ciphers_to_send[0].clone()).unwrap(); + let bob_parsed_pcd_return = parse_cipher(bob_received_pcd).unwrap(); debug!("bob_parsed_pcd: {:#?}", bob_parsed_pcd_return); - let (root_commitment, prd_update) = bob_parsed_pcd_return.updated_process.unwrap(); + // Here we would update our database + bob_process_cache.insert( + root_commitment.clone(), + bob_parsed_pcd_return.updated_process.unwrap().1, + ); + + // We now need Alice prd response, and update our process with it + debug!("Bob also parses alice prd response"); + let bob_parsed_response = parse_cipher(bob_received_response).unwrap(); + + debug!("bob_parsed_response: {:#?}", bob_parsed_response); + + bob_process_cache.insert( + root_commitment.clone(), + bob_parsed_response.updated_process.unwrap().1, + ); + + debug!("{:#?}", bob_process_cache.get(&root_commitment).unwrap()); // 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(root_commitment.clone()).unwrap(); + let alice_proposal = get_update_proposals(root_commitment.clone()).unwrap(); debug!("Alice proposal: {:#?}", alice_proposal); - // get the pairing tx from the proposal let proposal = Value::from_str(&alice_proposal.get(0).unwrap()).unwrap(); debug!("proposal: {:#?}", proposal); - let pairing_tx = proposal - .get("pairing_tx") - .unwrap() - .as_str() - .unwrap() - .trim_matches('"'); + // get the roles from the proposal let roles = proposal .get("roles") .and_then(|v| Value::from_str(v.as_str().unwrap()).ok()) @@ -253,31 +261,40 @@ fn test_pairing() { debug!("proposal_members: {:?}", proposal_members); - // we can now show all the addresses + pairing tx to the user on device to prompt confirmation + // we can now show all the addresses to the user on device to prompt confirmation + info!("Pop-up: User confirmation"); + + // If user is ok, we can add our own validation token + let prd_to_respond = bob_process_cache + .get(&root_commitment) + .unwrap() + .get_impending_requests() + .get(0) + .unwrap() + .to_owned(); + let bob_added_validation = + add_validation_token_to_prd(root_commitment.clone(), prd_to_respond.create_commitment().to_string(), true).unwrap(); + + bob_process_cache.insert( + root_commitment.clone(), + bob_added_validation.updated_process.unwrap().1, + ); + + // We create the commit msg for the relay that includes Alice and Bob's proofs + let commit_msg = create_commit_message(root_commitment.clone(), "tsp1qqvfm6wvd55r68ltysdhmagg7qavxrzlmm9a7tujsp8qqy6x2vr0muqajt5p2jdxfw450wyeygevypxte29sxlxzgprmh2gwnutnt09slrcqqy5h4".to_owned(), 1).unwrap().commit_to_send.unwrap(); + + let tx: Transaction = deserialize(&Vec::from_hex(&commit_msg.init_tx).unwrap()).unwrap(); + + // We send the commit_msg to the relay we got the address from + // We also send + + // We can just take the txid of the transaction we created for the commitment + let commitment_outpoint = OutPoint::new(tx.txid(), 0); debug!("Bob pairs device with Alice"); - pair_device(pairing_tx.to_owned(), proposal_members.clone()).unwrap(); - - let prd_to_respond = prd_update.get_impending_requests().get(0).unwrap().to_string(); - - // Bob signs the proposal and sends a prd response too - let bob_prd_response = response_prd(root_commitment, prd_to_respond, true) - .unwrap() - .ciphers_to_send - .get(0) - .unwrap(); + pair_device(commitment_outpoint.to_string(), proposal_members).unwrap(); // To make the pairing effective, alice and bob must now creates a new transaction where they both control one output - // login logic: user must have access to both devices to login - // user must still have access to both devices in case an action needs both devices (as defined in the roles) - // process can define that acting on some fields of the state only needs a fraction of the devices to sign - - // Problem: we need both devices to sign the next login transaction. - // Simplest solution: device A creates the transaction with both inputs and outputs, signs its input and sends to device B - // device B notify user that a login is underway, user either accepts (sign the transaction and broadcast), or refuses (actually we should think of some revokation step from here) - // login(); - - // Once we know this tx id, we can commit to the relay } diff --git a/tests/utils.rs b/tests/utils.rs index 177d7bb..e04736c 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -2,21 +2,25 @@ use std::collections::HashMap; use sdk_client::api::{parse_new_tx, ApiReturn}; use sdk_common::network::NewTxMessage; -use sdk_common::sp_client::bitcoin::consensus::serialize; -use sdk_common::sp_client::bitcoin::hex::DisplayHex; +use sdk_common::sp_client::bitcoin::consensus::{deserialize, serialize}; +use sdk_common::sp_client::bitcoin::hex::{DisplayHex, FromHex}; use sdk_common::sp_client::bitcoin::secp256k1::PublicKey; use sdk_common::sp_client::bitcoin::{OutPoint, ScriptBuf, Transaction}; use sdk_common::sp_client::silentpayments::utils::receiving::{ calculate_tweak_data, get_pubkey_from_input, }; use sdk_common::sp_client::spclient::{OwnedOutput, SpWallet}; -use serde_json; +use serde_json::{self, json, Value}; // We're using alice and bob for clarity, but it's important to remember that for pairing and login Alice and Bob are the same person -pub const ALICE_START_WALLET: &str = "{\"client\":{\"network\":\"regtest\",\"label\":\"default\",\"scan_sk\":\"e3d8922a41a7cb1a84a90f4334e987bb5ea2df6a1fdf44f789b5302de119f9e2\",\"spend_key\":{\"Secret\":\"93292e5b21042c6cfc742ba30e9d2a1e01609b12d154a1825184ed12c7b9631b\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Regtest\",\"scan_pubkey\":[2,104,242,105,185,6,124,208,34,44,149,52,163,38,63,221,150,12,198,24,95,143,126,235,37,149,233,88,118,32,86,233,152],\"spend_pubkey\":[3,198,82,196,243,12,59,126,109,143,144,157,128,176,168,94,54,134,232,139,115,102,11,178,128,244,239,251,40,228,67,153,72],\"change_label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"labels\":[[\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",[2,244,223,255,57,50,216,27,133,112,138,69,120,126,85,110,6,242,141,33,136,191,82,164,241,54,179,115,84,161,145,174,154]]]}},\"outputs\":{\"wallet_fingerprint\":[187,119,108,230,171,125,106,11],\"birthday\":1620,\"last_scan\":2146,\"outputs\":{\"9a4a67cc5a40bf882d8b300d91024d7c97024b3b68b2df7745a5b9ea1df1888c:1\":{\"blockheight\":1620,\"tweak\":\"b8b63b3ed97d297b744135cfac2fb4a344c881a77543b71f1fcd16bc67514f26\",\"amount\":3938643,\"script\":\"51205b7b324bb71d411e32f2c61fda5d1db23f5c7d6d416a77fab87c913a1b120be1\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":\"Unspent\"}}},\"tx_history\":[]}"; -pub const ALICE_LOGIN_WALLET: &str = "{\"client\":{\"label\":\"default\",\"scan_sk\":\"e3d8922a41a7cb1a84a90f4334e987bb5ea2df6a1fdf44f789b5302de119f9e2\",\"spend_key\":{\"Secret\":\"93292e5b21042c6cfc742ba30e9d2a1e01609b12d154a1825184ed12c7b9631b\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Regtest\",\"scan_pubkey\":[2,104,242,105,185,6,124,208,34,44,149,52,163,38,63,221,150,12,198,24,95,143,126,235,37,149,233,88,118,32,86,233,152],\"spend_pubkey\":[3,198,82,196,243,12,59,126,109,143,144,157,128,176,168,94,54,134,232,139,115,102,11,178,128,244,239,251,40,228,67,153,72],\"change_label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"labels\":[[\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",[2,244,223,255,57,50,216,27,133,112,138,69,120,126,85,110,6,242,141,33,136,191,82,164,241,54,179,115,84,161,145,174,154]]]},\"network\":\"regtest\"},\"outputs\":{\"wallet_fingerprint\":[187,119,108,230,171,125,106,11],\"birthday\":1620,\"last_scan\":2146,\"outputs\":{\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:1\":{\"blockheight\":0,\"tweak\":\"7c84a3074c18c23a65eceaca49a327989ef6e7240e0e080421afb80f06906d73\",\"amount\":306,\"script\":\"5120eb78084d7a2ccbdb7eb7e9bba7cf875c4e54a5aba0beac57c5d3e41133bd8fdd\",\"label\":null,\"spend_status\":\"Unspent\"},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:2\":{\"blockheight\":0,\"tweak\":\"e3e21d551e933199f8c977bc0362616bdfb128da7ca9728bd7254977541c39cc\",\"amount\":3936897,\"script\":\"5120df3af55a63bd056c5d6d09f47a3a19c382d938c08db8bc41a59c5235970209ad\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":\"Unspent\"},\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f:0\":{\"blockheight\":0,\"tweak\":\"6e5c1d4690b9ff4fa26e5185ada25af5c2987650e629a518db8a43fdaad7a26c\",\"amount\":349,\"script\":\"512088ac90e180c87b7fa6aa33db4c72a8620cd08fda3ba1c71430b904eb068c587f\",\"label\":null,\"spend_status\":\"Unspent\"},\"9a4a67cc5a40bf882d8b300d91024d7c97024b3b68b2df7745a5b9ea1df1888c:1\":{\"blockheight\":1620,\"tweak\":\"b8b63b3ed97d297b744135cfac2fb4a344c881a77543b71f1fcd16bc67514f26\",\"amount\":3938643,\"script\":\"51205b7b324bb71d411e32f2c61fda5d1db23f5c7d6d416a77fab87c913a1b120be1\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":{\"Spent\":\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292\"}}}},\"tx_history\":[]}"; -pub const BOB_START_WALLET: &str = "{\"client\":{\"label\":\"default\",\"scan_sk\":\"0de90b7195c1380d5fde13de3f1d66d53423a9896314839e36ba672653af60b4\",\"spend_key\":{\"Secret\":\"affe686075ecbe17b8ce7de45ec31314804259d0a4bc1c863de21ffd6dc598f8\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Regtest\",\"scan_pubkey\":[2,85,96,92,243,247,237,192,205,9,178,146,101,237,132,232,15,2,69,138,31,118,76,140,142,207,90,13,192,94,254,150,133],\"spend_pubkey\":[3,5,157,91,250,169,41,61,190,37,30,98,152,253,180,138,250,86,162,102,82,148,130,220,44,153,127,83,43,246,93,17,232],\"change_label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"labels\":[[\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",[2,237,237,247,213,154,87,34,239,168,235,87,122,152,94,41,35,101,184,201,58,201,6,185,58,157,52,208,129,167,2,224,198]]]},\"network\":\"regtest\"},\"outputs\":{\"wallet_fingerprint\":[203,200,4,248,139,36,241,232],\"birthday\":2146,\"last_scan\":2146,\"outputs\":{\"fbd9c63e0dd08c2569b51a0d6095a79ee2acfcac66acdb594328a095f1fadb63:1\":{\"blockheight\":2146,\"tweak\":\"678dbcbdb40cd3733c8dbbd508761a0937009cf75a9f466e3c98877e79037cbc\",\"amount\":99896595,\"script\":\"5120deab0c5a3d23de30477b0b5a95a261c96e29afdd9813c665d2bf025ad2b3f919\",\"label\":null,\"spend_status\":\"Unspent\"}}},\"tx_history\":[]}"; -pub const BOB_LOGIN_WALLET: &str = "{\"client\":{\"label\":\"default\",\"scan_sk\":\"0de90b7195c1380d5fde13de3f1d66d53423a9896314839e36ba672653af60b4\",\"spend_key\":{\"Secret\":\"affe686075ecbe17b8ce7de45ec31314804259d0a4bc1c863de21ffd6dc598f8\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Regtest\",\"scan_pubkey\":[2,85,96,92,243,247,237,192,205,9,178,146,101,237,132,232,15,2,69,138,31,118,76,140,142,207,90,13,192,94,254,150,133],\"spend_pubkey\":[3,5,157,91,250,169,41,61,190,37,30,98,152,253,180,138,250,86,162,102,82,148,130,220,44,153,127,83,43,246,93,17,232],\"change_label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"labels\":[[\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",[2,237,237,247,213,154,87,34,239,168,235,87,122,152,94,41,35,101,184,201,58,201,6,185,58,157,52,208,129,167,2,224,198]]]},\"network\":\"regtest\"},\"outputs\":{\"wallet_fingerprint\":[203,200,4,248,139,36,241,232],\"birthday\":2146,\"last_scan\":2146,\"outputs\":{\"93722ea2fb9b74954210b4cdd1360e280b7ff1bc156d6b75f847e62411c588fb:0\":{\"blockheight\":0,\"tweak\":\"da5e3aa2378e3a257f99eb1e0ae4c672916f6a2f32a8ed9a8e146f2074da981b\",\"amount\":443,\"script\":\"51209eb9e950127b6a7d81668f25b4d5b164b42dafe59ce40b80e6c489ec983540d7\",\"label\":null,\"spend_status\":\"Unspent\"},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:0\":{\"blockheight\":0,\"tweak\":\"0e3395ff27bde9187ffaeeb2521f6277d3b83911f16ccbaf59a1a68d99a0ab93\",\"amount\":1200,\"script\":\"512010f06f764cbc923ec3198db946307bf0c06a1b4f09206055e47a6fec0a33d52c\",\"label\":null,\"spend_status\":{\"Spent\":\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f\"}},\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f:1\":{\"blockheight\":0,\"tweak\":\"f0ad83734cdc7d73575e5a32651390cf30b92cc7e44cf94ec37da46900ecaf71\",\"amount\":654,\"script\":\"5120230cc1e85829be238e666f469653cbc2f1c0e3675a9bf33e1d1f91115f5dd306\",\"label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"spend_status\":\"Unspent\"},\"fbd9c63e0dd08c2569b51a0d6095a79ee2acfcac66acdb594328a095f1fadb63:1\":{\"blockheight\":2146,\"tweak\":\"678dbcbdb40cd3733c8dbbd508761a0937009cf75a9f466e3c98877e79037cbc\",\"amount\":99896595,\"script\":\"5120deab0c5a3d23de30477b0b5a95a261c96e29afdd9813c665d2bf025ad2b3f919\",\"label\":null,\"spend_status\":\"Unspent\"}}},\"tx_history\":[]}"; +pub const ALICE_START_WALLET: &str = "{\"client\":{\"network\":\"testnet\",\"label\":\"default\",\"scan_sk\":\"e3d8922a41a7cb1a84a90f4334e987bb5ea2df6a1fdf44f789b5302de119f9e2\",\"spend_key\":{\"Secret\":\"93292e5b21042c6cfc742ba30e9d2a1e01609b12d154a1825184ed12c7b9631b\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Testnet\",\"scan_pubkey\":[2,104,242,105,185,6,124,208,34,44,149,52,163,38,63,221,150,12,198,24,95,143,126,235,37,149,233,88,118,32,86,233,152],\"spend_pubkey\":[3,198,82,196,243,12,59,126,109,143,144,157,128,176,168,94,54,134,232,139,115,102,11,178,128,244,239,251,40,228,67,153,72],\"change_label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"labels\":[[\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",[2,244,223,255,57,50,216,27,133,112,138,69,120,126,85,110,6,242,141,33,136,191,82,164,241,54,179,115,84,161,145,174,154]]]}},\"outputs\":{\"wallet_fingerprint\":[187,119,108,230,171,125,106,11],\"birthday\":1620,\"last_scan\":2146,\"outputs\":{\"9a4a67cc5a40bf882d8b300d91024d7c97024b3b68b2df7745a5b9ea1df1888c:1\":{\"blockheight\":1620,\"tweak\":\"b8b63b3ed97d297b744135cfac2fb4a344c881a77543b71f1fcd16bc67514f26\",\"amount\":3938643,\"script\":\"51205b7b324bb71d411e32f2c61fda5d1db23f5c7d6d416a77fab87c913a1b120be1\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":\"Unspent\"}}},\"tx_history\":[]}"; +pub const ALICE_LOGIN_WALLET: &str = "{\"client\":{\"label\":\"default\",\"scan_sk\":\"e3d8922a41a7cb1a84a90f4334e987bb5ea2df6a1fdf44f789b5302de119f9e2\",\"spend_key\":{\"Secret\":\"93292e5b21042c6cfc742ba30e9d2a1e01609b12d154a1825184ed12c7b9631b\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Testnet\",\"scan_pubkey\":[2,104,242,105,185,6,124,208,34,44,149,52,163,38,63,221,150,12,198,24,95,143,126,235,37,149,233,88,118,32,86,233,152],\"spend_pubkey\":[3,198,82,196,243,12,59,126,109,143,144,157,128,176,168,94,54,134,232,139,115,102,11,178,128,244,239,251,40,228,67,153,72],\"change_label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"labels\":[[\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",[2,244,223,255,57,50,216,27,133,112,138,69,120,126,85,110,6,242,141,33,136,191,82,164,241,54,179,115,84,161,145,174,154]]]},\"network\":\"testnet\"},\"outputs\":{\"wallet_fingerprint\":[187,119,108,230,171,125,106,11],\"birthday\":1620,\"last_scan\":2146,\"outputs\":{\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:1\":{\"blockheight\":0,\"tweak\":\"7c84a3074c18c23a65eceaca49a327989ef6e7240e0e080421afb80f06906d73\",\"amount\":306,\"script\":\"5120eb78084d7a2ccbdb7eb7e9bba7cf875c4e54a5aba0beac57c5d3e41133bd8fdd\",\"label\":null,\"spend_status\":\"Unspent\"},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:2\":{\"blockheight\":0,\"tweak\":\"e3e21d551e933199f8c977bc0362616bdfb128da7ca9728bd7254977541c39cc\",\"amount\":3936897,\"script\":\"5120df3af55a63bd056c5d6d09f47a3a19c382d938c08db8bc41a59c5235970209ad\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":\"Unspent\"},\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f:0\":{\"blockheight\":0,\"tweak\":\"6e5c1d4690b9ff4fa26e5185ada25af5c2987650e629a518db8a43fdaad7a26c\",\"amount\":349,\"script\":\"512088ac90e180c87b7fa6aa33db4c72a8620cd08fda3ba1c71430b904eb068c587f\",\"label\":null,\"spend_status\":\"Unspent\"},\"9a4a67cc5a40bf882d8b300d91024d7c97024b3b68b2df7745a5b9ea1df1888c:1\":{\"blockheight\":1620,\"tweak\":\"b8b63b3ed97d297b744135cfac2fb4a344c881a77543b71f1fcd16bc67514f26\",\"amount\":3938643,\"script\":\"51205b7b324bb71d411e32f2c61fda5d1db23f5c7d6d416a77fab87c913a1b120be1\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":{\"Spent\":\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292\"}}}},\"tx_history\":[]}"; +pub const BOB_START_WALLET: &str = "{\"client\":{\"label\":\"default\",\"scan_sk\":\"0de90b7195c1380d5fde13de3f1d66d53423a9896314839e36ba672653af60b4\",\"spend_key\":{\"Secret\":\"affe686075ecbe17b8ce7de45ec31314804259d0a4bc1c863de21ffd6dc598f8\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Testnet\",\"scan_pubkey\":[2,85,96,92,243,247,237,192,205,9,178,146,101,237,132,232,15,2,69,138,31,118,76,140,142,207,90,13,192,94,254,150,133],\"spend_pubkey\":[3,5,157,91,250,169,41,61,190,37,30,98,152,253,180,138,250,86,162,102,82,148,130,220,44,153,127,83,43,246,93,17,232],\"change_label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"labels\":[[\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",[2,237,237,247,213,154,87,34,239,168,235,87,122,152,94,41,35,101,184,201,58,201,6,185,58,157,52,208,129,167,2,224,198]]]},\"network\":\"testnet\"},\"outputs\":{\"wallet_fingerprint\":[203,200,4,248,139,36,241,232],\"birthday\":2146,\"last_scan\":2146,\"outputs\":{\"fbd9c63e0dd08c2569b51a0d6095a79ee2acfcac66acdb594328a095f1fadb63:1\":{\"blockheight\":2146,\"tweak\":\"678dbcbdb40cd3733c8dbbd508761a0937009cf75a9f466e3c98877e79037cbc\",\"amount\":99896595,\"script\":\"5120deab0c5a3d23de30477b0b5a95a261c96e29afdd9813c665d2bf025ad2b3f919\",\"label\":null,\"spend_status\":\"Unspent\"}}},\"tx_history\":[]}"; +pub const BOB_LOGIN_WALLET: &str = "{\"client\":{\"label\":\"default\",\"scan_sk\":\"0de90b7195c1380d5fde13de3f1d66d53423a9896314839e36ba672653af60b4\",\"spend_key\":{\"Secret\":\"affe686075ecbe17b8ce7de45ec31314804259d0a4bc1c863de21ffd6dc598f8\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Testnet\",\"scan_pubkey\":[2,85,96,92,243,247,237,192,205,9,178,146,101,237,132,232,15,2,69,138,31,118,76,140,142,207,90,13,192,94,254,150,133],\"spend_pubkey\":[3,5,157,91,250,169,41,61,190,37,30,98,152,253,180,138,250,86,162,102,82,148,130,220,44,153,127,83,43,246,93,17,232],\"change_label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"labels\":[[\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",[2,237,237,247,213,154,87,34,239,168,235,87,122,152,94,41,35,101,184,201,58,201,6,185,58,157,52,208,129,167,2,224,198]]]},\"network\":\"testnet\"},\"outputs\":{\"wallet_fingerprint\":[203,200,4,248,139,36,241,232],\"birthday\":2146,\"last_scan\":2146,\"outputs\":{\"93722ea2fb9b74954210b4cdd1360e280b7ff1bc156d6b75f847e62411c588fb:0\":{\"blockheight\":0,\"tweak\":\"da5e3aa2378e3a257f99eb1e0ae4c672916f6a2f32a8ed9a8e146f2074da981b\",\"amount\":443,\"script\":\"51209eb9e950127b6a7d81668f25b4d5b164b42dafe59ce40b80e6c489ec983540d7\",\"label\":null,\"spend_status\":\"Unspent\"},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:0\":{\"blockheight\":0,\"tweak\":\"0e3395ff27bde9187ffaeeb2521f6277d3b83911f16ccbaf59a1a68d99a0ab93\",\"amount\":1200,\"script\":\"512010f06f764cbc923ec3198db946307bf0c06a1b4f09206055e47a6fec0a33d52c\",\"label\":null,\"spend_status\":{\"Spent\":\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f\"}},\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f:1\":{\"blockheight\":0,\"tweak\":\"f0ad83734cdc7d73575e5a32651390cf30b92cc7e44cf94ec37da46900ecaf71\",\"amount\":654,\"script\":\"5120230cc1e85829be238e666f469653cbc2f1c0e3675a9bf33e1d1f91115f5dd306\",\"label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"spend_status\":\"Unspent\"},\"fbd9c63e0dd08c2569b51a0d6095a79ee2acfcac66acdb594328a095f1fadb63:1\":{\"blockheight\":2146,\"tweak\":\"678dbcbdb40cd3733c8dbbd508761a0937009cf75a9f466e3c98877e79037cbc\",\"amount\":99896595,\"script\":\"5120deab0c5a3d23de30477b0b5a95a261c96e29afdd9813c665d2bf025ad2b3f919\",\"label\":null,\"spend_status\":\"Unspent\"}}},\"tx_history\":[]}"; +pub const ALICE_PAIRED_DEVICE: &str = "{\"sp_wallet\":{\"client\":{\"label\":\"default\",\"scan_sk\":\"e3d8922a41a7cb1a84a90f4334e987bb5ea2df6a1fdf44f789b5302de119f9e2\",\"spend_key\":{\"Secret\":\"93292e5b21042c6cfc742ba30e9d2a1e01609b12d154a1825184ed12c7b9631b\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Testnet\",\"scan_pubkey\":[2,104,242,105,185,6,124,208,34,44,149,52,163,38,63,221,150,12,198,24,95,143,126,235,37,149,233,88,118,32,86,233,152],\"spend_pubkey\":[3,198,82,196,243,12,59,126,109,143,144,157,128,176,168,94,54,134,232,139,115,102,11,178,128,244,239,251,40,228,67,153,72],\"change_label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"labels\":[[\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",[2,244,223,255,57,50,216,27,133,112,138,69,120,126,85,110,6,242,141,33,136,191,82,164,241,54,179,115,84,161,145,174,154]]]},\"network\":\"testnet\"},\"outputs\":{\"wallet_fingerprint\":[187,119,108,230,171,125,106,11],\"birthday\":1620,\"last_scan\":2146,\"outputs\":{\"9a4a67cc5a40bf882d8b300d91024d7c97024b3b68b2df7745a5b9ea1df1888c:1\":{\"blockheight\":1620,\"tweak\":\"b8b63b3ed97d297b744135cfac2fb4a344c881a77543b71f1fcd16bc67514f26\",\"amount\":3938643,\"script\":\"51205b7b324bb71d411e32f2c61fda5d1db23f5c7d6d416a77fab87c913a1b120be1\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":{\"Spent\":\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292\"}},\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f:0\":{\"blockheight\":0,\"tweak\":\"6e5c1d4690b9ff4fa26e5185ada25af5c2987650e629a518db8a43fdaad7a26c\",\"amount\":349,\"script\":\"512088ac90e180c87b7fa6aa33db4c72a8620cd08fda3ba1c71430b904eb068c587f\",\"label\":null,\"spend_status\":{\"Spent\":\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165\"}},\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165:3\":{\"blockheight\":0,\"tweak\":\"ad5d59f98e2a49f2097d6847c4be66ab6e2125d3620924c5135c178afe0c450f\",\"amount\":3935006,\"script\":\"5120da6a7f478a357e277b4ebd295d65cc58900b29236f57cdf2d1541363c8eddd9d\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":\"Unspent\"},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:1\":{\"blockheight\":0,\"tweak\":\"7c84a3074c18c23a65eceaca49a327989ef6e7240e0e080421afb80f06906d73\",\"amount\":306,\"script\":\"5120eb78084d7a2ccbdb7eb7e9bba7cf875c4e54a5aba0beac57c5d3e41133bd8fdd\",\"label\":null,\"spend_status\":{\"Spent\":\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165\"}},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:2\":{\"blockheight\":0,\"tweak\":\"e3e21d551e933199f8c977bc0362616bdfb128da7ca9728bd7254977541c39cc\",\"amount\":3936897,\"script\":\"5120df3af55a63bd056c5d6d09f47a3a19c382d938c08db8bc41a59c5235970209ad\",\"label\":\"ac14a827e2d023b8f7804303a47259366117d99ed932b641d4a8eaf1b82cc992\",\"spend_status\":{\"Spent\":\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165\"}},\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165:2\":{\"blockheight\":0,\"tweak\":\"c2ab55a30f0a575d139639ab2bc78e5e524dd85e5f1981297f601e890760c6d7\",\"amount\":546,\"script\":\"512040fb549d9cbb51f01fc29df8cd0714d33e3608507d1e3adaf015e35ed5e87b9f\",\"label\":null,\"spend_status\":\"Unspent\"},\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165:0\":{\"blockheight\":0,\"tweak\":\"cfea493360d6ffe2bfd13e4c5c2f677351e0c038f1ce0cd5383fadad6adc79f1\",\"amount\":602,\"script\":\"51200f008ff13f876bf328c69f10ad8621c9770ff8d5eb1861cb67199189a6308bb9\",\"label\":null,\"spend_status\":\"Unspent\"}}},\"tx_history\":[]},\"pairing_process_commitment\":\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165\",\"paired_member\":{\"sp_addresses\":[\"sprt1qqf2kqh8n7lkupngfk2fxtmvyaq8sy3v2ramyeryweadqmsz7l6tg2qc9n4dl42ff8klz28nznr7mfzh6263xv555stwzextl2v4lvhg3aqq7ru8u\",\"sprt1qqf50y6deqe7dqg3vj562xf3lmktqe3sct78ha6e9jh54sa3q2m5esq7x2tz0xrpm0ekclyyaszc2sh3ksm5gkumxpwegpa80lv5wgsuefqaufx8q\"]}}"; +pub const BOB_PAIRED_DEVICE: &str = "{\"sp_wallet\":{\"client\":{\"label\":\"default\",\"scan_sk\":\"0de90b7195c1380d5fde13de3f1d66d53423a9896314839e36ba672653af60b4\",\"spend_key\":{\"Secret\":\"affe686075ecbe17b8ce7de45ec31314804259d0a4bc1c863de21ffd6dc598f8\"},\"mnemonic\":null,\"sp_receiver\":{\"version\":0,\"network\":\"Testnet\",\"scan_pubkey\":[2,85,96,92,243,247,237,192,205,9,178,146,101,237,132,232,15,2,69,138,31,118,76,140,142,207,90,13,192,94,254,150,133],\"spend_pubkey\":[3,5,157,91,250,169,41,61,190,37,30,98,152,253,180,138,250,86,162,102,82,148,130,220,44,153,127,83,43,246,93,17,232],\"change_label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"labels\":[[\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",[2,237,237,247,213,154,87,34,239,168,235,87,122,152,94,41,35,101,184,201,58,201,6,185,58,157,52,208,129,167,2,224,198]]]},\"network\":\"testnet\"},\"outputs\":{\"wallet_fingerprint\":[203,200,4,248,139,36,241,232],\"birthday\":2146,\"last_scan\":2146,\"outputs\":{\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f:1\":{\"blockheight\":0,\"tweak\":\"f0ad83734cdc7d73575e5a32651390cf30b92cc7e44cf94ec37da46900ecaf71\",\"amount\":654,\"script\":\"5120230cc1e85829be238e666f469653cbc2f1c0e3675a9bf33e1d1f91115f5dd306\",\"label\":\"56572fc770b52096879662f97f98263d3e126f5a4a38f00f2895a9dde4c47c1c\",\"spend_status\":\"Unspent\"},\"93722ea2fb9b74954210b4cdd1360e280b7ff1bc156d6b75f847e62411c588fb:0\":{\"blockheight\":0,\"tweak\":\"da5e3aa2378e3a257f99eb1e0ae4c672916f6a2f32a8ed9a8e146f2074da981b\",\"amount\":443,\"script\":\"51209eb9e950127b6a7d81668f25b4d5b164b42dafe59ce40b80e6c489ec983540d7\",\"label\":null,\"spend_status\":\"Unspent\"},\"8c701e6b62f4d2c4ddc779262f368dd156ea1c75a7097247fbdb6d344ac9c165:1\":{\"blockheight\":0,\"tweak\":\"898284108952bd8b0e74030e00b81c1b387ee151a810ca3b40143da227707df2\",\"amount\":1000,\"script\":\"5120c0ff94a1318f0061960a713c927ff175a0d71a791497e94e70601c3baae739b8\",\"label\":null,\"spend_status\":\"Unspent\"},\"e2c6ff9927c8a5f7a60087117732c07ab7cd82c0c65462e9c780eb5ce9c35292:0\":{\"blockheight\":0,\"tweak\":\"0e3395ff27bde9187ffaeeb2521f6277d3b83911f16ccbaf59a1a68d99a0ab93\",\"amount\":1200,\"script\":\"512010f06f764cbc923ec3198db946307bf0c06a1b4f09206055e47a6fec0a33d52c\",\"label\":null,\"spend_status\":{\"Spent\":\"576c2e53fe924d68deb7262cfc0e4023b5889652dec35671e1e7cf255d61c28f\"}},\"fbd9c63e0dd08c2569b51a0d6095a79ee2acfcac66acdb594328a095f1fadb63:1\":{\"blockheight\":2146,\"tweak\":\"678dbcbdb40cd3733c8dbbd508761a0937009cf75a9f466e3c98877e79037cbc\",\"amount\":99896595,\"script\":\"5120deab0c5a3d23de30477b0b5a95a261c96e29afdd9813c665d2bf025ad2b3f919\",\"label\":null,\"spend_status\":\"Unspent\"}}},\"tx_history\":[]},\"pairing_process_commitment\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"paired_member\":{\"sp_addresses\":[\"sprt1qqf50y6deqe7dqg3vj562xf3lmktqe3sct78ha6e9jh54sa3q2m5esq7x2tz0xrpm0ekclyyaszc2sh3ksm5gkumxpwegpa80lv5wgsuefqaufx8q\",\"sprt1qqf2kqh8n7lkupngfk2fxtmvyaq8sy3v2ramyeryweadqmsz7l6tg2qc9n4dl42ff8klz28nznr7mfzh6263xv555stwzextl2v4lvhg3aqq7ru8u\"]}}"; + +pub const PAIRING_PROCESS: &str = "{\"816fc00efc0e4ead5c6683f51e74433ea8b9a520cda48b23cdae6c42639c540f:0\":{\"states\":[],\"shared_secrets\":{\"sprt1qqf50y6deqe7dqg3vj562xf3lmktqe3sct78ha6e9jh54sa3q2m5esq7x2tz0xrpm0ekclyyaszc2sh3ksm5gkumxpwegpa80lv5wgsuefqaufx8q\":\"a86c30250a8e6a8dc9581b3ab2dacafda6446f6c65f4debe124f5870b6796ea1\"},\"impending_requests\":[{\"prd_type\":\"Update\",\"root_commitment\":\"816fc00efc0e4ead5c6683f51e74433ea8b9a520cda48b23cdae6c42639c540f:4294967295\",\"sender\":\"{\\\"sp_addresses\\\":[\\\"sprt1qqf2kqh8n7lkupngfk2fxtmvyaq8sy3v2ramyeryweadqmsz7l6tg2qc9n4dl42ff8klz28nznr7mfzh6263xv555stwzextl2v4lvhg3aqq7ru8u\\\",\\\"sprt1qqf50y6deqe7dqg3vj562xf3lmktqe3sct78ha6e9jh54sa3q2m5esq7x2tz0xrpm0ekclyyaszc2sh3ksm5gkumxpwegpa80lv5wgsuefqaufx8q\\\"]}\",\"keys\":{\"roles\":\"eb4e967297c40d55d96d61568849df75bf42ddd756a14b3309aa774f9d58cff1\",\"pairing_tx\":\"6484145ebc037a0b0033c103e47e211699473eef6172348e9a40a4d4c4d8c0ac\"},\"validation_tokens\":[],\"payload\":\"{\\\"html\\\":\\\"cd0e3fdb60ec8da76c16ca727e4bb486937f82e081cee8abc1ea6a5dbde8\\\",\\\"style\\\":\\\"24f6169aa2c4e9e46f34ac477347215f0b87f54cc333f24cf4f9b788e09f\\\",\\\"script\\\":\\\"ab6880c844ba8d3a14a47ae5ac586f60ac77aa8945288246d3894526c054\\\",\\\"description\\\":\\\"e30f5aa7999a169defb65f586d15764f80c952e9bfb6e864759cae9eea1184febb31d2d542c5\\\",\\\"roles\\\":\\\"849c2dca2c8bc9e28a7f22bc98a4e9a1ef18d9daea4c956421a6f66161cf6f2b1e0ed438814699b69770e9c6feb2ca62696a6d4800fa9c8973c989d35fdff01a1c72619510bceb025f020ad62e772924b9fa693ce10836ac542b754c8ef18788a34a01ca03fb3ed732db960a6a74b3ad22a2f638214c153a6c2586095f945c08df90cfa3e42686715cac878095228ad38de955a678d8f628eb85e894631d204b8441db7b87b5c67664831ed6dc97eba0334e15cbbe036b9767de703414277a08e40af83259a93e6aaaeff9471fb4e3a8a1f351d0a61450996288df8ecfe3b006c40d7e93f7f1b66267300c9e570dc425ed2d2cc6584b938f01dde2472c00f4a5b6122659ef834ec114abeceac9ed37be44faf99fa92f421b669818f40ae6a5c8d3092a76e17c478caa9ae43eef8e2ab60ad73d430637ad4056e0fc3547ab85ca859b2cda6dadd3f40c1dc297b9874ec5174f6a154ecd4a295d502ea497da534fb56294514713f3837950a30685d67e0dd2823855a0f4a35f86675ce8c4da2b254d6406b432a96dba5cc9503afc00490fb4\\\",\\\"pairing_tx\\\":\\\"95eb6b93f53d0909dc72ad53a1d0d3e54426276e0b3b360d44e6392fa1af01f64aac00a9ef633170186a13c2924d6397f3a8364d8921f2614dbb748090d90815842d48f5165e3f0782e0e648f017848c83a1b497b3a0ef1417dde26523b34e0234758f9719ecc21b43\\\"}\",\"proof\":{\"signature\":\"2f6a504567b53565a48e94b3bb21c2493d208534045dab69e68e813c466cd580058518d1f452cadabb51252b643a5bd1db515d4b157b61adffa28ba7b57b5266\",\"message\":{\"Message\":\"f4eea3b2932fc02aab2b84fbdc071b50b93f544fb4e2f732d6491d5c64f9af5b\"},\"key\":\"c652c4f30c3b7e6d8f909d80b0a85e3686e88b73660bb280f4effb28e4439948\"}}]}}"; pub const RELAY_ADDRESS: &str = "sprt1qqfmqt0ngq99y8t4ke6uhtm2a2vc2zxvhj7hjrqu599kn30d4cs9rwqn6n079mdr4dfqg72yrtvuxf43yswscw86nvvl09mc5ljx65vfh75fkza35"; pub const DEFAULT_NYM: &str = "AliceBob"; @@ -31,10 +35,8 @@ pub fn helper_get_bob_address() -> String { wallet.get_client().get_receiving_address() } -pub fn helper_get_tweak_data( - tx: &Transaction, - outpoints: HashMap, -) -> String { +pub fn helper_get_tweak_data(tx: &str, outpoints: HashMap) -> String { + let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()).unwrap(); let mut outpoint_data = vec![]; let mut witnesses = vec![]; let mut spks = vec![]; @@ -59,9 +61,10 @@ pub fn helper_get_tweak_data( tweak_data.to_string() } -pub fn helper_parse_transaction(transaction: &Transaction, tweak_data: &str) -> ApiReturn { +pub fn helper_parse_transaction(transaction: &str, tweak_data: &str) -> ApiReturn { + let tx: Transaction = deserialize(&Vec::from_hex(transaction).unwrap()).unwrap(); let new_tx_msg = serde_json::to_string(&NewTxMessage::new( - serialize(transaction).to_lower_hex_string(), + serialize(&tx).to_lower_hex_string(), Some(tweak_data.to_owned()), )) .unwrap();