Skip to content

Commit

Permalink
Merge branch 'main' into fix/credentials-preview-attribute-name
Browse files Browse the repository at this point in the history
  • Loading branch information
TimoGlastra authored Jun 15, 2022
2 parents 34b3aed + ba03fa0 commit 6199e2b
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 7 deletions.
6 changes: 6 additions & 0 deletions packages/core/src/modules/ledger/IndyPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ import { isIndyError } from '../../utils/indyError'
import { LedgerError } from './error/LedgerError'
import { isLedgerRejectResponse, isLedgerReqnackResponse } from './ledgerUtil'

export interface TransactionAuthorAgreement {
version: `${number}.${number}` | `${number}`
acceptanceMechanism: string
}

export interface IndyPoolConfig {
genesisPath?: string
genesisTransactions?: string
id: string
isProduction: boolean
transactionAuthorAgreement?: TransactionAuthorAgreement
}

export class IndyPool {
Expand Down
145 changes: 145 additions & 0 deletions packages/core/src/modules/ledger/__tests__/IndyLedgerService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import type { IndyPoolConfig } from '../IndyPool'
import type { LedgerReadReplyResponse, LedgerWriteReplyResponse } from 'indy-sdk'

import { getAgentConfig, mockFunction } from '../../../../tests/helpers'
import { CacheRepository } from '../../../cache/CacheRepository'
import { IndyWallet } from '../../../wallet/IndyWallet'
import { IndyIssuerService } from '../../indy/services/IndyIssuerService'
import { IndyPool } from '../IndyPool'
import { IndyLedgerService } from '../services/IndyLedgerService'
import { IndyPoolService } from '../services/IndyPoolService'

jest.mock('../services/IndyPoolService')
const IndyPoolServiceMock = IndyPoolService as jest.Mock<IndyPoolService>
jest.mock('../../indy/services/IndyIssuerService')
const IndyIssuerServiceMock = IndyIssuerService as jest.Mock<IndyIssuerService>
jest.mock('../../../cache/CacheRepository')
const CacheRepositoryMock = CacheRepository as jest.Mock<CacheRepository>

const pools: IndyPoolConfig[] = [
{
id: 'sovrinMain',
isProduction: true,
genesisTransactions: 'xxx',
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
]

describe('IndyLedgerService', () => {
const config = getAgentConfig('IndyLedgerServiceTest', {
indyLedgers: pools,
})
let wallet: IndyWallet
let poolService: IndyPoolService
let cacheRepository: CacheRepository
let indyIssuerService: IndyIssuerService
let ledgerService: IndyLedgerService

beforeAll(async () => {
wallet = new IndyWallet(config)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await wallet.createAndOpen(config.walletConfig!)
})

afterAll(async () => {
await wallet.delete()
})

beforeEach(async () => {
cacheRepository = new CacheRepositoryMock()
mockFunction(cacheRepository.findById).mockResolvedValue(null)
indyIssuerService = new IndyIssuerServiceMock()
poolService = new IndyPoolServiceMock()
const pool = new IndyPool(config, pools[0])
jest.spyOn(pool, 'submitWriteRequest').mockResolvedValue({} as LedgerWriteReplyResponse)
jest.spyOn(pool, 'submitReadRequest').mockResolvedValue({} as LedgerReadReplyResponse)
jest.spyOn(pool, 'connect').mockResolvedValue(0)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
poolService.ledgerWritePool = pool

ledgerService = new IndyLedgerService(wallet, config, indyIssuerService, poolService)
})

describe('LedgerServiceWrite', () => {
it('should throw an error if the config version does not match', async () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
jest.spyOn(ledgerService, 'getTransactionAuthorAgreement').mockResolvedValue({
digest: 'abcde',
version: 'abdcg',
text: 'jhsdhbv',
ratification_ts: 12345678,
acceptanceMechanisms: {
aml: { accept: 'accept' },
amlContext: 'accept',
version: '3',
},
} as never)
await expect(
ledgerService.registerPublicDid(
'BBPoJqRKatdcfLEAFL7exC',
'N8NQHLtCKfPmWMgCSdfa7h',
'GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf',
'Heinz57'
)
).rejects.toThrowError(
'Unable to satisfy matching TAA with mechanism "accept" and version "1" in pool.\n Found ["accept"] and version 3 in pool.'
)
})

it('should throw an error if the config acceptance mechanism does not match', async () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
jest.spyOn(ledgerService, 'getTransactionAuthorAgreement').mockResolvedValue({
digest: 'abcde',
version: 'abdcg',
text: 'jhsdhbv',
ratification_ts: 12345678,
acceptanceMechanisms: {
aml: { decline: 'accept' },
amlContext: 'accept',
version: '1',
},
} as never)
await expect(
ledgerService.registerPublicDid(
'BBPoJqRKatdcfLEAFL7exC',
'N8NQHLtCKfPmWMgCSdfa7h',
'GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf',
'Heinz57'
)
).rejects.toThrowError(
'Unable to satisfy matching TAA with mechanism "accept" and version "1" in pool.\n Found ["decline"] and version 1 in pool.'
)
})

it('should throw an error if no config is present', async () => {
poolService.ledgerWritePool.authorAgreement = undefined
poolService.ledgerWritePool.config.transactionAuthorAgreement = undefined

ledgerService = new IndyLedgerService(wallet, config, indyIssuerService, poolService)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
jest.spyOn(ledgerService, 'getTransactionAuthorAgreement').mockResolvedValue({
digest: 'abcde',
version: 'abdcg',
text: 'jhsdhbv',
ratification_ts: 12345678,
acceptanceMechanisms: {
aml: { accept: 'accept' },
amlContext: 'accept',
version: '3',
},
} as never)
await expect(
ledgerService.registerPublicDid(
'BBPoJqRKatdcfLEAFL7exC',
'N8NQHLtCKfPmWMgCSdfa7h',
'GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf',
'Heinz57'
)
).rejects.toThrowError(/Please, specify a transaction author agreement with version and acceptance mechanism/)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,31 @@ const pools: IndyPoolConfig[] = [
id: 'sovrinMain',
isProduction: true,
genesisTransactions: 'xxx',
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
{
id: 'sovrinBuilder',
isProduction: false,
genesisTransactions: 'xxx',
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
{
id: 'sovrinStaging',
isProduction: false,
genesisTransactions: 'xxx',
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
{
id: 'indicioMain',
isProduction: true,
genesisTransactions: 'xxx',
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
{
id: 'bcovrinTest',
isProduction: false,
genesisTransactions: 'xxx',
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
]

Expand Down
33 changes: 26 additions & 7 deletions packages/core/src/modules/ledger/services/IndyLedgerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { isIndyError } from '../../../utils/indyError'
import { IndyWallet } from '../../../wallet/IndyWallet'
import { IndyIssuerService } from '../../indy/services/IndyIssuerService'
import { LedgerError } from '../error/LedgerError'

import { IndyPoolService } from './IndyPoolService'

Expand Down Expand Up @@ -454,18 +455,41 @@ export class IndyLedgerService {
private async appendTaa(pool: IndyPool, request: Indy.LedgerRequest) {
try {
const authorAgreement = await this.getTransactionAuthorAgreement(pool)
const taa = pool.config.transactionAuthorAgreement

// If ledger does not have TAA, we can just send request
if (authorAgreement == null) {
return request
}
// Ledger has taa but user has not specified which one to use
if (!taa) {
throw new LedgerError(
`Please, specify a transaction author agreement with version and acceptance mechanism. ${JSON.stringify(
authorAgreement
)}`
)
}

// Throw an error if the pool doesn't have the specified version and acceptance mechanism
if (
authorAgreement.acceptanceMechanisms.version !== taa.version ||
!(taa.acceptanceMechanism in authorAgreement.acceptanceMechanisms.aml)
) {
// Throw an error with a helpful message
const errMessage = `Unable to satisfy matching TAA with mechanism ${JSON.stringify(
taa.acceptanceMechanism
)} and version ${JSON.stringify(taa.version)} in pool.\n Found ${JSON.stringify(
Object.keys(authorAgreement.acceptanceMechanisms.aml)
)} and version ${authorAgreement.acceptanceMechanisms.version} in pool.`
throw new LedgerError(errMessage)
}

const requestWithTaa = await this.indy.appendTxnAuthorAgreementAcceptanceToRequest(
request,
authorAgreement.text,
authorAgreement.version,
taa.version,
authorAgreement.digest,
this.getFirstAcceptanceMechanism(authorAgreement),
taa.acceptanceMechanism,
// Current time since epoch
// We can't use ratification_ts, as it must be greater than 1499906902
Math.floor(new Date().getTime() / 1000)
Expand Down Expand Up @@ -507,11 +531,6 @@ export class IndyLedgerService {
throw isIndyError(error) ? new IndySdkError(error) : error
}
}

private getFirstAcceptanceMechanism(authorAgreement: AuthorAgreement) {
const [firstMechanism] = Object.keys(authorAgreement.acceptanceMechanisms.aml)
return firstMechanism
}
}

export interface SchemaTemplate {
Expand Down
1 change: 1 addition & 0 deletions packages/core/tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function getBaseConfig(name: string, extraConfig: Partial<InitConfig> = {
id: `pool-${name}`,
isProduction: false,
genesisPath,
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
},
],
// TODO: determine the log level based on an environment variable. This will make it
Expand Down

0 comments on commit 6199e2b

Please sign in to comment.