Skip to content

Commit

Permalink
Merge pull request #80 from alan-turing-institute/79-refactor-api
Browse files Browse the repository at this point in the history
Revise workspace structure adding API, CLI and FFI crates (#79)
  • Loading branch information
sgreenbury authored Jul 31, 2023
2 parents 7f47610 + 5ba7089 commit 4162d5a
Show file tree
Hide file tree
Showing 28 changed files with 759 additions and 170 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ members = [
"trustchain-core",
"trustchain-ion",
"trustchain-http",
"trustchain-api",
"trustchain-cli",
"trustchain-ffi"
]
15 changes: 15 additions & 0 deletions trustchain-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "trustchain-api"
version = "0.1.0"
authors = ["Trustchain Devs"]
edition = "2021"


[dependencies]
trustchain-core = { path = "../trustchain-core" }
trustchain-ion = { path = "../trustchain-ion" }

async-trait = "0.1"
serde_json = "1.0"
ssi = "0.4"
did-ion = "0.1.0"
123 changes: 123 additions & 0 deletions trustchain-api/src/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use async_trait::async_trait;
use did_ion::sidetree::DocumentState;
use ssi::{
did_resolve::DIDResolver,
ldp::LinkedDataDocument,
vc::LinkedDataProofOptions,
vc::{Credential, URI},
};
use std::error::Error;
use trustchain_core::{
chain::DIDChain,
issuer::{Issuer, IssuerError},
resolver::{Resolver, ResolverResult},
vc::CredentialError,
verifier::{Timestamp, Verifier, VerifierError},
};
use trustchain_ion::{attest::attest_operation, attestor::IONAttestor, create::create_operation};

/// API for Trustchain CLI DID functionality.
#[async_trait]
pub trait TrustchainDIDAPI {
/// Creates a controlled DID from a passed document state, writing the associated create
/// operation to file in the operations path returning the file name including the created DID
/// suffix.
// TODO: consider replacing error variant with specific IONError/DIDError in future version.
fn create(
document_state: Option<DocumentState>,
verbose: bool,
) -> Result<String, Box<dyn Error>> {
create_operation(document_state, verbose)
}
/// An uDID attests to a dDID, writing the associated update operation to file in the operations
/// path.
async fn attest(did: &str, controlled_did: &str, verbose: bool) -> Result<(), Box<dyn Error>> {
attest_operation(did, controlled_did, verbose).await
}
/// Resolves a given DID using given endpoint.
async fn resolve<T>(did: &str, resolver: &Resolver<T>) -> ResolverResult
where
T: DIDResolver + Send + Sync,
{
// Result metadata, Document, Document metadata
resolver.resolve_as_result(did).await
}

/// Verifies a given DID using a resolver available at given endpoint, returning a result.
async fn verify<T, U>(
did: &str,
root_event_time: Timestamp,
verifier: &U,
) -> Result<DIDChain, VerifierError>
where
T: DIDResolver + Send,
U: Verifier<T> + Send + Sync,
{
verifier.verify(did, root_event_time).await
}

// // TODO: the below have no CLI implementation currently but are planned
// /// Generates an update operation and writes to operations path.
// fn update(did: &str, controlled_did: &str, verbose: bool) -> Result<(), Box<dyn Error>> {
// todo!()
// }
// /// Generates a recover operation and writes to operations path.
// fn recover(did: &str, verbose: bool) -> Result<(), Box<dyn Error>> {
// todo!()
// }
// /// Generates a deactivate operation and writes to operations path.
// fn deactivate(did: &str, verbose: bool) -> Result<(), Box<dyn Error>> {
// todo!()
// }
// /// Publishes operations within the operations path (queue).
// fn publish(did: &str, verbose: bool) -> Result<(), Box<dyn Error>> {
// todo!()
// }
}

/// API for Trustchain CLI VC functionality.
#[async_trait]
pub trait TrustchainVCAPI {
/// Signs a credential.
async fn sign<T: DIDResolver>(
mut credential: Credential,
did: &str,
linked_data_proof_options: Option<LinkedDataProofOptions>,
key_id: Option<&str>,
resolver: &T,
) -> Result<Credential, IssuerError> {
credential.issuer = Some(ssi::vc::Issuer::URI(URI::String(did.to_string())));
let attestor = IONAttestor::new(did);
attestor
.sign(&credential, linked_data_proof_options, key_id, resolver)
.await
}

/// Verifies a credential
async fn verify_credential<T, U>(
credential: &Credential,
linked_data_proof_options: Option<LinkedDataProofOptions>,
root_event_time: Timestamp,
verifier: &U,
) -> Result<DIDChain, CredentialError>
where
T: DIDResolver + Send,
U: Verifier<T> + Send + Sync,
{
// Verify signature
let result = credential
.verify(linked_data_proof_options, verifier.resolver())
.await;
if !result.errors.is_empty() {
return Err(CredentialError::VerificationResultError(result));
}
// Verify issuer
let issuer = credential
.get_issuer()
.ok_or(CredentialError::NoIssuerPresent)?;
Ok(verifier.verify(issuer, root_event_time).await?)
}
}

#[cfg(test)]
mod tests {}
8 changes: 8 additions & 0 deletions trustchain-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod api;
use crate::api::{TrustchainDIDAPI, TrustchainVCAPI};

/// A type for implementing CLI traits on.
pub struct TrustchainAPI;

impl TrustchainDIDAPI for TrustchainAPI {}
impl TrustchainVCAPI for TrustchainAPI {}
23 changes: 23 additions & 0 deletions trustchain-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "trustchain-cli"
version = "0.1.0"
authors = ["Trustchain Devs"]
edition = "2021"

[[bin]]
name = "trustchain-cli"
path = "src/bin/main.rs"

[dependencies]
trustchain-core = { path = "../trustchain-core" }
trustchain-ion = { path = "../trustchain-ion" }
trustchain-api = { path = "../trustchain-api" }

clap = { version = "4.0.32", features=["derive", "cargo"] }
did-ion = "0.1.0"
lazy_static="1.4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
ssi = "0.4"
tokio = {version = "1.20.1", features = ["full"]}
toml="0.7.2"
Loading

0 comments on commit 4162d5a

Please sign in to comment.