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

Replace did:key with did:foo in resolution example #1086

Merged
merged 1 commit into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 27 additions & 39 deletions examples/1_advanced/6_custom_resolution.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
// Copyright 2020-2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use anyhow::Context;
// Use the external did-key crate to avoid implementing the entire DID key method in this example.
use did_key::Config;
use did_key::DIDCore;
use did_key::DIDKey;
use did_key::KeyPair;
use examples::create_did;
use examples::random_stronghold_path;
use examples::API_ENDPOINT;
Expand All @@ -16,7 +10,6 @@ use identity_iota::credential::AbstractThreadSafeValidatorDocument;
use identity_iota::crypto::KeyPair as IotaKeyPair;
use identity_iota::did::CoreDID;
use identity_iota::did::CoreDocument;
use identity_iota::did::DID;
use identity_iota::iota::IotaDID;
use identity_iota::iota::IotaDocument;
use identity_iota::resolver::Resolver;
Expand All @@ -31,18 +24,18 @@ use iota_client::Client;
/// Resolver<CoreDocument> in this example and just worked with `CoreDocument` representations throughout.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a method agnostic resolver and attach handlers for the "key" and "iota" methods.
// Create a method agnostic resolver and attach handlers for the "foo" and "iota" methods.
let mut resolver: Resolver = Resolver::new();

// Create a new client to interact with the IOTA ledger.
let client: Client = Client::builder().with_primary_node(API_ENDPOINT, None)?.finish()?;

// This is a convenience method for attaching a handler for the "iota" method by providing just a client.
resolver.attach_iota_handler(client.clone());
resolver.attach_handler("key".to_owned(), resolve_ed25519_did_key);
resolver.attach_handler("foo".to_owned(), resolve_did_foo);

// A valid Ed25519 did:key value taken from https://w3c-ccg.github.io/did-method-key/#example-1-a-simple-ed25519-did-key-value.
let did_key: CoreDID = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK".parse()?;
// A fake did:foo DID for demonstration purposes.
let did_foo: CoreDID = "did:foo:0e9c8294eeafee326a4e96d65dbeaca0".parse()?;

// Create a new secret manager backed by a Stronghold.
let mut secret_manager: SecretManager = SecretManager::Stronghold(
Expand All @@ -55,21 +48,21 @@ async fn main() -> anyhow::Result<()> {
let (_, iota_document, _): (Address, IotaDocument, IotaKeyPair) = create_did(&client, &mut secret_manager).await?;
let iota_did: IotaDID = iota_document.id().clone();

// Resolve did_key to get an abstract document.
let did_key_doc: AbstractThreadSafeValidatorDocument = resolver.resolve(&did_key).await?;
// Resolve did_foo to get an abstract document.
let did_foo_doc: AbstractThreadSafeValidatorDocument = resolver.resolve(&did_foo).await?;

// Resolve iota_did to get an abstract document.
let iota_doc: AbstractThreadSafeValidatorDocument = resolver.resolve(&iota_did).await?;

// These documents are mainly meant for validating credentials and presentations, but one can also attempt to cast
// them to concrete document types.

let did_key_doc: CoreDocument = *did_key_doc
let did_foo_doc: CoreDocument = *did_foo_doc
.into_any()
.downcast::<CoreDocument>()
.expect("downcasting to the return type of the did:key handler should be fine");
.expect("downcasting to the return type of the did:foo handler should be fine");

println!("Resolved DID Key document: {}", did_key_doc.to_json_pretty()?);
println!("Resolved DID foo document: {}", did_foo_doc.to_json_pretty()?);

let iota_doc: IotaDocument = *iota_doc
.into_any()
Expand All @@ -80,27 +73,22 @@ async fn main() -> anyhow::Result<()> {
Ok(())
}

/// Resolves an Ed25519 did:key DID to a spec compliant DID Document represented as a [`CoreDocument`].
///
/// # Errors
/// Errors if the DID is not a valid Ed25519 did:key.
async fn resolve_ed25519_did_key(did: CoreDID) -> anyhow::Result<CoreDocument> {
DIDKey::try_from(did.as_str())
.map_err(|err| anyhow::anyhow!("the provided DID does not satisfy the did:key format: {:?}", err))
.and_then(|key_pair| {
if let KeyPair::Ed25519(..) = key_pair {
Ok(key_pair)
} else {
Err(anyhow::anyhow!("the provided DID is not an Ed25519 did:key"))
}
})
.map(|key| {
key.get_did_document(Config {
use_jose_format: false,
serialize_secrets: false,
})
})?
.to_json()
.and_then(|doc_json| CoreDocument::from_json(&doc_json))
.context("failed to obtain a supported DID Document")
/// Resolve a did:foo to a DID document.
async fn resolve_did_foo(did: CoreDID) -> anyhow::Result<CoreDocument> {
Ok(
CoreDocument::from_json(&format!(
r#"{{
"id": "{did}",
"verificationMethod": [
{{
"id": "{did}#key-1",
"controller": "{did}",
"type": "Ed25519VerificationKey2018",
"publicKeyMultibase": "zGurPxZGpqnJ6j866DNBXYQJH2KzJjmQ9KBpCYp9oYJom"
}}
]
}}"#,
))
.unwrap(),
)
}
1 change: 0 additions & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ publish = false

[dependencies]
anyhow = "1.0.62"
did-key = { version = "0.1.1", default-features = false }
identity_iota = { path = "../identity_iota" }
iota-client = { version = "2.0.1-rc.3", default-features = false, features = ["tls", "stronghold"] }
# Remove once iota-client 2.0.1-rc.4 is released.
Expand Down