From e19220fc046c524ac167b68c053e143c10c204f4 Mon Sep 17 00:00:00 2001 From: Ariel Gentile Date: Sat, 11 Mar 2023 11:57:37 -0300 Subject: [PATCH] feat(anoncreds-rs): use new API methods for json conversion (#1373) Signed-off-by: Ariel Gentile --- packages/anoncreds-rs/package.json | 4 +- .../src/services/AnonCredsRsHolderService.ts | 170 ++++++++++-------- .../src/services/AnonCredsRsIssuerService.ts | 74 ++++---- .../services/AnonCredsRsVerifierService.ts | 34 ++-- .../AnonCredsRsHolderService.test.ts | 17 +- .../src/services/__tests__/helpers.ts | 103 +++++++---- yarn.lock | 4 +- 7 files changed, 226 insertions(+), 180 deletions(-) diff --git a/packages/anoncreds-rs/package.json b/packages/anoncreds-rs/package.json index 49622b9fb7..1539c8dd9d 100644 --- a/packages/anoncreds-rs/package.json +++ b/packages/anoncreds-rs/package.json @@ -26,14 +26,14 @@ "dependencies": { "@aries-framework/core": "0.3.3", "@aries-framework/anoncreds": "0.3.3", - "@hyperledger/anoncreds-shared": "^0.1.0-dev.6", + "@hyperledger/anoncreds-shared": "^0.1.0-dev.9", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "rxjs": "^7.2.0", "tsyringe": "^4.7.0" }, "devDependencies": { - "@hyperledger/anoncreds-nodejs": "^0.1.0-dev.6", + "@hyperledger/anoncreds-nodejs": "^0.1.0-dev.9", "rimraf": "^4.0.7", "typescript": "~4.9.4" } diff --git a/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts b/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts index f0516665ee..88d167d722 100644 --- a/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts +++ b/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts @@ -15,9 +15,16 @@ import type { AnonCredsCredential, AnonCredsRequestedAttributeMatch, AnonCredsRequestedPredicateMatch, + AnonCredsCredentialRequest, + AnonCredsCredentialRequestMetadata, } from '@aries-framework/anoncreds' import type { AgentContext, Query, SimpleQuery } from '@aries-framework/core' -import type { CredentialEntry, CredentialProve } from '@hyperledger/anoncreds-shared' +import type { + CredentialEntry, + CredentialProve, + CredentialRequestMetadata, + JsonObject, +} from '@hyperledger/anoncreds-shared' import { AnonCredsCredentialRecord, @@ -26,18 +33,14 @@ import { } from '@aries-framework/anoncreds' import { utils, injectable } from '@aries-framework/core' import { - CredentialRequestMetadata, + anoncreds, Credential, - CredentialDefinition, - CredentialOffer, CredentialRequest, CredentialRevocationState, MasterSecret, Presentation, - PresentationRequest, RevocationRegistryDefinition, RevocationStatusList, - Schema, } from '@hyperledger/anoncreds-shared' import { AnonCredsRsError } from '../errors/AnonCredsRsError' @@ -48,31 +51,35 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { agentContext: AgentContext, options?: CreateLinkSecretOptions ): Promise { + let masterSecret: MasterSecret | undefined try { + masterSecret = MasterSecret.create() + + // FIXME: This is a very specific format of anoncreds-rs. I think it should be simply a string + const linkSecretJson = masterSecret.toJson() as { value: { ms: string } } + return { linkSecretId: options?.linkSecretId ?? utils.uuid(), - linkSecretValue: JSON.parse(MasterSecret.create().toJson()).value.ms, + linkSecretValue: linkSecretJson.value.ms, } - } catch (error) { - agentContext.config.logger.error(`Error creating Link Secret`, { - error, - }) - throw new AnonCredsRsError('Error creating Link Secret', { cause: error }) + } finally { + masterSecret?.handle.clear() } } public async createProof(agentContext: AgentContext, options: CreateProofOptions): Promise { const { credentialDefinitions, proofRequest, selectedCredentials, schemas } = options + let presentation: Presentation | undefined try { - const rsCredentialDefinitions: Record = {} + const rsCredentialDefinitions: Record = {} for (const credDefId in credentialDefinitions) { - rsCredentialDefinitions[credDefId] = CredentialDefinition.load(JSON.stringify(credentialDefinitions[credDefId])) + rsCredentialDefinitions[credDefId] = credentialDefinitions[credDefId] as unknown as JsonObject } - const rsSchemas: Record = {} + const rsSchemas: Record = {} for (const schemaId in schemas) { - rsSchemas[schemaId] = Schema.load(JSON.stringify(schemas[schemaId])) + rsSchemas[schemaId] = schemas[schemaId] as unknown as JsonObject } const credentialRepository = agentContext.dependencyManager.resolve(AnonCredsCredentialRepository) @@ -89,30 +96,30 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { retrievedCredentials.set(attribute.credentialId, credentialRecord) } - const credential = Credential.load(JSON.stringify(credentialRecord.credential)) - - const revocationRegistryDefinitionId = credential.revocationRegistryId - const revocationRegistryIndex = credential.revocationRegistryIndex + const revocationRegistryDefinitionId = credentialRecord.credential.rev_reg_id + const revocationRegistryIndex = credentialRecord.credentialRevocationId // TODO: Check if credential has a revocation registry id (check response from anoncreds-rs API, as it is // sending back a mandatory string in Credential.revocationRegistryId) const timestamp = attribute.timestamp - let revocationState - if (timestamp) { - if (revocationRegistryIndex) { + let revocationState: CredentialRevocationState | undefined + let revocationRegistryDefinition: RevocationRegistryDefinition | undefined + try { + if (timestamp && revocationRegistryIndex && revocationRegistryDefinitionId) { if (!options.revocationRegistries[revocationRegistryDefinitionId]) { throw new AnonCredsRsError(`Revocation Registry ${revocationRegistryDefinitionId} not found`) } const { definition, tailsFilePath } = options.revocationRegistries[revocationRegistryDefinitionId] - const revocationRegistryDefinition = RevocationRegistryDefinition.load(JSON.stringify(definition)) + revocationRegistryDefinition = RevocationRegistryDefinition.fromJson(definition as unknown as JsonObject) revocationState = CredentialRevocationState.create({ - revocationRegistryIndex, + revocationRegistryIndex: Number(revocationRegistryIndex), revocationRegistryDefinition, tailsPath: tailsFilePath, revocationStatusList: RevocationStatusList.create({ + issuerId: definition.issuerId, issuanceByDefault: true, revocationRegistryDefinition, revocationRegistryDefinitionId, @@ -120,14 +127,17 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { }), }) } - } - return { - linkSecretId: credentialRecord.linkSecretId, - credentialEntry: { - credential, - revocationState, - timestamp, - }, + return { + linkSecretId: credentialRecord.linkSecretId, + credentialEntry: { + credential: credentialRecord.credential as unknown as JsonObject, + revocationState: revocationState?.toJson(), + timestamp, + }, + } + } finally { + revocationState?.handle.clear() + revocationRegistryDefinition?.handle.clear() } } @@ -163,24 +173,19 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { throw new AnonCredsRsError('Link Secret value not stored') } - const presentation = Presentation.create({ + presentation = Presentation.create({ credentialDefinitions: rsCredentialDefinitions, schemas: rsSchemas, - presentationRequest: PresentationRequest.load(JSON.stringify(proofRequest)), + presentationRequest: proofRequest as unknown as JsonObject, credentials: credentials.map((entry) => entry.credentialEntry), credentialsProve, selfAttest: selectedCredentials.selfAttestedAttributes, - masterSecret: MasterSecret.load(JSON.stringify({ value: { ms: linkSecretRecord.value } })), + masterSecret: { value: { ms: linkSecretRecord.value } }, }) - return JSON.parse(presentation.toJson()) - } catch (error) { - agentContext.config.logger.error(`Error creating AnonCreds Proof`, { - error, - proofRequest, - selectedCredentials, - }) - throw new AnonCredsRsError(`Error creating proof: ${error}`, { cause: error }) + return presentation.toJson() as unknown as AnonCredsProof + } finally { + presentation?.handle.clear() } } @@ -189,6 +194,9 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { options: CreateCredentialRequestOptions ): Promise { const { credentialDefinition, credentialOffer } = options + let createReturnObj: + | { credentialRequest: CredentialRequest; credentialRequestMetadata: CredentialRequestMetadata } + | undefined try { const linkSecretRepository = agentContext.dependencyManager.resolve(AnonCredsLinkSecretRepository) @@ -204,19 +212,22 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { ) } - const { credentialRequest, credentialRequestMetadata } = CredentialRequest.create({ - credentialDefinition: CredentialDefinition.load(JSON.stringify(credentialDefinition)), - credentialOffer: CredentialOffer.load(JSON.stringify(credentialOffer)), - masterSecret: MasterSecret.load(JSON.stringify({ value: { ms: linkSecretRecord.value } })), + createReturnObj = CredentialRequest.create({ + entropy: anoncreds.generateNonce(), // FIXME: find a better source of entropy + credentialDefinition: credentialDefinition as unknown as JsonObject, + credentialOffer: credentialOffer as unknown as JsonObject, + masterSecret: { value: { ms: linkSecretRecord.value } }, masterSecretId: linkSecretRecord.linkSecretId, }) return { - credentialRequest: JSON.parse(credentialRequest.toJson()), - credentialRequestMetadata: JSON.parse(credentialRequestMetadata.toJson()), + credentialRequest: createReturnObj.credentialRequest.toJson() as unknown as AnonCredsCredentialRequest, + credentialRequestMetadata: + createReturnObj.credentialRequestMetadata.toJson() as unknown as AnonCredsCredentialRequestMetadata, } - } catch (error) { - throw new AnonCredsRsError(`Error creating credential request: ${error}`, { cause: error }) + } finally { + createReturnObj?.credentialRequest.handle.clear() + createReturnObj?.credentialRequestMetadata.handle.clear() } } @@ -227,35 +238,42 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { .resolve(AnonCredsLinkSecretRepository) .getByLinkSecretId(agentContext, credentialRequestMetadata.master_secret_name) - const revocationRegistryDefinition = revocationRegistry?.definition - ? RevocationRegistryDefinition.load(JSON.stringify(revocationRegistry.definition)) - : undefined + const revocationRegistryDefinition = revocationRegistry?.definition as unknown as JsonObject const credentialId = options.credentialId ?? utils.uuid() - const processedCredential = Credential.load(JSON.stringify(credential)).process({ - credentialDefinition: CredentialDefinition.load(JSON.stringify(credentialDefinition)), - credentialRequestMetadata: CredentialRequestMetadata.load(JSON.stringify(credentialRequestMetadata)), - masterSecret: MasterSecret.load(JSON.stringify({ value: { ms: linkSecretRecord.value } })), - revocationRegistryDefinition, - }) - - const credentialRepository = agentContext.dependencyManager.resolve(AnonCredsCredentialRepository) - await credentialRepository.save( - agentContext, - new AnonCredsCredentialRecord({ - credential: JSON.parse(processedCredential.toJson()) as AnonCredsCredential, - credentialId, - linkSecretId: linkSecretRecord.linkSecretId, - issuerId: options.credentialDefinition.issuerId, - schemaName: schema.name, - schemaIssuerId: schema.issuerId, - schemaVersion: schema.version, - credentialRevocationId: processedCredential.revocationRegistryIndex?.toString(), + let credentialObj: Credential | undefined + let processedCredential: Credential | undefined + try { + credentialObj = Credential.fromJson(credential as unknown as JsonObject) + processedCredential = credentialObj.process({ + credentialDefinition: credentialDefinition as unknown as JsonObject, + credentialRequestMetadata: credentialRequestMetadata as unknown as JsonObject, + masterSecret: { value: { ms: linkSecretRecord.value } }, + revocationRegistryDefinition, }) - ) - return credentialId + const credentialRepository = agentContext.dependencyManager.resolve(AnonCredsCredentialRepository) + + await credentialRepository.save( + agentContext, + new AnonCredsCredentialRecord({ + credential: processedCredential.toJson() as unknown as AnonCredsCredential, + credentialId, + linkSecretId: linkSecretRecord.linkSecretId, + issuerId: options.credentialDefinition.issuerId, + schemaName: schema.name, + schemaIssuerId: schema.issuerId, + schemaVersion: schema.version, + credentialRevocationId: processedCredential.revocationRegistryIndex?.toString(), + }) + ) + + return credentialId + } finally { + credentialObj?.handle.clear() + processedCredential?.handle.clear() + } } public async getCredential( diff --git a/packages/anoncreds-rs/src/services/AnonCredsRsIssuerService.ts b/packages/anoncreds-rs/src/services/AnonCredsRsIssuerService.ts index 17b3c91d91..91c439d4b1 100644 --- a/packages/anoncreds-rs/src/services/AnonCredsRsIssuerService.ts +++ b/packages/anoncreds-rs/src/services/AnonCredsRsIssuerService.ts @@ -9,8 +9,10 @@ import type { AnonCredsSchema, AnonCredsCredentialDefinition, CreateCredentialDefinitionReturn, + AnonCredsCredential, } from '@aries-framework/anoncreds' import type { AgentContext } from '@aries-framework/core' +import type { CredentialDefinitionPrivate, JsonObject, KeyCorrectnessProof } from '@hyperledger/anoncreds-shared' import { AnonCredsKeyCorrectnessProofRepository, @@ -18,15 +20,7 @@ import { AnonCredsCredentialDefinitionRepository, } from '@aries-framework/anoncreds' import { injectable, AriesFrameworkError } from '@aries-framework/core' -import { - Credential, - CredentialDefinition, - CredentialDefinitionPrivate, - CredentialRequest, - CredentialOffer, - KeyCorrectnessProof, - Schema, -} from '@hyperledger/anoncreds-shared' +import { Credential, CredentialDefinition, CredentialOffer, Schema } from '@hyperledger/anoncreds-shared' import { AnonCredsRsError } from '../errors/AnonCredsRsError' @@ -35,6 +29,7 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { public async createSchema(agentContext: AgentContext, options: CreateSchemaOptions): Promise { const { issuerId, name, version, attrNames: attributeNames } = options + let schema: Schema | undefined try { const schema = Schema.create({ issuerId, @@ -43,9 +38,9 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { attributeNames, }) - return JSON.parse(schema.toJson()) as AnonCredsSchema - } catch (error) { - throw new AnonCredsRsError('Error creating schema', { cause: error }) + return schema.toJson() as unknown as AnonCredsSchema + } finally { + schema?.handle.clear() } } @@ -55,9 +50,16 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { ): Promise { const { tag, supportRevocation, schema, issuerId, schemaId } = options + let createReturnObj: + | { + credentialDefinition: CredentialDefinition + credentialDefinitionPrivate: CredentialDefinitionPrivate + keyCorrectnessProof: KeyCorrectnessProof + } + | undefined try { - const { credentialDefinition, credentialDefinitionPrivate, keyCorrectnessProof } = CredentialDefinition.create({ - schema: Schema.load(JSON.stringify(schema)), + createReturnObj = CredentialDefinition.create({ + schema: schema as unknown as JsonObject, issuerId, schemaId, tag, @@ -66,12 +68,14 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { }) return { - credentialDefinition: JSON.parse(credentialDefinition.toJson()) as AnonCredsCredentialDefinition, - credentialDefinitionPrivate: JSON.parse(credentialDefinitionPrivate.toJson()), - keyCorrectnessProof: JSON.parse(keyCorrectnessProof.toJson()), + credentialDefinition: createReturnObj.credentialDefinition.toJson() as unknown as AnonCredsCredentialDefinition, + credentialDefinitionPrivate: createReturnObj.credentialDefinitionPrivate.toJson(), + keyCorrectnessProof: createReturnObj.keyCorrectnessProof.toJson(), } - } catch (error) { - throw new AnonCredsRsError('Error creating credential definition', { cause: error }) + } finally { + createReturnObj?.credentialDefinition.handle.clear() + createReturnObj?.credentialDefinitionPrivate.handle.clear() + createReturnObj?.keyCorrectnessProof.handle.clear() } } @@ -81,6 +85,7 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { ): Promise { const { credentialDefinitionId } = options + let credentialOffer: CredentialOffer | undefined try { const credentialDefinitionRecord = await agentContext.dependencyManager .resolve(AnonCredsCredentialDefinitionRepository) @@ -94,15 +99,15 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { throw new AnonCredsRsError(`Credential Definition ${credentialDefinitionId} not found`) } - const credentialOffer = CredentialOffer.create({ + credentialOffer = CredentialOffer.create({ credentialDefinitionId, - keyCorrectnessProof: KeyCorrectnessProof.load(JSON.stringify(keyCorrectnessProofRecord?.value)), + keyCorrectnessProof: keyCorrectnessProofRecord?.value, schemaId: credentialDefinitionRecord.credentialDefinition.schemaId, }) - return JSON.parse(credentialOffer.toJson()) as AnonCredsCredentialOffer - } catch (error) { - throw new AnonCredsRsError(`Error creating credential offer: ${error}`, { cause: error }) + return credentialOffer.toJson() as unknown as AnonCredsCredentialOffer + } finally { + credentialOffer?.handle.clear() } } @@ -112,6 +117,7 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { ): Promise { const { tailsFilePath, credentialOffer, credentialRequest, credentialValues, revocationRegistryId } = options + let credential: Credential | undefined try { if (revocationRegistryId || tailsFilePath) { throw new AriesFrameworkError('Revocation not supported yet') @@ -133,26 +139,22 @@ export class AnonCredsRsIssuerService implements AnonCredsIssuerService { .resolve(AnonCredsCredentialDefinitionPrivateRepository) .getByCredentialDefinitionId(agentContext, options.credentialRequest.cred_def_id) - const credential = Credential.create({ - credentialDefinition: CredentialDefinition.load( - JSON.stringify(credentialDefinitionRecord.credentialDefinition) - ), - credentialOffer: CredentialOffer.load(JSON.stringify(credentialOffer)), - credentialRequest: CredentialRequest.load(JSON.stringify(credentialRequest)), + credential = Credential.create({ + credentialDefinition: credentialDefinitionRecord.credentialDefinition as unknown as JsonObject, + credentialOffer: credentialOffer as unknown as JsonObject, + credentialRequest: credentialRequest as unknown as JsonObject, revocationRegistryId, attributeEncodedValues, attributeRawValues, - credentialDefinitionPrivate: CredentialDefinitionPrivate.load( - JSON.stringify(credentialDefinitionPrivateRecord.value) - ), + credentialDefinitionPrivate: credentialDefinitionPrivateRecord.value, }) return { - credential: JSON.parse(credential.toJson()), + credential: credential.toJson() as unknown as AnonCredsCredential, credentialRevocationId: credential.revocationRegistryIndex?.toString(), } - } catch (error) { - throw new AnonCredsRsError(`Error creating credential: ${error}`, { cause: error }) + } finally { + credential?.handle.clear() } } } diff --git a/packages/anoncreds-rs/src/services/AnonCredsRsVerifierService.ts b/packages/anoncreds-rs/src/services/AnonCredsRsVerifierService.ts index be4952d632..81edd11c56 100644 --- a/packages/anoncreds-rs/src/services/AnonCredsRsVerifierService.ts +++ b/packages/anoncreds-rs/src/services/AnonCredsRsVerifierService.ts @@ -1,34 +1,27 @@ import type { AnonCredsVerifierService, VerifyProofOptions } from '@aries-framework/anoncreds' import type { AgentContext } from '@aries-framework/core' +import type { JsonObject } from '@hyperledger/anoncreds-shared' import { injectable } from '@aries-framework/core' -import { - CredentialDefinition, - Presentation, - PresentationRequest, - RevocationRegistryDefinition, - RevocationStatusList, - Schema, -} from '@hyperledger/anoncreds-shared' - -import { AnonCredsRsError } from '../errors/AnonCredsRsError' +import { Presentation, RevocationRegistryDefinition, RevocationStatusList } from '@hyperledger/anoncreds-shared' @injectable() export class AnonCredsRsVerifierService implements AnonCredsVerifierService { public async verifyProof(agentContext: AgentContext, options: VerifyProofOptions): Promise { const { credentialDefinitions, proof, proofRequest, revocationRegistries, schemas } = options + let presentation: Presentation | undefined try { - const presentation = Presentation.load(JSON.stringify(proof)) + presentation = Presentation.fromJson(proof as unknown as JsonObject) - const rsCredentialDefinitions: Record = {} + const rsCredentialDefinitions: Record = {} for (const credDefId in credentialDefinitions) { - rsCredentialDefinitions[credDefId] = CredentialDefinition.load(JSON.stringify(credentialDefinitions[credDefId])) + rsCredentialDefinitions[credDefId] = credentialDefinitions[credDefId] as unknown as JsonObject } - const rsSchemas: Record = {} + const rsSchemas: Record = {} for (const schemaId in schemas) { - rsSchemas[schemaId] = Schema.load(JSON.stringify(schemas[schemaId])) + rsSchemas[schemaId] = schemas[schemaId] as unknown as JsonObject } const revocationRegistryDefinitions: Record = {} @@ -37,13 +30,14 @@ export class AnonCredsRsVerifierService implements AnonCredsVerifierService { for (const revocationRegistryDefinitionId in revocationRegistries) { const { definition, revocationStatusLists } = options.revocationRegistries[revocationRegistryDefinitionId] - revocationRegistryDefinitions[revocationRegistryDefinitionId] = RevocationRegistryDefinition.load( - JSON.stringify(definition) + revocationRegistryDefinitions[revocationRegistryDefinitionId] = RevocationRegistryDefinition.fromJson( + definition as unknown as JsonObject ) for (const timestamp in revocationStatusLists) { lists.push( RevocationStatusList.create({ + issuerId: definition.issuerId, issuanceByDefault: true, revocationRegistryDefinition: revocationRegistryDefinitions[revocationRegistryDefinitionId], revocationRegistryDefinitionId, @@ -54,14 +48,14 @@ export class AnonCredsRsVerifierService implements AnonCredsVerifierService { } return presentation.verify({ - presentationRequest: PresentationRequest.load(JSON.stringify(proofRequest)), + presentationRequest: proofRequest as unknown as JsonObject, credentialDefinitions: rsCredentialDefinitions, schemas: rsSchemas, revocationRegistryDefinitions, revocationStatusLists: lists, }) - } catch (error) { - throw new AnonCredsRsError('Error verifying proof', { cause: error }) + } finally { + presentation?.handle.clear() } } } diff --git a/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsHolderService.test.ts b/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsHolderService.test.ts index 23565f8e2b..3240dd5ff9 100644 --- a/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsHolderService.test.ts +++ b/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsHolderService.test.ts @@ -5,7 +5,10 @@ import type { AnonCredsCredential, AnonCredsSchema, AnonCredsSelectedCredentials, + AnonCredsRevocationRegistryDefinition, + AnonCredsCredentialRequestMetadata, } from '@aries-framework/anoncreds' +import type { JsonObject } from '@hyperledger/anoncreds-nodejs' import { AnonCredsHolderServiceSymbol, @@ -56,7 +59,7 @@ const agentContext = getAgentContext({ describe('AnonCredsRsHolderService', () => { const getByCredentialIdMock = jest.spyOn(anoncredsCredentialRepositoryMock, 'getByCredentialId') - afterEach(() => { + beforeEach(() => { getByCredentialIdMock.mockClear() }) @@ -160,7 +163,7 @@ describe('AnonCredsRsHolderService', () => { height: '179', age: '19', }, - credentialDefinition: personCredentialDefinition, + credentialDefinition: personCredentialDefinition as unknown as JsonObject, schemaId: 'personschema:uri', credentialDefinitionId: 'personcreddef:uri', credentialDefinitionPrivate: personCredentialDefinitionPrivate, @@ -180,7 +183,7 @@ describe('AnonCredsRsHolderService', () => { attributes: { phoneNumber: 'linkSecretId56', }, - credentialDefinition: phoneCredentialDefinition, + credentialDefinition: phoneCredentialDefinition as unknown as JsonObject, schemaId: 'phoneschema:uri', credentialDefinitionId: 'phonecreddef:uri', credentialDefinitionPrivate: phoneCredentialDefinitionPrivate, @@ -454,7 +457,7 @@ describe('AnonCredsRsHolderService', () => { height: '179', age: '19', }, - credentialDefinition, + credentialDefinition: credentialDefinition as unknown as JsonObject, schemaId: 'personschema:uri', credentialDefinitionId: 'personcreddef:uri', credentialDefinitionPrivate, @@ -474,11 +477,13 @@ describe('AnonCredsRsHolderService', () => { credentialDefinition, schema, credentialDefinitionId: 'personcreddefid:uri', - credentialRequestMetadata: JSON.parse(credentialRequestMetadata.toJson()), + credentialRequestMetadata: credentialRequestMetadata.toJson() as unknown as AnonCredsCredentialRequestMetadata, credentialId: 'personCredId', revocationRegistry: { id: 'personrevregid:uri', - definition: JSON.parse(new RevocationRegistryDefinition(revocationRegistryDefinition.handle).toJson()), + definition: new RevocationRegistryDefinition( + revocationRegistryDefinition.handle + ).toJson() as unknown as AnonCredsRevocationRegistryDefinition, }, }) diff --git a/packages/anoncreds-rs/src/services/__tests__/helpers.ts b/packages/anoncreds-rs/src/services/__tests__/helpers.ts index 07d5b09f49..b71cfdcf6d 100644 --- a/packages/anoncreds-rs/src/services/__tests__/helpers.ts +++ b/packages/anoncreds-rs/src/services/__tests__/helpers.ts @@ -1,13 +1,22 @@ -import type { AnonCredsCredentialInfo } from '@aries-framework/anoncreds' +import type { + AnonCredsCredential, + AnonCredsCredentialDefinition, + AnonCredsCredentialInfo, + AnonCredsCredentialOffer, +} from '@aries-framework/anoncreds' +import type { JsonObject } from '@hyperledger/anoncreds-nodejs' import { anoncreds, + Credential, CredentialDefinition, - CredentialDefinitionPrivate, CredentialOffer, CredentialRequest, - KeyCorrectnessProof, + CredentialRevocationConfig, MasterSecret, + RevocationRegistryDefinition, + RevocationRegistryDefinitionPrivate, + RevocationStatusList, Schema, } from '@hyperledger/anoncreds-shared' @@ -34,24 +43,33 @@ export function createCredentialDefinition(options: { attributeNames: string[]; tag: 'TAG', }) - return { - credentialDefinition: JSON.parse(credentialDefinition.toJson()), - credentialDefinitionPrivate: JSON.parse(credentialDefinitionPrivate.toJson()), - keyCorrectnessProof: JSON.parse(keyCorrectnessProof.toJson()), - schema: JSON.parse(schema.toJson()), + const returnObj = { + credentialDefinition: credentialDefinition.toJson() as unknown as AnonCredsCredentialDefinition, + credentialDefinitionPrivate: credentialDefinitionPrivate.toJson() as unknown as JsonObject, + keyCorrectnessProof: keyCorrectnessProof.toJson() as unknown as JsonObject, + schema: schema.toJson() as unknown as Schema, } + + credentialDefinition.handle.clear() + credentialDefinitionPrivate.handle.clear() + keyCorrectnessProof.handle.clear() + schema.handle.clear() + + return returnObj } /** * Creates a valid credential offer and returns itsf */ -export function createCredentialOffer(kcp: Record) { +export function createCredentialOffer(keyCorrectnessProof: Record) { const credentialOffer = CredentialOffer.create({ credentialDefinitionId: 'creddef:uri', - keyCorrectnessProof: KeyCorrectnessProof.load(JSON.stringify(kcp)), + keyCorrectnessProof, schemaId: 'schema:uri', }) - return JSON.parse(credentialOffer.toJson()) + const credentialOfferJson = credentialOffer.toJson() as unknown as AnonCredsCredentialOffer + credentialOffer.handle.clear() + return credentialOfferJson } /** @@ -59,13 +77,16 @@ export function createCredentialOffer(kcp: Record) { * @returns Creates a valid link secret value for anoncreds-rs */ export function createLinkSecret() { - return JSON.parse(MasterSecret.create().toJson()).value.ms as string + const masterSecret = MasterSecret.create() + const ms = (masterSecret.toJson() as { value: { ms: string } }).value.ms as string + masterSecret.handle.clear() + return ms } export function createCredentialForHolder(options: { - credentialDefinition: Record - credentialDefinitionPrivate: Record - keyCorrectnessProof: Record + credentialDefinition: JsonObject + credentialDefinitionPrivate: JsonObject + keyCorrectnessProof: JsonObject schemaId: string credentialDefinitionId: string attributes: Record @@ -89,19 +110,18 @@ export function createCredentialForHolder(options: { const credentialOffer = CredentialOffer.create({ credentialDefinitionId, - keyCorrectnessProof: KeyCorrectnessProof.load(JSON.stringify(keyCorrectnessProof)), + keyCorrectnessProof, schemaId, }) const { credentialRequest, credentialRequestMetadata } = CredentialRequest.create({ - credentialDefinition: CredentialDefinition.load(JSON.stringify(credentialDefinition)), + entropy: 'some-entropy', + credentialDefinition, credentialOffer, - masterSecret: MasterSecret.load(JSON.stringify({ value: { ms: linkSecret } })), + masterSecret: { value: { ms: linkSecret } }, masterSecretId: linkSecretId, }) - // FIXME: Revocation config should not be mandatory but current anoncreds-rs is requiring it - const { revocationRegistryDefinition, revocationRegistryDefinitionPrivate, tailsPath } = createRevocationRegistryDefinition({ credentialDefinitionId, @@ -109,30 +129,29 @@ export function createCredentialForHolder(options: { }) const timeCreateRevStatusList = 12 - const revocationStatusList = anoncreds.createRevocationStatusList({ + const revocationStatusList = RevocationStatusList.create({ + issuerId: credentialDefinition.issuerId as string, timestamp: timeCreateRevStatusList, issuanceByDefault: true, - revocationRegistryDefinition, - revocationRegistryDefinitionId: revocationRegistryDefinitionId, + revocationRegistryDefinition: new RevocationRegistryDefinition(revocationRegistryDefinition.handle), + revocationRegistryDefinitionId: 'mock:uri', }) - // TODO: Use Credential.create (needs to update the paramters in anoncreds-rs) - const credentialObj = anoncreds.createCredential({ - credentialDefinition: CredentialDefinition.load(JSON.stringify(credentialDefinition)).handle, - credentialDefinitionPrivate: CredentialDefinitionPrivate.load(JSON.stringify(credentialDefinitionPrivate)).handle, - credentialOffer: credentialOffer.handle, - credentialRequest: credentialRequest.handle, + const credentialObj = Credential.create({ + credentialDefinition, + credentialDefinitionPrivate, + credentialOffer, + credentialRequest, attributeRawValues: attributes, revocationRegistryId: revocationRegistryDefinitionId, revocationStatusList, - revocationConfiguration: { + revocationConfiguration: new CredentialRevocationConfig({ + registryDefinition: new RevocationRegistryDefinition(revocationRegistryDefinition.handle), + registryDefinitionPrivate: new RevocationRegistryDefinitionPrivate(revocationRegistryDefinitionPrivate.handle), registryIndex: 9, - revocationRegistryDefinition, - revocationRegistryDefinitionPrivate, tailsPath, - }, + }), }) - const credential = anoncreds.getJson({ objectHandle: credentialObj }) const credentialInfo: AnonCredsCredentialInfo = { attributes, @@ -140,13 +159,21 @@ export function createCredentialForHolder(options: { credentialId, schemaId, } - return { - credential: JSON.parse(credential), + const returnObj = { + credential: credentialObj.toJson() as unknown as AnonCredsCredential, credentialInfo, revocationRegistryDefinition, tailsPath, credentialRequestMetadata, } + + credentialObj.handle.clear() + credentialOffer.handle.clear() + credentialRequest.handle.clear() + revocationRegistryDefinitionPrivate.clear() + revocationStatusList.handle.clear() + + return returnObj } export function createRevocationRegistryDefinition(options: { @@ -157,8 +184,8 @@ export function createRevocationRegistryDefinition(options: { const { revocationRegistryDefinition, revocationRegistryDefinitionPrivate } = anoncreds.createRevocationRegistryDefinition({ credentialDefinitionId, - credentialDefinition: CredentialDefinition.load(JSON.stringify(credentialDefinition)).handle, - issuerId: 'mock:uri', + credentialDefinition: CredentialDefinition.fromJson(credentialDefinition).handle, + issuerId: credentialDefinition.issuerId as string, tag: 'some_tag', revocationRegistryType: 'CL_ACCUM', maximumCredentialNumber: 10, diff --git a/yarn.lock b/yarn.lock index 6382acd35c..32245f9bd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -877,7 +877,7 @@ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== -"@hyperledger/anoncreds-nodejs@^0.1.0-dev.6": +"@hyperledger/anoncreds-nodejs@^0.1.0-dev.9": version "0.1.0-dev.10" resolved "https://registry.yarnpkg.com/@hyperledger/anoncreds-nodejs/-/anoncreds-nodejs-0.1.0-dev.10.tgz#80c093ecb08a277fb494399b64aad1b900c3103f" integrity sha512-ju5mJPwuyebAPziuf+eUOwxEws02G2FHEp/qG3GV3kxtlx7THW7HVB7dMSNqhRVKCsbcNnZtWJB1UiPvWqboUg== @@ -890,7 +890,7 @@ ref-napi "3.0.3" ref-struct-di "1.1.1" -"@hyperledger/anoncreds-shared@0.1.0-dev.10", "@hyperledger/anoncreds-shared@^0.1.0-dev.6": +"@hyperledger/anoncreds-shared@0.1.0-dev.10", "@hyperledger/anoncreds-shared@^0.1.0-dev.9": version "0.1.0-dev.10" resolved "https://registry.yarnpkg.com/@hyperledger/anoncreds-shared/-/anoncreds-shared-0.1.0-dev.10.tgz#9d67f64e98ff41971644c95b03dabafd741df4df" integrity sha512-POvcwQrUcPrwoZehQa38pN1dnjyeUlrQ6VlksbBRS8SUHJuyixZsD+d3XoumqaNfl9Z1DCjfuOgEiPlec01gXQ==