From 17ad1a0319f90d6da8a5aab6e367e2a6eb5c21d7 Mon Sep 17 00:00:00 2001 From: NicolasCantu Date: Fri, 7 Feb 2025 22:44:14 +0100 Subject: [PATCH] Roles is now part of ProcessState out of the pcd --- src/pcd.rs | 31 +------------------------------ src/process.rs | 41 +++++++++++++++-------------------------- 2 files changed, 16 insertions(+), 56 deletions(-) diff --git a/src/pcd.rs b/src/pcd.rs index b99e258..b62e033 100644 --- a/src/pcd.rs +++ b/src/pcd.rs @@ -1,7 +1,7 @@ use anyhow::{Error, Result}; use rs_merkle::{algorithms::Sha256, MerkleTree}; use serde::ser::SerializeStruct; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::hash::{Hash as StdHash, Hasher}; use std::fmt; @@ -336,34 +336,6 @@ pub trait Pcd<'a>: Serialize + Deserialize<'a> { } } - fn extract_roles(&self) -> Result> { - let obj = self.to_value_object()?; - - let parse_roles_map = |m: &Map| { - let mut res: HashMap = HashMap::new(); - for (name, role_def) in m { - res.insert(name.clone(), serde_json::from_value(role_def.clone())?); - } - , Error>>::Ok(res) - }; - - if let Some(roles) = obj.get("roles") { - match roles { - Value::Object(m) => { - parse_roles_map(m) - }, - Value::String(s) => { - let m: Map = serde_json::from_str(&s)?; - - parse_roles_map(&m) - } - _ => Err(Error::msg("\"roles\" is not an object")) - } - } else { - Err(Error::msg("No \"roles\" key in this pcd")) - } - } - fn is_hex_string(&self, length: Option) -> Result<()> { let value = serde_json::to_value(self)?; @@ -1003,7 +975,6 @@ mod tests { let new_state_merkle_root = Value::Object(new_state_commitments).create_merkle_tree().unwrap().root().unwrap(); let validation_hash = AnkValidationYesHash::from_merkle_root(new_state_merkle_root); - // let validation_hash = AnkValidationNoHash::from_commitment(new_state_hash); let alice_spend_key: SecretKey = alice_wallet .get_client() diff --git a/src/process.rs b/src/process.rs index ad553c5..ae41326 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet}, sync::{Mutex, MutexGuard, OnceLock}, }; @@ -28,10 +28,12 @@ pub struct ProcessState { pub validation_tokens: Vec, // Signature of the hash of the encrypted pcd tagged with some decision like "yes" or "no" #[tsify(type = "Record")] pub descriptions: Map, // long descriptions that can be used for the ihm + #[tsify(type = "Record")] + pub roles: BTreeMap, } impl ProcessState { - pub fn new(commited_in: OutPoint, clear_state: Map, descriptions: Map) -> anyhow::Result { + pub fn new(commited_in: OutPoint, clear_state: Map, descriptions: Map, roles: BTreeMap) -> anyhow::Result { // Check all descriptions matches clear_state for (key, _) in &descriptions { clear_state.get(key).ok_or(anyhow::Error::msg("Missing field in descriptions"))?; @@ -59,6 +61,7 @@ impl ProcessState { keys, validation_tokens: vec![], descriptions, + roles, }; Ok(res) @@ -160,22 +163,11 @@ impl ProcessState { return Err(anyhow::anyhow!("State is identical to the previous state")); } - let roles2rules = match self.encrypted_pcd.extract_roles() { - Ok(roles) => roles, - Err(_) => { - let mut fields2plains = Map::new(); - let fields2commit = self.pcd_commitment.as_object().ok_or(anyhow::Error::msg("pcd_commitment is not an object"))?; - self.encrypted_pcd - .decrypt_all(self.commited_in, &fields2commit, &self.keys, &mut fields2plains)?; - - Value::Object(fields2plains).extract_roles()? - } - }; // Check if each modified field satisfies at least one applicable rule across all roles let all_fields_validated = modified_fields.iter().all(|field| { // Collect applicable rules from all roles for the current field - let applicable_roles: Vec = roles2rules + let applicable_roles: Vec = self.roles .iter() .filter_map(|(_, role_def)| { let mut filtered_role_def = role_def.clone(); @@ -222,19 +214,15 @@ impl ProcessState { } pub fn get_fields_to_validate_for_member(&self, member: &Member) -> anyhow::Result> { - let decrypted = self.decrypt_pcd()?; - - let roles = Value::Object(decrypted).extract_roles()?; - let mut res: HashSet = HashSet::new(); // Are we in that role? - for (_, role_def) in roles { + for (_, role_def) in &self.roles { if !role_def.members.contains(member) { continue; } else { // what are the fields we can modify? - for rule in role_def.validation_rules { + for rule in &role_def.validation_rules { if rule.allows_modification() { res.extend(rule.fields.iter().map(|f| f.clone())); } @@ -656,7 +644,7 @@ mod tests { let carol = Member::new(vec![carol_address]).unwrap(); let validation_rule1 = - ValidationRule::new(1.0, vec!["field1".to_owned(), "roles".to_owned()], 0.5).unwrap(); + ValidationRule::new(1.0, vec!["field1".to_owned()], 0.5).unwrap(); let validation_rule2 = ValidationRule::new(1.0, vec!["field2".to_owned()], 0.5).unwrap(); let role_def1 = RoleDefinition { @@ -670,18 +658,19 @@ mod tests { storages: vec![] }; + let roles: BTreeMap = BTreeMap::from([ + ("role1".to_owned(), role_def1), + ("role2".to_owned(), role_def2) + ]); + let clear_pcd = json!({ "field1": "value1", "field2": "value2", - "roles": { - "role1": role_def1, - "role2": role_def2 - } }); let outpoint = OutPoint::null(); - ProcessState::new(outpoint, clear_pcd.as_object().unwrap().clone(), Map::new()).unwrap() + ProcessState::new(outpoint, clear_pcd.as_object().unwrap().clone(), Map::new(), roles).unwrap() } #[test]