Add the members_list everywhere necessary
This commit is contained in:
parent
a02b752aaa
commit
4e8ac88336
112
src/api.rs
112
src/api.rs
@ -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())
|
||||
|
Loading…
x
Reference in New Issue
Block a user