diff --git a/package-lock.json b/package-lock.json index cbed846..4773ea0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@blockcerts/explorer-lookup": "^1.3.0", "@trust/keyto": "^1.0.1", - "@vaultie/lds-merkle-proof-2019": "^0.0.9", + "@vaultie/lds-merkle-proof-2019": "^0.0.10", "bitcoinjs-lib": "^6.0.2", "bs58": "^4.0.1", "core-js": "^3.7.0", @@ -2041,9 +2041,9 @@ } }, "node_modules/@vaultie/lds-merkle-proof-2019": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@vaultie/lds-merkle-proof-2019/-/lds-merkle-proof-2019-0.0.9.tgz", - "integrity": "sha512-ZatItEvNBJeAF8Tb+4vrhtj+8WdY65OnteY7KaKB2SIUG8ZSyQ1lHWTyJC/zlPknIzU6fJe0MIdG3COkjAzrsg==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@vaultie/lds-merkle-proof-2019/-/lds-merkle-proof-2019-0.0.10.tgz", + "integrity": "sha512-E9Lc+FZWxHwhZITqDVcYLxe5/Dlmzxg2RtC1BnFaYq6nH5CYNZ9x3AP0RT0QPotWiU1LoOdZ0ej8XRnrqky7sA==", "dependencies": { "ajv": "^6.10.2", "cbor": "^5.0.1", @@ -14087,9 +14087,9 @@ } }, "@vaultie/lds-merkle-proof-2019": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@vaultie/lds-merkle-proof-2019/-/lds-merkle-proof-2019-0.0.9.tgz", - "integrity": "sha512-ZatItEvNBJeAF8Tb+4vrhtj+8WdY65OnteY7KaKB2SIUG8ZSyQ1lHWTyJC/zlPknIzU6fJe0MIdG3COkjAzrsg==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@vaultie/lds-merkle-proof-2019/-/lds-merkle-proof-2019-0.0.10.tgz", + "integrity": "sha512-E9Lc+FZWxHwhZITqDVcYLxe5/Dlmzxg2RtC1BnFaYq6nH5CYNZ9x3AP0RT0QPotWiU1LoOdZ0ej8XRnrqky7sA==", "requires": { "ajv": "^6.10.2", "cbor": "^5.0.1", diff --git a/package.json b/package.json index 7fb6704..00838eb 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "dependencies": { "@blockcerts/explorer-lookup": "^1.3.0", "@trust/keyto": "^1.0.1", - "@vaultie/lds-merkle-proof-2019": "^0.0.9", + "@vaultie/lds-merkle-proof-2019": "^0.0.10", "bitcoinjs-lib": "^6.0.2", "bs58": "^4.0.1", "core-js": "^3.7.0", diff --git a/src/index.ts b/src/index.ts index 6405009..52f5814 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import { lookForTx, ExplorerAPI, TransactionData } from '@blockcerts/explorer-lo import { DecodedProof, VCProof } from './models/Proof'; import getTransactionId from './helpers/getTransactionId'; import getChain from './helpers/getChain'; +import { removeEntry } from './utils/array'; import { isTransactionIdValid, computeLocalHash, @@ -44,6 +45,7 @@ export interface MerkleProof2019VerificationResult { export interface MerkleProof2019VerifyProofAPI { documentLoader?: (url: string) => any; // jsonld document loader hook verifyIdentity?: boolean; // allow splitting verification process for more control + isMocknet?: boolean; // limit amount of checks for mocknet specificity } export class LDMerkleProof2019 extends LinkedDataProof { @@ -115,13 +117,17 @@ export class LDMerkleProof2019 extends LinkedDataProof { this.proofValue = base58Decoder.decode(); } - async verifyProof ({ documentLoader, verifyIdentity }: MerkleProof2019VerifyProofAPI = { + async verifyProof ({ documentLoader, verifyIdentity, isMocknet }: MerkleProof2019VerifyProofAPI = { documentLoader: (url): any => {}, - verifyIdentity: true + verifyIdentity: true, + isMocknet: false }): Promise { this.documentLoader = documentLoader; let verified: boolean; let error: string = ''; + if (isMocknet) { + this.adaptProofVerificationProcessToMocknet(); + } try { await this.verifyProcess(this.proofVerificationProcess); if (verifyIdentity) { @@ -180,6 +186,12 @@ export class LDMerkleProof2019 extends LinkedDataProof { this.chain = getChain(this.proofValue); } + private adaptProofVerificationProcessToMocknet (): void { + removeEntry(this.proofVerificationProcess, 'getTransactionId'); + removeEntry(this.proofVerificationProcess, 'fetchRemoteHash'); + removeEntry(this.proofVerificationProcess, 'checkMerkleRoot'); + } + private setOptions (options: MerkleProof2019Options): void { this.explorerAPIs = options.explorerAPIs ?? []; if (options.executeStepMethod && typeof options.executeStepMethod === 'function') { diff --git a/src/utils/array.ts b/src/utils/array.ts new file mode 100644 index 0000000..f52b6d6 --- /dev/null +++ b/src/utils/array.ts @@ -0,0 +1,7 @@ +export function removeEntry (map: any[], key: any): void { + const stepIndex = map.findIndex(entry => entry === key); + if (stepIndex > -1) { + // delete by reference + map.splice(stepIndex, 1); + } +} diff --git a/tests/fixtures/mocknet-v3.ts b/tests/fixtures/mocknet-v3.ts new file mode 100644 index 0000000..59fd5bc --- /dev/null +++ b/tests/fixtures/mocknet-v3.ts @@ -0,0 +1,40 @@ +export default { + '@context': ['https://www.w3.org/2018/credentials/v1', 'https://w3id.org/blockcerts/v3.1'], + id: 'urn:uuid:e3351aa6-61e2-4d13-bd96-e848aa0c75cd', + type: ['VerifiableCredential', 'BlockcertsCredential'], + issuer: 'https://issuer.dev.hylandcredentials.com/93d02af5-8683-452a-a79c-959deae72495/issuer_profile.json', + issuanceDate: '2022-11-03T17:08:34Z', + credentialSubject: { + type: 'email', + name: 'Piotr Nalewajka', + publicKey: 'piotr.nalewajka@gmail.com', + id: 'urn:uuid:7d3d512e-ba58-4d7c-886e-acb5f4ee20d9', + email: 'piotr.nalewajka@gmail.com' + }, + metadata: '{}', + display: { + contentMediaType: 'text/html', + content: '
This is a me, Piotr Nalewajka
Miskatonic University, Department of Ancient History
' + }, + proof: [{ + type: 'EcdsaSecp256k1Signature2019', + created: '2022-11-03T17:12:32Z', + verificationMethod: 'https://issuer.dev.hylandcredentials.com/93d02af5-8683-452a-a79c-959deae72495/issuer_profile.json#ckKpEaMGujwETK7Zpp8Rw6w9gTjmSbR5pZomLdxStq6j', + proofPurpose: 'assertionMethod', + jws: 'eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..d3Eh5cX2WyoW8dYR8eiD7iCnAKdqAntLgA_sdrC3Op9wCdw7toC3USbf5YdEDJnFXivnWX05cSJxE0atzLYItw' + }, { + type: 'ChainedProof2021', + verificationMethod: 'https://issuer.dev.hylandcredentials.com/61e6c3fc-5779-4a6d-b05f-fdd10fdac5f0/issuer_profile.json#mocknet-public-key', + chainedProofType: 'MerkleProof2019', + created: '2022-11-15T13:57:49.216Z', + proofPurpose: 'assertionMethod', + proofValue: 'z52dKXiCeigz15WBp2vdftTWVgPqc33rrZDc7iVhzfhYh4y5irhV8AVPpGyP9BGZGCx7GDQKVBk8Lqj69tZKMHVGAmLtQ8qHkRBkxZsy8w4qBXgirTtNt56QWAJ7yzMmCDmtyWrbjvhZWd1fZn6SAtLbd5xn858tC3hvxLsrbnPhvtpCK1jiSCLfX2pBrqpLLNuKaP6PUVnEN2AkXwqv2gvkp35c', + previousProof: { + type: 'EcdsaSecp256k1Signature2019', + created: '2022-11-03T17:12:32Z', + verificationMethod: 'https://issuer.dev.hylandcredentials.com/93d02af5-8683-452a-a79c-959deae72495/issuer_profile.json#ckKpEaMGujwETK7Zpp8Rw6w9gTjmSbR5pZomLdxStq6j', + proofPurpose: 'assertionMethod', + jws: 'eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..d3Eh5cX2WyoW8dYR8eiD7iCnAKdqAntLgA_sdrC3Op9wCdw7toC3USbf5YdEDJnFXivnWX05cSJxE0atzLYItw' + } + }] +}; diff --git a/tests/verification/mocknet-v3.test.ts b/tests/verification/mocknet-v3.test.ts new file mode 100644 index 0000000..0ec217f --- /dev/null +++ b/tests/verification/mocknet-v3.test.ts @@ -0,0 +1,19 @@ +import fixture from '../fixtures/mocknet-v3'; +import { LDMerkleProof2019 } from '../../src'; + +describe('Given the test chain is Mocknet', function () { + describe('when the certificate is valid', function () { + it('should verify successfully', async function () { + const instance = new LDMerkleProof2019({ + document: fixture, + proof: fixture.proof[1] // merkle proof + }); + const result = await instance.verifyProof({ isMocknet: true }); + expect(result).toEqual({ + verified: true, + verificationMethod: null, + error: '' + }); + }); + }); +});