Skip to main content

Revoke (and remove) Public Credentials

Depending on the use cases, some credentials, as with any other type of credential, might need to be temporarily or permanently revoked.

The KILT SDK provides different features depending on the needs of the use case.

Revoke and Remove a Credential

As we have seen for public credential retrieval, a credential identifier is sufficient to perform most operations on public credentials. This is true also for revocation and removal.

Some use cases might need a revoked credential to remain on chain and marked as revoked, while other use cases might combine together revocation and removal, removing a credential whenever it is to be marked as revoked, fulfilling the same goal of marking the credential as invalid.

In the former case, the deposit taken at the time when the credential is created is not returned, since the credential is still on chain. In the latter case, all information about the information is cleared, hence the deposit is returned to its original payer.

import * as Kilt from '@kiltprotocol/sdk-js'

export async function revokeCredentialById(
attester: Kilt.DidUri,
submitterAccount: Kilt.KiltKeyringPair,
signCallback: Kilt.SignExtrinsicCallback,
credentialId: Kilt.IPublicCredential['id'],
shouldRemove = false
): Promise<void> {
const api = Kilt.ConfigService.get('api')

const tx = shouldRemove
? api.tx.publicCredentials.remove(credentialId, null)
: api.tx.publicCredentials.revoke(credentialId, null)

// Same as for traditional KILT credentials
const authorizedAttestationTx = await Kilt.Did.authorizeTx(
attester,
tx,
signCallback,
submitterAccount.address
)
await Kilt.Blockchain.signAndSubmitTx(
authorizedAttestationTx,
submitterAccount
)
}

Because a credential identifier can also be calculated starting from the credential itself and the information about its attester, it is also possible to revoke (and optionally remove) a credential given the credential itself.

import * as Kilt from '@kiltprotocol/sdk-js'

export async function revokeCredential(
attester: Kilt.DidUri,
submitterAccount: Kilt.KiltKeyringPair,
signCallback: Kilt.SignExtrinsicCallback,
credential: Kilt.IPublicCredentialInput,
shouldRemove = false
): Promise<void> {
const api = Kilt.ConfigService.get('api')

const credentialId = Kilt.PublicCredential.getIdForCredential(
credential,
attester
)
const tx = shouldRemove
? api.tx.publicCredentials.remove(credentialId, null)
: api.tx.publicCredentials.revoke(credentialId, null)

// Same as for traditional KILT credentials
const authorizedAttestationTx = await Kilt.Did.authorizeTx(
attester,
tx,
signCallback,
submitterAccount.address
)
await Kilt.Blockchain.signAndSubmitTx(
authorizedAttestationTx,
submitterAccount
)
}

Unrevoke a Credential

For public credentials that have been revoked but not removed from chain, it is possible to un-revoke them, making them valid again.

For instance, a driving license can be marked as "suspended" for three years, without being completely invalidated. At the end of the suspension period, it is enabled again by being unrevoked.

As for revocation, both the credential ID and the whole credential can be used, since the SDK provides the primitives to always obtain the former from the latter, but here we show how the whole credential can be used to generate and submit an un-revocation transaction.

import * as Kilt from '@kiltprotocol/sdk-js'

export async function unrevokeCredential(
attester: Kilt.DidUri,
submitterAccount: Kilt.KiltKeyringPair,
signCallback: Kilt.SignExtrinsicCallback,
credential: Kilt.IPublicCredentialInput
): Promise<void> {
const api = Kilt.ConfigService.get('api')

const credentialId = Kilt.PublicCredential.getIdForCredential(
credential,
attester
)
const tx = api.tx.publicCredentials.unrevoke(credentialId, null)

const authorizedAttestationTx = await Kilt.Did.authorizeTx(
attester,
tx,
signCallback,
submitterAccount.address
)
await Kilt.Blockchain.signAndSubmitTx(
authorizedAttestationTx,
submitterAccount
)
}

Reclaim the Deposit for a Credential

All the operations mentioned so far, always require the participation of the public credential attester, who must use their assertion key to sign all operations before they are submitted to the KILT blockchain.

The only operation that can be submitted directly by someone else, as with other places in the SDK, is the transaction to remove a credential and obtain the initial deposit.

This is, technically speaking, a different operation compared to the one to remove a credential, albeit the two yield the same result: all traces of the credential are removed from the chain and the deposit is returned to its payer. The difference between the two is about who is authorized to perform the operation: while credential removal requires a DID signature by the original credential creator (a.k.a. issuer), the deposit claiming operation requires a regular transaction signature by the KILT account that paid the original deposit, with no involvement of the original attester.

import * as Kilt from '@kiltprotocol/sdk-js'

export async function reclaimDeposit(
submitterAddress: Kilt.KiltKeyringPair,
credential: Kilt.IPublicCredential
): Promise<void> {
const api = Kilt.ConfigService.get('api')

// Generate the tx to claim the deposit back.
const credentialId = Kilt.PublicCredential.getIdForCredential(
credential,
credential.attester
)
const depositReclaimTx = api.tx.publicCredentials.reclaimDeposit(credentialId)

// Submit the revocation tx to the KILT blockchain.
await Kilt.Blockchain.signAndSubmitTx(depositReclaimTx, submitterAddress)
}