Add the members_list everywhere necessary

This commit is contained in:
NicolasCantu 2025-03-26 12:42:59 +01:00
parent a02b752aaa
commit 4e8ac88336

View File

@ -23,6 +23,7 @@ use sdk_common::crypto::{
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::serialization::OutPointMemberMap;
use sdk_common::signature::{AnkHash, AnkMessageHash, AnkValidationNoHash, AnkValidationYesHash, Proof};
use sdk_common::sp_client::bitcoin::blockdata::fee_rate;
use sdk_common::sp_client::bitcoin::consensus::{deserialize, serialize};
@ -566,6 +567,7 @@ fn process_transaction(
tx_hex: String,
blockheight: u32,
tweak_data_hex: String,
members_list: &OutPointMemberMap
) -> anyhow::Result<ApiReturn> {
let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?;
@ -575,7 +577,7 @@ fn process_transaction(
let processes = lock_processes()?;
let process = processes.get(&outpoint).unwrap();
let new_state = process.get_latest_commited_state().unwrap();
let diffs = if let Ok(diffs) = create_diffs(process, new_state) { diffs } else { vec![] };
let diffs = if let Ok(diffs) = create_diffs(process, new_state, members_list) { diffs } else { vec![] };
let updated_process = UpdatedProcess {
process_id: outpoint,
current_process: process.clone(),
@ -609,7 +611,7 @@ fn process_transaction(
}
#[wasm_bindgen]
pub fn parse_new_tx(new_tx_msg: String, block_height: u32) -> ApiResult<ApiReturn> {
pub fn parse_new_tx(new_tx_msg: String, block_height: u32, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
let new_tx: NewTxMessage = serde_json::from_str(&new_tx_msg)?;
if let Some(error) = new_tx.error {
@ -627,6 +629,7 @@ pub fn parse_new_tx(new_tx_msg: String, block_height: u32) -> ApiResult<ApiRetur
new_tx.transaction,
block_height,
new_tx.tweak_data.unwrap(),
&members_list
)?)
}
@ -650,13 +653,22 @@ fn confirm_prd(prd: &Prd, shared_secret: &AnkSharedSecretHash) -> AnyhowResult<S
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) -> AnyhowResult<Vec<UserDiff>> {
fn create_diffs(process: &Process, new_state: &ProcessState, members_list: &OutPointMemberMap) -> AnyhowResult<Vec<UserDiff>> {
let new_state_commitments = &new_state.pcd_commitment;
let device = lock_local_device()?;
let our_id = device.to_member();
let our_id = device.get_pairing_commitment();
let fields_to_validate = new_state.get_fields_to_validate_for_member(&our_id)?;
let fields_to_validate = if let Some(our_id) = our_id {
new_state.get_fields_to_validate_for_member(&our_id)?
} else {
// Device is unpaired, we just take all the fields in the `pairing` role
if let Some(pairing_role) = new_state.roles.get("pairing") {
pairing_role.validation_rules.iter().flat_map(|r| r.fields.clone()).collect()
} else {
return Err(AnyhowError::msg("Missing pairing role"))
}
};
let new_state_id = &new_state.state_id;
@ -740,7 +752,8 @@ fn handle_prd_connect(prd: Prd, secret: AnkSharedSecretHash) -> AnyhowResult<Api
fn handle_prd(
prd: Prd,
secret: AnkSharedSecretHash
secret: AnkSharedSecretHash,
members_list: &OutPointMemberMap,
) -> AnyhowResult<ApiReturn> {
debug!("handle_prd: {:#?}", prd);
// Connect is a bit different here because there's no associated process
@ -782,7 +795,7 @@ fn handle_prd(
};
// Compute the diffs
let diffs = create_diffs(&relevant_process, &new_state)?;
let diffs = create_diffs(&relevant_process, &new_state, members_list)?;
relevant_process.insert_concurrent_state(new_state)?;
@ -858,7 +871,15 @@ fn handle_prd(
PrdType::Request => {
// We are being requested encrypted data for one or more states, to be uploaded on storage
let states: Vec<[u8; 32]> = serde_json::from_str(&prd.payload)?;
let requester = prd.sender;
let requester = if let Some((requester_process_id, _)) = members_list.0.iter()
.find(|(outpoint, member)| {
**member == prd.sender
})
{
requester_process_id
} else {
return Err(AnyhowError::msg("Unknown requester"));
};
// diffs will trigger upload of the encrypted data on storage
let mut diffs = vec![];
@ -909,7 +930,7 @@ fn handle_prd(
full_prd.filter_keys(&relevant_fields);
let prd_msg = full_prd.to_network_msg(sp_wallet)?;
let addresses = requester.get_addresses();
let addresses = prd.sender.get_addresses();
for sp_address in addresses.into_iter() {
// We skip our own device address, no point sending ourself a cipher
if sp_address == local_address {
@ -963,17 +984,18 @@ fn handle_prd(
fn handle_decrypted_message(
secret: AnkSharedSecretHash,
plain: Vec<u8>,
members_list: &OutPointMemberMap
) -> anyhow::Result<ApiReturn> {
let local_address: SilentPaymentAddress = lock_local_device()?.get_wallet().get_client().get_receiving_address().try_into()?;
if let Ok(prd) = Prd::extract_from_message(&plain, local_address) {
handle_prd(prd, secret)
handle_prd(prd, secret, members_list)
} else {
Err(anyhow::Error::msg("Failed to handle decrypted message"))
}
}
#[wasm_bindgen]
pub fn parse_cipher(cipher_msg: String) -> ApiResult<ApiReturn> {
pub fn parse_cipher(cipher_msg: String, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
// Check that the cipher is not empty or too long
if cipher_msg.is_empty() || cipher_msg.len() > MAX_PRD_PAYLOAD_SIZE {
return Err(ApiError::new(
@ -985,7 +1007,7 @@ pub fn parse_cipher(cipher_msg: String) -> ApiResult<ApiReturn> {
let decrypt_res = lock_shared_secrets()?.try_decrypt(&cipher);
if let Ok((secret, plain)) = decrypt_res {
return handle_decrypted_message(secret, plain)
return handle_decrypted_message(secret, plain, &members_list)
.map_err(|e| ApiError::new(format!("Failed to handle decrypted message: {}", e)));
}
@ -1109,6 +1131,7 @@ pub fn create_new_process(
public_data: JsValue,
relay_address: String,
fee_rate: u32,
members_list: OutPointMemberMap,
) -> ApiResult<ApiReturn> {
let init_state: Pcd = serde_wasm_bindgen::from_value(init_state)?;
let roles: Roles = serde_wasm_bindgen::from_value(roles)?;
@ -1140,7 +1163,7 @@ pub fn create_new_process(
let mut process = Process::new(process_id);
let diffs = create_diffs(&process, &new_state)?;
let diffs = create_diffs(&process, &new_state, &members_list)?;
let all_fields: Vec<String> = init_state.iter().map(|(field, _)| field.clone()).collect();
let mut fields2keys = BTreeMap::new();
@ -1198,9 +1221,7 @@ pub fn create_new_process(
/// TODO allow modifications from user that doesn't have read access to all attributes
pub fn update_process(
mut process: Process,
new_attributes: JsValue,
roles: JsValue,
new_public_data: JsValue,
members_list: OutPointMemberMap,
) -> ApiResult<ApiReturn> {
let new_attributes: Pcd = serde_wasm_bindgen::from_value(new_attributes)?;
let roles: Roles = serde_wasm_bindgen::from_value(roles)?;
@ -1239,7 +1260,7 @@ pub fn update_process(
return Err(ApiError::new("New state already known".to_owned()));
}
let diffs = create_diffs(&process, &new_state)?;
let diffs = create_diffs(&process, &new_state, &members_list)?;
let all_fields: Vec<String> = new_attributes.iter().map(|(field, _)| field.clone()).collect();
let mut encrypted_data = BTreeMap::new();
@ -1288,7 +1309,7 @@ pub fn update_process(
}
#[wasm_bindgen]
pub fn request_data(process_id: String, state_ids_str: Vec<String>, roles: JsValue) -> ApiResult<ApiReturn> {
pub fn request_data(process_id: String, state_ids_str: Vec<String>, roles: JsValue, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
let process_id = OutPoint::from_str(&process_id)?;
let local_device = lock_local_device()?;
let sender = local_device.to_member();
@ -1323,7 +1344,7 @@ pub fn request_data(process_id: String, state_ids_str: Vec<String>, roles: JsVal
let prd_request = Prd::new_request(
process_id,
sender,
members_list.0.get(&sender_pairing_id).unwrap().clone(),
state_ids
);
@ -1351,6 +1372,7 @@ pub fn request_data(process_id: String, state_ids_str: Vec<String>, roles: JsVal
pub fn create_update_message(
process_id: String,
state_id: String,
members_list: OutPointMemberMap
) -> ApiResult<ApiReturn> {
let mut processes = lock_processes()?;
@ -1433,26 +1455,30 @@ pub fn create_update_message(
}
#[wasm_bindgen]
pub fn validate_state(process: Process, state_id: String) -> ApiResult<ApiReturn> {
add_validation_token(process, state_id, true)
pub fn validate_state(process: Process, state_id: String, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
add_validation_token(process, state_id, true, &members_list)
}
#[wasm_bindgen]
pub fn refuse_state(process: Process, state_id: String) -> ApiResult<ApiReturn> {
add_validation_token(process, state_id, false)
pub fn refuse_state(process: Process, state_id: String, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
add_validation_token(process, state_id, false, &members_list)
}
#[wasm_bindgen]
pub fn evaluate_state(process_id: String, previous_state: Option<ProcessState>, process_state: ProcessState) -> ApiResult<ApiReturn> {
process_state.is_valid(previous_state.as_ref())?;
pub fn evaluate_state(process: Process, state_id: String, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
let state_id: [u8; 32] = Vec::from_hex(&state_id)?.try_into().map_err(|_| ApiError::new("Invalid state id".to_owned()))?;
let process_id = process.get_process_id()?;
let process_state = process.get_state_for_id(&state_id)?;
let previous_state = process.get_parent_state(&process_state.commited_in);
process_state.is_valid(previous_state, &members_list)?;
// We create a commit msg with the valid state
let outpoint: OutPoint = OutPoint::from_str(&process_id)?;
let commit_msg = CommitMessage::new(
outpoint,
process_state.pcd_commitment,
process_state.roles,
process_state.public_data,
process_id,
process_state.pcd_commitment.clone(),
process_state.roles.clone(),
process_state.public_data.clone(),
vec![]
);
@ -1462,7 +1488,7 @@ pub fn evaluate_state(process_id: String, previous_state: Option<ProcessState>,
})
}
fn add_validation_token(mut process: Process, state_id: String, approval: bool) -> ApiResult<ApiReturn> {
fn add_validation_token(mut process: Process, state_id: String, approval: bool, members_list: &OutPointMemberMap) -> ApiResult<ApiReturn> {
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()))?;
@ -1497,7 +1523,7 @@ fn add_validation_token(mut process: Process, state_id: String, approval: bool)
..Default::default()
};
let ciphers_to_send = new_response_prd(process_id, process.get_state_for_id_mut(&state_id)?)?;
let ciphers_to_send = new_response_prd(process_id, process.get_state_for_id(&state_id)?, members_list)?;
Ok(ApiReturn {
updated_process: Some(updated_process),
@ -1508,18 +1534,13 @@ fn add_validation_token(mut process: Process, state_id: String, approval: bool)
}
#[wasm_bindgen]
pub fn create_response_prd(process_id: String, state_id: String) -> ApiResult<ApiReturn> {
let mut processes = lock_processes()?;
pub fn create_response_prd(process: Process, state_id: String, members_list: OutPointMemberMap) -> ApiResult<ApiReturn> {
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 outpoint = OutPoint::from_str(&process_id)?;
let update_state: &ProcessState = process.get_state_for_id(&state_id)?;
let process = processes.get_mut(&outpoint)
.ok_or(ApiError::new("Unknown process".to_owned()))?;
let update_state: &mut ProcessState = process.get_state_for_id_mut(&state_id)?;
let ciphers = new_response_prd(outpoint, update_state)?;
let ciphers = new_response_prd(process_id, update_state, &members_list)?;
Ok(ApiReturn {
ciphers_to_send: ciphers,
@ -1527,7 +1548,7 @@ pub fn create_response_prd(process_id: String, state_id: String) -> ApiResult<Ap
})
}
fn new_response_prd(process_id: OutPoint, update_state: &mut ProcessState) -> 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 sp_wallet = local_device.get_wallet();
let local_address = sp_wallet.get_client().get_receiving_address();
@ -1540,7 +1561,12 @@ fn new_response_prd(process_id: OutPoint, update_state: &mut ProcessState) -> An
.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())