diff --git a/apps/ssi-abstraction/.env.example b/apps/ssi-abstraction/.env.example index 73ad4533fee88fde13e14fb45fd9e8d7d38b3e87..708869532475cb102148eeb805ed1f8d90c1acca 100644 --- a/apps/ssi-abstraction/.env.example +++ b/apps/ssi-abstraction/.env.example @@ -11,10 +11,11 @@ AGENT_WALLET_ID=ssi-wallet-id AGENT_WALLET_KEY=ssi-wallet-key AGENT_HOST=http://localhost AGENT_INBOUND_PORT=3001 -AGENT_PUBLIC_DID_SEED=6b8b882e2618fa5d45ee7229ca000000 +AGENT_LEDGER_ID=ID_UNION +AGENT_INDY_DID_SEED=00000000000_OCM_E1_Test_Endorser +AGENT_INDY_DID=RVKyFidnaqJPznu8bgodDb AGENT_AUTO_ACCEPT_CONNECTION=true AGENT_AUTO_ACCEPT_CREDENTIAL=contentApproved -AGENT_LEDGER_ID=BCOVRIN_TEST TAILS_SERVER_BASE_URL=http://localhost:9000 TAILS_SERVER_BUCKET_NAME=ssi diff --git a/apps/ssi-abstraction/src/agent/dids/dids.service.ts b/apps/ssi-abstraction/src/agent/dids/dids.service.ts index ef2d8e837c15c21bed59393ab33eda7a73ef7c01..fac1839c84e0da3b0f2f56ca0c2854645bd95462 100644 --- a/apps/ssi-abstraction/src/agent/dids/dids.service.ts +++ b/apps/ssi-abstraction/src/agent/dids/dids.service.ts @@ -128,10 +128,12 @@ export class DidsService { >; const indyDidSeed = this.configService.get('agent.indyDidSeed') as string; + const indyDid = this.configService.get('agent.indyDid') as string; const indyDids = await registerIndyDids({ ledgerIds, seed: indyDidSeed, + did: indyDid, }); const privKey = { diff --git a/apps/ssi-abstraction/src/agent/ledger/register.ts b/apps/ssi-abstraction/src/agent/ledger/register.ts index b7127ff680ee0fd031b657a3a16167602bab3bd7..a40c1efa16a84c51b308f3e4487aa98ccc84a17f 100644 --- a/apps/ssi-abstraction/src/agent/ledger/register.ts +++ b/apps/ssi-abstraction/src/agent/ledger/register.ts @@ -8,6 +8,7 @@ import { LEDGERS } from '../../config/ledger.js'; type RegisterPublicDidOptions = { ledgerIds: Array<LedgerIds>; seed: string; + did?: string; }; type LedgerRegistrationBody = { @@ -20,20 +21,42 @@ type LedgerRegistrationBody = { type RegisterPublicDidResponse = { seed: string; did: string; - verkey: string; + verkey?: string; namespace: string; }; export const registerPublicDids = async ({ ledgerIds, seed, + did, }: RegisterPublicDidOptions): Promise<Array<RegisterPublicDidResponse>> => { const responses: Array<RegisterPublicDidResponse> = []; + for (const ledgerId of ledgerIds) { - try { - const ledgerRegisterUrl = LEDGERS[ledgerId].registerNymUrl; - const ledgerNamespace = LEDGERS[ledgerId].namespace; + const ledgerConfig = LEDGERS[ledgerId]; + const ledgerNamespace = ledgerConfig.namespace; + + if (did) { + const indyDid = `did:indy:${ledgerNamespace}:${did}`; + logger.warn( + `Agent DID '${indyDid}' provided in config. Assuming it was registered manually.`, + ); + responses.push({ + did: indyDid, + seed, + namespace: ledgerNamespace, + }); + continue; + } else if ( + !('registerNymUrl' in ledgerConfig) || + !ledgerConfig.registerNymUrl + ) { + throw new Error( + `Ledger ${ledgerId} does not have a 'registerNymUrl'. Must register DID manually and provide it in 'AGENT_INDY_DID' env variable. Cannot continue without a DID.`, + ); + } + try { const body: LedgerRegistrationBody = { role: 'ENDORSER', seed, @@ -41,7 +64,7 @@ export const registerPublicDids = async ({ const res = await axios({ method: 'post', - url: ledgerRegisterUrl, + url: ledgerConfig.registerNymUrl, data: body, }); @@ -57,5 +80,6 @@ export const registerPublicDids = async ({ if (err instanceof axios.AxiosError) logAxiosError(err); } } + return responses; }; diff --git a/apps/ssi-abstraction/src/agent/revocation/revocation.service.ts b/apps/ssi-abstraction/src/agent/revocation/revocation.service.ts index fc33f32248359a7fb8b8642e4cfd12171b007914..c8b4bc0fc630dd70667fa269411a7e172c5087db 100644 --- a/apps/ssi-abstraction/src/agent/revocation/revocation.service.ts +++ b/apps/ssi-abstraction/src/agent/revocation/revocation.service.ts @@ -143,23 +143,46 @@ export class RevocationService { }: EventAnonCredsRevocationRegisterRevocationStatusListInput): Promise< EventAnonCredsRevocationRegisterRevocationStatusList['data'] > { + const endorserDid = await this.agentService.getEndorserDid(issuerDid); return this.withTenantService.invoke(tenantId, async (t) => { - const result = await t.modules.anoncreds.registerRevocationStatusList({ - options: {}, - revocationStatusList: { - revocationRegistryDefinitionId, - issuerId: issuerDid, - }, - }); + const { revocationStatusListState } = + await t.modules.anoncreds.registerRevocationStatusList({ + options: { + endorserMode: 'external', + endorserDid, + }, + revocationStatusList: { + revocationRegistryDefinitionId, + issuerId: issuerDid, + }, + }); - if (result.revocationStatusListState.state !== 'finished') { + if ( + revocationStatusListState.state !== 'action' || + revocationStatusListState.action !== 'endorseIndyTransaction' + ) { throw new Error( - `Error registering the revocation status list. Error: ${JSON.stringify( - result, - )}`, + `Error registering revocation registry definition: ${ + revocationStatusListState.state === 'failed' + ? revocationStatusListState.reason + : 'Not Finished' + }`, ); } + const signedRevocationRegistryDefinitionRequest = + await this.agentService.endorseTransaction( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + revocationStatusListState.revocationStatusListRequest, + endorserDid, + ); + + await t.modules.indyVdr.submitTransaction( + signedRevocationRegistryDefinitionRequest, + issuerDid, + ); + return {}; }); } diff --git a/apps/ssi-abstraction/src/config/agent.config.ts b/apps/ssi-abstraction/src/config/agent.config.ts index c69046384fc24eaea1a66584a54d3ad6f3a7ba69..22884d6fb57ad5cf2702feec4a6a570eb8d806d1 100644 --- a/apps/ssi-abstraction/src/config/agent.config.ts +++ b/apps/ssi-abstraction/src/config/agent.config.ts @@ -6,10 +6,11 @@ export const agentConfig = registerAs('agent', () => ({ walletId: process.env.AGENT_WALLET_ID || '', walletKey: process.env.AGENT_WALLET_KEY || '', ledgerIds: process.env.AGENT_LEDGER_ID?.split(',') || [], + indyDidSeed: process.env.AGENT_INDY_DID_SEED || '', + indyDid: process.env.AGENT_INDY_DID || '', host: process.env.AGENT_HOST || '', inboundPort: Number(process.env.AGENT_INBOUND_PORT || '3001'), path: process.env.AGENT_URL_PATH || '', - indyDidSeed: process.env.AGENT_INDY_DID_SEED || '', autoAcceptConnection: process.env.AGENT_AUTO_ACCEPT_CONNECTION === 'true', autoAcceptCredential: (process.env.AGENT_AUTO_ACCEPT_CREDENTIAL as AutoAcceptCredential) || diff --git a/apps/ssi-abstraction/src/config/ledger.ts b/apps/ssi-abstraction/src/config/ledger.ts index c23776d3cb54e5659c73d384262ea4874003a6bb..400a2c68916e15eee49433dd6666f3def39d2b0a 100644 --- a/apps/ssi-abstraction/src/config/ledger.ts +++ b/apps/ssi-abstraction/src/config/ledger.ts @@ -1,6 +1,5 @@ export const LEDGERS = { ID_UNION: { - registerNymUrl: 'https://idu.cloudcompass.ca/register', namespace: 'idunion:test', genesisTransaction: `{"reqSignature":{},"txn":{"data":{"data":{"alias":"MainIncubator","blskey":"14MPfxHnRvCL5dnbpD3SjxekAGnKyjkmifDFLnMJAvHcvEAarDLWX6KawhubPujSmmUMqRmQfPQzBambrdUqBGgHDryDS6Aj8BioWRwZkyTcH1zzkVQ7vZjE5S6ri5epkiS1VkVX42Z22z4cohdHVuKTgeQB5mjAwi55xNeRxpxhrNb","blskey_pop":"QoqRe3vMPr5Bt1qHDstYewWkxb5VEdugnvumLCWpkZAeUpdqjjaSTSKKJtT7U7aCe8CmShGSdCZFWs9hcpmMSGfMnmon7R99UTJj4jEr48smyxo1UpBcgooznc8N8USkZ8hSec3bRbN9y6NppuaFzfgt1WmJ3cdFi9L1Wbj1fNs5CK","client_ip":"35.207.81.15","client_port":"9702","node_ip":"35.207.81.15","node_port":"9701","services":["VALIDATOR"]},"dest":"EQ2oCtWpMdUCzKgQ2hvbyQ2i6VyJuQF9LcpHRfiah6rW"},"metadata":{"from":"2MZYuPv2Km7Q1eD4GCsSb6"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"0a35c047f19448f12a0c2961d8e3085140b8149d87291acbdaf56ed956900d48"},"ver":"1"} {"reqSignature":{},"txn":{"data":{"data":{"alias":"tubzecm","blskey":"3Zpdx6LMWPdybnQKPq62S3TaWUhwypr7RV2BBFkeFigjKuue7KJ7rh5w1gZY9qgugww9vZnpURLSjBuTonJpfyfN5nn2ofwFQQa3viiT77hhFf6kQqoMH53f66ZfBNWU2LzphQikXsma9zjZWALMtMsNWx7ftNZ8yzMrZpf1X6VqYX5","blskey_pop":"RbPQSMsV8iuxNXVFNEUPvb6k1wQe1rxaXroMMkpHTstiiJfCApER38jW79Ew1yrnt5ndz7wJeDRU7CkLNzJ6pEZaRYjLzhZL2shRgyaGqnMqkxvD1ewxNMSz7cSgBSChwUgLBxsms5iDyshwAM5dx8B1GayMyATcFxAdgCRiDv3EHm","client_ip":"141.23.35.186","client_port":"9702","node_ip":"141.23.35.186","node_port":"9701","services":["VALIDATOR"]},"dest":"Ddqm5GATTcEb5hrgMBbVL8w6R6mtTHjUpdpyCeWg3pVS"},"metadata":{"from":"JhyMn8Nn3xy2zsXjPaPu3B"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"e2f9efff1bfef015098ae299a665154fa39a898a5071d0af03c7f2311fe8577f"},"ver":"1"} diff --git a/apps/ssi-abstraction/src/config/validation.ts b/apps/ssi-abstraction/src/config/validation.ts index 3eac1f0b59668b9c589594aa71a74658670b05da..31887bb5c658cd4ab64ffee8276d7fa92bd0b6a3 100644 --- a/apps/ssi-abstraction/src/config/validation.ts +++ b/apps/ssi-abstraction/src/config/validation.ts @@ -22,10 +22,11 @@ export const validationSchema = Joi.object({ AGENT_HOST: Joi.string().required(), AGENT_INBOUND_PORT: Joi.string(), AGENT_URL_PATH: Joi.string(), - AGENT_INDY_DID_SEED: Joi.string().optional(), AGENT_AUTO_ACCEPT_CONNECTION: Joi.boolean().default(true), AGENT_AUTO_ACCEPT_CREDENTIAL: Joi.string().default( AutoAcceptCredential.ContentApproved, ), - AGENT_ID_UNION_KEY: Joi.string(), + AGENT_LEDGER_ID: Joi.string().required(), + AGENT_INDY_DID_SEED: Joi.string().required(), + AGENT_INDY_DID: Joi.string().optional(), }); diff --git a/apps/ssi-abstraction/test/revocation.e2e-spec.ts b/apps/ssi-abstraction/test/revocation.e2e-spec.ts index 7365ff69d8dd4a88e052511419c02588feb2b304..d34767ebe345aefac892d3f9d77a1ec974e60261 100644 --- a/apps/ssi-abstraction/test/revocation.e2e-spec.ts +++ b/apps/ssi-abstraction/test/revocation.e2e-spec.ts @@ -29,7 +29,6 @@ import { import { randomBytes } from 'crypto'; import { firstValueFrom } from 'rxjs'; -import { natsConfig } from '../dist/config/nats.config.js'; import { AgentModule } from '../src/agent/agent.module.js'; import { AnonCredsCredentialsModule } from '../src/agent/anoncredsCredentials/anoncredsCredentials.module.js'; import { ConnectionsModule } from '../src/agent/connections/connections.module.js'; @@ -43,8 +42,9 @@ import { SchemasService } from '../src/agent/schemas/schemas.service.js'; import { TenantsModule } from '../src/agent/tenants/tenants.module.js'; import { TenantsService } from '../src/agent/tenants/tenants.service.js'; import { mockConfigModule } from '../src/config/__tests__/mockConfig.js'; +import { natsConfig } from '../src/config/nats.config.js'; -describe.skip('Revocation', () => { +describe('Revocation', () => { const TOKEN = 'REVOCATION_CLIENT_SERVICE'; let app: INestApplication; let client: ClientProxy; diff --git a/docker-compose.yml b/docker-compose.yml index 1c27b6e8dfd64ce172478e666f5bfda5bb8af08c..fd389b84fb6c80cc920c044795e7dae6b0ff62d4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,10 +79,11 @@ services: AGENT_WALLET_KEY: ssi-wallet-key AGENT_HOST: http://ssi-abstraction AGENT_INBOUND_PORT: 3001 - AGENT_INDY_DID_SEED: 000000000000000_OCM_E2E_ENDORSER + AGENT_LEDGER_ID: ID_UNION + AGENT_INDY_DID_SEED: 00000000000_OCM_E1_Test_Endorser + AGENT_INDY_DID: RVKyFidnaqJPznu8bgodDb AGENT_AUTO_ACCEPT_CONNECTION: true AGENT_AUTO_ACCEPT_CREDENTIAL: contentApproved - AGENT_LEDGER_ID: BCOVRIN_TEST TAILS_SERVER_BASE_URL: http://s3:9000 TAILS_SERVER_BUCKET_NAME: ssi S3_ACCESS_KEY: ssi-abstraction