Skip to content

Commit

Permalink
feat(indy-vdr): register revocation registry definitions and status l…
Browse files Browse the repository at this point in the history
…ist (#1693)
  • Loading branch information
berendsliedrecht committed Jan 18, 2024
1 parent 1d33377 commit ee34fe7
Show file tree
Hide file tree
Showing 22 changed files with 1,127 additions and 379 deletions.
2 changes: 1 addition & 1 deletion demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"refresh": "rm -rf ./node_modules ./yarn.lock && yarn"
},
"dependencies": {
"@hyperledger/indy-vdr-nodejs": "^0.2.0-dev.5",
"@hyperledger/indy-vdr-nodejs": "^0.2.0-dev.6",
"@hyperledger/anoncreds-nodejs": "^0.2.0-dev.5",
"@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5",
"inquirer": "^8.2.5"
Expand Down
2 changes: 1 addition & 1 deletion packages/anoncreds-rs/tests/anoncreds-flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ async function anonCredsFlowTest(options: { issuerId: string; revocable: boolean
options: {},
})

if (!revocationStatusListState.revocationStatusList || !revocationStatusListState.timestamp) {
if (!revocationStatusListState.revocationStatusList) {
throw new Error('Failed to create revocation status list')
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/anoncreds/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export { generateLegacyProverDidLikeString } from './utils/proverDid'
export * from './utils/indyIdentifiers'
export { assertBestPracticeRevocationInterval } from './utils/revocationInterval'
export { storeLinkSecret } from './utils/linkSecret'
export { dateToTimestamp } from './utils'
2 changes: 1 addition & 1 deletion packages/anoncreds/src/models/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface AnonCredsRevocationRegistryDefinition {
export interface AnonCredsRevocationStatusList {
issuerId: string
revRegDefId: string
revocationList: number[]
revocationList: Array<number>
currentAccumulator: string
timestamp: number
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
AnonCredsOperationStateFinished,
AnonCredsResolutionMetadata,
Extensible,
AnonCredsOperationStateAction,
} from './base'
import type { AnonCredsRevocationRegistryDefinition } from '../../models/registry'

Expand All @@ -19,27 +20,33 @@ export interface RegisterRevocationRegistryDefinitionOptions {
options: Extensible
}

export interface RegisterRevocationRegistryDefinitionReturnStateAction extends AnonCredsOperationStateAction {
revocationRegistryDefinition: AnonCredsRevocationRegistryDefinition
revocationRegistryDefinitionId: string
}

export interface RegisterRevocationRegistryDefinitionReturnStateFailed extends AnonCredsOperationStateFailed {
revocationRegistryDefinition?: AnonCredsRevocationRegistryDefinition
revocationRegistryDefinitionId?: string
}

export interface RegisterRevocationRegistryDefinitionReturnStateWait extends AnonCredsOperationStateWait {
revocationRegistryDefinition?: AnonCredsRevocationRegistryDefinition
revocationRegistryDefinitionId?: string
}

export interface RegisterRevocationRegistryDefinitionReturnStateFinished extends AnonCredsOperationStateFinished {
revocationRegistryDefinition: AnonCredsRevocationRegistryDefinition
revocationRegistryDefinitionId: string
}

export interface RegisterRevocationRegistryDefinitionReturnState extends AnonCredsOperationStateWait {
revocationRegistryDefinition?: AnonCredsRevocationRegistryDefinition
revocationRegistryDefinitionId?: string
}

export interface RegisterRevocationRegistryDefinitionReturn {
jobId?: string
revocationRegistryDefinitionState:
| RegisterRevocationRegistryDefinitionReturnStateWait
| RegisterRevocationRegistryDefinitionReturnStateAction
| RegisterRevocationRegistryDefinitionReturnStateFailed
| RegisterRevocationRegistryDefinitionReturnStateFinished
| RegisterRevocationRegistryDefinitionReturnState
revocationRegistryDefinitionMetadata: Extensible
registrationMetadata: Extensible
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,50 @@ import type {
AnonCredsOperationStateFinished,
AnonCredsResolutionMetadata,
Extensible,
AnonCredsOperationStateAction,
} from './base'
import type { AnonCredsRevocationStatusList } from '../../models/registry'
import type { Optional } from '@aries-framework/core'

export interface GetRevocationStatusListReturn {
revocationStatusList?: AnonCredsRevocationStatusList
resolutionMetadata: AnonCredsResolutionMetadata
revocationStatusListMetadata: Extensible
}

// Timestamp is often calculated by the ledger, otherwise method should just take current time
// Return type does include the timestamp.
export type AnonCredsRevocationStatusListWithoutTimestamp = Omit<AnonCredsRevocationStatusList, 'timestamp'>
export type AnonCredsRevocationStatusListWithOptionalTimestamp = Optional<AnonCredsRevocationStatusList, 'timestamp'>

export interface RegisterRevocationStatusListOptions {
// Timestamp is often calculated by the ledger, otherwise method should just take current time
// Return type does include the timestamp.
revocationStatusList: Omit<AnonCredsRevocationStatusList, 'timestamp'>
revocationStatusList: AnonCredsRevocationStatusListWithoutTimestamp
options: Extensible
}

export interface RegisterRevocationStatusListReturnStateAction extends AnonCredsOperationStateAction {
revocationStatusList: AnonCredsRevocationStatusListWithOptionalTimestamp
}

export interface RegisterRevocationStatusListReturnStateFailed extends AnonCredsOperationStateFailed {
revocationStatusList?: AnonCredsRevocationStatusList
timestamp?: string
revocationStatusList?: AnonCredsRevocationStatusListWithOptionalTimestamp
}

export interface RegisterRevocationStatusListReturnStateFinished extends AnonCredsOperationStateFinished {
revocationStatusList: AnonCredsRevocationStatusList
timestamp: string
export interface RegisterRevocationStatusListReturnStateWait extends AnonCredsOperationStateWait {
revocationStatusList?: AnonCredsRevocationStatusListWithOptionalTimestamp
}

export interface RegisterRevocationStatusListReturnState extends AnonCredsOperationStateWait {
revocationStatusList?: AnonCredsRevocationStatusList
timestamp?: string
export interface RegisterRevocationStatusListReturnStateFinished extends AnonCredsOperationStateFinished {
revocationStatusList: AnonCredsRevocationStatusList
}

export interface RegisterRevocationStatusListReturn {
jobId?: string
revocationStatusListState:
| RegisterRevocationStatusListReturnStateWait
| RegisterRevocationStatusListReturnStateAction
| RegisterRevocationStatusListReturnStateFailed
| RegisterRevocationStatusListReturnStateFinished
| RegisterRevocationStatusListReturnState
revocationStatusListMetadata: Extensible
registrationMetadata: Extensible
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
getUnqualifiedCredentialDefinitionId,
getUnqualifiedRevocationRegistryId,
getUnqualifiedRevocationRegistryDefinitionId,
getUnqualifiedSchemaId,
parseIndyCredentialDefinitionId,
parseIndyRevocationRegistryId,
Expand Down Expand Up @@ -67,7 +67,7 @@ describe('Legacy Indy Identifier Regex', () => {
const credentialDefinitionTag = 'someTag'
const tag = 'anotherTag'

expect(getUnqualifiedRevocationRegistryId(did, seqNo, credentialDefinitionTag, tag)).toEqual(
expect(getUnqualifiedRevocationRegistryDefinitionId(did, seqNo, credentialDefinitionTag, tag)).toEqual(
'12345:4:12345:3:CL:420:someTag:CL_ACCUM:anotherTag'
)
})
Expand Down
16 changes: 10 additions & 6 deletions packages/anoncreds/src/utils/indyIdentifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const didIndyCredentialDefinitionIdRegex = new RegExp(
`^${didIndyAnonCredsBase.source}/CLAIM_DEF/([1-9][0-9]*)/(.+)$`
)

// <namespaceIdentifier>:4:<schemaSeqNo>:3:CL:<credentialDefinitionTag>:CL_ACCUM:<revocationRegistryTag>
// <namespaceIdentifier>:4:<namespaceIdentifier>:3:CL:<schemaSeqNo>:<credentialDefinitionTag>:CL_ACCUM:<revocationRegistryTag>
export const unqualifiedRevocationRegistryIdRegex =
/^([a-zA-Z0-9]{21,22}):4:[a-zA-Z0-9]{21,22}:3:CL:([1-9][0-9]*):(.+):CL_ACCUM:(.+)$/
// did:indy:<namespace>:<namespaceIdentifier>/anoncreds/v0/REV_REG_DEF/<schemaSeqNo>/<credentialDefinitionTag>/<revocationRegistryTag>
Expand All @@ -32,18 +32,22 @@ export function getUnqualifiedSchemaId(unqualifiedDid: string, name: string, ver
return `${unqualifiedDid}:2:${name}:${version}`
}

export function getUnqualifiedCredentialDefinitionId(unqualifiedDid: string, seqNo: string | number, tag: string) {
return `${unqualifiedDid}:3:CL:${seqNo}:${tag}`
export function getUnqualifiedCredentialDefinitionId(
unqualifiedDid: string,
schemaSeqNo: string | number,
tag: string
) {
return `${unqualifiedDid}:3:CL:${schemaSeqNo}:${tag}`
}

// TZQuLp43UcYTdtc3HewcDz:4:TZQuLp43UcYTdtc3HewcDz:3:CL:98158:BaustellenzertifikateNU1:CL_ACCUM:1-100
export function getUnqualifiedRevocationRegistryId(
export function getUnqualifiedRevocationRegistryDefinitionId(
unqualifiedDid: string,
seqNo: string | number,
schemaSeqNo: string | number,
credentialDefinitionTag: string,
revocationRegistryTag: string
) {
return `${unqualifiedDid}:4:${unqualifiedDid}:3:CL:${seqNo}:${credentialDefinitionTag}:CL_ACCUM:${revocationRegistryTag}`
return `${unqualifiedDid}:4:${unqualifiedDid}:3:CL:${schemaSeqNo}:${credentialDefinitionTag}:CL_ACCUM:${revocationRegistryTag}`
}

export function isUnqualifiedCredentialDefinitionId(credentialDefinitionId: string) {
Expand Down
26 changes: 12 additions & 14 deletions packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import type {
AnonCredsRegistry,
GetSchemaReturn,
Expand All @@ -25,12 +24,12 @@ import BigNumber from 'bn.js'

import {
getDidIndyCredentialDefinitionId,
getDidIndyRevocationRegistryId,
getDidIndyRevocationRegistryDefinitionId,
getDidIndySchemaId,
} from '../../indy-sdk/src/anoncreds/utils/identifiers'
import {
parseIndyCredentialDefinitionId,
getUnqualifiedRevocationRegistryId,
getUnqualifiedRevocationRegistryDefinitionId,
getUnqualifiedCredentialDefinitionId,
getUnqualifiedSchemaId,
parseIndyDid,
Expand Down Expand Up @@ -71,7 +70,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
this.revocationStatusLists = existingRevocationStatusLists
}

public async getSchema(agentContext: AgentContext, schemaId: string): Promise<GetSchemaReturn> {
public async getSchema(_agentContext: AgentContext, schemaId: string): Promise<GetSchemaReturn> {
const schema = this.schemas[schemaId]

const parsed = parseIndySchemaId(schemaId)
Expand Down Expand Up @@ -103,7 +102,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async registerSchema(
agentContext: AgentContext,
_agentContext: AgentContext,
options: RegisterSchemaOptions
): Promise<RegisterSchemaReturn> {
const { namespace, namespaceIdentifier } = parseIndyDid(options.schema.issuerId)
Expand Down Expand Up @@ -140,7 +139,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async getCredentialDefinition(
agentContext: AgentContext,
_agentContext: AgentContext,
credentialDefinitionId: string
): Promise<GetCredentialDefinitionReturn> {
const credentialDefinition = this.credentialDefinitions[credentialDefinitionId]
Expand All @@ -165,7 +164,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async registerCredentialDefinition(
agentContext: AgentContext,
_agentContext: AgentContext,
options: RegisterCredentialDefinitionOptions
): Promise<RegisterCredentialDefinitionReturn> {
const parsedSchema = parseIndySchemaId(options.credentialDefinition.schemaId)
Expand Down Expand Up @@ -211,7 +210,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async getRevocationRegistryDefinition(
agentContext: AgentContext,
_agentContext: AgentContext,
revocationRegistryDefinitionId: string
): Promise<GetRevocationRegistryDefinitionReturn> {
const revocationRegistryDefinition = this.revocationRegistryDefinitions[revocationRegistryDefinitionId]
Expand All @@ -236,7 +235,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async registerRevocationRegistryDefinition(
agentContext: AgentContext,
_agentContext: AgentContext,
options: RegisterRevocationRegistryDefinitionOptions
): Promise<RegisterRevocationRegistryDefinitionReturn> {
const parsedCredentialDefinition = parseIndyCredentialDefinitionId(options.revocationRegistryDefinition.credDefId)
Expand All @@ -249,7 +248,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {

const { namespace, namespaceIdentifier } = parseIndyDid(options.revocationRegistryDefinition.issuerId)
const legacyIssuerId = namespaceIdentifier
const didIndyRevocationRegistryDefinitionId = getDidIndyRevocationRegistryId(
const didIndyRevocationRegistryDefinitionId = getDidIndyRevocationRegistryDefinitionId(
namespace,
namespaceIdentifier,
indyLedgerSeqNo,
Expand All @@ -259,7 +258,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {

this.revocationRegistryDefinitions[didIndyRevocationRegistryDefinitionId] = options.revocationRegistryDefinition

const legacyRevocationRegistryDefinitionId = getUnqualifiedRevocationRegistryId(
const legacyRevocationRegistryDefinitionId = getUnqualifiedRevocationRegistryDefinitionId(
legacyIssuerId,
indyLedgerSeqNo,
parsedCredentialDefinition.tag,
Expand All @@ -284,7 +283,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async getRevocationStatusList(
agentContext: AgentContext,
_agentContext: AgentContext,
revocationRegistryId: string,
timestamp: number
): Promise<GetRevocationStatusListReturn> {
Expand Down Expand Up @@ -322,7 +321,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
}

public async registerRevocationStatusList(
agentContext: AgentContext,
_agentContext: AgentContext,
options: RegisterRevocationStatusListOptions
): Promise<RegisterRevocationStatusListReturn> {
const timestamp = (options.options.timestamp as number) ?? dateToTimestamp(new Date())
Expand All @@ -341,7 +340,6 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
revocationStatusListState: {
state: 'finished',
revocationStatusList,
timestamp: timestamp.toString(),
},
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export * from './crypto/'

// TODO: clean up util exports
export { encodeAttachment, isLinkedAttachment } from './utils/attachment'
export type { Optional } from './utils'
export { Hasher, HashName } from './utils/Hasher'
export { MessageValidator } from './utils/MessageValidator'
export { LinkedAttachment, LinkedAttachmentOptions } from './utils/LinkedAttachment'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type { Schema as IndySdkSchema } from 'indy-sdk'

import {
getUnqualifiedCredentialDefinitionId,
getUnqualifiedRevocationRegistryId,
getUnqualifiedRevocationRegistryDefinitionId,
getUnqualifiedSchemaId,
parseIndyCredentialDefinitionId,
parseIndyDid,
Expand Down Expand Up @@ -394,7 +394,7 @@ export class IndySdkAnonCredsRegistry implements AnonCredsRegistry {
`Using ledger '${pool.didIndyNamespace}' to retrieve revocation registry definition '${revocationRegistryDefinitionId}'`
)

const legacyRevocationRegistryId = getUnqualifiedRevocationRegistryId(
const legacyRevocationRegistryId = getUnqualifiedRevocationRegistryDefinitionId(
namespaceIdentifier,
schemaSeqNo,
credentialDefinitionTag,
Expand Down Expand Up @@ -492,7 +492,7 @@ export class IndySdkAnonCredsRegistry implements AnonCredsRegistry {
`Using ledger '${pool.didIndyNamespace}' to retrieve revocation registry deltas with revocation registry definition id '${revocationRegistryId}' until ${timestamp}`
)

const legacyRevocationRegistryId = getUnqualifiedRevocationRegistryId(
const legacyRevocationRegistryId = getUnqualifiedRevocationRegistryDefinitionId(
namespaceIdentifier,
schemaSeqNo,
credentialDefinitionTag,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
getDidIndyCredentialDefinitionId,
getDidIndyRevocationRegistryId,
getDidIndyRevocationRegistryDefinitionId,
getDidIndySchemaId,
indySdkAnonCredsRegistryIdentifierRegex,
} from '../identifiers'
Expand Down Expand Up @@ -72,7 +72,7 @@ describe('identifiers', () => {
const credentialDefinitionTag = 'someTag'
const tag = 'anotherTag'

expect(getDidIndyRevocationRegistryId(namespace, did, seqNo, credentialDefinitionTag, tag)).toEqual(
expect(getDidIndyRevocationRegistryDefinitionId(namespace, did, seqNo, credentialDefinitionTag, tag)).toEqual(
'did:indy:sovrin:test:12345/anoncreds/v0/REV_REG_DEF/420/someTag/anotherTag'
)
})
Expand Down
10 changes: 5 additions & 5 deletions packages/indy-sdk/src/anoncreds/utils/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ export function getDidIndySchemaId(namespace: string, unqualifiedDid: string, na
export function getDidIndyCredentialDefinitionId(
namespace: string,
unqualifiedDid: string,
seqNo: string | number,
schemaSeqNo: string | number,
tag: string
) {
return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/CLAIM_DEF/${seqNo}/${tag}`
return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/CLAIM_DEF/${schemaSeqNo}/${tag}`
}

export function getDidIndyRevocationRegistryId(
export function getDidIndyRevocationRegistryDefinitionId(
namespace: string,
unqualifiedDid: string,
seqNo: string | number,
schemaSeqNo: string | number,
credentialDefinitionTag: string,
revocationRegistryTag: string
) {
return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/REV_REG_DEF/${seqNo}/${credentialDefinitionTag}/${revocationRegistryTag}`
return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/REV_REG_DEF/${schemaSeqNo}/${credentialDefinitionTag}/${revocationRegistryTag}`
}
Loading

0 comments on commit ee34fe7

Please sign in to comment.