Update ValidationRule is_satisfied()
This commit is contained in:
parent
0ad63d347b
commit
da4c752df0
60
src/pcd.rs
60
src/pcd.rs
@ -20,7 +20,7 @@ use tsify::Tsify;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
crypto::AAD,
|
crypto::AAD,
|
||||||
signature::{AnkValidationNoHash, AnkValidationYesHash, Proof},
|
signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Tsify)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Tsify)]
|
||||||
@ -317,13 +317,15 @@ impl ValidationRule {
|
|||||||
pub fn is_satisfied(
|
pub fn is_satisfied(
|
||||||
&self,
|
&self,
|
||||||
field: &str,
|
field: &str,
|
||||||
new_state_hash: AnkPcdHash,
|
merkle_root: [u8; 32],
|
||||||
proofs: &[Proof],
|
proofs: &[Proof],
|
||||||
members: &[Member],
|
members: &[Member],
|
||||||
) -> bool {
|
) -> Result<()> {
|
||||||
// Check if this rule applies to the field
|
// Check if this rule applies to the field
|
||||||
if !self.fields.contains(&field.to_string()) || members.is_empty() {
|
if !self.fields.contains(&field.to_string()) {
|
||||||
return false;
|
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;
|
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()))
|
.filter(|p| member.key_is_part_of_member(&p.get_key()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.satisfy_min_sig_member(member, new_state_hash, &member_proofs)
|
self.satisfy_min_sig_member(member, merkle_root, &member_proofs)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
})
|
})
|
||||||
.count();
|
.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(
|
pub fn satisfy_min_sig_member(
|
||||||
&self,
|
&self,
|
||||||
member: &Member,
|
member: &Member,
|
||||||
new_state_hash: AnkPcdHash,
|
merkle_root: [u8; 32],
|
||||||
proofs: &[&Proof],
|
proofs: &[&Proof],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if proofs.len() == 0 {
|
if proofs.len() == 0 {
|
||||||
@ -369,9 +371,8 @@ impl ValidationRule {
|
|||||||
let mut yes_votes: Vec<Proof> = Vec::new();
|
let mut yes_votes: Vec<Proof> = Vec::new();
|
||||||
let mut no_votes: Vec<Proof> = Vec::new();
|
let mut no_votes: Vec<Proof> = Vec::new();
|
||||||
|
|
||||||
// Compute both yes and no commitment
|
let yes = AnkHash::ValidationYes(AnkValidationYesHash::from_byte_array(merkle_root));
|
||||||
let yes = AnkValidationYesHash::from_commitment(new_state_hash).to_byte_array();
|
let no = AnkHash::ValidationNo(AnkValidationNoHash::from_byte_array(merkle_root));
|
||||||
let no = AnkValidationNoHash::from_commitment(new_state_hash).to_byte_array();
|
|
||||||
|
|
||||||
// Validate proofs here
|
// Validate proofs here
|
||||||
for proof in proofs {
|
for proof in proofs {
|
||||||
@ -381,9 +382,9 @@ impl ValidationRule {
|
|||||||
|
|
||||||
let signed_message = proof.get_message();
|
let signed_message = proof.get_message();
|
||||||
|
|
||||||
if signed_message == yes {
|
if signed_message == yes.to_byte_array() {
|
||||||
yes_votes.push(**proof);
|
yes_votes.push(**proof);
|
||||||
} else if signed_message == no {
|
} else if signed_message == no.to_byte_array() {
|
||||||
no_votes.push(**proof);
|
no_votes.push(**proof);
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::msg("We don't know what this proof signs for"));
|
return Err(Error::msg("We don't know what this proof signs for"));
|
||||||
@ -407,33 +408,20 @@ pub struct RoleDefinition {
|
|||||||
impl RoleDefinition {
|
impl RoleDefinition {
|
||||||
pub fn is_satisfied(
|
pub fn is_satisfied(
|
||||||
&self,
|
&self,
|
||||||
new_state: &Value,
|
diff: Vec<String>,
|
||||||
previous_state: &Value,
|
new_state_merkle_root: [u8; 32],
|
||||||
proofs: &[Proof],
|
proofs: &[Proof],
|
||||||
) -> bool {
|
) -> Result<()> {
|
||||||
// compute the modified fields
|
if diff.iter().all(|field| {
|
||||||
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| {
|
|
||||||
self.validation_rules
|
self.validation_rules
|
||||||
.iter()
|
.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> {
|
pub fn get_applicable_rules(&self, field: &str) -> Vec<&ValidationRule> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user