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

feat: IndyVdrAnonCredsRegistry revocation methods #1328

Merged
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
202 changes: 183 additions & 19 deletions packages/indy-vdr/src/anoncreds/IndyVdrAnonCredsRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,21 @@ import {
GetCredentialDefinitionRequest,
CredentialDefinitionRequest,
GetTransactionRequest,
GetRevocationRegistryDeltaRequest,
GetRevocationRegistryDefinitionRequest,
} from '@hyperledger/indy-vdr-shared'

import { IndyVdrPoolService } from '../pool'

import {
didFromSchemaId,
didFromCredentialDefinitionId,
didFromRevocationRegistryDefinitionId,
getLegacySchemaId,
getLegacyCredentialDefinitionId,
indyVdrAnonCredsRegistryIdentifierRegex,
} from './utils/identifiers'
import { anonCredsRevocationStatusListFromIndyVdr } from './utils/transform'

export class IndyVdrAnonCredsRegistry implements AnonCredsRegistry {
public readonly supportedIdentifier = indyVdrAnonCredsRegistryIdentifierRegex
Expand Down Expand Up @@ -390,31 +394,191 @@ export class IndyVdrAnonCredsRegistry implements AnonCredsRegistry {
}
}

public async getRevocationRegistryDefinition(
agentContext: AgentContext,
revocationRegistryDefinitionId: string
): Promise<GetRevocationRegistryDefinitionReturn> {
try {
const indySdkPoolService = agentContext.dependencyManager.resolve(IndyVdrPoolService)
const did = didFromRevocationRegistryDefinitionId(revocationRegistryDefinitionId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're calling didFromRevocationRegistryDefinitionId. I think you can reuse the value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TimoGlastra This is not clear. What do I reuse the value for?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to say you're calling didFromRevocationRegistryDefinitionId twice


const pool = await indySdkPoolService.getPoolForDid(agentContext, did)

agentContext.config.logger.debug(
`Using ledger '${pool.indyNamespace}' to retrieve revocation registry definition '${revocationRegistryDefinitionId}'`
)

const request = new GetRevocationRegistryDefinitionRequest({
submitterDid: did,
revocationRegistryId: revocationRegistryDefinitionId,
})

agentContext.config.logger.trace(
`Submitting get revocation registry definition request for revocation registry definition '${revocationRegistryDefinitionId}' to ledger`
)

const response = await pool.submitReadRequest(request)

if (!response.result.data) {
agentContext.config.logger.error(
`Error retrieving revocation registry definition '${revocationRegistryDefinitionId}' from ledger`,
{
revocationRegistryDefinitionId,
}
)

return {
resolutionMetadata: {
error: 'notFound',
message: `unable to resolve revocation registry definition`,
},
revocationRegistryDefinitionId,
revocationRegistryDefinitionMetadata: {},
}
}

const revocationRegistryDefinition = {
issuerId: did,
revocDefType: response.result.data?.revocDefType,
value: {
maxCredNum: response.result.data?.value.maxCredNum,
tailsHash: response.result.data?.value.tailsHash,
tailsLocation: response.result.data?.value.tailsLocation,
publicKeys: {
accumKey: {
z: response.result.data?.value.publicKeys.accumKey.z,
},
},
},
tag: response.result.data?.tag,
credDefId: response.result.data?.credDefId,
}

return {
revocationRegistryDefinitionId,
revocationRegistryDefinition,
revocationRegistryDefinitionMetadata: {
issuanceType: response.result.data?.value.issuanceType,
didIndyNamespace: pool.indyNamespace,
},
resolutionMetadata: {},
}
} catch (error) {
agentContext.config.logger.error(
`Error retrieving revocation registry definition '${revocationRegistryDefinitionId}' from ledger`,
{
error,
revocationRegistryDefinitionId,
}
)

return {
resolutionMetadata: {
error: 'notFound',
message: `unable to resolve revocation registry definition: ${error.message}`,
},
revocationRegistryDefinitionId,
revocationRegistryDefinitionMetadata: {},
}
}
}

public async getRevocationStatusList(
agentContext: AgentContext,
revocationRegistryId: string,
timestamp: number
): Promise<GetRevocationStatusListReturn> {
return {
resolutionMetadata: {
error: 'Not Implemented',
message: `Revocation list not yet implemented `,
},
revocationStatusListMetadata: {},
}
}
try {
const indySdkPoolService = agentContext.dependencyManager.resolve(IndyVdrPoolService)
const did = didFromRevocationRegistryDefinitionId(revocationRegistryId)

public async getRevocationRegistryDefinition(
agentContext: AgentContext,
revocationRegistryDefinitionId: string
): Promise<GetRevocationRegistryDefinitionReturn> {
return {
resolutionMetadata: {
error: 'Not Implemented',
message: `Revocation registry definition not yet implemented`,
},
revocationRegistryDefinitionId,
revocationRegistryDefinitionMetadata: {},
const pool = await indySdkPoolService.getPoolForDid(agentContext, did)

agentContext.config.logger.debug(
`Using ledger '${pool.indyNamespace}' to retrieve revocation registry deltas with revocation registry definition id '${revocationRegistryId}' until ${timestamp}`
)

const request = new GetRevocationRegistryDeltaRequest({
submitterDid: did,
revocationRegistryId,
toTs: timestamp,
})

agentContext.config.logger.trace(
`Submitting get revocation registry delta request for revocation registry '${revocationRegistryId}' to ledger`
)

const response = await pool.submitReadRequest(request)

agentContext.config.logger.debug(
`Got revocation registry deltas '${revocationRegistryId}' until timestamp ${timestamp} from ledger`
)

const { revocationRegistryDefinition, resolutionMetadata, revocationRegistryDefinitionMetadata } =
await this.getRevocationRegistryDefinition(agentContext, revocationRegistryId)

if (
!revocationRegistryDefinition ||
!revocationRegistryDefinitionMetadata.issuanceType ||
typeof revocationRegistryDefinitionMetadata.issuanceType !== 'string'
) {
return {
resolutionMetadata: {
error: `error resolving revocation registry definition with id ${revocationRegistryId}: ${resolutionMetadata.error} ${resolutionMetadata.message}`,
},
revocationStatusListMetadata: {
didIndyNamespace: pool.indyNamespace,
},
}
}

const isIssuanceByDefault = revocationRegistryDefinitionMetadata.issuanceType === 'ISSUANCE_BY_DEFAULT'

if (!response.result.data) {
return {
resolutionMetadata: {
error: 'notFound',
message: `Error retrieving revocation registry delta '${revocationRegistryId}' from ledger, potentially revocation interval ends before revocation registry creation`,
},
revocationStatusListMetadata: {},
}
}

const revocationRegistryDelta = {
accum: response.result.data?.value.accum_to.value.accum,
issued: response.result.data?.value.issued,
revoked: response.result.data?.value.revoked,
}

return {
resolutionMetadata: {},
revocationStatusList: anonCredsRevocationStatusListFromIndyVdr(
revocationRegistryId,
revocationRegistryDefinition,
revocationRegistryDelta,
response.result.data.value.accum_to.txnTime,
isIssuanceByDefault
),
revocationStatusListMetadata: {
didIndyNamespace: pool.indyNamespace,
},
}
} catch (error) {
agentContext.config.logger.error(
`Error retrieving revocation registry delta '${revocationRegistryId}' from ledger, potentially revocation interval ends before revocation registry creation?"`,
{
error,
revocationRegistryId: revocationRegistryId,
}
)

return {
resolutionMetadata: {
error: 'notFound',
message: `Error retrieving revocation registry delta '${revocationRegistryId}' from ledger, potentially revocation interval ends before revocation registry creation: ${error.message}`,
},
revocationStatusListMetadata: {},
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions packages/indy-vdr/src/anoncreds/utils/transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { AnonCredsRevocationStatusList, AnonCredsRevocationRegistryDefinition } from '@aries-framework/anoncreds'

export function anonCredsRevocationStatusListFromIndyVdr(
revocationRegistryDefinitionId: string,
revocationRegistryDefinition: AnonCredsRevocationRegistryDefinition,
delta: RevocRegDelta,
timestamp: number,
isIssuanceByDefault: boolean
): AnonCredsRevocationStatusList {
// 0 means unrevoked, 1 means revoked
const defaultState = isIssuanceByDefault ? 0 : 1

// Fill with default value
const revocationList = new Array(revocationRegistryDefinition.value.maxCredNum).fill(defaultState)

// Set all `issuer` indexes to 0 (not revoked)
for (const issued of delta.issued ?? []) {
revocationList[issued] = 0
}

// Set all `revoked` indexes to 1 (revoked)
for (const revoked of delta.revoked ?? []) {
revocationList[revoked] = 1
}

return {
issuerId: revocationRegistryDefinition.issuerId,
currentAccumulator: delta.accum,
revRegId: revocationRegistryDefinitionId,
revocationList,
timestamp,
}
}

interface RevocRegDelta {
accum: string
issued: number[]
revoked: number[]
}
Loading