Replace Member with Outpoint in RoleDefinition
This commit is contained in:
parent
b71e3f7525
commit
df5d40ce96
21
src/pcd.rs
21
src/pcd.rs
@ -17,6 +17,7 @@ use sp_client::{
|
||||
};
|
||||
use tsify::Tsify;
|
||||
|
||||
use crate::serialization::OutPointMemberMap;
|
||||
use crate::{
|
||||
signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof},
|
||||
serialization::hex_array_btree
|
||||
@ -316,7 +317,7 @@ impl ValidationRule {
|
||||
field: &str,
|
||||
merkle_root: [u8; 32],
|
||||
proofs: &[Proof],
|
||||
members: &[Member],
|
||||
members: &[&Member],
|
||||
) -> Result<()> {
|
||||
// Check if this rule applies to the field
|
||||
if !self.fields.contains(&field.to_string()) {
|
||||
@ -329,6 +330,7 @@ impl ValidationRule {
|
||||
let validating_members = members
|
||||
.iter()
|
||||
.filter(|member| {
|
||||
if member.sp_addresses.is_empty() { return false }; // This can happen when a member in the rule wasn't found in the network
|
||||
let member_proofs: Vec<&Proof> = proofs
|
||||
.iter()
|
||||
.filter(|p| member.key_is_part_of_member(&p.get_key()))
|
||||
@ -398,7 +400,7 @@ impl ValidationRule {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct RoleDefinition {
|
||||
pub members: Vec<Member>,
|
||||
pub members: Vec<OutPoint>, // We use the pairing process id so we don't have to update the role if the user add a device
|
||||
pub validation_rules: Vec<ValidationRule>,
|
||||
pub storages: Vec<String>,
|
||||
}
|
||||
@ -409,11 +411,24 @@ impl RoleDefinition {
|
||||
diff: Vec<String>,
|
||||
new_state_merkle_root: [u8; 32],
|
||||
proofs: &[Proof],
|
||||
members_list: &OutPointMemberMap,
|
||||
) -> Result<()> {
|
||||
let empty_member = Member::new(vec![]);
|
||||
if diff.iter().all(|field| {
|
||||
self.validation_rules
|
||||
.iter()
|
||||
.any(|rule| rule.is_satisfied(field, new_state_merkle_root, proofs, &self.members).is_ok())
|
||||
.any(|rule| {
|
||||
let members: Vec<&Member> = self.members.iter()
|
||||
.map(|outpoint| {
|
||||
if let Some(member) = members_list.0.get(outpoint) {
|
||||
member
|
||||
} else {
|
||||
&empty_member
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
rule.is_satisfied(field, new_state_merkle_root, proofs, &members).is_ok()
|
||||
})
|
||||
})
|
||||
{
|
||||
Ok(())
|
||||
|
@ -99,16 +99,37 @@ impl ProcessState {
|
||||
}
|
||||
|
||||
/// This is a simplified and streamlined validation for obliteration state
|
||||
fn handle_obliteration(&self) -> anyhow::Result<()> {
|
||||
fn handle_obliteration(&self, members_list: &OutPointMemberMap) -> anyhow::Result<()> {
|
||||
// We need an Apophis role
|
||||
if let Some(apophis) = self.roles.get(SpecialRoles::APOPHIS.to_string().as_str()) {
|
||||
apophis.is_satisfied(vec!["".to_owned()], [0u8; 32], &self.validation_tokens)
|
||||
// Apophis should have only one rule
|
||||
if apophis.validation_rules.len() != 1 { return Err(anyhow::Error::msg("Should have only one rule")); };
|
||||
let obliteration_rule = apophis.validation_rules.get(0).unwrap();
|
||||
|
||||
let empty_field = "";
|
||||
// This rule should have only one empty string as field
|
||||
if obliteration_rule.fields.len() != 1 { return Err(anyhow::Error::msg("Should have only one field")); };
|
||||
if obliteration_rule.fields.get(0).unwrap() != empty_field { return Err(anyhow::Error::msg("Field should be empty")); };
|
||||
|
||||
let members: Vec<&Member> = apophis.members.iter()
|
||||
.filter_map(|outpoint| {
|
||||
members_list.0.get(outpoint)
|
||||
})
|
||||
.collect();
|
||||
|
||||
if apophis.validation_rules.iter().all(
|
||||
|r| r.is_satisfied(empty_field, [0u8; 32], &self.validation_tokens, &members).is_ok()
|
||||
) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::Error::msg("Apophis is not satisfied"))
|
||||
}
|
||||
} else {
|
||||
Err(anyhow::Error::msg("Missing an apophis role"))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_valid(&self, previous_state: Option<&ProcessState>) -> anyhow::Result<()> {
|
||||
pub fn is_valid(&self, previous_state: Option<&ProcessState>, members_list: &OutPointMemberMap) -> anyhow::Result<()> {
|
||||
if self.validation_tokens.is_empty() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Can't validate a state with no proofs attached"
|
||||
@ -117,7 +138,7 @@ impl ProcessState {
|
||||
|
||||
if self.validation_tokens.get(0).unwrap().get_message() == OBLITERATION_MSG {
|
||||
// We're dealing with a destruction update
|
||||
return self.handle_obliteration();
|
||||
return self.handle_obliteration(members_list);
|
||||
}
|
||||
|
||||
// Compute modified fields
|
||||
@ -155,11 +176,16 @@ impl ProcessState {
|
||||
|
||||
applicable_roles.into_iter().any(|role_def| {
|
||||
role_def.validation_rules.iter().any(|rule| {
|
||||
let members: Vec<&Member> = role_def.members.iter()
|
||||
.filter_map(|outpoint| {
|
||||
members_list.0.get(outpoint)
|
||||
})
|
||||
.collect();
|
||||
rule.is_satisfied(
|
||||
field,
|
||||
self.state_id,
|
||||
&self.validation_tokens,
|
||||
&role_def.members,
|
||||
members.as_slice(),
|
||||
).is_ok()
|
||||
})
|
||||
})
|
||||
@ -176,7 +202,7 @@ impl ProcessState {
|
||||
self.state_id == [0u8; 32]
|
||||
}
|
||||
|
||||
pub fn get_fields_to_validate_for_member(&self, member: &Member) -> anyhow::Result<Vec<String>> {
|
||||
pub fn get_fields_to_validate_for_member(&self, member: &OutPoint) -> anyhow::Result<Vec<String>> {
|
||||
let mut res: HashSet<String> = HashSet::new();
|
||||
|
||||
// Are we in that role?
|
||||
|
Loading…
x
Reference in New Issue
Block a user