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)]
#[allow(non_camel_case_types)]
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 value_commitment: String,
pub field: String,
pub description: Option<String>,
pub previous_value: Value,
pub new_value: Value,
pub notify_user: bool,
@ -711,24 +713,30 @@ fn create_diffs(process: &Process, new_state: &ProcessState) -> AnyhowResult<Vec
Err(_) => Map::new()
};
let new_state_descriptions = &new_state.descriptions;
let process_id = process.get_process_id()?.to_string();
let mut diffs = vec![];
if let Some(prev_state) = process.get_latest_commited_state() {
// We first decrypt as much as we can of the prev_state
let clear_prev_state = prev_state.decrypt_pcd()?;
// 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() {
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 new_hash.as_str() == prev_hash.as_str() {
continue;
} else {
// There's a diff
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 {
process_id: process_id.clone(),
new_state_merkle_root: new_state_root.to_owned(),
value_commitment: new_hash.as_str().unwrap().to_string(),
field: field.to_owned(),
description,
previous_value,
new_value,
notify_user: false,
@ -744,12 +752,15 @@ fn create_diffs(process: &Process, new_state: &ProcessState) -> AnyhowResult<Vec
} else {
// All fields need a diff
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 need_validation = if (is_pairing && field.as_str() == "roles" && new_value != Value::Null) || fields_to_validate.contains(field) { true } else { false };
diffs.push(UserDiff {
process_id: process_id.clone(),
new_state_merkle_root: new_state_root.to_owned(),
value_commitment: hash.as_str().unwrap().to_string(),
field: field.to_owned(),
description,
previous_value: Value::Null,
new_value,
notify_user: false,
@ -1145,26 +1156,16 @@ pub fn create_connect_transaction(members_str: Vec<String>, fee_rate: u32) -> Ap
#[wasm_bindgen]
pub fn create_new_process(
init_state: String,
init_state_str: String,
descriptions_str: Option<String>,
relay_address: String,
fee_rate: u32,
) -> 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
let roles = pcd.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);
let roles = init_state.extract_roles()?;
// We create a transaction that spends to the relay address
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
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 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 new_state = ProcessState::new(outpoint, init_state.to_value_object()?, descriptions.to_value_object()?)?;
let mut process = Process::new(outpoint);
// We now create the first process state with all that data
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, &new_state)?;
let diffs = create_diffs(&process, &process_state)?;
process.insert_concurrent_state(process_state.clone())?;
process.insert_concurrent_state(new_state.clone())?;
{
let mut processes = lock_processes()?;
@ -1214,7 +1202,7 @@ pub fn create_new_process(
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 {
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()))?;
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 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
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()));
}
process.insert_impending_request(full_prd);
let updated_process = UpdatedProcess {
commitment_tx: outpoint,
current_process: process.clone(),

View File

@ -166,7 +166,7 @@ fn test_pairing() {
});
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();