From afc40b4395d4c92553097554205b546b3ea94bce Mon Sep 17 00:00:00 2001 From: NicolasCantu Date: Wed, 26 Mar 2025 12:37:12 +0100 Subject: [PATCH] Refactor ProcessState validation logic --- src/process.rs | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/process.rs b/src/process.rs index 9a319a8..4473f91 100644 --- a/src/process.rs +++ b/src/process.rs @@ -132,28 +132,48 @@ impl ProcessState { )); } - if self.validation_tokens.get(0).unwrap().get_message() == OBLITERATION_MSG { - // We're dealing with a destruction update - return self.handle_obliteration(members_list); - } - - // Compute modified fields - let modified_fields = self.list_modified_fields(previous_state); - - if modified_fields.is_empty() { - return Err(anyhow::anyhow!("State is identical to the previous state")); + // We first handle obliteration + if self.state_id == [0u8; 32] { + if let Some(prev_state) = previous_state { + if let Some(apophis) = prev_state.roles.get(APOPHIS) { + return self.handle_obliteration(apophis, members_list); + } + } + return Err(anyhow::anyhow!("Can't find apophis")); + // then pairing + } else if let Some(pairing_role) = self.roles.get(PAIRING) { + if self.pcd_commitment.contains_key(PAIREDADDRESSES) { + if let Some(prev_state) = previous_state { + let prev_paired_addresses = prev_state.public_data.get(PAIREDADDRESSES).ok_or(anyhow::Error::msg("Missing pairedAddresses"))?; + let paired_addresses = extract_paired_addresses(prev_paired_addresses)?; + return self.handle_pairing(pairing_role.clone(), paired_addresses); + } else { + // We are in a creation + return self.handle_pairing(pairing_role.clone(), vec![]); + } + } + // If we don't update pairedAddresses, we don't need to bother about pairing } // Check if each modified field satisfies at least one applicable rule across all roles - let all_fields_validated = modified_fields.iter().all(|field| { + let all_fields_validated = !self.pcd_commitment.is_empty() && self.pcd_commitment.keys().all(|field| { // Collect applicable rules from all roles for the current field let applicable_roles: Vec = self.roles .iter() .filter_map(|(role_name, role_def)| { - // We allow for a special case with a role that works only for initial state - // That's optional though - if previous_state.is_some() && *role_name == crate::SpecialRoles::DEMIURGE.to_string() { return None; } - if *role_name == crate::SpecialRoles::APOPHIS.to_string() { return None; } // We handle destructions separately + if let Ok(special_role) = SpecialRoles::from_str(&role_name) { + match special_role { + // We allow for a special case with a role that works only for initial state + // That's optional though + SpecialRoles::Demiurge => { + // If we're not in initial state just ignore it + if previous_state.is_some() { return None; } + // Otherwise we just continue normal validation + } + // We already handled other special roles + _ => return None + } + } let mut filtered_role_def = role_def.clone(); let rules = filtered_role_def.get_applicable_rules(field); filtered_role_def.validation_rules =