Update ProcessState with descriptions

This commit is contained in:
Sosthene 2024-12-12 16:47:36 +01:00
parent 40dbc1b2ba
commit f899719cc1
2 changed files with 25 additions and 38 deletions

View File

@ -90,9 +90,11 @@ pub enum DiffStatus {
#[tsify(into_wasm_abi)] #[tsify(into_wasm_abi)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct UserDiff { pub struct UserDiff {
pub process_id: String,
pub new_state_merkle_root: String, // TODO add a merkle proof that the new_value belongs to that state pub new_state_merkle_root: String, // TODO add a merkle proof that the new_value belongs to that state
pub value_commitment: String, pub value_commitment: String,
pub field: String, pub field: String,
pub description: Option<String>,
pub previous_value: Value, pub previous_value: Value,
pub new_value: Value, pub new_value: Value,
pub notify_user: bool, pub notify_user: bool,
@ -711,24 +713,30 @@ fn create_diffs(process: &Process, new_state: &ProcessState) -> AnyhowResult<Vec
Err(_) => Map::new() Err(_) => Map::new()
}; };
let new_state_descriptions = &new_state.descriptions;
let process_id = process.get_process_id()?.to_string();
let mut diffs = vec![]; let mut diffs = vec![];
if let Some(prev_state) = process.get_latest_commited_state() { if let Some(prev_state) = process.get_latest_commited_state() {
// We first decrypt as much as we can of the prev_state // We first decrypt as much as we can of the prev_state
let clear_prev_state = prev_state.decrypt_pcd()?; let clear_prev_state = prev_state.decrypt_pcd()?;
// We just make a diff for values that are different from previous state // We just make a diff for values that are different from previous state
for (field, prev_hash) in prev_state.pcd_commitment.as_object().unwrap() { for (field, prev_hash) in prev_state.pcd_commitment.as_object().unwrap() {
let description = new_state_descriptions.get(field).map(|d| d.to_string());
let new_value = if let Some(val) = new_state_decrypted.get(field.as_str()) { val.clone() } else { Value::Null };
let need_validation = if (is_pairing && field.as_str() == "roles" && new_value != Value::Null) || fields_to_validate.contains(field) { true } else { false };
if let Some(new_hash) = new_state_commitments.get(field.as_str()) { if let Some(new_hash) = new_state_commitments.get(field.as_str()) {
if new_hash.as_str() == prev_hash.as_str() { if new_hash.as_str() == prev_hash.as_str() {
continue; continue;
} else { } else {
// There's a diff // There's a diff
let previous_value = clear_prev_state.get(field.as_str()).unwrap().clone(); let previous_value = clear_prev_state.get(field.as_str()).unwrap().clone();
let new_value = if let Some(val) = new_state_decrypted.get(field.as_str()) { val.clone() } else { Value::Null };
let need_validation = if (is_pairing && field.as_str() == "roles" && new_value != Value::Null) || fields_to_validate.contains(field) { true } else { false };
diffs.push(UserDiff { diffs.push(UserDiff {
process_id: process_id.clone(),
new_state_merkle_root: new_state_root.to_owned(), new_state_merkle_root: new_state_root.to_owned(),
value_commitment: new_hash.as_str().unwrap().to_string(), value_commitment: new_hash.as_str().unwrap().to_string(),
field: field.to_owned(), field: field.to_owned(),
description,
previous_value, previous_value,
new_value, new_value,
notify_user: false, notify_user: false,
@ -744,12 +752,15 @@ fn create_diffs(process: &Process, new_state: &ProcessState) -> AnyhowResult<Vec
} else { } else {
// All fields need a diff // All fields need a diff
for (field, hash) in new_state_commitments { for (field, hash) in new_state_commitments {
let description = new_state_descriptions.get(field).map(|d| d.to_string());
let new_value = if let Some(val) = new_state_decrypted.get(field.as_str()) { val.clone() } else { Value::Null }; let new_value = if let Some(val) = new_state_decrypted.get(field.as_str()) { val.clone() } else { Value::Null };
let need_validation = if (is_pairing && field.as_str() == "roles" && new_value != Value::Null) || fields_to_validate.contains(field) { true } else { false }; let need_validation = if (is_pairing && field.as_str() == "roles" && new_value != Value::Null) || fields_to_validate.contains(field) { true } else { false };
diffs.push(UserDiff { diffs.push(UserDiff {
process_id: process_id.clone(),
new_state_merkle_root: new_state_root.to_owned(), new_state_merkle_root: new_state_root.to_owned(),
value_commitment: hash.as_str().unwrap().to_string(), value_commitment: hash.as_str().unwrap().to_string(),
field: field.to_owned(), field: field.to_owned(),
description,
previous_value: Value::Null, previous_value: Value::Null,
new_value, new_value,
notify_user: false, notify_user: false,
@ -1145,26 +1156,16 @@ pub fn create_connect_transaction(members_str: Vec<String>, fee_rate: u32) -> Ap
#[wasm_bindgen] #[wasm_bindgen]
pub fn create_new_process( pub fn create_new_process(
init_state: String, init_state_str: String,
descriptions_str: Option<String>,
relay_address: String, relay_address: String,
fee_rate: u32, fee_rate: u32,
) -> ApiResult<ApiReturn> { ) -> ApiResult<ApiReturn> {
let pcd = <Value as Pcd>::new_from_string(&init_state)?; let init_state = <Value as Pcd>::new_from_string(&init_state_str)?;
let descriptions = if let Some(d) = descriptions_str { <Value as Pcd>::new_from_string(&d)? } else { Value::Object(Map::new()) };
// check that we have a proper roles map // check that we have a proper roles map
let roles = pcd.extract_roles()?; let roles = init_state.extract_roles()?;
// We create the encryption keys for each field and encrypt them
let mut fields2keys = Map::new();
let mut fields2cipher = Map::new();
let fields_to_encrypt: Vec<String> = pcd
.as_object()
.unwrap()
.keys()
.map(|k| k.clone())
.collect();
pcd.encrypt_fields(&fields_to_encrypt, &mut fields2keys, &mut fields2cipher);
// 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 psbt = create_transaction_for_addresses(vec![relay_address.clone()], fee_rate)?;
@ -1184,26 +1185,13 @@ pub fn create_new_process(
// 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 outpoint = OutPoint::new(transaction.txid(), 0); let outpoint = OutPoint::new(transaction.txid(), 0);
// We now need a hash that commits to the clear value of each field + the process id (or outpoint) let new_state = ProcessState::new(outpoint, init_state.to_value_object()?, descriptions.to_value_object()?)?;
let pcd_commitment = Value::Object(pcd.hash_all_fields(outpoint)?);
let merkle_root = pcd_commitment.create_merkle_tree()?.root().ok_or(ApiError::new("Invalid merkle tree".to_owned()))?.to_lower_hex_string();
let mut process = Process::new(outpoint); let mut process = Process::new(outpoint);
// We now create the first process state with all that data let diffs = create_diffs(&process, &new_state)?;
let process_state = ProcessState {
commited_in: outpoint,
pcd_commitment: pcd_commitment.clone(),
merkle_root: merkle_root.clone(),
encrypted_pcd: Value::Object(fields2cipher.clone()),
keys: fields2keys.clone(),
validation_tokens: vec![],
};
let diffs = create_diffs(&process, &process_state)?; process.insert_concurrent_state(new_state.clone())?;
process.insert_concurrent_state(process_state.clone())?;
{ {
let mut processes = lock_processes()?; let mut processes = lock_processes()?;
@ -1214,7 +1202,7 @@ pub fn create_new_process(
processes.insert(outpoint.clone(), process.clone()); processes.insert(outpoint.clone(), process.clone());
} }
let commit_msg = CommitMessage::new_first_commitment(transaction, pcd_commitment, roles); let commit_msg = CommitMessage::new_first_commitment(transaction, new_state.pcd_commitment, roles);
let updated_process = UpdatedProcess { let updated_process = UpdatedProcess {
commitment_tx: outpoint, commitment_tx: outpoint,
@ -1246,10 +1234,11 @@ pub fn update_process(
.ok_or(ApiError::new("Process must have at least one state already commited".to_owned()))?; .ok_or(ApiError::new("Process must have at least one state already commited".to_owned()))?;
let last_state_commitments = &prev_state.pcd_commitment; let last_state_commitments = &prev_state.pcd_commitment;
let last_state_descriptions = &prev_state.descriptions;
let clear_new_state = Value::from_str(&new_state_str)?.to_value_object()?; let clear_new_state = Value::from_str(&new_state_str)?.to_value_object()?;
let new_state = ProcessState::new(prev_state.commited_in, clear_new_state.clone())?; let new_state = ProcessState::new(prev_state.commited_in, clear_new_state.clone(), last_state_descriptions.clone())?;
// We compare the new state with the previous one // We compare the new state with the previous one
let last_state_merkle_root = &prev_state.merkle_root; let last_state_merkle_root = &prev_state.merkle_root;
@ -1373,8 +1362,6 @@ pub fn create_update_message(
return Err(ApiError::new("Empty ciphers list".to_owned())); return Err(ApiError::new("Empty ciphers list".to_owned()));
} }
process.insert_impending_request(full_prd);
let updated_process = UpdatedProcess { let updated_process = UpdatedProcess {
commitment_tx: outpoint, commitment_tx: outpoint,
current_process: process.clone(), current_process: process.clone(),

View File

@ -166,7 +166,7 @@ fn test_pairing() {
}); });
debug!("Alice creates the pairing process"); debug!("Alice creates the pairing process");
let create_process_return = create_new_process(pairing_init_state.to_string(), RELAY_ADDRESS.to_owned(), 1).unwrap(); let create_process_return = create_new_process(pairing_init_state.to_string(), None, RELAY_ADDRESS.to_owned(), 1).unwrap();
let commit_msg = create_process_return.commit_to_send.unwrap(); let commit_msg = create_process_return.commit_to_send.unwrap();