Skip to content

Commit

Permalink
feat: ensure local overrides global interval req
Browse files Browse the repository at this point in the history
  • Loading branch information
whalelephant committed Feb 13, 2023
1 parent db0e6e6 commit 47c3db9
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 28 deletions.
33 changes: 33 additions & 0 deletions src/data_types/pres_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ pub struct NonRevocedInterval {
}

impl NonRevocedInterval {
pub fn new(from: Option<u64>, to: Option<u64>) -> 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) {
Expand Down Expand Up @@ -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);
}
}
19 changes: 10 additions & 9 deletions src/services/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down Expand Up @@ -1263,11 +1271,4 @@ mod tests {
);
res
}

fn _interval() -> NonRevocedInterval {
NonRevocedInterval {
from: None,
to: Some(1234),
}
}
}
51 changes: 36 additions & 15 deletions tests/multiple-credentials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"}"#;
Expand All @@ -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<PresentationRequest> {
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,
Expand All @@ -57,22 +72,23 @@ fn test_2_different_revoke_reqs() -> Vec<PresentationRequest> {
});

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");
}
Expand All @@ -83,15 +99,12 @@ fn test_2_different_revoke_reqs() -> Vec<PresentationRequest> {
]
}

#[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,
(
Expand Down Expand Up @@ -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([
(
Expand Down
6 changes: 3 additions & 3 deletions tests/utils/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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,
) {
Expand Down Expand Up @@ -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,
) {
Expand Down
2 changes: 1 addition & 1 deletion tests/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod anoncreds;
pub mod mock;

pub use mock::{IsserValues, Mock, ProverValues};
pub use mock::{IssuerValues, Mock, ProverValues};

0 comments on commit 47c3db9

Please sign in to comment.