Skip to content

Soroban smart contract for decentralized identifiers (DIDs)

License

Notifications You must be signed in to change notification settings

kommitters/soroban-did-contract

Repository files navigation

Soroban DID Smart Contract

Soroban Smart Contract for Decentralized Identifiers as standardized by W3C DIDs v1.0 specification.

Release Badge License Badge Build Badge Coverage Status OSSF-Scorecard Score

Important

🤝 In line with our commitment to contribute to the Stellar community, we have developed this DID smart contract that serves as an interface. This contract can be utilized by anyone seeking to innovate with a solution that follows the W3C specification.

Features

The DID contract enables you to manage a Decentralized Identifier within the Soroban & Stellar ecosystem. With this smart contract, you will be able to:

  • Create a DID.
  • Update the DID attributes.
  • Retrieve the DID document.
  • Set the contract admin.
  • Upgrade the contract.
  • Get the contract version.

Types

VerificationMethodType

Defines the type of verification method associated with a DID subject.

Tip

Allowed values: Ed25519VerificationKey2020, X25519KeyAgreementKey2020

VerificationRelationship

Expresses the relationship between the DID subject and a verification method.

Tip

Allowed values: Authentication, AssertionMethod, KeyAgreement, CapabilityInvocation, CapabilityDelegation.

VerificationMethodEntry

Represents a cryptographic key or method used for verification purposes.

This type is used as parameter to set the verification methods in the Initialize and Update DID functions.

Attributes

Name Type Values
id String Arbitrary identifier (e.g., keys-1).
type_ VerificationMethodType See VerificationMethodType.
controller String If the DID URI is not provided, the DID URI from the contract is set as the controller.
public_key_multibase String Public key encoded in Multibase format (Base58BTC).
verification_relationships Vec<VerificationRelationship> List of VerificationRelationships.

Example

{
  "id": "keys-1",
  "type_": "Ed25519VerificationKey2020",
  "controller": "",
  "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ",
  "verification_relationships": ["Authentication", "AssertionMethod"]
}

VerificationMethod

Represents a cryptographic key or method used for verification purposes.

This type is used to represent a verification method in the DIDDocument type.

Attributes

Name Type Values
id String DID URI appended with an arbitrary identifier.
type_ VerificationMethodType See VerificationMethodType.
controller String DID URI of the key controller.
public_key_multibase String Public key encoded in Multibase format (Base58BTC).

Example

{
  "id": "did:chaincerts:565s4nk6hch3jxlqjtn3e4il#keys-1",
  "type_": "Ed25519VerificationKey2020",
  "controller": "did:chaincerts:565s4nk6hch3jxlqjtn3e4il",
  "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ",
}

ServiceType

Defines the service type associated with a DID.

Tip

Allowed values: LinkedDomains, DIDComm, DIDCommMessaging, CredentialRegistry, OID4VCI, OID4VP.

Service

Extends the functionality of DIDs by providing detailed information about specific services associated with a DID.

Attributes

Name Type Values
id String Arbitrary identifier.
type_ ServiceType See ServiceType.
service_endpoint String The service endpoint URL.

Example

{
  "id": "chaincerts",
  "type_": "LinkedDomains",
  "service_endpoint": "https://chaincerts.co"
}

DIDDocument

Represents a W3C DID document, which is a set of data that describes the DID subject.

Attributes

Name Type Values
id String DID URI generated on initialization.
context Vec<String> List of URLs defining W3C DID spec version and verification method suites.
verification_method Vec<VerificationMethod> List of VerificationMethods
authentication Vec<String> List of verification method ids for authentication.
assertion_method Vec<String> List of verification method ids for assertion.
key_agreement Vec<String> List of verification method ids for key agreement.
capability_invocation Vec<String> List of verification method ids for capability invocation.
capability_delegation Vec<String> List of verification method ids for capability delegation.
service Vec<Service> List of Services.

Example

{
  "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
  "context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1",
    "https://w3id.org/security/suites/x25519-2020/v1"
  ],
  "verification_method": [
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1",
      "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ",
      "type_": "Ed25519VerificationKey2020"
    },
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-2",
      "public_key_multibase": "z6LSnL6WNE3cqZyWBqh9JTQ3DwWNNvXuNVD8oKZL8jdFyuWN",
      "type_": "X25519KeyAgreementKey2020"
    }
  ],
  "authentication": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "assertion_method": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "key_agreement": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-2"
  ],
  "capability_invocation": [],
  "capability_delegation": [],
  "service": [
    {
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#chaincerts",
      "service_endpoint": "https://chaincerts.co",
      "type_": "LinkedDomains"
    }
  ]
}

Functions

Initialize

Initializes the DID Contract by generating the DID URI, setting the contract admin, and storing the DID attributes: Context, VerificationMethods, and Services. The DID URI is generated by concatenating the DID method name with a random value encoded in Base32.

fn initialize(
    e: Env,
    admin: Address,
    did_method: String,
    context: Vec<String>,
    verification_methods: Vec<VerificationMethodEntry>,
    services: Vec<Service>
) -> DIDDocument;

Output

Returns a DID document.

Example

soroban contract invoke \
  --id CONTRACT_ID \
  --source SOURCE_ACCOUNT_SECRET_KEY \
  --rpc-url https://soroban-testnet.stellar.org:443 \
  --network-passphrase 'Test SDF Network ; September 2015' \
  -- \
  initialize \
  --admin ADMIN_PUBLIC_KEY \
  --did_method chaincerts \
  --services '[{"id": "chaincerts", "type_": "LinkedDomains", "service_endpoint": "https://chaincerts.co"}]' \
  --verification_methods '[{"id": "keys-1", "type_": "Ed25519VerificationKey2020", "controller": "", "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ", "verification_relationships": ["Authentication", "AssertionMethod"]}, {"id": "keys-2", "type_": "X25519KeyAgreementKey2020", "controller": "", "public_key_multibase": "z6LSnL6WNE3cqZyWBqh9JTQ3DwWNNvXuNVD8oKZL8jdFyuWN", "verification_relationships": ["KeyAgreement"]}]' \
  --context '["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1", "https://w3id.org/security/suites/x25519-2020/v1"]'

# Output: DID DOCUMENT
{
  "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
  "context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1",
    "https://w3id.org/security/suites/x25519-2020/v1"
  ],
  "verification_method": [
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1",
      "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ",
      "type_": "Ed25519VerificationKey2020"
    },
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-2",
      "public_key_multibase": "z6LSnL6WNE3cqZyWBqh9JTQ3DwWNNvXuNVD8oKZL8jdFyuWN",
      "type_": "X25519KeyAgreementKey2020"
    }
  ],
  "authentication": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "assertion_method": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "key_agreement": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-2"
  ],
  "capability_invocation": [],
  "capability_delegation": [],
  "service": [
    {
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#chaincerts",
      "service_endpoint": "https://chaincerts.co",
      "type_": "LinkedDomains"
    }
  ]
}

Get DID

Provides the DID document.

fn get_did(e: Env) -> DIDDocument;

Output

Returns a DID document.

Example

soroban contract invoke \
  --id CONTRACT_ID \
  --source SOURCE_ACCOUNT_SECRET_KEY \
  --rpc-url https://soroban-testnet.stellar.org:443 \
  --network-passphrase 'Test SDF Network ; September 2015' \
  -- \
  get_did

# Output: DID DOCUMENT
{
  "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
  "context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1",
    "https://w3id.org/security/suites/x25519-2020/v1"
  ],
  "verification_method": [
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1",
      "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ",
      "type_": "Ed25519VerificationKey2020"
    },
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-2",
      "public_key_multibase": "z6LSnL6WNE3cqZyWBqh9JTQ3DwWNNvXuNVD8oKZL8jdFyuWN",
      "type_": "X25519KeyAgreementKey2020"
    }
  ],
  "authentication": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "assertion_method": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "key_agreement": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-2"
  ],
  "capability_invocation": [],
  "capability_delegation": [],
  "service": [
    {
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#chaincerts",
      "service_endpoint": "https://chaincerts.co",
      "type_": "LinkedDomains"
    }
  ]
}

Update DID

Updates the DID attributes in the storage for an initialized DID Contract. Only the admin account is authorized to invoke this function.

The updatable DID attributes include Context, VerificationMethods, and Services.

You have the flexibility to update one or more attributes in the same invocation by providing the corresponding parameters. For attributes that are not intended to be updated, simply pass None in the respective parameter.

Verification Methods and Context must not be empty; otherwise, a contract error will be thrown.

fn update_did(
    e: Env,
    context: Option<Vec<String>>,
    verification_methods: Option<Vec<VerificationMethodEntry>>,
    services: Option<Vec<Service>>
) -> DIDDocument;

Output

Returns a DID document.

Example

soroban contract invoke \
  --id CONTRACT_ID \
  --source SOURCE_ACCOUNT_SECRET_KEY \
  --rpc-url https://soroban-testnet.stellar.org:443 \
  --network-passphrase 'Test SDF Network ; September 2015' \
  -- \
  update_did \
  --services '[{"id": "ChaincertsVault", "type_": "LinkedDomains", "service_endpoint": "https://vault.chaincerts.co"}]' \
  --verification_methods '[{"id": "keys-1", "type_": "Ed25519VerificationKey2020", "controller": "", "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ", "verification_relationships": ["Authentication", "AssertionMethod"]}]' \
  --context '["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]'

# Output: DID DOCUMENT
{
  "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
  "context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "verification_method": [
    {
      "controller": "did:chaincerts:vyfrxab6umfxddlzl62jktu7",
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1",
      "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ",
      "type_": "Ed25519VerificationKey2020"
    }
  ],
  "authentication": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "assertion_method": [
    "did:chaincerts:vyfrxab6umfxddlzl62jktu7#keys-1"
  ],
  "key_agreement": [],
  "capability_invocation": [],
  "capability_delegation": [],
  "service": [
    {
      "id": "did:chaincerts:vyfrxab6umfxddlzl62jktu7#ChaincertsVault",
      "service_endpoint": "https://vault.chaincerts.co",
      "type_": "LinkedDomains"
    }
  ]
}

Set contract admin

Replaces the current contract admin with a new one. Also, you have the flexibility to update the VerificationMethods, if it is not intended to be updated, simply pass None.

Verification Methods must not be empty; otherwise, a contract error will be thrown.

fn set_admin(e: Env, new_admin: Address, new_verification_methods: Option<Vec<VerificationMethodEntry>>);

Example

soroban contract invoke \
  --id CONTRACT_ID \
  --source SOURCE_ACCOUNT_SECRET_KEY \
  --rpc-url https://soroban-testnet.stellar.org:443 \
  --network-passphrase 'Test SDF Network ; September 2015' \
  -- \
  set_admin \
  --new_admin GCWZBFEKWUGQKYLCLI5ULI4DTXLEA7LPC5QVB55NZPC7FY2NGMLP4YMC \
  --new_verification_methods '[{"id": "keys-1", "type_": "Ed25519VerificationKey2020", "controller": "", "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ", "verification_relationships": ["Authentication", "AssertionMethod"]}]'

Upgrade contract

Replaces the current contract code with a new one.

fn upgrade(e: Env, new_wasm_hash: BytesN<32>);

Example

soroban contract invoke \
  --id CONTRACT_ID \
  --source SOURCE_ACCOUNT_SECRET_KEY \
  --rpc-url https://soroban-testnet.stellar.org:443 \
  --network-passphrase 'Test SDF Network ; September 2015' \
  -- \
  upgrade \
  --new_wasm_hash 4e3e2a3e6286149775c308c8420fd87c9e5f655549073506f72b917577ef1e33

Get contract version

Returns the contract version.

fn version(e: Env) -> String;

Output

Returns the contract version as a string.

Example

soroban contract invoke \
  --id CONTRACT_ID \
  --source SOURCE_ACCOUNT_SECRET_KEY \
  --rpc-url https://soroban-testnet.stellar.org:443 \
  --network-passphrase 'Test SDF Network ; September 2015' \
  -- \
  version

# Output: CONTRACT VERSION
"0.5.0"

Contract Errors

Code Error Description
1 AlreadyInitialized Contract already initialized
2 EmptyContext Context provided is an empty vector
3 EmptyVerificationMethods Verification Methods provided is an empty vector

Development

Pre-requirements

In order to develop and test the smart contract, you need to install Rust and Soroban CLI. The process is outlined in the Soroban setup documentation, which can be accessed at Soroban setup.

Setup

  1. Clone the repository:

    git clone git@github.com:kommitters/soroban-did-contract.git
    
  2. Build the project and install dependencies:

    cd soroban-did-contract
    soroban contract build
    
  3. Run tests:

    cargo test
    

Deployment

  1. Build the contract:

    soroban contract build
    

    This will generate a WASM file for the contract in the target/wasm32-unknown-unknown/release/ directory.

  2. Deploy using Soroban CLI:

    soroban contract deploy \
        --source SOURCE_ACCOUNT_SECRET_KEY \
        --rpc-url https://soroban-testnet.stellar.org:443 \
        --network-passphrase 'Test SDF Network ; September 2015' \
        --wasm target/wasm32-unknown-unknown/release/soroban_did_contract.wasm
    
    CONTRACT_ID
    

Changelog

Features and bug fixes are listed in the CHANGELOG file.

Code of conduct

We welcome everyone to contribute. Make sure you have read the CODE_OF_CONDUCT before.

Contributing

For information on how to contribute, please refer to our CONTRIBUTING guide.

License

This software is licensed under the MIT © kommit.



kommit

WebsiteGithubXLinkedIn