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

Create AnonCreds service that can handle multiple AnonCredsRegistries #1123

Closed
3 tasks
karimStekelenburg opened this issue Nov 28, 2022 · 1 comment · Fixed by #1204
Closed
3 tasks

Create AnonCreds service that can handle multiple AnonCredsRegistries #1123

karimStekelenburg opened this issue Nov 28, 2022 · 1 comment · Fixed by #1204
Assignees

Comments

@karimStekelenburg
Copy link
Contributor

karimStekelenburg commented Nov 28, 2022

Description

One of the things we're building into AFJ is the ability to talk to multiple ledgers. In the architecture we're building (as depicted in the image below), we separate the credential format-related logic (orange box) from the logic that deals with communication to the ledgers (red box). Connection management and ledger communication are handled by implementations of the AnonCredsRegistry interface. In order to support multiple ledgers, we need to create an AnonCredsService that manages these AnonCredsRegistrys.

Knowing which ledger to use

With support for multiple ledgers, the AnonCredsService will need to figure out what AnonCredsRegistry instance it should use when a call is being made. This can be derived from the identifiers that are passed via the method parameters. The AnonCredsService needs a regex-like mechanism to match this identifier to the corresponding registry.

Identifiers

Indy networks can be identified in two ways: did:indy identifiers and legacy identifiers. More information on did:indy identifiers can be found here.

The other network that we will add support for is cheqd. This network uses the did:cheqd identifier. More info here.

💡 The logic required here is similar to That that of the DidRegistrarService and DidResolverService.

Approaches

There are two possible approaches to implementing this.

Using AnonCredsService as a bridge

Here the AnonCredsService fetches the right AnonCredsRegistry and calls it.

class AnonCredsService {
  holder: AnonCredsHolder;
  issuer: AnonCredsIssuer;
  verifier: AnonCredsVerifier;

  registries: AnonCredsRegistry[];

  private getRegistryForIdentifier(identifier: string): AnonCredsRegistry { /** not important **/ }

  public async createCredentialDefinition(options: CreateCredentialOptions) {
    const registry = getRegistryForIdentifier(options.schemaId);
    const credentialDefinition = await this.issuer.createCredentialDefinition(options);

    // Here AnonCredsService is responsible for calling the registry
    await registry.writeCredentialDefinition(credentialDefinition);

    return credentialDefinition
  }
}

Using AnonCredsApi as a bridge

Another option is to move the responsibility of calling the AnonCredsRegistry one level up, and let it be handled by the AnonCredsApi.

class AnonCredsService {
  holder: AnonCredsHolder;
  issuer: AnonCredsIssuer;
  verifier: AnonCredsVerifier;

  registries: AnonCredsRegistry[];

  public getRegistryForIdentifier(identifier: string): AnonCredsRegistry { /** not important **/ }

  public async createCredentialDefinition(options: CreateCredentialOptions) {
    // We don't bother dealing with the registry here
    const credentialDefinition = await this.issuer.createCredentialDefinition(options);
    return credentialDefinition
  }
}

class AnonCredsApi {
  service: AnonCredsService

  private getRegistryForIdentifier(identifier: string): AnonCredsRegistry { /** not important **/ }

  public async createCredentialDefinition(options: CreateCredentialOptions) {
    const registry = service.getRegistryForIdentifier(options.schemaId);
    const credentialDefinition = await service.createCredentialDefinition(options);

    // Here AnonCredsApi is responsible for calling the registry
    await registry.writeCredentialDefinition(credentialDefinition);

    return credentialDefinition
  }
}

Todo

  • Decide on the approach
  • Create a mechanism to resolve the right registry based on the identifiers in the parameters
  • Implement all methods, calling the AnonCredsHolder, AnonCredsIssuerorAnonCredsVerifierand appropriateAnonCredsRegistry` instance.

DOD: There is an AnonCredsRegistryService that can be called to find the registry instance for a specific anoncreds model identifier (schema id, credential definition id, revocation registry id)

@TimoGlastra
Copy link
Contributor

TimoGlastra commented Nov 29, 2022

I think for the second approach we could move it up even more by making the AnonCreds service more an AnonCredsRegistryService (like we have the IndyPoolService) and only let it manage the registires. The code in the API will then look something like:

class AnonCredsRegistryService {
  registries: AnonCredsRegistry[];

  public getRegistryForIdentifier(identifier: string): AnonCredsRegistry { /** not important **/ }
}

class AnonCredsApi {
  registryService: AnonCredsRegistryService
  issuer: AnonCredsIssuerService
  

  private getRegistryForIdentifier(identifier: string): AnonCredsRegistry { /** not important **/ }

  public async createCredentialDefinition(options: CreateCredentialOptions) {
    const registry = registryService.getRegistryForIdentifier(options.schemaId);
    const credentialDefinition = await issuer.createCredentialDefinition(options);

    // Here AnonCredsApi is responsible for calling the registry
    await registry.writeCredentialDefinition(credentialDefinition);

    return credentialDefinition
  }
}

Just posting it here for comparison. I don't have strong preferences. But we should probably look at what the purpose of each service is. If we need to expose all methods from the issuer / holder /verifier services on the AnonCreds service that will be quite some. Or will it only add methods related to reading / writing to/from the registry?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants