Update ValidationRule is_satisfied()

This commit is contained in:
Sosthene 2024-11-29 09:50:41 +01:00
parent 0ad63d347b
commit da4c752df0

View File

@ -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<Proof> = Vec::new();
let mut no_votes: Vec<Proof> = 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<String>,
new_state_merkle_root: [u8; 32],
proofs: &[Proof],
) -> bool {
// compute the modified fields
let modified_fields: Vec<String> = 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> {