-
Notifications
You must be signed in to change notification settings - Fork 85
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
Remove generics in CoreDocument
, VerificationMethod
, Service
, DIDUrl
and LinkedDomainService
#1110
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
olivereanderson
added
the
Breaking change
A change to the API that requires a major release. Part of "Changed" section in changelog
label
Jan 30, 2023
Co-authored-by: Philipp Gackstatter <philipp.gackstatter@iota.org>
Co-authored-by: Philipp Gackstatter <philipp.gackstatter@iota.org>
Co-authored-by: Philipp Gackstatter <philipp.gackstatter@iota.org>
Co-authored-by: Philipp Gackstatter <philipp.gackstatter@iota.org>
Co-authored-by: Philipp Gackstatter <philipp.gackstatter@iota.org>
…edger/identity.rs into chore/remove-coredocument-generics
abdulmth
approved these changes
Feb 1, 2023
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.
Looks good to me, I agree with Philipp that this PR is an improvement and I like how simpler everything became. I added minor comments, mostly nits.
Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>
Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>
Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>
Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>
PhilippGackstatter
changed the title
Remove generics in
Remove generics in Aug 15, 2023
CoreDocument
, VerificationMethod
, Service
, DIDUrl
and LinkedDomainService
. CoreDocument
, VerificationMethod
, Service
, DIDUrl
and LinkedDomainService
This pull request was closed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Breaking change
A change to the API that requires a major release. Part of "Changed" section in changelog
Rust
Related to the core Rust code. Becomes part of the Rust changelog.
Wasm
Related to Wasm bindings. Becomes part of the Wasm changelog
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description of change
This PR simplifies the library by removing the Document trait as well as all generics on
CoreDocument
,Service
,VerificationMethod
,DomainLinkageService
andDIDUrl
. As this is a somewhat radical change the reviewers are encouraged to carefully read the justification below and judge if it is sufficient.This PR additionally upgrades the
wasm-bindgen
dependency to version0. 2.84
as we need the following change. As a consequence of that I think we can removebindings/build/lint::lintPtrNullWithoutFree
, but I will leave that for another PR.Why?
At the time the generic DID parameter was introduced it brought a lot of value as we could remove several casts that required opting out of the safe subset of Rust. The problem with
generics in the DID document however is that one cannot directly put documents not parameterized with the same types in a container (such as a
Vec
orslice
). We tried to work around this problem with aDocument
trait and a closely related object safeValidatorDocument
trait, but when designing the newResolver
it was hard to work with those traits. More specifically I found it almost impossible to implement the Document trait for something likeenum DocumentType {SomeDIDType(CoreDocument<SomeDIDType>), OtherDIDType(CoreDocument<OtherDIDType>)}
or more realistically
enum DocumentType {Iota(IotaDocument), Core(CoreDocument)}
. This led to the introduction of theAbstractThreadSafeValidatorDocument
that both has a terrible name and is a very leaky abstraction. This is very much the sort of thing we do not want users to have to deal with.One possible way of discarding the
AbstractThreadSafeValidatorDocument
would be to make theResolver
only resolveCoreDocument
(in which case all document types would have to implementInto<CoreDocument>
). With that approach one would have to use a specific client directly if one wishes to preserve method specific information when resolving. After discussing with the team we arrived at the conclusion that we would prefer not to do that.Another possibility would be to focus more on promoting the object safe
ValidatorDocument
trait, but that trait is fairly abstract as is now and such an approach would need more careful consideration. Furthermore it is likely that we want verification functionality to not be a direct concern of the document, but rather another structure such as aJwtVerifier
where custom cryptographic algorithms can be registered. In other words this seems to be a case where it is a good idea to separate data from functionality.The third approach which is what this PR does is to just remove the generics from
CoreDocument
altogether. I have yet to see the rewards of having type enforced method specific DID Urls for a document's verification methods or services. In fact most of the time you would want them to have the same DID component (not just method) as that of the document which is something we cannot enforce in the type system, and there could also be niche cases where you would even want the URLs to refer to other DID methods which the spec allows (this is perhaps more so the case for controllers). If I am overlooking something I would of course be happy to strongly consider closing this PR.What about the non-DID specific parameters in VerificationMethod, Service, etc.
In practice we have so far found that they are either not used, or a (JSON)
Object
representation is enough. If we should later become aware of (or get requests for supporting) use-cases requiring the ability to inject more specific types into these structures, we can consider re-adding those (non-DID specific) parameters in an almost non-breaking manner (in the case when the same parameters can be used across different document types only though).Also note that the generic parameter
T
in theproperties
field in the currentCoreDocument<D,T,U,V>
can be avoided by instead introducing a wrapperWhat about identifiers one would expect to be method specific?
A good example of such an identifier is the identifier of a DID document published with the
IOTA
UTXO method specification. Even though represented internally using aCoreDID
, one will still receive a&IotaDID
when callingIotaDocument::id
. Like before this is not expressible in the safe subset of Rust (yet), but this time we wrap this functionality in a safe interface generated by theref-cast
crate. A crate created bydtolnay
with more than five million downloads. Unfortunately the#![forbid(unsafe_code)]
lint has to be removed from theidentity_iota_core
crate to accommodate for this as the macro fromref-cast
generates anunsafe
code block (while checking its soundness).Similarly one would expect the controller(s) of an
IotaDocument
to be IOTA DIDs. To accommodate for this theIotaDocument::controller
method now returns an iterator over the controller(s) and this uses the same trick as mentioned in the previous paragraph to obtainIotaDID
references (in the bindings there is no change as we need to clone anyway).Note that there is (at least to the best of my knowledge) no unchecked way to mutate the identifier of an
IotaDocument
(or its controllers) after construction in the public API hencehanding out
IotaDID
references to said identifiers should be sound, but I am very much aware that this approach creates more opportunities for bugs to be introduced.How do these changes affect the PresentationValidator?
The API stays pretty much the same as before except all the
ValidatorDocument
trait bounds are now replaced withAsRef<CoreDocument>
which should be simpler for Rust developers to understand.Short summary
The advantages are:
AsRef<CoreDocument>
instead ofValidatorDocument
).IotaDocument
and satisfiesAsRef<CoreDocument>
, henceAbstractThreadSafeValidatorDocument
can be removed. I have some ideas for how to generalize theResolver
in the bindings, but that is for another PR.CoreDocument
/IotaDocument
without needing to import theDocument
trait (more suggestions from IDEs).AsRef<CoreDocument>
.The disadvantages are:
IotaDID
.AsRef<CoreDocument>
trait bound forces implementers to build their types usingCoreDocument
. This is something a trait abstraction might be able to avoid, but as it is now theDocument
trait still pretty much enforces the use of some types from our library.Open Questions
DID
trait and instead bake its methods directly in toCoreDID
andIotaDID
so users don't need to import it (the trait is no longer really necessary for polymorphism).&IotaDID
fromIotaDocument::id
(and an iterator of these in the case ofcontroller
), or would it also be OK to just return&CoreDID
and we can worry less about accidental bugs breaking user's expectations?Links to any relevant issues
Sub-task of #1103 .
Type of change
Add an
x
to the boxes that are relevant to your changes.How the change has been tested
Runs under
cargo test
.Change checklist
Add an
x
to the boxes that are relevant to your changes.