Replace Member with Outpoint in RoleDefinition
This commit is contained in:
parent
2b511caa14
commit
70616dfc94
21
src/pcd.rs
21
src/pcd.rs
@ -17,6 +17,7 @@ use sp_client::{
|
|||||||
};
|
};
|
||||||
use tsify::Tsify;
|
use tsify::Tsify;
|
||||||
|
|
||||||
|
use crate::serialization::OutPointMemberMap;
|
||||||
use crate::{
|
use crate::{
|
||||||
signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof},
|
signature::{AnkHash, AnkValidationNoHash, AnkValidationYesHash, Proof},
|
||||||
serialization::hex_array_btree
|
serialization::hex_array_btree
|
||||||
@ -316,7 +317,7 @@ impl ValidationRule {
|
|||||||
field: &str,
|
field: &str,
|
||||||
merkle_root: [u8; 32],
|
merkle_root: [u8; 32],
|
||||||
proofs: &[Proof],
|
proofs: &[Proof],
|
||||||
members: &[Member],
|
members: &[&Member],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Check if this rule applies to the field
|
// Check if this rule applies to the field
|
||||||
if !self.fields.contains(&field.to_string()) {
|
if !self.fields.contains(&field.to_string()) {
|
||||||
@ -329,6 +330,7 @@ impl ValidationRule {
|
|||||||
let validating_members = members
|
let validating_members = members
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|member| {
|
.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
|
let member_proofs: Vec<&Proof> = proofs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|p| member.key_is_part_of_member(&p.get_key()))
|
.filter(|p| member.key_is_part_of_member(&p.get_key()))
|
||||||
@ -398,7 +400,7 @@ impl ValidationRule {
|
|||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Tsify)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Tsify)]
|
||||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||||
pub struct RoleDefinition {
|
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 validation_rules: Vec<ValidationRule>,
|
||||||
pub storages: Vec<String>,
|
pub storages: Vec<String>,
|
||||||
}
|
}
|
||||||
@ -409,11 +411,24 @@ impl RoleDefinition {
|
|||||||
diff: Vec<String>,
|
diff: Vec<String>,
|
||||||
new_state_merkle_root: [u8; 32],
|
new_state_merkle_root: [u8; 32],
|
||||||
proofs: &[Proof],
|
proofs: &[Proof],
|
||||||
|
members_list: &OutPointMemberMap,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let empty_member = Member::new(vec![]);
|
||||||
if diff.iter().all(|field| {
|
if diff.iter().all(|field| {
|
||||||
self.validation_rules
|
self.validation_rules
|
||||||
.iter()
|
.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(())
|
Ok(())
|
||||||
|
@ -99,16 +99,37 @@ impl ProcessState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This is a simplified and streamlined validation for obliteration state
|
/// 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
|
// We need an Apophis role
|
||||||
if let Some(apophis) = self.roles.get(SpecialRoles::APOPHIS.to_string().as_str()) {
|
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 {
|
} else {
|
||||||
Err(anyhow::Error::msg("Missing an apophis role"))
|
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() {
|
if self.validation_tokens.is_empty() {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"Can't validate a state with no proofs attached"
|
"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 {
|
if self.validation_tokens.get(0).unwrap().get_message() == OBLITERATION_MSG {
|
||||||
// We're dealing with a destruction update
|
// We're dealing with a destruction update
|
||||||
return self.handle_obliteration();
|
return self.handle_obliteration(members_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute modified fields
|
// Compute modified fields
|
||||||
@ -155,11 +176,16 @@ impl ProcessState {
|
|||||||
|
|
||||||
applicable_roles.into_iter().any(|role_def| {
|
applicable_roles.into_iter().any(|role_def| {
|
||||||
role_def.validation_rules.iter().any(|rule| {
|
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(
|
rule.is_satisfied(
|
||||||
field,
|
field,
|
||||||
self.state_id,
|
self.state_id,
|
||||||
&self.validation_tokens,
|
&self.validation_tokens,
|
||||||
&role_def.members,
|
members.as_slice(),
|
||||||
).is_ok()
|
).is_ok()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -176,7 +202,7 @@ impl ProcessState {
|
|||||||
self.state_id == [0u8; 32]
|
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();
|
let mut res: HashSet<String> = HashSet::new();
|
||||||
|
|
||||||
// Are we in that role?
|
// Are we in that role?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user