Skip to content
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

Update Wiki: DID Resolution #823

Merged
merged 20 commits into from
May 6, 2022
154 changes: 144 additions & 10 deletions documentation/docs/decentralized_identifiers/resolve.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,152 @@ keywords:
- Resolve
---
import CodeSnippet from '../../src/components/CodeSnippetComponent'
import resolution from '!!raw-loader!../../../examples/low-level-api/resolution.rs';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';

TODO: Explain how resolving works including arguments.

## Example
DID resolution is the process of fetching a [DID Document](https://www.w3.org/TR/did-core/#dfn-did-documents) corresponding to a given [DID](https://www.w3.org/TR/did-core/#dfn-decentralized-identifiers).
The [IOTA Identity Framework](https://github.com/iotaledger/identity.rs) supports resolving DID Documents that are stored on an IOTA Tangle (public or private). The main tool supplied
by the IOTA Identity Framework to handle DID Document resolution in a type safe manner is the `Resolver`. A DID Resolver as defined in the [W3C Decentralized Identifiers specification](https://www.w3.org/TR/did-core/#dfn-did-resolvers)
enforces the signature of the resolution function in a manner that is more centered around Web/API resolution rather than a strongly typed framework. This is the reason why the `Resolver` provided by the IOTA Identity Framework deviates somewhat from
the W3C specification.

A short example that shows how you can resolve a DID Document. This example returns the latest DID Document.

<CodeSnippet
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the example. You can move it to the bottom if you don't want to refer to it at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That example uses the now deprecated spec compliant resolution API hence I think it is better if we no longer link to it in our v0.5 documentation. I have included code snippets explaining how to resolve using the new Resolver. Is that OK?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH no, in that case please update the example to use the new resolution API ;D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but that example should probably be a separate PR. I will attend to it now 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it better now?

nodeReplitLink="https://repl.it/@IOTAFoundation/resolution?lite=true"
rustContent={resolution}
nodeGithubLink = "https://github.com/iotaledger/identity.rs/blob/support/v0.5/bindings/wasm/examples/src/resolution.js"
rustGithubLink = "https://github.com/iotaledger/identity.rs/blob/support/v0.5/examples/low-level-api/resolution.rs"
/>
## Resolving a DID from the main network

The following example demonstrates how to resolve the DID: "did:iota:H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" from the `main` network.
<Tabs>
<TabItem value="Rust" label="Rust">

```rust
use identity::iota::Resolver;
use identity::iota_core::IotaDID;
use identity::iota::ResolvedIotaDocument;

let resolver: Resolver = Resolver::new().await?;
let did: IotaDID = IotaDID::parse("did:iota:H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV")?;

let doc: ResolvedIotaDocument = resolver.resolve(&did).await?;

```

</TabItem>
<TabItem value="node" label="Node.js">

```js
const {
DID,
Resolver,
ResolvedDocument,
} = require('@iota/identity-wasm/node');

const resolver = new Resolver();
const did = DID.parse("did:iota:H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV");
const doc = await resolver.resolve(did);

```
</TabItem>
</Tabs>
The technical details of how resolution exactly works in terms of querying the Tangle is explained in the [IOTA DID Method Specification](./../specs/did/iota_did_method_spec#read).
olivereanderson marked this conversation as resolved.
Show resolved Hide resolved

## Resolving from a private tangle
Resolving a DID from a private tangle is similar to resolving a DID from the main net. The only difference is that
the resolver needs to be configured to have a client capable of operating on said private tangle. Building a `Client` configured for a specified Tangle is explained in [this example in Rust](https://github.com/iotaledger/identity.rs/blob/dev/examples/low-level-api/private_tangle.rs) and [this example in Javascript](https://github.com/iotaledger/identity.rs/blob/dev/bindings/wasm/examples/src/private_tangle.js).
olivereanderson marked this conversation as resolved.
Show resolved Hide resolved

The following example demonstrates how one can setup a `Resolver` with a given `client` and then attempt resolving a specified `did` which may be on any Tangle (public or private).
<Tabs>
<TabItem value="Rust" label="Rust">

```rust
use identity::iota::Resolver;
use identity::iota::ResolverBuilder;
use identity::iota_core::IotaDID;
use identity::iota::Client;
use identity::iota::Result;


async fn build_and_resolve(client: Client, did: IotaDID) -> Result<ResolvedIotaDocument> {
let resolver: Resolver = ResolverBuilder.new().client(client).build().await?;
resolver.resolve(did).await
}
```

</TabItem>
<TabItem value="node" label="Node.js">

```js
const {
DID,
Resolver,
ResolvedDocument,
Client,
} = require('@iota/identity-wasm/node');


async function buildAndResolve(client, did) {
const resolver = await Resolver.builder().client(client).build();
const resolvedDocument = await resolver.resolve(did);
return resolvedDocument;
}

```
</TabItem>
</Tabs>

In the example above the resolver will automatically try to resolve the DID from the network specified in the `did` (See [DID Format](./../specs/did/iota_did_method_spec#did-format)).
If the resolver was not built with a client configured for the given network name then an error will be thrown. Note that the `ResolverBuilder` can configure the `Resolver` to use
multiple networks as long as they have distinct valid names (max six characters).

Note that in the context of an identity managed by an `Account` the DID document can also be resolved by simply calling the `resolve` method on the `Account` directly.

## Resolution in the context of Verifiable Presentations
As explained in [Verifiable Presentations](./../verifiable_credentials/verifiable_presentations) one resolves the DID Documents of the credential issuers and presentation holder
during verification of a verifiable presentation. Resolving the necessary DID Documents is done automatically when verifying presentations via the `Resolver`, but there are certain
advanced use cases where more control is desired. To accommodate for such situations the `Resolver` also comes equipped with additional stand alone methods that enable:
- resolving a presentation holder's DID Document,
olivereanderson marked this conversation as resolved.
Show resolved Hide resolved
- resolving all DID Documents of the distinct issuers of the credentials contained in the presentation,
- resolving the issuer's DID Document for a given verifiable credential


## Resolving the history of a DID Document.
olivereanderson marked this conversation as resolved.
Show resolved Hide resolved
The fact that a DID Document [can be updated](./update.mdx) implies that the state of the DID Document can change over time, or in other words the result of resolving a DID
also depends on when this operation was carried out. The `Resolver` provides a way to view the entire history of a DID Document (up to the time when the method is called).

<Tabs>
<TabItem value="Rust" label="Rust">

```rust
use identity::iota::Resolver;
use identity::iota_core::IotaDID;
use identity::iota::DocumentHistory;
use identity::iota::Result;


async fn call_resolve_history(did: IotaDID) -> Result<DocumentHistory> {
let resolver: Resolver = Resolver::new().await?;
resolver.resolve_history(did).await?
}
```

</TabItem>
<TabItem value="node" label="Node.js">

```js
const {
DID,
Resolver,
DocumentHistory,
} = require('@iota/identity-wasm/node');


async function callResolveHistory(did) {
const resolver = new Resolver();
const documentHistory = await resolver.resolveHistory(did);
return documentHistory;
}

```
</TabItem>
</Tabs>