diff --git a/src/pcd.rs b/src/pcd.rs index 0c01128..db7fb94 100644 --- a/src/pcd.rs +++ b/src/pcd.rs @@ -570,4 +570,249 @@ mod tests { let result = validation_rule.satisfy_min_sig_member(&member, new_state_hash, &proofs); assert!(result.is_ok()); // Example check - make more meaningful assertions based on real Proof and Member implementations } + + #[test] + fn test_all_rules_satisfied() { + let alice_wallet = create_alice_wallet(); + let bob_wallet = create_bob_wallet(); + + let members = vec![ + Member::new(vec![SilentPaymentAddress::try_from( + alice_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + Member::new(vec![SilentPaymentAddress::try_from( + bob_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + ]; + + let fields = vec!["field1".to_string(), "field2".to_string()]; + let validation_rule1 = ValidationRule::new(1.0, vec![fields[0].clone()], 0.5).unwrap(); + let validation_rule2 = ValidationRule::new(1.0, vec![fields[1].clone()], 0.5).unwrap(); + + let rules = vec![validation_rule1, validation_rule2]; + + // 2 rules, to modify each field, all members must agree + let role_def = RoleDefinition { + members: members.clone(), + validation_rules: rules.clone(), + }; + + let previous_state = json!({ "field1": "old_value1", "field2": "old_value2" }); + let new_state = json!({ "field1": "new_value1", "field2": "new_value2" }); + + let new_state_hash = AnkPcdHash::from_value(&new_state); + + let validation_hash = AnkValidationYesHash::from_commitment(new_state_hash); + // let validation_hash = AnkValidationNoHash::from_commitment(new_state_hash); + + let alice_spend_key: SecretKey = alice_wallet + .get_client() + .get_spend_key() + .try_into() + .unwrap(); + let bob_spend_key: SecretKey = bob_wallet.get_client().get_spend_key().try_into().unwrap(); + + let alice_proof = Proof::new(AnkHash::ValidationYes(validation_hash), alice_spend_key); + let bob_proof = Proof::new(AnkHash::ValidationYes(validation_hash), bob_spend_key); + + let proofs = vec![alice_proof, bob_proof]; + + assert!(role_def.is_satisfied(&new_state, &previous_state, &proofs)); + } + + #[test] + fn test_no_rule_satisfied() { + let alice_wallet = create_alice_wallet(); + let bob_wallet = create_bob_wallet(); + + let members = vec![ + Member::new(vec![SilentPaymentAddress::try_from( + alice_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + Member::new(vec![SilentPaymentAddress::try_from( + bob_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + ]; + + let fields = vec!["field1".to_string(), "field2".to_string()]; + let validation_rule1 = ValidationRule::new(1.0, vec![fields[0].clone()], 0.5).unwrap(); + let validation_rule2 = ValidationRule::new(1.0, vec![fields[1].clone()], 0.5).unwrap(); + + let rules = vec![validation_rule1, validation_rule2]; + + // 2 rules, to modify each field, all members must agree + let role_def = RoleDefinition { + members: members.clone(), + validation_rules: rules.clone(), + }; + + let previous_state = json!({ "field1": "old_value1", "field2": "old_value2" }); + let new_state = json!({ "field1": "new_value1", "field2": "new_value2" }); + + let new_state_hash = AnkPcdHash::from_value(&new_state); + + // let validation_hash1 = AnkValidationYesHash::from_commitment(new_state_hash); + let validation_hash = AnkValidationNoHash::from_commitment(new_state_hash); + + let alice_spend_key: SecretKey = alice_wallet + .get_client() + .get_spend_key() + .try_into() + .unwrap(); + let bob_spend_key: SecretKey = bob_wallet.get_client().get_spend_key().try_into().unwrap(); + + let alice_proof = Proof::new(AnkHash::ValidationNo(validation_hash), alice_spend_key); + let bob_proof = Proof::new(AnkHash::ValidationNo(validation_hash), bob_spend_key); + + let proofs = vec![alice_proof, bob_proof]; + + assert!(!role_def.is_satisfied(&new_state, &previous_state, &proofs)); + } + + #[test] + fn test_partial_modification_satisfied() { + let alice_wallet = create_alice_wallet(); + let bob_wallet = create_bob_wallet(); + + let members = vec![ + Member::new(vec![SilentPaymentAddress::try_from( + alice_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + Member::new(vec![SilentPaymentAddress::try_from( + bob_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + ]; + + let fields = vec!["field1".to_string(), "field2".to_string()]; + let validation_rule1 = ValidationRule::new(1.0, vec![fields[0].clone()], 0.5).unwrap(); + let validation_rule2 = ValidationRule::new(1.0, vec![fields[1].clone()], 0.5).unwrap(); + + let rules = vec![validation_rule1, validation_rule2]; + + // 2 rules, to modify each field, all members must agree + let role_def = RoleDefinition { + members: members.clone(), + validation_rules: rules.clone(), + }; + + let previous_state = json!({ "field1": "old_value1", "field2": "old_value2" }); + let new_state = json!({ "field1": "old_value1", "field2": "new_value2" }); + + let new_state_hash = AnkPcdHash::from_value(&new_state); + + let validation_hash = AnkValidationYesHash::from_commitment(new_state_hash); + // let validation_hash = AnkValidationNoHash::from_commitment(new_state_hash); + + let alice_spend_key: SecretKey = alice_wallet + .get_client() + .get_spend_key() + .try_into() + .unwrap(); + let bob_spend_key: SecretKey = bob_wallet.get_client().get_spend_key().try_into().unwrap(); + + let alice_proof = Proof::new(AnkHash::ValidationYes(validation_hash), alice_spend_key); + let bob_proof = Proof::new(AnkHash::ValidationYes(validation_hash), bob_spend_key); + + let proofs = vec![alice_proof, bob_proof]; + + assert!(role_def.is_satisfied(&new_state, &previous_state, &proofs)); + } + + #[test] + fn test_partial_modification_not_satisfied() { + let alice_wallet = create_alice_wallet(); + let bob_wallet = create_bob_wallet(); + + let members = vec![ + Member::new(vec![SilentPaymentAddress::try_from( + alice_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + Member::new(vec![SilentPaymentAddress::try_from( + bob_wallet.get_client().get_receiving_address(), + ) + .unwrap()]) + .unwrap(), + ]; + + let fields = vec!["field1".to_string(), "field2".to_string()]; + let validation_rule1 = ValidationRule::new(1.0, vec![fields[0].clone()], 0.5).unwrap(); + let validation_rule2 = ValidationRule::new(1.0, vec![fields[1].clone()], 0.5).unwrap(); + + let rules = vec![validation_rule1, validation_rule2]; + + // 2 rules, to modify each field, all members must agree + let role_def = RoleDefinition { + members: members.clone(), + validation_rules: rules.clone(), + }; + + let previous_state = json!({ "field1": "old_value1", "field2": "old_value2" }); + let new_state = json!({ "field1": "old_value1", "field2": "new_value2" }); + + let new_state_hash = AnkPcdHash::from_value(&new_state); + + let validation_hash = AnkValidationYesHash::from_commitment(new_state_hash); + // let validation_hash = AnkValidationNoHash::from_commitment(new_state_hash); + + let alice_spend_key: SecretKey = alice_wallet + .get_client() + .get_spend_key() + .try_into() + .unwrap(); + // let bob_spend_key: SecretKey = bob_wallet.get_client().get_spend_key().try_into().unwrap(); + + let alice_proof = Proof::new(AnkHash::ValidationYes(validation_hash), alice_spend_key); + // let bob_proof = Proof::new(AnkHash::ValidationYes(validation_hash), bob_spend_key); + + let proofs = vec![alice_proof]; + + assert!(!role_def.is_satisfied(&new_state, &previous_state, &proofs)); + } + + #[test] + fn test_get_applicable_rules() { + let fields = vec!["field1".to_string(), "field2".to_string()]; + let validation_rule1 = ValidationRule::new(1.0, vec![fields[0].clone()], 0.5).unwrap(); + let validation_rule2 = ValidationRule::new(1.0, vec![fields[1].clone()], 0.5).unwrap(); + + let rules = vec![validation_rule1.clone(), validation_rule2]; + let role_def = RoleDefinition { + members: vec![], + validation_rules: rules, + }; + + let applicable_rules = role_def.get_applicable_rules("field1"); + assert_eq!(applicable_rules.len(), 1); + assert_eq!(*applicable_rules[0], validation_rule1); + } + + #[test] + fn test_get_applicable_rules_no_rules() { + let fields = vec!["field1".to_string(), "field2".to_string()]; + let validation_rule1 = ValidationRule::new(1.0, vec![fields[0].clone()], 0.5).unwrap(); + let validation_rule2 = ValidationRule::new(1.0, vec![fields[1].clone()], 0.5).unwrap(); + + let rules = vec![validation_rule1.clone(), validation_rule2]; + let role_def = RoleDefinition { + members: vec![], + validation_rules: rules, + }; + + let applicable_rules = role_def.get_applicable_rules("nonexistent_field"); + assert_eq!(applicable_rules.len(), 0); + } }