Refactor ProcessState validation logic

This commit is contained in:
NicolasCantu 2025-03-26 12:37:12 +01:00
parent 491f260374
commit afc40b4395

View File

@ -132,28 +132,48 @@ impl ProcessState {
)); ));
} }
if self.validation_tokens.get(0).unwrap().get_message() == OBLITERATION_MSG { // We first handle obliteration
// We're dealing with a destruction update if self.state_id == [0u8; 32] {
return self.handle_obliteration(members_list); if let Some(prev_state) = previous_state {
if let Some(apophis) = prev_state.roles.get(APOPHIS) {
return self.handle_obliteration(apophis, members_list);
} }
}
// Compute modified fields return Err(anyhow::anyhow!("Can't find apophis"));
let modified_fields = self.list_modified_fields(previous_state); // then pairing
} else if let Some(pairing_role) = self.roles.get(PAIRING) {
if modified_fields.is_empty() { if self.pcd_commitment.contains_key(PAIREDADDRESSES) {
return Err(anyhow::anyhow!("State is identical to the previous state")); 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 // 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 // Collect applicable rules from all roles for the current field
let applicable_roles: Vec<RoleDefinition> = self.roles let applicable_roles: Vec<RoleDefinition> = self.roles
.iter() .iter()
.filter_map(|(role_name, role_def)| { .filter_map(|(role_name, role_def)| {
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 // We allow for a special case with a role that works only for initial state
// That's optional though // That's optional though
if previous_state.is_some() && *role_name == crate::SpecialRoles::DEMIURGE.to_string() { return None; } SpecialRoles::Demiurge => {
if *role_name == crate::SpecialRoles::APOPHIS.to_string() { return None; } // We handle destructions separately // 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 mut filtered_role_def = role_def.clone();
let rules = filtered_role_def.get_applicable_rules(field); let rules = filtered_role_def.get_applicable_rules(field);
filtered_role_def.validation_rules = filtered_role_def.validation_rules =