Skip to content

Commit

Permalink
feat(indy-sdk)!: move to did:indy with limited support (openwallet-fo…
Browse files Browse the repository at this point in the history
…undation#1347)

Signed-off-by: Timo Glastra <timo@animo.id>
  • Loading branch information
TimoGlastra committed Mar 3, 2023
1 parent 7795975 commit 8f6b344
Show file tree
Hide file tree
Showing 40 changed files with 2,297 additions and 1,124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const agentContext = getAgentContext({

describe('AnonCredsRsServices', () => {
test('issuance flow without revocation', async () => {
const issuerId = 'issuer:uri'
const issuerId = 'did:indy:pool:localtest:TL1EaPFCZ8Si5aUrqScBDt'

const schema = await anonCredsIssuerService.createSchema(agentContext, {
attrNames: ['name', 'age'],
Expand Down
2 changes: 1 addition & 1 deletion packages/anoncreds-rs/tests/indy-flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const legacyIndyCredentialFormatService = new LegacyIndyCredentialFormatService(
const legacyIndyProofFormatService = new LegacyIndyProofFormatService()

// This is just so we don't have to register an actually indy did (as we don't have the indy did registrar configured)
const indyDid = 'TL1EaPFCZ8Si5aUrqScBDt'
const indyDid = 'did:indy:pool:localtest:TL1EaPFCZ8Si5aUrqScBDt'

describe('Legacy indy format services using anoncreds-rs', () => {
test('issuance and verification flow starting from proposal without negotiation and without revocation', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ import {
IndySdkWallet,
} from '../../../../indy-sdk/src'
import { IndySdkRevocationService } from '../../../../indy-sdk/src/anoncreds/services/IndySdkRevocationService'
import { indyDidFromPublicKeyBase58 } from '../../../../indy-sdk/src/utils/did'
import {
getLegacyCredentialDefinitionId,
getLegacySchemaId,
parseCredentialDefinitionId,
parseSchemaId,
} from '../../../../indy-sdk/src/anoncreds/utils/identifiers'
import { legacyIndyDidFromPublicKeyBase58 } from '../../../../indy-sdk/src/utils/did'
import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry'
import { AnonCredsModuleConfig } from '../../AnonCredsModuleConfig'
import { AnonCredsLinkSecretRecord, AnonCredsLinkSecretRepository } from '../../repository'
Expand Down Expand Up @@ -79,7 +85,8 @@ describe('Legacy indy format services', () => {
test('issuance and verification flow starting from proposal without negotiation and without revocation', async () => {
// This is just so we don't have to register an actual indy did (as we don't have the indy did registrar configured)
const key = await wallet.createKey({ keyType: KeyType.Ed25519 })
const indyDid = indyDidFromPublicKeyBase58(key.publicKeyBase58)
const unqualifiedIndyDid = legacyIndyDidFromPublicKeyBase58(key.publicKeyBase58)
const indyDid = `did:indy:pool1:${unqualifiedIndyDid}`

// Create link secret
await anonCredsHolderService.createLinkSecret(agentContext, {
Expand Down Expand Up @@ -155,14 +162,20 @@ describe('Legacy indy format services', () => {
}),
]

const cd = parseCredentialDefinitionId(credentialDefinitionState.credentialDefinitionId)
const legacyCredentialDefinitionId = getLegacyCredentialDefinitionId(cd.didIdentifier, cd.schemaSeqNo, cd.tag)

const s = parseSchemaId(schemaState.schemaId)
const legacySchemaId = getLegacySchemaId(s.didIdentifier, s.schemaName, s.schemaVersion)

// Holder creates proposal
holderCredentialRecord.credentialAttributes = credentialAttributes
const { attachment: proposalAttachment } = await indyCredentialFormatService.createProposal(agentContext, {
credentialRecord: holderCredentialRecord,
credentialFormats: {
indy: {
attributes: credentialAttributes,
credentialDefinitionId: credentialDefinitionState.credentialDefinitionId,
credentialDefinitionId: legacyCredentialDefinitionId,
},
},
})
Expand Down Expand Up @@ -225,16 +238,16 @@ describe('Legacy indy format services', () => {
age: '25',
name: 'John',
},
schemaId: schemaState.schemaId,
credentialDefinitionId: credentialDefinitionState.credentialDefinitionId,
schemaId: legacySchemaId,
credentialDefinitionId: legacyCredentialDefinitionId,
revocationRegistryId: null,
credentialRevocationId: null,
})

expect(holderCredentialRecord.metadata.data).toEqual({
'_anonCreds/anonCredsCredential': {
schemaId: schemaState.schemaId,
credentialDefinitionId: credentialDefinitionState.credentialDefinitionId,
schemaId: legacySchemaId,
credentialDefinitionId: legacyCredentialDefinitionId,
},
'_anonCreds/anonCredsCredentialRequest': {
master_secret_blinding_data: expect.any(Object),
Expand All @@ -245,8 +258,8 @@ describe('Legacy indy format services', () => {

expect(issuerCredentialRecord.metadata.data).toEqual({
'_anonCreds/anonCredsCredential': {
schemaId: schemaState.schemaId,
credentialDefinitionId: credentialDefinitionState.credentialDefinitionId,
schemaId: legacySchemaId,
credentialDefinitionId: legacyCredentialDefinitionId,
},
})

Expand All @@ -267,14 +280,14 @@ describe('Legacy indy format services', () => {
attributes: [
{
name: 'name',
credentialDefinitionId: credentialDefinitionState.credentialDefinitionId,
credentialDefinitionId: legacyCredentialDefinitionId,
value: 'John',
referent: '1',
},
],
predicates: [
{
credentialDefinitionId: credentialDefinitionState.credentialDefinitionId,
credentialDefinitionId: legacyCredentialDefinitionId,
name: 'age',
predicate: '>=',
threshold: 18,
Expand Down
66 changes: 55 additions & 11 deletions packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,23 @@ import type { AgentContext } from '@aries-framework/core'
import { Hasher, TypedArrayEncoder } from '@aries-framework/core'
import BigNumber from 'bn.js'

import {
getDidIndyCredentialDefinitionId,
getDidIndySchemaId,
getLegacyCredentialDefinitionId,
getLegacySchemaId,
parseSchemaId,
} from '../../indy-sdk/src/anoncreds/utils/identifiers'
import { parseIndyDid } from '../../indy-sdk/src/dids/didIndyUtil'

/**
* In memory implementation of the {@link AnonCredsRegistry} interface. Useful for testing.
*/
export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
// Roughly match that the identifier starts with an unqualified indy did. Once the
// anoncreds tests are not based on the indy-sdk anymore, we can use any identifier
// we want, but the indy-sdk is picky about the identifier format.
public readonly supportedIdentifier = /^[a-zA-Z0-9]{21,22}/
public readonly supportedIdentifier = /.+/

private schemas: Record<string, AnonCredsSchema>
private credentialDefinitions: Record<string, AnonCredsCredentialDefinition>
Expand All @@ -52,7 +61,11 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {

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

const parsed = parseSchemaId(schemaId)

const legacySchemaId = getLegacySchemaId(parsed.didIdentifier, parsed.schemaName, parsed.schemaVersion)
const indyLedgerSeqNo = getSeqNoFromSchemaId(legacySchemaId)

if (!schema) {
return {
Expand Down Expand Up @@ -81,10 +94,17 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
agentContext: AgentContext,
options: RegisterSchemaOptions
): Promise<RegisterSchemaReturn> {
const schemaId = `${options.schema.issuerId}:2:${options.schema.name}:${options.schema.version}`
const indyLedgerSeqNo = getSeqNoFromSchemaId(schemaId)
const { id: didIdentifier, namespace } = parseIndyDid(options.schema.issuerId)
const didIndySchemaId = getDidIndySchemaId(namespace, didIdentifier, options.schema.name, options.schema.version)
const legacySchemaId = getLegacySchemaId(didIdentifier, options.schema.name, options.schema.version)

this.schemas[schemaId] = options.schema
const indyLedgerSeqNo = getSeqNoFromSchemaId(legacySchemaId)

this.schemas[didIndySchemaId] = options.schema
this.schemas[legacySchemaId] = {
...options.schema,
issuerId: didIdentifier,
}

return {
registrationMetadata: {},
Expand All @@ -96,7 +116,7 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
schemaState: {
state: 'finished',
schema: options.schema,
schemaId,
schemaId: didIndySchemaId,
},
}
}
Expand Down Expand Up @@ -130,18 +150,42 @@ export class InMemoryAnonCredsRegistry implements AnonCredsRegistry {
agentContext: AgentContext,
options: RegisterCredentialDefinitionOptions
): Promise<RegisterCredentialDefinitionReturn> {
const indyLedgerSeqNo = getSeqNoFromSchemaId(options.credentialDefinition.schemaId)
const credentialDefinitionId = `${options.credentialDefinition.issuerId}:3:CL:${indyLedgerSeqNo}:${options.credentialDefinition.tag}`

this.credentialDefinitions[credentialDefinitionId] = options.credentialDefinition
const parsedSchema = parseSchemaId(options.credentialDefinition.schemaId)
const legacySchemaId = getLegacySchemaId(
parsedSchema.didIdentifier,
parsedSchema.schemaName,
parsedSchema.schemaVersion
)
const indyLedgerSeqNo = getSeqNoFromSchemaId(legacySchemaId)

const { id: didIdentifier, namespace } = parseIndyDid(options.credentialDefinition.issuerId)

const didIndyCredentialDefinitionId = getDidIndyCredentialDefinitionId(
namespace,
didIdentifier,
indyLedgerSeqNo,
options.credentialDefinition.tag
)
const legacyCredentialDefinitionId = getLegacyCredentialDefinitionId(
didIdentifier,
indyLedgerSeqNo,
options.credentialDefinition.tag
)

this.credentialDefinitions[didIndyCredentialDefinitionId] = options.credentialDefinition
this.credentialDefinitions[legacyCredentialDefinitionId] = {
...options.credentialDefinition,
issuerId: didIdentifier,
schemaId: legacySchemaId,
}

return {
registrationMetadata: {},
credentialDefinitionMetadata: {},
credentialDefinitionState: {
state: 'finished',
credentialDefinition: options.credentialDefinition,
credentialDefinitionId,
credentialDefinitionId: didIndyCredentialDefinitionId,
},
}
}
Expand Down
32 changes: 16 additions & 16 deletions packages/anoncreds/tests/anoncreds.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe('AnonCreds API', () => {
options: {},
schema: {
attrNames: ['name', 'age'],
issuerId: '6xDN7v3AiGgusRp4bqZACZ',
issuerId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ',
name: 'Employee Credential',
version: '1.0.0',
},
Expand All @@ -136,34 +136,34 @@ describe('AnonCreds API', () => {
state: 'finished',
schema: {
attrNames: ['name', 'age'],
issuerId: '6xDN7v3AiGgusRp4bqZACZ',
issuerId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ',
name: 'Employee Credential',
version: '1.0.0',
},
schemaId: '6xDN7v3AiGgusRp4bqZACZ:2:Employee Credential:1.0.0',
schemaId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ/anoncreds/v0/SCHEMA/Employee Credential/1.0.0',
},
})

// Check if record was created
const anonCredsSchemaRepository = agent.dependencyManager.resolve(AnonCredsSchemaRepository)
const schemaRecord = await anonCredsSchemaRepository.getBySchemaId(
agent.context,
'6xDN7v3AiGgusRp4bqZACZ:2:Employee Credential:1.0.0'
'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ/anoncreds/v0/SCHEMA/Employee Credential/1.0.0'
)

expect(schemaRecord).toMatchObject({
schemaId: '6xDN7v3AiGgusRp4bqZACZ:2:Employee Credential:1.0.0',
schemaId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ/anoncreds/v0/SCHEMA/Employee Credential/1.0.0',
schema: {
attrNames: ['name', 'age'],
issuerId: '6xDN7v3AiGgusRp4bqZACZ',
issuerId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ',
name: 'Employee Credential',
version: '1.0.0',
},
})

expect(schemaRecord.getTags()).toEqual({
schemaId: '6xDN7v3AiGgusRp4bqZACZ:2:Employee Credential:1.0.0',
issuerId: '6xDN7v3AiGgusRp4bqZACZ',
schemaId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ/anoncreds/v0/SCHEMA/Employee Credential/1.0.0',
issuerId: 'did:indy:pool:localtest:6xDN7v3AiGgusRp4bqZACZ',
schemaName: 'Employee Credential',
schemaVersion: '1.0.0',
})
Expand Down Expand Up @@ -192,7 +192,7 @@ describe('AnonCreds API', () => {
keyType: KeyType.Ed25519,
})

const issuerId = 'VsKV7grR1BUE29mG2Fm2kX'
const issuerId = 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX'

const credentialDefinitionResult = await agent.modules.anoncreds.registerCredentialDefinition({
credentialDefinition: {
Expand All @@ -209,7 +209,7 @@ describe('AnonCreds API', () => {
credentialDefinitionState: {
state: 'finished',
credentialDefinition: {
issuerId: 'VsKV7grR1BUE29mG2Fm2kX',
issuerId: 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX',
tag: 'TAG',
schemaId: '7Cd2Yj9yEZNcmNoH54tq9i:2:Test Schema:1.0.0',
type: 'CL',
Expand All @@ -227,7 +227,7 @@ describe('AnonCreds API', () => {
},
},
},
credentialDefinitionId: 'VsKV7grR1BUE29mG2Fm2kX:3:CL:75206:TAG',
credentialDefinitionId: 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX/anoncreds/v0/CLAIM_DEF/75206/TAG',
},
})

Expand All @@ -237,13 +237,13 @@ describe('AnonCreds API', () => {
)
const credentialDefinitionRecord = await anonCredsCredentialDefinitionRepository.getByCredentialDefinitionId(
agent.context,
'VsKV7grR1BUE29mG2Fm2kX:3:CL:75206:TAG'
'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX/anoncreds/v0/CLAIM_DEF/75206/TAG'
)

expect(credentialDefinitionRecord).toMatchObject({
credentialDefinitionId: 'VsKV7grR1BUE29mG2Fm2kX:3:CL:75206:TAG',
credentialDefinitionId: 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX/anoncreds/v0/CLAIM_DEF/75206/TAG',
credentialDefinition: {
issuerId: 'VsKV7grR1BUE29mG2Fm2kX',
issuerId: 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX',
tag: 'TAG',
schemaId: '7Cd2Yj9yEZNcmNoH54tq9i:2:Test Schema:1.0.0',
type: 'CL',
Expand All @@ -264,9 +264,9 @@ describe('AnonCreds API', () => {
})

expect(credentialDefinitionRecord.getTags()).toEqual({
credentialDefinitionId: 'VsKV7grR1BUE29mG2Fm2kX:3:CL:75206:TAG',
credentialDefinitionId: 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX/anoncreds/v0/CLAIM_DEF/75206/TAG',
schemaId: '7Cd2Yj9yEZNcmNoH54tq9i:2:Test Schema:1.0.0',
issuerId: 'VsKV7grR1BUE29mG2Fm2kX',
issuerId: 'did:indy:pool:localhost:VsKV7grR1BUE29mG2Fm2kX',
tag: 'TAG',
})
})
Expand Down

0 comments on commit 8f6b344

Please sign in to comment.