Update to latest sp_client
This commit is contained in:
parent
f7e5c1e2e7
commit
ef7749b4a5
229
src/api.rs
229
src/api.rs
@ -23,7 +23,7 @@ use sdk_common::crypto::{
|
|||||||
decrypt_with_key, encrypt_with_key, generate_key, AeadCore, Aes256Gcm, AnkSharedSecretHash, KeyInit, AAD
|
decrypt_with_key, encrypt_with_key, generate_key, AeadCore, Aes256Gcm, AnkSharedSecretHash, KeyInit, AAD
|
||||||
};
|
};
|
||||||
use sdk_common::process::{check_tx_for_process_updates, lock_processes, Process, ProcessState};
|
use sdk_common::process::{check_tx_for_process_updates, lock_processes, Process, ProcessState};
|
||||||
use sdk_common::serialization::OutPointMemberMap;
|
use sdk_common::serialization::{OutPointMemberMap, OutPointProcessMap};
|
||||||
use sdk_common::signature::{AnkHash, AnkMessageHash, AnkValidationNoHash, AnkValidationYesHash, Proof};
|
use sdk_common::signature::{AnkHash, AnkMessageHash, AnkValidationNoHash, AnkValidationYesHash, Proof};
|
||||||
use sdk_common::sp_client::bitcoin::blockdata::fee_rate;
|
use sdk_common::sp_client::bitcoin::blockdata::fee_rate;
|
||||||
use sdk_common::sp_client::bitcoin::consensus::{deserialize, serialize};
|
use sdk_common::sp_client::bitcoin::consensus::{deserialize, serialize};
|
||||||
@ -47,7 +47,7 @@ use sdk_common::sp_client::constants::{
|
|||||||
};
|
};
|
||||||
use sdk_common::sp_client::silentpayments::utils as sp_utils;
|
use sdk_common::sp_client::silentpayments::utils as sp_utils;
|
||||||
use sdk_common::sp_client::silentpayments::{
|
use sdk_common::sp_client::silentpayments::{
|
||||||
utils::{Network as SpNetwork, SilentPaymentAddress},
|
SilentPaymentAddress,
|
||||||
Error as SpError,
|
Error as SpError,
|
||||||
};
|
};
|
||||||
use sdk_common::{signature, MutexExt, MAX_PRD_PAYLOAD_SIZE};
|
use sdk_common::{signature, MutexExt, MAX_PRD_PAYLOAD_SIZE};
|
||||||
@ -67,11 +67,8 @@ use sdk_common::pcd::{
|
|||||||
AnkPcdHash, AnkPcdTag, Member, Pcd, PcdCommitments, RoleDefinition, Roles, ValidationRule
|
AnkPcdHash, AnkPcdTag, Member, Pcd, PcdCommitments, RoleDefinition, Roles, ValidationRule
|
||||||
};
|
};
|
||||||
use sdk_common::prd::{AnkPrdHash, Prd, PrdType};
|
use sdk_common::prd::{AnkPrdHash, Prd, PrdType};
|
||||||
use sdk_common::silentpayments::{create_transaction, map_outputs_to_sp_address};
|
use sdk_common::silentpayments::{create_transaction as internal_create_transaction, sign_transaction as internal_sign_tx, TsUnsignedTransaction};
|
||||||
use sdk_common::sp_client::spclient::{
|
use sdk_common::sp_client::{OutputSpendStatus, OwnedOutput, Recipient, RecipientAddress, SilentPaymentUnsignedTransaction, SpClient, SpendKey};
|
||||||
derive_keys_from_seed, OutputList, OutputSpendStatus, OwnedOutput, Recipient, SpClient,
|
|
||||||
};
|
|
||||||
use sdk_common::sp_client::spclient::{SpWallet, SpendKey};
|
|
||||||
use sdk_common::secrets::SecretsStore;
|
use sdk_common::secrets::SecretsStore;
|
||||||
|
|
||||||
use crate::user::{lock_local_device, set_new_device, LOCAL_DEVICE};
|
use crate::user::{lock_local_device, set_new_device, LOCAL_DEVICE};
|
||||||
@ -125,6 +122,7 @@ pub struct ApiReturn {
|
|||||||
pub ciphers_to_send: Vec<String>,
|
pub ciphers_to_send: Vec<String>,
|
||||||
pub commit_to_send: Option<CommitMessage>,
|
pub commit_to_send: Option<CommitMessage>,
|
||||||
pub push_to_storage: Vec<String>, // hash of the requested data, must be in db
|
pub push_to_storage: Vec<String>, // hash of the requested data, must be in db
|
||||||
|
pub partial_tx: Option<TsUnsignedTransaction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ApiResult<T: FromWasmAbi> = Result<T, ApiError>;
|
pub type ApiResult<T: FromWasmAbi> = Result<T, ApiError>;
|
||||||
@ -250,10 +248,12 @@ pub fn setup() {
|
|||||||
pub fn get_address() -> ApiResult<String> {
|
pub fn get_address() -> ApiResult<String> {
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
|
|
||||||
Ok(local_device
|
let address = local_device
|
||||||
.get_wallet()
|
.get_sp_client()
|
||||||
.get_client()
|
.get_receiving_address()
|
||||||
.get_receiving_address())
|
.to_string();
|
||||||
|
debug!("{}", address);
|
||||||
|
Ok(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@ -277,7 +277,7 @@ pub fn restore_device(device_str: String) -> ApiResult<()> {
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_device_from_sp_wallet(sp_wallet: String) -> ApiResult<String> {
|
pub fn create_device_from_sp_wallet(sp_wallet: String) -> ApiResult<String> {
|
||||||
let sp_wallet: SpWallet = serde_json::from_str(&sp_wallet)?;
|
let sp_wallet: SpClient = serde_json::from_str(&sp_wallet)?;
|
||||||
|
|
||||||
let our_address = set_new_device(sp_wallet)?;
|
let our_address = set_new_device(sp_wallet)?;
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ pub fn create_device_from_sp_wallet(sp_wallet: String) -> ApiResult<String> {
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_new_device(birthday: u32, network_str: String) -> ApiResult<String> {
|
pub fn create_new_device(birthday: u32, network_str: String) -> ApiResult<String> {
|
||||||
let sp_wallet = generate_sp_wallet(None, Network::from_core_arg(&network_str)?)?;
|
let sp_wallet = generate_sp_wallet(Network::from_core_arg(&network_str)?)?;
|
||||||
|
|
||||||
let our_address = set_new_device(sp_wallet)?;
|
let our_address = set_new_device(sp_wallet)?;
|
||||||
|
|
||||||
@ -309,9 +309,9 @@ pub fn pair_device(process_id: String, mut sp_addresses: Vec<String>) -> ApiResu
|
|||||||
}
|
}
|
||||||
|
|
||||||
let local_address = local_device
|
let local_address = local_device
|
||||||
.get_wallet()
|
.get_sp_client()
|
||||||
.get_client()
|
.get_receiving_address()
|
||||||
.get_receiving_address();
|
.to_string();
|
||||||
|
|
||||||
if !sp_addresses.iter().any(|a| *a == local_address) {
|
if !sp_addresses.iter().any(|a| *a == local_address) {
|
||||||
sp_addresses.push(local_address);
|
sp_addresses.push(local_address);
|
||||||
@ -343,7 +343,7 @@ pub fn unpair_device() -> ApiResult<()> {
|
|||||||
pub fn dump_wallet() -> ApiResult<String> {
|
pub fn dump_wallet() -> ApiResult<String> {
|
||||||
let device = lock_local_device()?;
|
let device = lock_local_device()?;
|
||||||
|
|
||||||
Ok(serde_json::to_string(device.get_wallet()).unwrap())
|
Ok(serde_json::to_string(device.get_sp_client()).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@ -453,14 +453,13 @@ pub fn dump_neutered_device() -> ApiResult<Device> {
|
|||||||
return Err(ApiError::new("Device must be paired".to_owned()));
|
return Err(ApiError::new("Device must be paired".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = local_device.get_wallet().get_client();
|
let client = local_device.get_sp_client();
|
||||||
let scan_key = client.get_scan_key();
|
let scan_key = client.get_scan_key();
|
||||||
let spend_pubkey: PublicKey = client.get_spend_key().into();
|
let spend_pubkey: PublicKey = client.get_spend_key().into();
|
||||||
|
|
||||||
let neutered_client = SpClient::new("default".to_owned(), scan_key, SpendKey::Public(spend_pubkey), None, Network::Signet)?;
|
let neutered_client = SpClient::new(scan_key, SpendKey::Public(spend_pubkey), Network::Signet)?;
|
||||||
|
|
||||||
let new_wallet = SpWallet::new(neutered_client, None, vec![])?;
|
let mut neutered_device = Device::new(neutered_client);
|
||||||
let mut neutered_device = Device::new(new_wallet);
|
|
||||||
|
|
||||||
neutered_device.pair(local_device.get_pairing_commitment().unwrap(), local_device.to_member());
|
neutered_device.pair(local_device.get_pairing_commitment().unwrap(), local_device.to_member());
|
||||||
|
|
||||||
@ -493,11 +492,11 @@ fn handle_transaction(
|
|||||||
) -> AnyhowResult<ApiReturn> {
|
) -> AnyhowResult<ApiReturn> {
|
||||||
let b_scan: SecretKey;
|
let b_scan: SecretKey;
|
||||||
let local_member: Member;
|
let local_member: Member;
|
||||||
let sp_wallet: SpWallet;
|
let sp_wallet: SpClient;
|
||||||
{
|
{
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
sp_wallet = local_device.get_wallet().clone();
|
sp_wallet = local_device.get_sp_client().clone();
|
||||||
b_scan = local_device.get_wallet().get_client().get_scan_key();
|
b_scan = local_device.get_sp_client().get_scan_key();
|
||||||
local_member = local_device.to_member();
|
local_member = local_device.to_member();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,7 +576,7 @@ fn process_transaction(
|
|||||||
let processes = lock_processes()?;
|
let processes = lock_processes()?;
|
||||||
let process = processes.get(&outpoint).unwrap();
|
let process = processes.get(&outpoint).unwrap();
|
||||||
let new_state = process.get_latest_commited_state().unwrap();
|
let new_state = process.get_latest_commited_state().unwrap();
|
||||||
let diffs = if let Ok(diffs) = create_diffs(process, new_state, members_list) { diffs } else { vec![] };
|
let diffs = if let Ok(diffs) = create_diffs(&lock_local_device()?, process, new_state, members_list) { diffs } else { vec![] };
|
||||||
let updated_process = UpdatedProcess {
|
let updated_process = UpdatedProcess {
|
||||||
process_id: outpoint,
|
process_id: outpoint,
|
||||||
current_process: process.clone(),
|
current_process: process.clone(),
|
||||||
@ -599,8 +598,7 @@ fn process_transaction(
|
|||||||
let updated: HashMap<OutPoint, OwnedOutput>;
|
let updated: HashMap<OutPoint, OwnedOutput>;
|
||||||
{
|
{
|
||||||
let mut device = lock_local_device()?;
|
let mut device = lock_local_device()?;
|
||||||
let wallet = device.get_mut_wallet();
|
updated = device.update_outputs_with_transaction(&tx, blockheight, tweak_data)?;
|
||||||
updated = wallet.update_wallet_with_transaction(&tx, blockheight, tweak_data)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if updated.len() > 0 {
|
if updated.len() > 0 {
|
||||||
@ -648,15 +646,14 @@ fn confirm_prd(prd: &Prd, shared_secret: &AnkSharedSecretHash) -> AnyhowResult<S
|
|||||||
|
|
||||||
let prd_confirm = Prd::new_confirm(outpoint, sender, prd.pcd_commitments.clone());
|
let prd_confirm = Prd::new_confirm(outpoint, sender, prd.pcd_commitments.clone());
|
||||||
|
|
||||||
let prd_msg = prd_confirm.to_network_msg(local_device.get_wallet())?;
|
let prd_msg = prd_confirm.to_network_msg(local_device.get_sp_client())?;
|
||||||
|
|
||||||
Ok(encrypt_with_key(shared_secret.as_byte_array(), prd_msg.as_bytes())?.to_lower_hex_string())
|
Ok(encrypt_with_key(shared_secret.as_byte_array(), prd_msg.as_bytes())?.to_lower_hex_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_diffs(process: &Process, new_state: &ProcessState, members_list: &OutPointMemberMap) -> AnyhowResult<Vec<UserDiff>> {
|
fn create_diffs(device: &MutexGuard<Device>, process: &Process, new_state: &ProcessState, members_list: &OutPointMemberMap) -> AnyhowResult<Vec<UserDiff>> {
|
||||||
let new_state_commitments = &new_state.pcd_commitment;
|
let new_state_commitments = &new_state.pcd_commitment;
|
||||||
|
|
||||||
let device = lock_local_device()?;
|
|
||||||
let our_id = device.get_pairing_commitment();
|
let our_id = device.get_pairing_commitment();
|
||||||
|
|
||||||
let fields_to_validate = if let Some(our_id) = our_id {
|
let fields_to_validate = if let Some(our_id) = our_id {
|
||||||
@ -700,14 +697,14 @@ fn create_diffs(process: &Process, new_state: &ProcessState, members_list: &OutP
|
|||||||
fn handle_prd_connect(prd: Prd, secret: AnkSharedSecretHash) -> AnyhowResult<ApiReturn> {
|
fn handle_prd_connect(prd: Prd, secret: AnkSharedSecretHash) -> AnyhowResult<ApiReturn> {
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
let local_member = local_device.to_member();
|
let local_member = local_device.to_member();
|
||||||
let sp_wallet = local_device.get_wallet();
|
let sp_wallet = local_device.get_sp_client();
|
||||||
let secret_hash = AnkMessageHash::from_message(secret.as_byte_array());
|
let secret_hash = AnkMessageHash::from_message(secret.as_byte_array());
|
||||||
let mut shared_secrets = lock_shared_secrets()?;
|
let mut shared_secrets = lock_shared_secrets()?;
|
||||||
if let Some(prev_proof) = prd.validation_tokens.get(0) {
|
if let Some(prev_proof) = prd.validation_tokens.get(0) {
|
||||||
// check that the proof is valid
|
// check that the proof is valid
|
||||||
prev_proof.verify()?;
|
prev_proof.verify()?;
|
||||||
// Check it's signed with our key
|
// Check it's signed with our key
|
||||||
let local_address = SilentPaymentAddress::try_from(sp_wallet.get_client().get_receiving_address())?;
|
let local_address = SilentPaymentAddress::try_from(sp_wallet.get_receiving_address())?;
|
||||||
if prev_proof.get_key() != local_address.get_spend_key() {
|
if prev_proof.get_key() != local_address.get_spend_key() {
|
||||||
return Err(anyhow::Error::msg("Previous proof of a prd connect isn't signed by us"));
|
return Err(anyhow::Error::msg("Previous proof of a prd connect isn't signed by us"));
|
||||||
}
|
}
|
||||||
@ -795,7 +792,7 @@ fn handle_prd(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Compute the diffs
|
// Compute the diffs
|
||||||
let diffs = create_diffs(&relevant_process, &new_state, members_list)?;
|
let diffs = create_diffs(&lock_local_device()?, &relevant_process, &new_state, members_list)?;
|
||||||
|
|
||||||
relevant_process.insert_concurrent_state(new_state)?;
|
relevant_process.insert_concurrent_state(new_state)?;
|
||||||
|
|
||||||
@ -897,8 +894,8 @@ fn handle_prd(
|
|||||||
};
|
};
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
|
|
||||||
let sp_wallet = local_device.get_wallet();
|
let sp_wallet = local_device.get_sp_client();
|
||||||
let local_address = sp_wallet.get_client().get_receiving_address();
|
let local_address = sp_wallet.get_receiving_address().to_string();
|
||||||
|
|
||||||
let mut relevant_fields: HashSet<String> = HashSet::new();
|
let mut relevant_fields: HashSet<String> = HashSet::new();
|
||||||
let shared_secrets = lock_shared_secrets()?;
|
let shared_secrets = lock_shared_secrets()?;
|
||||||
@ -986,7 +983,7 @@ fn handle_decrypted_message(
|
|||||||
plain: Vec<u8>,
|
plain: Vec<u8>,
|
||||||
members_list: &OutPointMemberMap
|
members_list: &OutPointMemberMap
|
||||||
) -> anyhow::Result<ApiReturn> {
|
) -> anyhow::Result<ApiReturn> {
|
||||||
let local_address: SilentPaymentAddress = lock_local_device()?.get_wallet().get_client().get_receiving_address().try_into()?;
|
let local_address: SilentPaymentAddress = lock_local_device()?.get_address();
|
||||||
if let Ok(prd) = Prd::extract_from_message(&plain, local_address) {
|
if let Ok(prd) = Prd::extract_from_message(&plain, local_address) {
|
||||||
handle_prd(prd, secret, members_list)
|
handle_prd(prd, secret, members_list)
|
||||||
} else {
|
} else {
|
||||||
@ -1017,98 +1014,90 @@ pub fn parse_cipher(cipher_msg: String, members_list: OutPointMemberMap) -> ApiR
|
|||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn get_outputs() -> ApiResult<JsValue> {
|
pub fn get_outputs() -> ApiResult<JsValue> {
|
||||||
let device = lock_local_device()?;
|
let device = lock_local_device()?;
|
||||||
let outputs = device.get_wallet().get_outputs().clone();
|
Ok(JsValue::from_serde(device.get_outputs())?)
|
||||||
Ok(JsValue::from_serde(&outputs.to_outpoints_list())?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn get_available_amount() -> ApiResult<u64> {
|
pub fn get_available_amount() -> ApiResult<u64> {
|
||||||
let device = lock_local_device()?;
|
let device = lock_local_device()?;
|
||||||
|
|
||||||
Ok(device.get_wallet().get_outputs().get_balance().to_sat())
|
Ok(device.get_balance().to_sat())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_shared_secrets_in_transaction(
|
fn get_shared_secrets_in_transaction(
|
||||||
psbt: &Psbt,
|
unsigned_transaction: &SilentPaymentUnsignedTransaction,
|
||||||
addresses: Vec<String>
|
sp_addresses: &[SilentPaymentAddress]
|
||||||
) -> anyhow::Result<HashMap<SilentPaymentAddress, AnkSharedSecretHash>> {
|
) -> anyhow::Result<HashMap<SilentPaymentAddress, AnkSharedSecretHash>> {
|
||||||
let local_device = lock_local_device()?;
|
|
||||||
|
|
||||||
let sp_wallet = local_device.get_wallet();
|
|
||||||
|
|
||||||
let partial_secret = sp_wallet
|
|
||||||
.get_client()
|
|
||||||
.get_partial_secret_from_psbt(&psbt)?;
|
|
||||||
|
|
||||||
let mut new_secrets = HashMap::new();
|
let mut new_secrets = HashMap::new();
|
||||||
for address in addresses {
|
for sp_address in sp_addresses {
|
||||||
let sp_address = SilentPaymentAddress::try_from(address.as_str())?;
|
|
||||||
let shared_point = sp_utils::sending::calculate_ecdh_shared_secret(
|
let shared_point = sp_utils::sending::calculate_ecdh_shared_secret(
|
||||||
&sp_address.get_scan_key(),
|
&sp_address.get_scan_key(),
|
||||||
&partial_secret,
|
&unsigned_transaction.partial_secret,
|
||||||
);
|
);
|
||||||
|
|
||||||
let shared_secret = AnkSharedSecretHash::from_shared_point(shared_point);
|
let shared_secret = AnkSharedSecretHash::from_shared_point(shared_point);
|
||||||
|
|
||||||
new_secrets.insert(sp_address, shared_secret);
|
new_secrets.insert(*sp_address, shared_secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(new_secrets)
|
Ok(new_secrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_transaction_for_addresses(addresses: Vec<String>, fee_rate: u32) -> anyhow::Result<Psbt> {
|
fn create_transaction_for_addresses(
|
||||||
let mut sp_addresses: Vec<SilentPaymentAddress> = Vec::with_capacity(addresses.len());
|
device: &Device,
|
||||||
for address in &addresses {
|
freezed_utxos: &HashSet<OutPoint>,
|
||||||
let sp_address = SilentPaymentAddress::try_from(address.as_str())?;
|
sp_addresses: &[SilentPaymentAddress],
|
||||||
sp_addresses.push(sp_address);
|
fee_rate: u32
|
||||||
}
|
) -> anyhow::Result<SilentPaymentUnsignedTransaction> {
|
||||||
|
let mut recipients = Vec::with_capacity(sp_addresses.len());
|
||||||
let local_device = lock_local_device()?;
|
for sp_address in sp_addresses {
|
||||||
|
|
||||||
let sp_wallet = local_device.get_wallet();
|
|
||||||
let mut freezed_utxos = lock_freezed_utxos()?;
|
|
||||||
|
|
||||||
let mut recipients = Vec::with_capacity(addresses.len());
|
|
||||||
for address in addresses {
|
|
||||||
let recipient = Recipient {
|
let recipient = Recipient {
|
||||||
address,
|
address: RecipientAddress::SpAddress(*sp_address),
|
||||||
amount: DEFAULT_AMOUNT,
|
amount: DEFAULT_AMOUNT,
|
||||||
nb_outputs: 1,
|
|
||||||
};
|
};
|
||||||
recipients.push(recipient);
|
recipients.push(recipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
let signed_psbt = create_transaction(
|
let mut tx = internal_create_transaction(
|
||||||
vec![],
|
vec![],
|
||||||
&freezed_utxos,
|
device.get_outputs().clone(),
|
||||||
sp_wallet,
|
freezed_utxos,
|
||||||
|
device.get_sp_client(),
|
||||||
recipients,
|
recipients,
|
||||||
None,
|
None,
|
||||||
Amount::from_sat(fee_rate.into()),
|
Amount::from_sat(fee_rate.into()),
|
||||||
None,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// We add the used inputs in freezed utxos to prevent accidental double spends
|
let unsigned_transaction = SpClient::finalize_transaction(tx)?;
|
||||||
for input in &signed_psbt.unsigned_tx.input {
|
|
||||||
freezed_utxos.insert(input.previous_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(signed_psbt)
|
Ok(unsigned_transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
/// We send a transaction that pays at least one output to each address
|
/// We send a transaction that pays at least one output to each address
|
||||||
/// The goal is to establish a shared_secret to be used as an encryption key for further communication
|
/// The goal can be to establish a shared_secret to be used as an encryption key for further communication
|
||||||
pub fn create_connect_transaction(addresses: Vec<String>, fee_rate: u32) -> ApiResult<ApiReturn> {
|
/// or if the recipient is a relay it can be the init transaction for a new process
|
||||||
|
pub fn create_transaction(addresses: Vec<String>, fee_rate: u32) -> ApiResult<ApiReturn> {
|
||||||
if addresses.is_empty() {
|
if addresses.is_empty() {
|
||||||
return Err(ApiError::new("No addresses to connect to".to_owned()));
|
return Err(ApiError::new("No addresses to connect to".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let psbt = create_transaction_for_addresses(addresses.clone(), fee_rate)?;
|
let sp_addresses: anyhow::Result<Vec<SilentPaymentAddress>> = addresses.into_iter()
|
||||||
|
.map(|a| {
|
||||||
|
<SilentPaymentAddress>::try_from(a).map_err(|e| anyhow::Error::new(e))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let new_secrets = get_shared_secrets_in_transaction(&psbt, addresses)?;
|
let sp_addresses = sp_addresses?;
|
||||||
|
|
||||||
let transaction = psbt.extract_tx()?;
|
let mut local_device = lock_local_device()?;
|
||||||
|
|
||||||
|
let mut freezed_utxos = lock_freezed_utxos()?;
|
||||||
|
|
||||||
|
let partial_tx = create_transaction_for_addresses(&local_device, &freezed_utxos, &sp_addresses, fee_rate)?;
|
||||||
|
let new_secrets = get_shared_secrets_in_transaction(&partial_tx, &sp_addresses)?;
|
||||||
|
|
||||||
|
let unsigned_tx = SpClient::finalize_transaction(partial_tx)?;
|
||||||
|
|
||||||
let mut shared_secrets = lock_shared_secrets()?;
|
let mut shared_secrets = lock_shared_secrets()?;
|
||||||
let mut secrets_return = SecretsStore::new();
|
let mut secrets_return = SecretsStore::new();
|
||||||
@ -1117,13 +1106,34 @@ pub fn create_connect_transaction(addresses: Vec<String>, fee_rate: u32) -> ApiR
|
|||||||
secrets_return.confirm_secret_for_address(secret, address);
|
secrets_return.confirm_secret_for_address(secret, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let outputs = local_device.get_mut_outputs();
|
||||||
|
let new_txid = unsigned_tx.unsigned_tx.as_ref().unwrap().txid();
|
||||||
|
// We mark the utxos in the inputs as spent to prevent accidental double spends
|
||||||
|
for input in &unsigned_tx.unsigned_tx.as_ref().unwrap().input {
|
||||||
|
if let Some(output) = outputs.get_mut(&input.previous_output) {
|
||||||
|
output.spend_status = OutputSpendStatus::Spent(new_txid.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ApiReturn {
|
Ok(ApiReturn {
|
||||||
new_tx_to_send: Some(NewTxMessage::new(serialize(&transaction).to_lower_hex_string(), None)),
|
|
||||||
secrets: Some(secrets_return),
|
secrets: Some(secrets_return),
|
||||||
|
partial_tx: Some(TsUnsignedTransaction::new(unsigned_tx)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn sign_transaction(partial_tx: TsUnsignedTransaction) -> ApiResult<ApiReturn> {
|
||||||
|
let local_device = lock_local_device()?;
|
||||||
|
let partial_tweak = partial_tx.as_inner().partial_secret;
|
||||||
|
let tx = internal_sign_tx(local_device.get_sp_client(), partial_tx.to_inner())?;
|
||||||
|
let res = ApiReturn {
|
||||||
|
new_tx_to_send: Some(NewTxMessage::new(serialize(&tx).to_lower_hex_string(), Some(partial_tweak.secret_bytes().to_lower_hex_string()))),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_new_process(
|
pub fn create_new_process(
|
||||||
private_data: Pcd,
|
private_data: Pcd,
|
||||||
@ -1134,10 +1144,18 @@ pub fn create_new_process(
|
|||||||
members_list: OutPointMemberMap,
|
members_list: OutPointMemberMap,
|
||||||
) -> ApiResult<ApiReturn> {
|
) -> ApiResult<ApiReturn> {
|
||||||
// We create a transaction that spends to the relay address
|
// We create a transaction that spends to the relay address
|
||||||
let psbt = create_transaction_for_addresses(vec![relay_address.clone()], fee_rate)?;
|
let local_device = lock_local_device()?;
|
||||||
|
|
||||||
|
let mut freezed_utxos = lock_freezed_utxos()?;
|
||||||
|
|
||||||
|
let relay_address: SilentPaymentAddress = relay_address.try_into()?;
|
||||||
|
|
||||||
|
let tx = create_transaction_for_addresses(&local_device, &freezed_utxos, &vec![relay_address], fee_rate)?;
|
||||||
|
|
||||||
|
let unsigned_transaction = SpClient::finalize_transaction(tx)?;
|
||||||
|
|
||||||
// We take the secret out
|
// We take the secret out
|
||||||
let new_secrets = get_shared_secrets_in_transaction(&psbt, vec![relay_address])?;
|
let new_secrets = get_shared_secrets_in_transaction(&unsigned_transaction, &vec![relay_address])?;
|
||||||
|
|
||||||
let mut shared_secrets = lock_shared_secrets()?;
|
let mut shared_secrets = lock_shared_secrets()?;
|
||||||
let mut secrets_return = SecretsStore::new();
|
let mut secrets_return = SecretsStore::new();
|
||||||
@ -1146,12 +1164,8 @@ pub fn create_new_process(
|
|||||||
secrets_return.confirm_secret_for_address(secret, address);
|
secrets_return.confirm_secret_for_address(secret, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
let transaction = psbt.extract_tx()?;
|
|
||||||
|
|
||||||
// We now have the outpoint that will serve as id for the whole process
|
// We now have the outpoint that will serve as id for the whole process
|
||||||
let process_id = OutPoint::new(transaction.txid(), 0);
|
let process_id = OutPoint::new(unsigned_transaction.unsigned_tx.as_ref().unwrap().txid(), 0);
|
||||||
|
|
||||||
let new_tx_msg = NewTxMessage::new(serialize(&transaction).to_lower_hex_string(), None);
|
|
||||||
|
|
||||||
let mut new_state = ProcessState::new(process_id, private_data.clone(), public_data.clone(), roles.clone())?;
|
let mut new_state = ProcessState::new(process_id, private_data.clone(), public_data.clone(), roles.clone())?;
|
||||||
|
|
||||||
@ -1159,7 +1173,7 @@ pub fn create_new_process(
|
|||||||
|
|
||||||
let mut process = Process::new(process_id);
|
let mut process = Process::new(process_id);
|
||||||
|
|
||||||
let diffs = create_diffs(&process, &new_state, &members_list)?;
|
let diffs = create_diffs(&local_device, &process, &new_state, &members_list)?;
|
||||||
|
|
||||||
let mut encrypted_data = BTreeMap::new();
|
let mut encrypted_data = BTreeMap::new();
|
||||||
|
|
||||||
@ -1204,7 +1218,7 @@ pub fn create_new_process(
|
|||||||
secrets: Some(secrets_return),
|
secrets: Some(secrets_return),
|
||||||
commit_to_send: Some(commit_msg),
|
commit_to_send: Some(commit_msg),
|
||||||
updated_process: Some(updated_process),
|
updated_process: Some(updated_process),
|
||||||
new_tx_to_send: Some(new_tx_msg),
|
partial_tx: Some(TsUnsignedTransaction::new(unsigned_transaction)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1247,7 +1261,7 @@ pub fn update_process(
|
|||||||
return Err(ApiError::new("New state already known".to_owned()));
|
return Err(ApiError::new("New state already known".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let diffs = create_diffs(&process, &new_state, &members_list)?;
|
let diffs = create_diffs(&lock_local_device()?, &process, &new_state, &members_list)?;
|
||||||
|
|
||||||
let all_fields: Vec<String> = new_attributes.iter().map(|(field, _)| field.clone()).collect();
|
let all_fields: Vec<String> = new_attributes.iter().map(|(field, _)| field.clone()).collect();
|
||||||
let mut encrypted_data = BTreeMap::new();
|
let mut encrypted_data = BTreeMap::new();
|
||||||
@ -1300,8 +1314,7 @@ pub fn request_data(process_id: String, state_ids_str: Vec<String>, roles: JsVal
|
|||||||
let process_id = OutPoint::from_str(&process_id)?;
|
let process_id = OutPoint::from_str(&process_id)?;
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
let sender_pairing_id = local_device.get_pairing_commitment().ok_or(ApiError::new("Device not paired".to_owned()))?;
|
let sender_pairing_id = local_device.get_pairing_commitment().ok_or(ApiError::new("Device not paired".to_owned()))?;
|
||||||
let sp_wallet = local_device.get_wallet();
|
let local_address = local_device.get_address().to_string();
|
||||||
let local_address = sp_wallet.get_client().get_receiving_address();
|
|
||||||
let roles: Vec<Roles> = serde_wasm_bindgen::from_value(roles)?;
|
let roles: Vec<Roles> = serde_wasm_bindgen::from_value(roles)?;
|
||||||
|
|
||||||
let mut state_ids: Vec<[u8; 32]> = vec![];
|
let mut state_ids: Vec<[u8; 32]> = vec![];
|
||||||
@ -1337,7 +1350,7 @@ pub fn request_data(process_id: String, state_ids_str: Vec<String>, roles: JsVal
|
|||||||
state_ids
|
state_ids
|
||||||
);
|
);
|
||||||
|
|
||||||
let prd_msg = prd_request.to_network_msg(sp_wallet)?;
|
let prd_msg = prd_request.to_network_msg(local_device.get_sp_client())?;
|
||||||
|
|
||||||
// For now, we just send the request to all members we share the data with, but this could be refined
|
// For now, we just send the request to all members we share the data with, but this could be refined
|
||||||
let shared_secrets = lock_shared_secrets()?;
|
let shared_secrets = lock_shared_secrets()?;
|
||||||
@ -1370,8 +1383,7 @@ pub fn create_update_message(
|
|||||||
|
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
|
|
||||||
let sp_wallet = local_device.get_wallet();
|
let local_address = local_device.get_address().to_string();
|
||||||
let local_address = sp_wallet.get_client().get_receiving_address();
|
|
||||||
|
|
||||||
let mut all_members: HashMap<Member, HashSet<String>> = HashMap::new();
|
let mut all_members: HashMap<Member, HashSet<String>> = HashMap::new();
|
||||||
let shared_secrets = lock_shared_secrets()?;
|
let shared_secrets = lock_shared_secrets()?;
|
||||||
@ -1420,7 +1432,7 @@ pub fn create_update_message(
|
|||||||
for (member, visible_fields) in all_members {
|
for (member, visible_fields) in all_members {
|
||||||
let mut prd = full_prd.clone();
|
let mut prd = full_prd.clone();
|
||||||
prd.filter_keys(&visible_fields);
|
prd.filter_keys(&visible_fields);
|
||||||
let prd_msg = prd.to_network_msg(sp_wallet)?;
|
let prd_msg = prd.to_network_msg(local_device.get_sp_client())?;
|
||||||
|
|
||||||
let addresses = member.get_addresses();
|
let addresses = member.get_addresses();
|
||||||
for sp_address in addresses.into_iter() {
|
for sp_address in addresses.into_iter() {
|
||||||
@ -1491,12 +1503,10 @@ fn add_validation_token(mut process: Process, state_id: String, approval: bool,
|
|||||||
|
|
||||||
{
|
{
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
let sp_wallet = local_device.get_wallet();
|
let proof = Proof::new(message_hash, local_device.get_sp_client().get_spend_key().try_into()?);
|
||||||
let proof = Proof::new(message_hash, sp_wallet.get_client().get_spend_key().try_into()?);
|
|
||||||
update_state.validation_tokens.push(proof);
|
update_state.validation_tokens.push(proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let mut commit_msg = CommitMessage::new(
|
let mut commit_msg = CommitMessage::new(
|
||||||
process_id,
|
process_id,
|
||||||
update_state.pcd_commitment.clone(),
|
update_state.pcd_commitment.clone(),
|
||||||
@ -1539,8 +1549,7 @@ pub fn create_response_prd(process: Process, state_id: String, members_list: Out
|
|||||||
|
|
||||||
fn new_response_prd(process_id: OutPoint, update_state: &ProcessState, members_list: &OutPointMemberMap) -> AnyhowResult<Vec<String>> {
|
fn new_response_prd(process_id: OutPoint, update_state: &ProcessState, members_list: &OutPointMemberMap) -> AnyhowResult<Vec<String>> {
|
||||||
let local_device = lock_local_device()?;
|
let local_device = lock_local_device()?;
|
||||||
let sp_wallet = local_device.get_wallet();
|
let local_address = local_device.get_address().to_string();
|
||||||
let local_address = sp_wallet.get_client().get_receiving_address();
|
|
||||||
|
|
||||||
let mut all_members: HashMap<Member, HashSet<String>> = HashMap::new();
|
let mut all_members: HashMap<Member, HashSet<String>> = HashMap::new();
|
||||||
let shared_secrets = lock_shared_secrets()?;
|
let shared_secrets = lock_shared_secrets()?;
|
||||||
@ -1586,7 +1595,7 @@ fn new_response_prd(process_id: OutPoint, update_state: &ProcessState, members_l
|
|||||||
vec![*proof],
|
vec![*proof],
|
||||||
update_state.pcd_commitment.clone(),
|
update_state.pcd_commitment.clone(),
|
||||||
);
|
);
|
||||||
let prd_msg = response_prd.to_network_msg(sp_wallet)?;
|
let prd_msg = response_prd.to_network_msg(local_device.get_sp_client())?;
|
||||||
|
|
||||||
let mut ciphers = vec![];
|
let mut ciphers = vec![];
|
||||||
for (member, visible_fields) in all_members {
|
for (member, visible_fields) in all_members {
|
||||||
@ -1620,11 +1629,11 @@ pub struct encryptWithNewKeyResult {
|
|||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_faucet_msg() -> ApiResult<String> {
|
pub fn create_faucet_msg() -> ApiResult<String> {
|
||||||
let sp_address = lock_local_device()?
|
let sp_address = lock_local_device()?
|
||||||
.get_wallet()
|
.get_sp_client()
|
||||||
.get_client()
|
.get_receiving_address()
|
||||||
.get_receiving_address();
|
.to_string();
|
||||||
|
|
||||||
let faucet_msg = FaucetMessage::new(sp_address.clone());
|
let faucet_msg = FaucetMessage::new(sp_address);
|
||||||
|
|
||||||
Ok(faucet_msg.to_string())
|
Ok(faucet_msg.to_string())
|
||||||
}
|
}
|
||||||
|
20
src/user.rs
20
src/user.rs
@ -8,7 +8,7 @@ use sdk_common::sp_client::bitcoin::secp256k1::{PublicKey, SecretKey, ThirtyTwoB
|
|||||||
use sdk_common::sp_client::bitcoin::{
|
use sdk_common::sp_client::bitcoin::{
|
||||||
Network, OutPoint, ScriptBuf, Transaction, Txid, XOnlyPublicKey,
|
Network, OutPoint, ScriptBuf, Transaction, Txid, XOnlyPublicKey,
|
||||||
};
|
};
|
||||||
use sdk_common::sp_client::spclient::SpClient;
|
use sdk_common::sp_client::SpClient;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use tsify::Tsify;
|
use tsify::Tsify;
|
||||||
@ -24,8 +24,10 @@ use std::sync::{Mutex, MutexGuard, OnceLock};
|
|||||||
use sdk_common::device::Device;
|
use sdk_common::device::Device;
|
||||||
use sdk_common::sp_client::bitcoin::secp256k1::constants::SECRET_KEY_SIZE;
|
use sdk_common::sp_client::bitcoin::secp256k1::constants::SECRET_KEY_SIZE;
|
||||||
use sdk_common::sp_client::silentpayments::bitcoin_hashes::sha256;
|
use sdk_common::sp_client::silentpayments::bitcoin_hashes::sha256;
|
||||||
use sdk_common::sp_client::silentpayments::utils::{Network as SpNetwork, SilentPaymentAddress};
|
use sdk_common::sp_client::silentpayments::{
|
||||||
use sdk_common::sp_client::spclient::{OutputList, SpWallet, SpendKey};
|
Network as SpNetwork,
|
||||||
|
SilentPaymentAddress
|
||||||
|
};
|
||||||
|
|
||||||
use crate::peers::Peer;
|
use crate::peers::Peer;
|
||||||
use crate::wallet::generate_sp_wallet;
|
use crate::wallet::generate_sp_wallet;
|
||||||
@ -34,22 +36,20 @@ use sdk_common::crypto::{AeadCore, Aes256Gcm, KeyInit};
|
|||||||
|
|
||||||
pub static LOCAL_DEVICE: OnceLock<Mutex<Device>> = OnceLock::new();
|
pub static LOCAL_DEVICE: OnceLock<Mutex<Device>> = OnceLock::new();
|
||||||
|
|
||||||
pub fn set_new_device(sp_wallet: SpWallet) -> Result<String> {
|
pub fn set_new_device(sp_client: SpClient) -> Result<String> {
|
||||||
let mut device = Device::new(sp_wallet);
|
let mut device = Device::new(sp_client);
|
||||||
|
|
||||||
let mut local_device = lock_local_device()?;
|
let mut local_device = lock_local_device()?;
|
||||||
if *local_device.get_wallet().get_client() != SpClient::default() {
|
if *local_device.get_sp_client() != SpClient::default() {
|
||||||
return Err(Error::msg("Device already initialized".to_owned()));
|
return Err(Error::msg("Device already initialized".to_owned()));
|
||||||
} else {
|
} else {
|
||||||
*local_device = device;
|
*local_device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
let our_address = local_device
|
let our_address = local_device
|
||||||
.get_wallet()
|
.get_address();
|
||||||
.get_client()
|
|
||||||
.get_receiving_address();
|
|
||||||
|
|
||||||
Ok(our_address)
|
Ok(our_address.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_local_device() -> Result<MutexGuard<'static, Device>> {
|
pub fn lock_local_device() -> Result<MutexGuard<'static, Device>> {
|
||||||
|
@ -6,9 +6,9 @@ use std::{
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sdk_common::sp_client::{
|
use sdk_common::sp_client::{
|
||||||
bitcoin::{Network, OutPoint},
|
bitcoin::{secp256k1::SecretKey, Network, OutPoint},
|
||||||
silentpayments::utils::SilentPaymentAddress,
|
silentpayments::SilentPaymentAddress,
|
||||||
spclient::{derive_keys_from_seed, SpClient, SpWallet, SpendKey},
|
SpClient, SpendKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::MutexExt;
|
use crate::MutexExt;
|
||||||
@ -21,24 +21,11 @@ pub fn lock_freezed_utxos() -> Result<MutexGuard<'static, HashSet<OutPoint>>, Er
|
|||||||
.lock_anyhow()
|
.lock_anyhow()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_sp_wallet(label: Option<String>, network: Network) -> anyhow::Result<SpWallet> {
|
pub fn generate_sp_wallet(network: Network) -> anyhow::Result<SpClient> {
|
||||||
let mut seed = [0u8; 64];
|
let mut rng = rand::thread_rng();
|
||||||
rand::thread_rng().fill(&mut seed);
|
SpClient::new(
|
||||||
let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, network)?;
|
SecretKey::new(&mut rng),
|
||||||
let sp_client = SpClient::new(
|
SpendKey::Secret(SecretKey::new(&mut rng)),
|
||||||
label.unwrap_or("default".into()),
|
|
||||||
scan_sk,
|
|
||||||
SpendKey::Secret(spend_sk),
|
|
||||||
None,
|
|
||||||
network,
|
network,
|
||||||
)?;
|
)
|
||||||
let our_address: SilentPaymentAddress = sp_client.get_receiving_address().try_into()?;
|
|
||||||
sdk_common::log::info!(
|
|
||||||
"Created client for sp with address: {}",
|
|
||||||
our_address.to_string()
|
|
||||||
);
|
|
||||||
|
|
||||||
let res = SpWallet::new(sp_client, None, vec![])?;
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user