-
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
Add new crates for DID parsing, DID document building, and DID resolution #812
Conversation
f0e43ed
to
e3e8986
Compare
5b457ca
to
07f6ac2
Compare
Really nice! |
d62e108
to
39b3451
Compare
@nicobao most definitely we'll be adding support for more methods. Thanks for heads up about the spruce repo - I wasn't aware of it and it actually looks amazing 👍 💯 - so many did methods ready to tap into at the fingertips https://github.com/spruceid/ssi The main concern imo would be all the dependencies and the code it would bring it, many of which would likely be unnecessary. I think we could help spruceid to feature flag the dependencies, so it would be possible to bring in only the deps for desired set of did methods. @mirgee @bobozaur @gmulhearn check it out guys :-) |
@@ -432,6 +432,19 @@ jobs: | |||
run: | | |||
RUST_TEST_THREADS=1 cargo test --manifest-path="libvcx/Cargo.toml" -F "pool_tests"; | |||
|
|||
test-integration-resolver: |
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.
The name is not quite accurate right now, the command also currently run unit tests too. Either update the job name, or tweak the cargo cmd
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 like the DID parser using ranges of the input DID string, great job!
To me it feels like a lot of places would need documentation and comments, like the structs and traits and the larger functions that are not really easy to follow. I'm honestly not able to grasp everything that's happening just from browsing through the code so I tried to start conversations where appropriate.
There are some minor things to adjust as far as idioms go, but nothing terrible. Another broader idea would be to incorporate some of the utility functions as associated methods, because it's easier to grasp what they are about if they belong to a namespace and most seem to have unique use cases.
Great job over all!
pub fn extra(&self, key: &str) -> Option<&Value> { | ||
self.extra.get(key) | ||
} |
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.
This method is confusing to me. What if I wanted the whole extra
field? I think it would be better to return that and consumers can lookup stuff in the map themselves.
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.
The way this limits the use of extra
is intentional - you should never need the whole extra
field. Moreover, the client code needs not and should not be aware of the internal data structure used for extra fields so that changing it for another collection is not a breaking change.
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 in as is as discussed.
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.
How about renaming it then? The method looks like a getter of the map field instead of a lookup into the map. I agree though that the inner field should not be exposed.
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.
Apologies, forgot about the suggestion to rename. What name do you suggest?
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.
Something like lookup_extra_field
?
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.
How about get_extra_field
instead of lookup_extra_field
?
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 get is implicit. Maybe just extra_field
?
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, still continuing in review
let mut service_builder = | ||
Service::builder(service_id, endpoint.endpoint.as_str().try_into()?)?; | ||
for t in endpoint.types { | ||
if t != DidSovServiceType::Unknown { |
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.
This is just a nice to have, and I toched on this elsewhere. Feel free to pass this, I think this could be nice good-first-issue.
If you leave this up for good-first-issue, please leave this comment un-resolved.
Although DID Core does not specify possible values of type
, we could still make our code slightly developer friendlier making enum for types within our DidDocument structure. We could reuse DidSovServiceType
- rename it toServiceType
, move it to diddocument crate and tweak it a bit:
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Hash)]
pub enum ServiceType {
#[serde(rename = "endpoint")] // AIP 1.0
Endpoint,
#[serde(rename = "did-communication")] // AIP 2.0
DidCommunication,
#[serde(rename = "DIDComm")] // DIDComm V2
DIDComm,
#[serde(other)]
Unknown(value),
}
Just not sure about details how to get Unknown(value)
such that the value parameter would get filled 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.
This would require a custom impl for Serialize/Deserialize (or re-using the MaybeKnown
enum?). The #[serde(other)]
attribute only works with unit variants, unfortunately.
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
11ac111
to
c502bf9
Compare
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, can we move it from draft to ready state?
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, can we move it from draft to ready state?
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.
Most of the things left are minor things or personal opinions, so feel free to merely comment or ignore them, but I think the conversion between DidUrl
and Did
can really be optimized to avoid double-parsing.
did_parser/src/parsed_did.rs
Outdated
Self::parse( | ||
did_url | ||
.did() | ||
.ok_or(Self::Error::InvalidInput("No DID provided in the DID URL"))? | ||
.to_string(), | ||
) |
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.
Shouldn't there be a better way to convert? The DID is already parsed, so it's just a matter of whether there are path arguments and stuff like that. If the DidUrl
doesn't contain any of the additional stuff that makes it a did url, then the parts could be converted to a Did
, right?
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.
Are you suggesting to expose the fields of DidUrl
for 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.
Through pub(crate)
, yeah. Why not? Or simply a constructor method could be added that's crate internal, and the from impl could be near the ParsedDidUrl
type so the fields can stay private.
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 the overhead caused by this is so negligible it's not worth additional code or exposing the now private fields at all. But I will do as you wish.
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.
The crate public constructor is probably the best way to go about it, so the fields aren't touched.
I think it's highly worth it. Why not optimize this when it's easy to do so? The difference between parsing and not parsing the string is huge in the number of executed instructions.
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.
Again, I don't think this is worth either changing the visibility of the fields or adding additional code. Keeping a struct's trait implementations in the same module it's defined in also makes the code navigable, orderly and well-organized.
And again, a call to parse_did_method_id
has absolutely negligible performance cost.
But since you think it's highly worth it, I will change it according to your preference.
let mut service_builder = | ||
Service::builder(service_id, endpoint.endpoint.as_str().try_into()?)?; | ||
for t in endpoint.types { | ||
if t != DidSovServiceType::Unknown { |
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.
This would require a custom impl for Serialize/Deserialize (or re-using the MaybeKnown
enum?). The #[serde(other)]
attribute only works with unit variants, unfortunately.
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
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.
Just a small comment regarding the TryFrom impl between DidUrl
and Did
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.
Can we also change the parsed_did
and parsed_did_url
module file names, for consistency?
Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
@mirgee please rerun the CI without |
Codecov Report
@@ Coverage Diff @@
## main #812 +/- ##
==========================================
+ Coverage 49.06% 49.09% +0.03%
==========================================
Files 410 410
Lines 33501 33518 +17
Branches 7440 7444 +4
==========================================
+ Hits 16436 16455 +19
- Misses 11949 11951 +2
+ Partials 5116 5112 -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.
If the CI runs, I'm okay with the PR.
This PR introduces new crates related to DID parsing, DID document building, and DID resolution, thus partially addressing issue #706 .
Some features in the added crates have no immediate use inside of AriesVCX, and we may consider moving some of these crates to a separate project, especially as the number of implemented resolvers begins to grow. However, their inclusion in the PR is due to the immediate need for a Sovrin DID method resolver, while striving to keep in line with following design goals:
For example DID resolver HTTP(S) binding implementation using these crates, see here.
The following crates have been added:
did_parser
This crate is responsible for parsing DID URLs and DIDs into easily queriable components, as well as DID (URL) validation. Includes
ParsedDID
andParsedDIDUrl
structs, which are used heavily throughout the remaining crates.did_doc_builder
The
did_doc_builder
crate allows its users to construct, serialize and deserialize DID documents and their components that comply with the DID Core specification (https://www.w3.org/TR/did-core/).did_resolver
This crate defines traits that should be implemented by DID resolvers of specific DID methods. For now, the traits are
DIDResolvable
andDIDDereferenceable
.did_resolver_registry
The
did_resolver_registry
is a simple crate that enables the registration of multiple DID resolvers for different DID methods at runtime and subsequent resolution of DIDs for methods with a registered resolver, thus enabling support for variable number of DID methods.did_resolver_sov
This crate provides a DID resolver for the Sovrin DID method (https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html), and hence is the main candidate for possible use in AriesVCX.
Please review and let me know if any further changes are required.