diff --git a/src/api.rs b/src/api.rs index c982c6e..3eb0ae6 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1126,17 +1126,13 @@ pub fn create_connect_transaction(addresses: Vec, fee_rate: u32) -> ApiR #[wasm_bindgen] pub fn create_new_process( - init_state: JsValue, - roles: JsValue, - public_data: JsValue, + private_data: Pcd, + roles: Roles, + public_data: Pcd, relay_address: String, fee_rate: u32, members_list: OutPointMemberMap, ) -> ApiResult { - let init_state: Pcd = serde_wasm_bindgen::from_value(init_state)?; - let roles: Roles = serde_wasm_bindgen::from_value(roles)?; - let public_data: Pcd = serde_wasm_bindgen::from_value(public_data)?; - // We create a transaction that spends to the relay address let psbt = create_transaction_for_addresses(vec![relay_address.clone()], fee_rate)?; @@ -1157,7 +1153,7 @@ pub fn create_new_process( let new_tx_msg = NewTxMessage::new(serialize(&transaction).to_lower_hex_string(), None); - let mut new_state = ProcessState::new(process_id, init_state.clone(), public_data.clone(), roles.clone())?; + let mut new_state = ProcessState::new(process_id, private_data.clone(), public_data.clone(), roles.clone())?; let pcd_commitment = new_state.pcd_commitment.clone(); @@ -1165,22 +1161,18 @@ pub fn create_new_process( let diffs = create_diffs(&process, &new_state, &members_list)?; - let all_fields: Vec = init_state.iter().map(|(field, _)| field.clone()).collect(); - let mut fields2keys = BTreeMap::new(); let mut encrypted_data = BTreeMap::new(); let mut rng = thread_rng(); - for (field, plain_value) in init_state.iter() { + for (field, plain_value) in private_data.iter() { let hash = pcd_commitment.get(field).ok_or(anyhow::Error::msg("Missing commitment"))?; let key = generate_key(&mut rng); let serialized = serde_json::to_string(plain_value)?; let cipher = encrypt_with_key(&key, serialized.as_bytes())?; - fields2keys.insert(field.to_owned(), key); + new_state.keys.insert(field.to_owned(), key); encrypted_data.insert(hash.to_lower_hex_string(), cipher.to_lower_hex_string()); } - new_state.keys = fields2keys; - process.insert_concurrent_state(new_state.clone())?; { @@ -1218,15 +1210,13 @@ pub fn create_new_process( } #[wasm_bindgen] -/// TODO allow modifications from user that doesn't have read access to all attributes pub fn update_process( mut process: Process, + new_attributes: Pcd, + roles: Roles, + new_public_data: Pcd, members_list: OutPointMemberMap, ) -> ApiResult { - let new_attributes: Pcd = serde_wasm_bindgen::from_value(new_attributes)?; - let roles: Roles = serde_wasm_bindgen::from_value(roles)?; - let new_public_data: Pcd = serde_wasm_bindgen::from_value(new_public_data)?; - let process_id = process.get_process_id()?; let prev_state = process.get_latest_commited_state() @@ -1237,9 +1227,6 @@ pub fn update_process( prev_public_data.insert(field, value); } - // We expect the whole set of attributes for now, even if value doesn't change since previous state - // We rehash everything with the new txid, so we need the clear value - // eventually we would like to be able to create partial states even if we don't have read access to some attributes let mut new_state = ProcessState::new( process.get_process_tip()?, new_attributes.clone(), @@ -1312,7 +1299,7 @@ pub fn update_process( pub fn request_data(process_id: String, state_ids_str: Vec, roles: JsValue, members_list: OutPointMemberMap) -> ApiResult { let process_id = OutPoint::from_str(&process_id)?; let local_device = lock_local_device()?; - let sender = local_device.to_member(); + 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 = sp_wallet.get_client().get_receiving_address(); let roles: Vec = serde_wasm_bindgen::from_value(roles)?; @@ -1329,14 +1316,16 @@ pub fn request_data(process_id: String, state_ids_str: Vec, roles: JsVal let mut send_to: HashSet = HashSet::new(); for role in roles { for (_, role_def) in role { - let members = &role_def.members; - if !members.contains(&sender) { + let pairing_ids = &role_def.members; + if !pairing_ids.contains(&sender_pairing_id) { continue; } - for member in members { - for address in member.get_addresses() { - if address == local_address { continue }; - send_to.insert(SilentPaymentAddress::try_from(address)?); + for pairing_id in pairing_ids { + if let Some(member) = members_list.0.get(pairing_id) { + for address in member.get_addresses() { + if address == local_address { continue }; + send_to.insert(SilentPaymentAddress::try_from(address)?); + } } } } @@ -1370,18 +1359,13 @@ pub fn request_data(process_id: String, state_ids_str: Vec, roles: JsVal #[wasm_bindgen] pub fn create_update_message( - process_id: String, + process: Process, state_id: String, members_list: OutPointMemberMap ) -> ApiResult { - let mut processes = lock_processes()?; - - let process_id = OutPoint::from_str(&process_id)?; + let process_id = process.get_process_id()?; let state_id: [u8; 32] = Vec::from_hex(&state_id)?.try_into().map_err(|_| ApiError::new("Invalid state_id".to_owned()))?; - let process = processes.get_mut(&process_id) - .ok_or(ApiError::new("Unknown process".to_owned()))?; - let update_state = process.get_state_for_id(&state_id)?; let local_device = lock_local_device()?; @@ -1397,7 +1381,12 @@ pub fn create_update_message( .iter() .flat_map(|rule| rule.fields.clone()) .collect(); - for member in &role.members { + for pairing_id in &role.members { + let member = if let Some(member) = members_list.0.get(pairing_id) { + member + } else { + continue; + }; // Check that we have a shared_secret with all members if let Some(no_secret_address) = member.get_addresses().iter() .find(|a| shared_secrets.get_secret_for_address(a.as_str().try_into().unwrap()).is_none()) @@ -1405,7 +1394,7 @@ pub fn create_update_message( // We ignore it if we don't have a secret with ourselves if *no_secret_address != local_address { // for now we return an error to keep it simple - return Err(ApiError::new(format!("No shared secret for all addresses of {:?}\nPlease first connect", member))); + return Err(ApiError::new(format!("No shared secret for all addresses of {:?}\nPlease first connect", pairing_id))); } } if !all_members.contains_key(&member) {