Refactor ProcessState validation logic

This commit is contained in:
NicolasCantu 2025-03-26 12:37:12 +01:00 committed by Nicolas Cantu
parent 416d409fb9
commit bbd7e2a2be

View File

@ -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);
// 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);
}
// 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"));
}
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<RoleDefinition> = self.roles
.iter()
.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
// 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
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 =