[][src]Crate vade

This library is intended to be used as a core library for developing own self-sovereign identity based applications.

So why the name? "Vade" is an acronym for "VC and DID engine". It focuses on working with VCs and DIDs but does not hold much logic concerning their structure. Confused? Guessed as much, so what this library actually does is:

  • offering traits that define how actual implementations (aka "plugins") for working with VCs and DIDs should behave
  • storing those plugins in a Vade instance
  • querying against all registered plugins for certain actions (e.g. for getting VCs/DIDs)

It has been designed with the idea of offering a consistent interface to work with while supporting to move the actual work into plugins, which also helps to reduce the dependencies.

This library is currently under development. Behavior, as well as provided traits, will most probably change over time.

Basic Flow

When a Vade instance and its plugins have been set up (see next section), it will delegate calls to its plugins.

For example when fetching a VC document with a Vade instance with two plugins (a RustStorageCache and a RustVcResolverEvan) the flow looks like this:

vade_plugin_flow

Usage

Basic Usage

First add vade as a dependency to your Cargo.toml. Then you can create new instances in your code (taken from our tests):

extern crate vade;

use vade::Vade;

#[test]
fn library_can_be_created() {
    let _vade = Vade::new();
}

Okay, that did not do much yet. The core library also offers a simple in-memory cache, called RustStorageCache, which can be used when working with VC and DID documents, that are available offline and should just be stored and/or retrieved locally. So to use RustStorageCache as a VcResolver, we just need to add it as a VcResolver plugin:

extern crate vade;

use vade::Vade;
use vade::traits::VcResolver;
use vade::plugin::rust_storage_cache::RustStorageCache;


#[tokio::test]
async fn example() {
    let mut vade = Vade::new();
    let storage = RustStorageCache::new();
    vade.register_vc_resolver(Box::from(storage));

    match vade.set_vc_document("vc:example123", "{}").await {
        Ok(()) => (),
        Err(e) => panic!(format!("{}", e)),
    }
    let fetched = vade.get_vc_document("vc:example123").await.unwrap();
    assert!(fetched == "{}");
}

Keep in mind, that the RustStorageCache resolver can be considered a reference implementation about how resolvers may behave and that it does not validate integrity and validity of given documents. For features like these, you can implement your own resolvers by following the respective traits.

Examples

In the examples here initialization is omitted to keep the readability up. If you want to see the full flow code, you can have a look at the beginning of the vade library file.

VCs

Adding a VC

This, of course requires you to have an existing VC, that you can actually set, but this depends on the actual plugins used in your instance. As we use the RustStorageCache plugin in our examples here, this requirement is not a problem, as it just acts as a key-value store with out any checks around it.

match vade.set_vc_document("vc:example123", "{}").await {
    Ok(()) => (),
    Err(e) => panic!(format!("{}", e)),
}
Getting a VC
let fetched = vade.get_vc_document("vc:example123").await.unwrap();
Validating VCs

Note that the outcome of this function heavily depends on the used plugin. RustStorageCache for example will only accept VCs as valid, if their name is "test".

let vc_result = vade.check_vc("test", &fetched).await;
match vc_result {
    Ok(_) => (),
    Err(_) => panic!("VC not valid"),
}

DIDs

Adding a DID

If your registered plugin allows you to set DIDs you can set it with:

match vade.set_did_document("did:example123", "{}").await {
    Ok(()) => (),
    Err(e) => panic!(format!("{}", e)),
}
Getting a DID
let fetched = vade.get_did_document("did:example123").await.unwrap();
Validating DIDs

Again, note that the outcome of this function heavily depends on the used plugin. RustStorageCache for example will only accept DIDs as valid, if their name is "test".

let did_result = vade.check_did("test", &fetched).await;
match did_result {
    Ok(_) => (),
    Err(_) => panic!("VC not valid"),
}

Plugins

Plugins are the modules that perform the actual work in the Vade module. This project already has one plugin included, RustStorageCache, which can be used as a reference for creating own plugins.

Create new Plugins

Developing plugins for vade can be done by implementing one or more traits from vade::library::traits, e.g.

An example for a simple plugin is the provided RustStorageCache. It implements DidResolver as well as VcResolver functionalities. For your implementation you can, of course, decide to implement only a single trait in a plugin.

Basic Behavior

This plugin implements the following traits:

  • VcResolver - therefore, it can handle VC documents
  • DidResolver - therefore, it can handle DID documents

This allows us to register it as these resolvers with

respectively.

As soon as they are registered as a plugin for a certain type of operation, they are called for related operations (e.g. get_vc_document) by the Vade instance they are registered in.

Library Functions that utilize Plugins

This section shows a short overview over the plugin related functions. For more details, have a look at the Vade documentation.

Plugin registration

These functions can be used to register new resolver plugins:

Setters

These functions will call all registered plugins respectively and with given arguments (e.g. setting a DID will only call DID resolver functions, etc.):

If multiple plugins are registered, awaits completion of all actions. First plugin that fails lets this request fail.

Getters

These functions will call all registered plugins respectively and with given arguments (e.g. getting a DID will only call DID resolver functions, etc.):

If multiple plugins are registered, first successful response will be used. Request will fail if all plugins failed.

Validation

These functions will call all registered plugins respectively and with given arguments (e.g. getting a DID will only call DID resolver functions, etc.):

A document is considered valid if at least one resolver confirms its validity. Resolvers may throw to indicate:

  • that they are not responsible for this document
  • that they consider this document invalid

The current validation flow offers only a limited way of feedback for invalidity and may undergo further changes in future.

More Plugins

A plugin working with VCs and DIDs on evan.network called vade-evan has been implemented. Its usage is equivalent to the description above, more details can be found on its project page.

You can also start writing your own plugin, by following the behavior outlined with the traits in this library.

Wasm Support

Vade supports Wasm! ^^

For an example how to use Vade in Wasm and a how to guide, have a look at our vade-wasm-example project.

Modules

plugin

Plugins provided by the vade library. Currently includes the RustStorageCache plugin.

traits

Traits for interoperability with Vade instances.

Structs

Vade

Vade library, that holds plugins and delegates calls to them.