-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added 'names' attribute field parsing in credx #955
Conversation
Codecov Report
@@ Coverage Diff @@
## main #955 +/- ##
==========================================
- Coverage 44.47% 44.47% -0.01%
==========================================
Files 417 417
Lines 28964 28995 +31
Branches 6178 6184 +6
==========================================
+ Hits 12882 12895 +13
- Misses 12284 12298 +14
- Partials 3798 3802 +4
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments, but happy to see this
#927
now fully passing on top of this PR!
let _attr_name = requested_val.try_get("name")?; | ||
let _attr_name = _attr_name.try_as_str()?; | ||
let attr_name = _normalize_attr_name(_attr_name); | ||
if let Some(_attr_names) = requested_val.get("names").and_then(|v| v.as_array()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest to also make sanity check on name/names first - if none, or both are specific, it's invalid proof request (according to spec). Currently if:
- both are specified, we don't error but only prioritize
names
- if none is specified, we fail on line 765 with some error, but I imagine we could do a nicer one (signalling an invalid proof request for reason X).
|
||
let mut credentials_json = vec![]; | ||
let non_revoked = requested_val.get("non_revoked"); // note that aca-py askar fetches from proof_req json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, it should use the top level non_revoked
value by default, but get override if specified on specific level. And it seems like right now it's only looking on the level, is that right?
let _attr_name = _attr_name.try_as_str()?; | ||
let attr_name = _normalize_attr_name(_attr_name); | ||
if let Some(_attr_names) = requested_val.get("names").and_then(|v| v.as_array()) { | ||
let _attr_names = requested_val.try_get("names")?.as_array().ok_or_else(|| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like a code smell because the ok_or_else
err handling should be never reached. Perhaps would be cleaner to do a match on tuple of (requested_val.get("names"), requested_val.get("name"))
and that would also sort out the invalid cases referred to in the comment above.
for _attr_name in _attr_names { | ||
let _attr_name = _attr_name.try_as_str()?; | ||
let attr_name = _normalize_attr_name(_attr_name); | ||
|
||
let mut credentials_json = vec![]; | ||
let non_revoked = requested_val.get("non_revoked"); // note that aca-py askar fetches from proof_req json | ||
let restrictions = requested_val.get("restrictions"); | ||
|
||
for (cred_id, credx_cred) in credx_creds { | ||
credentials_json.push(json!({ | ||
"cred_info": _make_cred_info(&cred_id, &credx_cred)?, | ||
"interval": non_revoked | ||
})) | ||
} | ||
let credx_creds = self | ||
._get_credentials_for_proof_req_for_attr_name(restrictions, &attr_name) | ||
.await?; | ||
|
||
cred_by_attr[ATTRS][reft] = Value::Array(credentials_json); | ||
for (cred_id, credx_cred) in credx_creds { | ||
credentials_json.push(json!({ | ||
"cred_info": _make_cred_info(&cred_id, &credx_cred)?, | ||
"interval": non_revoked | ||
})) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I haven't checked how this is done in other implementations, but it seems like something might be missing. If verifier specified names: ["name", "surname"]
it means that fields from which these fields are selected from are originating from a single credential https://hyperledger.github.io/anoncreds-spec/#presentation-request-example
eg. not mixing "name" from one credential and "surname" from another.
While this code could coincidentally (and in practice currently even likely) work if there's not more alternative credentials in the wallet, it seems like prover is not trying to assure that property.
We don't necessarily have to address this right now, but lets at least create issue to track this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ye IMO this is the whole point of names
; requiring that multiple attributes are presented from the same credential. credentials_json
should only be populated with credentials which have ALL the attributes (names) present. would be good to address now rather than letting a new bug in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aight, tweak done. Can you check if it is sufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm no that doesn't fix it. Consider a request for names: ["a", "b", "c"]
, and a wallet with cred1 { a, d }
, cred2 { b, e }
, and cred3 { c, f }
.
The tweaked implementation with all_found
would result in cred1
, cred2
and cred3
being added to credentials_json
and included. Where really, none of the credentials satisfy the requirement of having all 3 attribute names (a, b, and c), so the credentials for that referent should be empty.
A credential should only be added to the list if it has ALL the name
/names
as attributes on the credential, AND it satisfies any restrictions applied to it.
The ideal way to do that IMO is to rewrite _get_credentials_for_proof_req_for_attr_name
a bit, such that it only needs to be called once per referent, and it takes in an array of attr_names
, and the WQL query will search for credentials which have ALL those attributes (currently it just checks for 1 attr_name passed in).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, will leave it up to you guys whether that is scope for this PR or for sometime else; as you've stated, the impl is far from perfect and a rewrite is probs best... the original impl was meant to act as a 'base' for the sake of getting it in there, so it's great that you guys are readdress the impl and improving
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I had another attempt at fixing this. Your insights were very valuable, thank you! I hope the query composition is fine, but I assume we'll see in the CI.
@Patrik-Stas Thanks for taking the time to review this. I want to highlight some things:
Given these things, my approach would be:
For instance, the I'd like to hear what you, or the others, think about this roadmap. |
Roadmap makes sense to me; only passing note i have to make is that we should make sure the interfaces (ledger traits or anoncreds traits) aren't married to credx (e.g. interfaces that expose 3rd party types). It could very well be the case that credx dies and we all move to anoncreds-rs in the soon or distance future. |
@bobozaur sounds good, although I am not sure what would you rewrite about the ledger trait (other than adding typing (which would ideally be the case for all of the Anyway, in scope of this PR I am fine with merge |
We could still add the associated types. It looks like @gmulhearn has the same concern so that we don't end up with a very rigid interface that only works with credx. |
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
bd34b29
to
ce34c7c
Compare
_ => json!(attrs), | ||
} | ||
} else { | ||
wql_attr_query | ||
json!(attrs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in these cases, we'd still want things to be ANDed together;
I.e. the query is for where 'attr1=="1" && attr2=="1" && attr3=="1" etc'. So I think it's still json({"$and": attrs}).
Either way, these branches are a bit of an edge case. I might make ticket about the wallet queries in this class, we really should be using the Indy-wql crate, or create our own utility for query construction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm assuming we make another ticket to address a revision to the wql structures
Addresses #948 .