Add Process

This commit is contained in:
Sosthene 2024-08-20 12:22:03 +02:00
parent d073b12340
commit 45628edb61
6 changed files with 79 additions and 218 deletions

View File

@ -14,6 +14,8 @@ use anyhow::Error as AnyhowError;
use sdk_common::crypto::{ use sdk_common::crypto::{
AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, AnkSharedSecret, KeyInit, Purpose, AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, AnkSharedSecret, KeyInit, Purpose,
}; };
use sdk_common::device::{REVOKATION_INDEX, SESSION_INDEX};
use sdk_common::process::{Member, PairingPcd, Process, Role, ValidationRules};
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};
use sdk_common::sp_client::bitcoin::hashes::HashEngine; use sdk_common::sp_client::bitcoin::hashes::HashEngine;
@ -47,20 +49,18 @@ use wasm_bindgen::convert::FromWasmAbi;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use sdk_common::network::{ use sdk_common::network::{
self, AnkFlag, CachedMessage, CachedMessageStatus, Envelope, FaucetMessage, NewTxMessage, Pcd, Prd self, AnkFlag, CachedMessage, CachedMessageStatus, Envelope, FaucetMessage, NewTxMessage, Pcd, Prd, PrdType
}; };
use sdk_common::silentpayments::{create_transaction, map_outputs_to_sp_address}; use sdk_common::silentpayments::{create_transaction, map_outputs_to_sp_address};
use crate::wallet::{generate_sp_wallet, lock_freezed_utxos};
use sdk_common::sp_client::spclient::{ use sdk_common::sp_client::spclient::{
derive_keys_from_seed, OutputList, OutputSpendStatus, OwnedOutput, Recipient, SpClient, derive_keys_from_seed, OutputList, OutputSpendStatus, OwnedOutput, Recipient, SpClient,
}; };
use sdk_common::sp_client::spclient::{SpWallet, SpendKey}; use sdk_common::sp_client::spclient::{SpWallet, SpendKey};
use sdk_common::device::Device;
use crate::user::{lock_local_device, set_new_device, Device, LOCAL_DEVICE}; use crate::user::{lock_local_device, set_new_device, LOCAL_DEVICE};
use crate::{lock_messages, CACHEDMESSAGES}; use crate::{lock_messages, CACHEDMESSAGES};
use crate::wallet::{generate_sp_wallet, lock_freezed_utxos};
use crate::process::Process;
pub type ApiResult<T: FromWasmAbi> = Result<T, ApiError>; pub type ApiResult<T: FromWasmAbi> = Result<T, ApiError>;
@ -218,7 +218,7 @@ pub fn create_new_device(birthday: u32, network_str: String) -> ApiResult<String
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn pair_device(message_id: u32, incoming_pairing_txid: String) -> ApiResult<()> { pub fn pair_device(nym: String, message_id: u32, incoming_pairing_txid: String) -> ApiResult<Process> {
let mut local_device = lock_local_device()?; let mut local_device = lock_local_device()?;
// check that we're still in pairing phase // check that we're still in pairing phase
@ -270,75 +270,25 @@ pub fn pair_device(message_id: u32, incoming_pairing_txid: String) -> ApiResult<
)?; )?;
message.status = CachedMessageStatus::Closed; message.status = CachedMessageStatus::Closed;
let pairing_pcd = PairingPcd::new(
nym,
local_device.get_wallet().get_client().get_receiving_address().try_into().unwrap(),
local_device.get_paired_device_info().unwrap().address.try_into().unwrap(),
SESSION_INDEX,
REVOKATION_INDEX,
Txid::from_str(&incoming_pairing_txid)?,
pairing_tx.txid
);
let pairing_process = Process::new_pairing_process(pairing_pcd, pairing_tx.txid);
Ok(pairing_process)
} else { } else {
return Err(ApiError { return Err(ApiError {
message: format!("Can't find message with id {}", message_id), message: format!("Can't find message with id {}", message_id),
}); });
} }
Ok(())
}
#[derive(Tsify, Serialize, Deserialize)]
#[tsify(into_wasm_abi)]
#[allow(non_camel_case_types)]
pub struct get_process_return(Vec<Process>);
#[wasm_bindgen]
pub fn get_processes() -> ApiResult<get_process_return> {
let MEMBERS: [String;5] = [
"tsp1qqdvmxycf3c3tf2qhpev0npx25rj05270d6j2pcsrfk2qn5gdy0rpwq6hd9u9sztl3fwmrzzqafzl3ymkq86aqfz5jl5egdkz72tqmhcnrswdz3pk".to_owned(),
"tsp1qqwafwn7dcr9d6ta0w8fjtd9s53u72x9qmmtgd8adqr7454xl90a5jq3vw23l2x8ypt55nrg7trl9lwz5xr5j357ucu4sf9rfmvc0zujcpqcps6rm".to_owned(),
"tsp1qqw02t5hmg5rxpjdkmjdnnmhvuc76wt6vlqdmn2zafnh6axxjd6e2gqcz04gzvnkzf572mur8spyx2a2s8sqzll2ymdpyz59cpl96j4zuvcdvrzxz".to_owned(),
"tsp1qqgpay2r5jswm7vcv24xd94shdf90w30vxtql9svw7qnlnrzd6xt02q7s7z57uw0sssh6c0xddcrryq4mxup93jsh3gfau3autrawl8umkgsyupkm".to_owned(),
"tsp1qqtsqmtgnxp0lsmnxyxcq52zpgxwugwlq8urlprs5pr5lwyqc789gjqhx5qra6g4rszsq43pms6nguee2l9trx905rk5sgntek05hnf7say4ru69y".to_owned(),
];
//instances of process
let process1 = Process {
id: 6,
name: String::from("Messaging"),
version: String::from("1.0"),
members: MEMBERS.to_vec(),
html: crate::process::HTML_MESSAGING.to_owned(),
style: crate::process::CSS.to_owned(),
script: "".to_owned(),
};
let process2 = Process {
id: 7,
name: String::from("Kotpart"),
version: String::from("1.0"),
members: MEMBERS.to_vec(),
html: crate::process::HTML_MESSAGING.to_owned(),
style: crate::process::CSS.to_owned(),
script: "".to_owned(),
};
let process3 = Process {
id: 8,
name: String::from("Storage"),
version: String::from("1.0"),
members: MEMBERS.to_vec(),
html: crate::process::HTML_MESSAGING.to_owned(),
style: crate::process::CSS.to_owned(),
script: "".to_owned(),
};
// vec with the instances of processes
let mut data_process: Vec<Process> = Vec::new();
data_process.push(process1);
data_process.push(process2);
data_process.push(process3);
Ok(get_process_return(data_process))
}
#[derive(Debug, Tsify, Serialize, Deserialize)]
#[tsify(from_wasm_abi)]
#[allow(non_camel_case_types)]
pub struct recover_data(Vec<u8>);
impl recover_data {
fn as_inner(&self) -> &[u8] {
&self.0
}
} }
#[derive(Debug, Tsify, Serialize, Deserialize)] #[derive(Debug, Tsify, Serialize, Deserialize)]
@ -728,6 +678,7 @@ pub fn parse_cipher(cipher_msg: String, fee_rate: u32) -> ApiResult<CachedMessag
message: "Prd doesn't match commitment".to_owned(), message: "Prd doesn't match commitment".to_owned(),
}); });
} }
message.prd_type = prd.prd_type.clone();
message.sender = Some(prd.sender.clone()); message.sender = Some(prd.sender.clone());
message.pcd_commitment = Some(prd.pcd_commitment.to_string()); message.pcd_commitment = Some(prd.pcd_commitment.to_string());
message.prd_cipher = None; message.prd_cipher = None;
@ -957,7 +908,20 @@ pub fn create_login_transaction(fee_rate: u32) -> ApiResult<createTransactionRet
let key: [u8; 32] = Aes256Gcm::generate_key(thread_rng()).into(); let key: [u8; 32] = Aes256Gcm::generate_key(thread_rng()).into();
let process = Process::new(
"empty".to_owned(),
vec![],
ValidationRules::new(0.0, Role::User),
Txid::all_zeros(),
String::default(),
String::default(),
String::default(),
Value::Null
);
let prd = Prd::new( let prd = Prd::new(
PrdType::Message,
process,
local_device local_device
.get_wallet() .get_wallet()
.get_client() .get_client()
@ -966,7 +930,7 @@ pub fn create_login_transaction(fee_rate: u32) -> ApiResult<createTransactionRet
.unwrap(), .unwrap(),
key, key,
pcd_commitment, pcd_commitment,
); )?;
let pcd_cipher = prd.encrypt_pcd(&pcd)?; let pcd_cipher = prd.encrypt_pcd(&pcd)?;
@ -1056,7 +1020,18 @@ pub fn create_pairing_transaction(
let pcd = Pcd::new("PAIRING".to_owned()); let pcd = Pcd::new("PAIRING".to_owned());
let mut res = create_notification_transaction(address, pcd, fee_rate)?; let process = Process::new(
"empty".to_owned(),
vec![],
ValidationRules::new(0.0, Role::User),
Txid::all_zeros(),
String::default(),
String::default(),
String::default(),
Value::Null
);
let mut res = create_notification_transaction(address, process, pcd, fee_rate)?;
let mut messages = lock_messages()?; let mut messages = lock_messages()?;
@ -1073,6 +1048,7 @@ pub fn create_pairing_transaction(
#[wasm_bindgen] #[wasm_bindgen]
pub fn create_notification_transaction( pub fn create_notification_transaction(
address: String, address: String,
process: Process,
pcd: Pcd, pcd: Pcd,
fee_rate: u32, fee_rate: u32,
) -> ApiResult<createTransactionReturn> { ) -> ApiResult<createTransactionReturn> {
@ -1093,10 +1069,12 @@ pub fn create_notification_transaction(
let key: [u8; 32] = Aes256Gcm::generate_key(thread_rng()).into(); let key: [u8; 32] = Aes256Gcm::generate_key(thread_rng()).into();
let prd = Prd::new( let prd = Prd::new(
PrdType::Message,
process,
sp_wallet.get_client().get_receiving_address().try_into().unwrap(), sp_wallet.get_client().get_receiving_address().try_into().unwrap(),
key, key,
pcd_commitment pcd_commitment
); )?;
let prd_commitment = sha256sum(prd.to_string().as_bytes()); let prd_commitment = sha256sum(prd.to_string().as_bytes());

View File

@ -10,7 +10,6 @@ use tsify::Tsify;
pub mod api; pub mod api;
mod peers; mod peers;
mod process;
mod user; mod user;
mod wallet; mod wallet;

View File

@ -25,6 +25,7 @@ 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::utils::{Network as SpNetwork, SilentPaymentAddress};
use sdk_common::sp_client::spclient::{OutputList, SpWallet, SpendKey}; use sdk_common::sp_client::spclient::{OutputList, SpWallet, SpendKey};
use sdk_common::device::Device;
use crate::peers::Peer; use crate::peers::Peer;
use crate::wallet::generate_sp_wallet; use crate::wallet::generate_sp_wallet;
@ -58,142 +59,3 @@ pub fn lock_local_device() -> Result<MutexGuard<'static, Device>> {
.get_or_init(|| Mutex::new(Device::default())) .get_or_init(|| Mutex::new(Device::default()))
.lock_anyhow() .lock_anyhow()
} }
#[derive(Debug, Serialize, Deserialize, Clone, Default, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct PairedDevice {
pub address: String,
pub outgoing_pairing_transaction: [u8; 32],
pub revokation_index: u32,
pub incoming_pairing_transaction: [u8; 32],
pub current_remote_key: [u8; 32],
pub current_session_outpoint: OutPoint, // This will be spend by remote device to notify us of next login
pub current_session_revokation_outpoint: OutPoint, // remote device can revoke current session by spending this
}
impl PairedDevice {
pub fn new(address: SilentPaymentAddress, pairing_txid: Txid, revokation_index: u32) -> Self {
let mut pairing_transaction_buf = [0u8; 32];
pairing_transaction_buf.copy_from_slice(&serialize(&pairing_txid));
Self {
address: address.into(),
outgoing_pairing_transaction: pairing_transaction_buf,
revokation_index,
incoming_pairing_transaction: [0u8; 32],
current_session_revokation_outpoint: OutPoint::default(),
current_session_outpoint: OutPoint::default(),
current_remote_key: [0u8; 32],
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct Device {
sp_wallet: SpWallet,
current_session_outpoint: OutPoint, // This is the notification output of incoming login tx
current_session_key: [u8; 32],
current_session_revokation_outpoint: OutPoint, // This is the revokation outpoint of outgoing login tx
paired_device: Option<PairedDevice>,
}
impl Device {
pub fn new(sp_wallet: SpWallet) -> Self {
Self {
sp_wallet,
current_session_outpoint: OutPoint::default(),
current_session_key: [0u8; 32],
current_session_revokation_outpoint: OutPoint::default(),
paired_device: None,
}
}
pub fn get_wallet(&self) -> &SpWallet {
&self.sp_wallet
}
pub fn get_mut_wallet(&mut self) -> &mut SpWallet {
&mut self.sp_wallet
}
pub fn is_linked(&self) -> bool {
self.paired_device.is_some()
}
pub fn is_pairing(&self) -> bool {
self.current_session_key == [0u8; 32]
}
pub fn get_paired_device_info(&self) -> Option<PairedDevice> {
self.paired_device.clone()
}
pub fn get_next_output_to_spend(&self) -> OutPoint {
self.current_session_outpoint
}
pub fn get_session_revokation_outpoint(&self) -> OutPoint {
self.current_session_revokation_outpoint
}
pub fn sign_with_current_session_key(&self) -> Result<()> {
unimplemented!();
}
pub fn encrypt_with_current_session_key(&self) -> Result<()> {
unimplemented!();
}
pub fn new_link(
&mut self,
link_with: SilentPaymentAddress,
outgoing_pairing_tx: Txid,
revokation_output: u32,
incoming_pairing_tx: Txid,
) -> Result<()> {
let address_looked_for: String = link_with.into();
if let Some(paired_device) = self.paired_device.as_ref() {
return Err(Error::msg(format!(
"Found an already paired device with address {} and revokable by {}:{}",
paired_device.address,
Txid::from_byte_array(paired_device.outgoing_pairing_transaction),
paired_device.revokation_index
)));
} else {
let mut new_device =
PairedDevice::new(link_with, outgoing_pairing_tx, revokation_output);
new_device.incoming_pairing_transaction = incoming_pairing_tx.to_byte_array();
self.paired_device = Some(new_device);
}
Ok(())
}
// We call that when we spent to the remote device and it similarly spent to us
pub fn update_session(
&mut self,
new_session_key: SecretKey,
new_session_outpoint: OutPoint,
new_revokation_outpoint: OutPoint,
new_remote_key: XOnlyPublicKey,
new_remote_session_outpoint: OutPoint,
new_remote_revokation_outpoint: OutPoint,
) -> Result<()> {
if !self.is_linked() {
return Err(Error::msg("Can't update an unpaired device"));
}
self.paired_device
.as_mut()
.map(|d| {
d.current_remote_key = new_remote_key.serialize();
d.current_session_outpoint = new_remote_session_outpoint;
d.current_session_revokation_outpoint = new_remote_revokation_outpoint;
});
self.current_session_key = new_session_key.secret_bytes();
self.current_session_outpoint = new_session_outpoint;
self.current_session_revokation_outpoint = new_revokation_outpoint;
Ok(())
}
}

View File

@ -79,7 +79,13 @@ fn test_pairing() {
helper_parse_transaction(&bob_pairing_tx.transaction, &bob_pairing_tweak_data); helper_parse_transaction(&bob_pairing_tx.transaction, &bob_pairing_tweak_data);
debug!("Bob pairs device with Alice"); debug!("Bob pairs device with Alice");
pair_device(bob_pairing_tx.new_network_msg.id, incoming_txid.to_string()).unwrap(); let pairing_process = pair_device(DEFAULT_NYM.to_owned(), bob_pairing_tx.new_network_msg.id, incoming_txid.to_string()).unwrap();
// sign the pairing process
// send it to Alice so that she can sign it too
// commit it to a transaction to make it public
// ======================== Alice // ======================== Alice
reset_device().unwrap(); reset_device().unwrap();
@ -95,7 +101,7 @@ fn test_pairing() {
assert!(bob_pairing_msg.status == CachedMessageStatus::Pairing); assert!(bob_pairing_msg.status == CachedMessageStatus::Pairing);
debug!("Alice pairs device"); debug!("Alice pairs device");
pair_device(alice_msg_id, bob_pairing_tx.txid).unwrap(); pair_device(DEFAULT_NYM.to_owned(), alice_msg_id, bob_pairing_tx.txid).unwrap();
} }
#[wasm_bindgen_test] #[wasm_bindgen_test]

View File

@ -7,9 +7,12 @@ use sdk_client::api::{
use sdk_common::network::{ use sdk_common::network::{
CachedMessage, CachedMessageStatus, Pcd CachedMessage, CachedMessageStatus, Pcd
}; };
use sdk_common::sp_client::bitcoin::OutPoint; use sdk_common::process::{Process, Role, ValidationRules};
use sdk_common::sp_client::bitcoin::hashes::Hash;
use sdk_common::sp_client::bitcoin::{OutPoint, Txid};
use sdk_common::sp_client::spclient::OwnedOutput; use sdk_common::sp_client::spclient::OwnedOutput;
use serde_json::Value;
use tsify::JsValueSerdeExt; use tsify::JsValueSerdeExt;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
@ -32,8 +35,19 @@ fn test_alice_sends_prd_message_to_bob() {
let pcd = Pcd::new("TEST".to_owned()); let pcd = Pcd::new("TEST".to_owned());
debug!("Alice notified Bob about a message it sent"); debug!("Alice notified Bob about a message it sent");
let empty_process = Process::new(
"empty".to_owned(),
vec![],
ValidationRules::new(0.0, Role::User),
Txid::all_zeros(),
String::default(),
String::default(),
String::default(),
Value::Null
);
let notification_tx = let notification_tx =
create_notification_transaction(helper_get_bob_address(), pcd, 1).unwrap(); create_notification_transaction(helper_get_bob_address(), empty_process, pcd, 1).unwrap();
let get_outputs_result = get_outputs().unwrap(); let get_outputs_result = get_outputs().unwrap();

File diff suppressed because one or more lines are too long