diff --git a/src/pcd.rs b/src/pcd.rs index 2cadc03..babeb31 100644 --- a/src/pcd.rs +++ b/src/pcd.rs @@ -20,7 +20,7 @@ use tsify::Tsify; use crate::{ crypto::AAD, - signature::{AnkValidationNoHash, AnkValidationYesHash, Proof}, + signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof}, }; #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Tsify)] @@ -317,13 +317,15 @@ impl ValidationRule { pub fn is_satisfied( &self, field: &str, - new_state_hash: AnkPcdHash, + merkle_root: [u8; 32], proofs: &[Proof], members: &[Member], - ) -> bool { + ) -> Result<()> { // Check if this rule applies to the field - if !self.fields.contains(&field.to_string()) || members.is_empty() { - return false; + if !self.fields.contains(&field.to_string()) { + return Err(Error::msg("Field isn't part of this rule")); + } else if members.is_empty() { + return Err(Error::msg("Members list is empty")); } let required_members = (members.len() as f32 * self.quorum).ceil() as usize; @@ -335,18 +337,18 @@ impl ValidationRule { .filter(|p| member.key_is_part_of_member(&p.get_key())) .collect(); - self.satisfy_min_sig_member(member, new_state_hash, &member_proofs) + self.satisfy_min_sig_member(member, merkle_root, &member_proofs) .is_ok() }) .count(); - validating_members >= required_members + if validating_members >= required_members { Ok(()) } else { Err(Error::msg("Not enough members to validate"))} } pub fn satisfy_min_sig_member( &self, member: &Member, - new_state_hash: AnkPcdHash, + merkle_root: [u8; 32], proofs: &[&Proof], ) -> Result<()> { if proofs.len() == 0 { @@ -369,9 +371,8 @@ impl ValidationRule { let mut yes_votes: Vec = Vec::new(); let mut no_votes: Vec = Vec::new(); - // Compute both yes and no commitment - let yes = AnkValidationYesHash::from_commitment(new_state_hash).to_byte_array(); - let no = AnkValidationNoHash::from_commitment(new_state_hash).to_byte_array(); + let yes = AnkHash::ValidationYes(AnkValidationYesHash::from_byte_array(merkle_root)); + let no = AnkHash::ValidationNo(AnkValidationNoHash::from_byte_array(merkle_root)); // Validate proofs here for proof in proofs { @@ -381,9 +382,9 @@ impl ValidationRule { let signed_message = proof.get_message(); - if signed_message == yes { + if signed_message == yes.to_byte_array() { yes_votes.push(**proof); - } else if signed_message == no { + } else if signed_message == no.to_byte_array() { no_votes.push(**proof); } else { return Err(Error::msg("We don't know what this proof signs for")); @@ -407,33 +408,20 @@ pub struct RoleDefinition { impl RoleDefinition { pub fn is_satisfied( &self, - new_state: &Value, - previous_state: &Value, + diff: Vec, + new_state_merkle_root: [u8; 32], proofs: &[Proof], - ) -> bool { - // compute the modified fields - let modified_fields: Vec = new_state - .as_object() - .unwrap() - .iter() - .filter_map(|(key, value)| { - let previous_value = previous_state.as_object().unwrap().get(key); - if previous_value.is_none() || value != previous_value.unwrap() { - Some(key.clone()) - } else { - None - } - }) - .collect(); - - let new_state_hash = AnkPcdHash::from_value(new_state); - - // check that for each field we can satisfy at least one rule - modified_fields.iter().all(|field| { + ) -> Result<()> { + if diff.iter().all(|field| { self.validation_rules .iter() - .any(|rule| rule.is_satisfied(field, new_state_hash, proofs, &self.members)) + .any(|rule| rule.is_satisfied(field, new_state_merkle_root, proofs, &self.members).is_ok()) }) + { + Ok(()) + } else { + Err(Error::msg("Failed to validate all rules")) + } } pub fn get_applicable_rules(&self, field: &str) -> Vec<&ValidationRule> {