Upgrade pairing

This commit is contained in:
Sosthene 2024-10-10 16:55:36 +02:00
parent 7c9eecab7a
commit cae49617d5
3 changed files with 282 additions and 180 deletions

View File

@ -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<String>) -> ApiR
Ok(())
}
#[wasm_bindgen]
pub fn get_pairing_tx() -> ApiResult<String> {
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<ApiReturn> {
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<ApiReturn> {
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>(&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<u8>, root_commitment: OutPoint) -> AnyhowResult<ApiRetu
// We update the process and return it
prd.payload = pcd.to_string();
debug!("New state of the process: {:#?}", prd);
return Ok(ApiReturn {
updated_process: Some((root_commitment.to_string(), relevant_process.clone())),
..Default::default()
@ -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<String> = encrypted_pcd.as_object().unwrap().keys().map(|k| k.clone()).collect();
let fields_to_encrypt: Vec<String> = 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<String> {
}
/// 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<Vec<String>> {
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<Vec<String>>
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)
}

View File

@ -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<OutPoint, OwnedOutput> = 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
}

View File

@ -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<OutPoint, OwnedOutput>,
) -> String {
pub fn helper_get_tweak_data(tx: &str, outpoints: HashMap<OutPoint, OwnedOutput>) -> 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();