From 47c3db9334d5b64a0d68b31014298308870b17bf Mon Sep 17 00:00:00 2001 From: bwty Date: Fri, 10 Feb 2023 18:16:45 +0800 Subject: [PATCH] feat: ensure local overrides global interval req --- src/data_types/pres_request.rs | 33 ++++++++++++++++++++++ src/services/verifier.rs | 19 +++++++------ tests/multiple-credentials.rs | 51 ++++++++++++++++++++++++---------- tests/utils/mock.rs | 6 ++-- tests/utils/mod.rs | 2 +- 5 files changed, 83 insertions(+), 28 deletions(-) diff --git a/src/data_types/pres_request.rs b/src/data_types/pres_request.rs index ef9ac15c..7ae4ed48 100644 --- a/src/data_types/pres_request.rs +++ b/src/data_types/pres_request.rs @@ -129,6 +129,9 @@ pub struct NonRevocedInterval { } impl NonRevocedInterval { + pub fn new(from: Option, to: Option) -> Self { + Self { from, to } + } // Returns the most stringent interval, // i.e. the latest from and the earliest to pub fn compare_and_set(&mut self, to_compare: &NonRevocedInterval) { @@ -387,4 +390,34 @@ mod tests { interval.update_with_override(&override_map); assert_eq!(interval.from.unwrap(), 5u64); } + + #[test] + fn compare_and_set_works() { + let mut int = NonRevocedInterval::default(); + let wide_int = NonRevocedInterval::new(Some(1), Some(100)); + let mid_int = NonRevocedInterval::new(Some(5), Some(80)); + let narrow_int = NonRevocedInterval::new(Some(10), Some(50)); + + assert_eq!(int.from, None); + assert_eq!(int.to, None); + + // From None to Some + int.compare_and_set(&wide_int); + assert_eq!(int.from, wide_int.from); + assert_eq!(int.to, wide_int.to); + + // Update when more narrow + int.compare_and_set(&mid_int); + assert_eq!(int.from, mid_int.from); + assert_eq!(int.to, mid_int.to); + + // Do Not Update when wider + int.compare_and_set(&wide_int); + assert_eq!(int.from, mid_int.from); + assert_eq!(int.to, mid_int.to); + + int.compare_and_set(&narrow_int); + assert_eq!(int.from, narrow_int.from); + assert_eq!(int.to, narrow_int.to); + } } diff --git a/src/services/verifier.rs b/src/services/verifier.rs index 85787c3d..6ddd1adf 100644 --- a/src/services/verifier.rs +++ b/src/services/verifier.rs @@ -144,12 +144,20 @@ pub fn verify_presentation( pres_req, )?; - // Collaspe to the most stringent interval, + // Collaspe to the most stringent local interval for the attributes / predicates, // we can do this because there is only 1 revocation status list for this credential // if it satsifies the most stringent interval, it will satisfy all intervals let mut cred_nonrevoked_interval = attrs_nonrevoked_interval; cred_nonrevoked_interval.compare_and_set(&pred_nonrevoked_interval); - if let Some(interval) = pres_req.non_revoked.as_ref() { + + // Global interval is override by the local one, + // we only need to update if local is None and Global is Some, + // do not need to update if global is more stringent + if let (Some(interval), None, None) = ( + pres_req.non_revoked.as_ref(), + cred_nonrevoked_interval.from, + cred_nonrevoked_interval.to, + ) { cred_nonrevoked_interval.compare_and_set(interval); }; @@ -1263,11 +1271,4 @@ mod tests { ); res } - - fn _interval() -> NonRevocedInterval { - NonRevocedInterval { - from: None, - to: Some(1234), - } - } } diff --git a/tests/multiple-credentials.rs b/tests/multiple-credentials.rs index 6e0ecb8f..46ef5b43 100644 --- a/tests/multiple-credentials.rs +++ b/tests/multiple-credentials.rs @@ -19,6 +19,16 @@ pub static REV_IDX_1: u32 = 9; pub static REV_IDX_2: u32 = 9; pub static MAX_CRED_NUM: u32 = 10; pub static TF_PATH: &str = "../.tmp"; + +// NonRevoked Interval consts +const GLOBAL_FROM: u64 = 5; +const GLOBAL_TO: u64 = 25; +const LOCAL_FROM: u64 = 10; +const OVERRIDE_LOCAL_FROM: u64 = 8; +const LOCAL_TO: u32 = 20; +const TS_WITHIN_LOCAL_OVERRIDE: u32 = 9; +const TS_WITHIN_GLOBAL_ONLY: u32 = 7; + const SCHEMA_ID_1: &str = "mock:uri:schema1"; const SCHEMA_ID_2: &str = "mock:uri:schema2"; const SCHEMA_1: &str = r#"{"name":"gvt","version":"1.0","attrNames":["name","sex","age","height"],"issuerId":"mock:issuer_id/path&q=bar"}"#; @@ -28,9 +38,14 @@ static CRED_DEF_ID_2: &'static str = "mock:uri:2"; static REV_REG_ID_1: &'static str = "mock:uri:revregid1"; static REV_REG_ID_2: &'static str = "mock:uri:revregid2"; +// This returns Presentation Requests with following nonrevoked intervals +// [0]: Global +// [1]: Local for attributes belonging to both credentials +// [2]: Global and Local, where local is more stringent fn test_2_different_revoke_reqs() -> Vec { let nonce_1 = verifier::generate_nonce().expect("Error generating presentation request nonce"); let nonce_2 = verifier::generate_nonce().expect("Error generating presentation request nonce"); + let nonce_3 = verifier::generate_nonce().expect("Error generating presentation request nonce"); let json = json!({ "nonce": nonce_1, @@ -57,22 +72,23 @@ fn test_2_different_revoke_reqs() -> Vec { }); let mut p1: PresentationRequestPayload = serde_json::from_value(json.clone()).unwrap(); - let mut p2: PresentationRequestPayload = serde_json::from_value(json).unwrap(); + let mut p2: PresentationRequestPayload = serde_json::from_value(json.clone()).unwrap(); + let mut p3: PresentationRequestPayload = serde_json::from_value(json).unwrap(); // Global non_revoked - p1.non_revoked = Some(NonRevocedInterval { - from: Some(10), - to: Some(20), - }); + p1.non_revoked = Some(NonRevocedInterval::new(Some(5), Some(25))); p1.nonce = nonce_1; p2.nonce = nonce_2; + p3.nonce = nonce_3; // Local non_revoked - if let Some(at) = p2.requested_attributes.get_mut("attr4_referent") { - at.non_revoked = Some(NonRevocedInterval { - from: Some(10), - to: Some(20), - }) + if let Some(at1) = p2.requested_attributes.get_mut("attr4_referent") { + at1.non_revoked = Some(NonRevocedInterval::new(Some(10), Some(20))); + } else { + panic!("Cannot add non_revoke to attri"); + } + if let Some(at2) = p2.requested_attributes.get_mut("attr5_referent") { + at2.non_revoked = Some(NonRevocedInterval::new(Some(10), Some(20))); } else { panic!("Cannot add non_revoke to attri"); } @@ -83,15 +99,12 @@ fn test_2_different_revoke_reqs() -> Vec { ] } -#[test] -fn anoncreds_with_multiple_credentials_per_request() { - let mut mock = utils::Mock::new(&[ISSUER_ID], &[PROVER_ID], TF_PATH, MAX_CRED_NUM); - +fn create_issuer_data<'a>() -> utils::IssuerValues<'a> { // These are what the issuer knows // Credential 1 is revocable // Credential 2 is non-revocable // There are 2 definitions, issued by 1 issuer - let issuer1_creds: utils::IsserValues = HashMap::from([ + let issuer1_creds: utils::IssuerValues = HashMap::from([ ( CRED_DEF_ID_1, ( @@ -122,6 +135,14 @@ fn anoncreds_with_multiple_credentials_per_request() { ), ), ]); + issuer1_creds +} + +#[test] +fn anoncreds_with_multiple_credentials_per_request() { + let mut mock = utils::Mock::new(&[ISSUER_ID], &[PROVER_ID], TF_PATH, MAX_CRED_NUM); + + let issuer1_creds = create_issuer_data(); let schemas = HashMap::from([ ( diff --git a/tests/utils/mock.rs b/tests/utils/mock.rs index acf8573d..a17eec89 100644 --- a/tests/utils/mock.rs +++ b/tests/utils/mock.rs @@ -26,7 +26,7 @@ use anoncreds::{ // {cred_def_id: { // schema_id, credential_values, support_revocation, rev_reg_id, rev_idx // }} -pub type IsserValues<'a> = +pub type IssuerValues<'a> = HashMap<&'a str, (&'a str, HashMap<&'a str, &'a str>, bool, &'a str, u32)>; // {cred_def_id: { @@ -109,7 +109,7 @@ impl<'a> Mock<'a> { &mut self, issuer_id: &'static str, prover_id: &'static str, - values: &'a IsserValues, + values: &'a IssuerValues, time_now: u64, issuance_by_default: bool, ) { @@ -288,7 +288,7 @@ impl<'a> Mock<'a> { &mut self, issuer_id: &'static str, prover_id: &'static str, - values: &'a IsserValues, + values: &'a IssuerValues, time_prev_rev_reg: u64, time_new_rev_reg: u64, ) { diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 393bb2c9..d7de4f06 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1,4 +1,4 @@ pub mod anoncreds; pub mod mock; -pub use mock::{IsserValues, Mock, ProverValues}; +pub use mock::{IssuerValues, Mock, ProverValues};