@twin.org/immutable-proof-service 0.0.1-next.3 → 0.0.1-next.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,6 @@ var standardsW3cDid = require('@twin.org/standards-w3c-did');
6
6
  var web = require('@twin.org/web');
7
7
  var crypto = require('@twin.org/crypto');
8
8
  var dataJsonLd = require('@twin.org/data-json-ld');
9
- var dataSchemaOrg = require('@twin.org/data-schema-org');
10
9
  var entity = require('@twin.org/entity');
11
10
  var entityStorageModels = require('@twin.org/entity-storage-models');
12
11
  var identityModels = require('@twin.org/identity-models');
@@ -362,7 +361,6 @@ class ImmutableProofService {
362
361
  this._config = options?.config ?? {};
363
362
  this._assertionMethodId = this._config.assertionMethodId ?? "immutable-proof";
364
363
  this._proofConfigKeyId = this._config.proofConfigKeyId ?? "immutable-proof";
365
- dataSchemaOrg.SchemaOrgDataTypes.registerRedirects();
366
364
  this._processing = false;
367
365
  }
368
366
  /**
@@ -393,7 +391,7 @@ class ImmutableProofService {
393
391
  proofObjectHash: core.Converter.bytesToBase64(hash)
394
392
  };
395
393
  await this._proofStorage.set(proofEntity);
396
- this.startProcessingProofs();
394
+ this.startProcessingProofs(0);
397
395
  return new core.Urn(ImmutableProofService.NAMESPACE, id).toString();
398
396
  }
399
397
  catch (error) {
@@ -507,13 +505,9 @@ class ImmutableProofService {
507
505
  * @returns The model.
508
506
  * @internal
509
507
  */
510
- proofEntityToModel(proofEntity) {
508
+ proofEntityToJsonLd(proofEntity) {
511
509
  const model = {
512
- "@context": [
513
- immutableProofModels.ImmutableProofTypes.ContextRoot,
514
- dataSchemaOrg.SchemaOrgTypes.ContextRoot,
515
- standardsW3cDid.DidContexts.ContextVCDataIntegrity
516
- ],
510
+ "@context": immutableProofModels.ImmutableProofTypes.ContextRoot,
517
511
  type: immutableProofModels.ImmutableProofTypes.ImmutableProof,
518
512
  id: proofEntity.id,
519
513
  userIdentity: proofEntity.userIdentity,
@@ -524,14 +518,16 @@ class ImmutableProofService {
524
518
  }
525
519
  /**
526
520
  * Start processing proofs.
521
+ * @param interval The interval to process proofs.
527
522
  * @returns Nothing.
528
523
  * @internal
529
524
  */
530
- startProcessingProofs() {
525
+ startProcessingProofs(interval) {
531
526
  if (!this._processing) {
527
+ this._processing = true;
532
528
  setTimeout(async () => {
533
529
  await this.processProofs();
534
- }, 0);
530
+ }, interval);
535
531
  }
536
532
  }
537
533
  /**
@@ -539,32 +535,48 @@ class ImmutableProofService {
539
535
  * @internal
540
536
  */
541
537
  async processProofs() {
542
- // Get the oldest pending proof, plus one more, we can then determine whether to
543
- // trigger another process after this one
544
- const pendingProofs = await this._proofStorage.query({
545
- property: "immutableStorageId",
546
- comparison: entity.ComparisonOperator.Equals,
547
- value: undefined
548
- }, [
549
- {
550
- property: "dateCreated",
551
- sortDirection: entity.SortDirection.Ascending
538
+ let remainingProofs = 0;
539
+ try {
540
+ // Get the oldest pending proof, plus one more, we can then determine whether to
541
+ // trigger another process after this one
542
+ const pendingProofs = await this._proofStorage.query({
543
+ property: "immutableStorageId",
544
+ comparison: entity.ComparisonOperator.Equals,
545
+ value: undefined
546
+ }, [
547
+ {
548
+ property: "dateCreated",
549
+ sortDirection: entity.SortDirection.Ascending
550
+ }
551
+ ], undefined, undefined, 2);
552
+ remainingProofs = pendingProofs.entities.length;
553
+ if (remainingProofs > 0) {
554
+ const proofEntity = pendingProofs.entities[0];
555
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
556
+ const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
557
+ // As we are adding the proof to the data we update its context
558
+ immutableProof["@context"] = [
559
+ immutableProofModels.ImmutableProofTypes.ContextRoot,
560
+ immutableStorageModels.ImmutableStorageTypes.ContextRoot,
561
+ standardsW3cDid.DidContexts.ContextVCDataIntegrity
562
+ ];
563
+ immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
564
+ if (core.Is.stringValue(immutableProof.proof.created)) {
565
+ proofEntity.dateCreated = immutableProof.proof.created;
566
+ }
567
+ const compacted = await dataJsonLd.JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
568
+ const immutableStoreResult = await this._immutableStorage.store(proofEntity.nodeIdentity, core.ObjectHelper.toBytes(compacted));
569
+ proofEntity.immutableStorageId = immutableStoreResult.id;
570
+ await this._proofStorage.set(proofEntity);
571
+ remainingProofs--;
552
572
  }
553
- ], undefined, undefined, 2);
554
- if (pendingProofs.entities.length > 0) {
555
- const proofEntity = pendingProofs.entities[0];
556
- const immutableProof = this.proofEntityToModel(proofEntity);
557
- const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
558
- immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
559
- proofEntity.dateCreated = immutableProof.proof.created ?? new Date(Date.now()).toISOString();
560
- const compacted = await dataJsonLd.JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
561
- proofEntity.immutableStorageId = await this._immutableStorage.store(proofEntity.nodeIdentity, core.ObjectHelper.toBytes(compacted));
562
- await this._proofStorage.set(proofEntity);
563
573
  }
564
- // If there are still remaining proofs, start the timer again
565
- this._processing = false;
566
- if (pendingProofs.entities.length > 1) {
567
- this.startProcessingProofs();
574
+ finally {
575
+ // If there are still remaining proofs, start the timer again
576
+ this._processing = false;
577
+ if (remainingProofs > 0) {
578
+ this.startProcessingProofs(100);
579
+ }
568
580
  }
569
581
  }
570
582
  /**
@@ -582,14 +594,15 @@ class ImmutableProofService {
582
594
  if (core.Is.empty(proofEntity)) {
583
595
  throw new core.NotFoundError(this.CLASS_NAME, "proofNotFound", id);
584
596
  }
585
- let proofModel = await this.proofEntityToModel(proofEntity);
597
+ let proofModel = await this.proofEntityToJsonLd(proofEntity);
586
598
  let verified = false;
587
599
  let failure = immutableProofModels.ImmutableProofFailure.NotIssued;
588
600
  if (core.Is.stringValue(proofEntity.immutableStorageId)) {
589
601
  failure = immutableProofModels.ImmutableProofFailure.ProofMissing;
590
- const immutableData = await this._immutableStorage.get(proofEntity.immutableStorageId);
591
- if (core.Is.uint8Array(immutableData)) {
592
- proofModel = core.ObjectHelper.fromBytes(immutableData);
602
+ const immutableResult = await this._immutableStorage.get(proofEntity.immutableStorageId);
603
+ if (core.Is.uint8Array(immutableResult.data)) {
604
+ proofModel = core.ObjectHelper.fromBytes(immutableResult.data);
605
+ proofModel.immutableReceipt = immutableResult.receipt;
593
606
  if (core.Is.object(proofModel.proof) && core.Is.object(proofObject)) {
594
607
  if (proofModel.proof.cryptosuite !== standardsW3cDid.DidCryptoSuites.EdDSAJcs2022) {
595
608
  failure = immutableProofModels.ImmutableProofFailure.CryptoSuiteMismatch;
@@ -626,7 +639,11 @@ class ImmutableProofService {
626
639
  * @internal
627
640
  */
628
641
  async generateHashData(nodeIdentity, immutableProof) {
629
- const canonicalDocument = core.JsonHelper.canonicalize(core.ObjectHelper.omit(immutableProof, ["proof"]));
642
+ // We hash the data for the proof with the proof or immutable receipt for the proof
643
+ // without these objects we can simplify the context
644
+ const object = core.ObjectHelper.omit(immutableProof, ["proof", "immutableReceipt"]);
645
+ object["@context"] = immutableProofModels.ImmutableProofTypes.ContextRoot;
646
+ const canonicalDocument = core.JsonHelper.canonicalize(object);
630
647
  const proofConfigKey = await this._vaultConnector.getKey(`${nodeIdentity}/${this._proofConfigKeyId}`);
631
648
  const proofConfigHash = crypto.Sha256.sum256(proofConfigKey.privateKey);
632
649
  const transformedDocumentHash = crypto.Sha256.sum256(core.Converter.utf8ToBytes(canonicalDocument));
@@ -4,11 +4,10 @@ import { DidContexts, DidTypes, DidCryptoSuites } from '@twin.org/standards-w3c-
4
4
  import { HttpStatusCode, HeaderTypes, MimeTypes } from '@twin.org/web';
5
5
  import { Blake2b, Sha256 } from '@twin.org/crypto';
6
6
  import { JsonLdHelper, JsonLdProcessor } from '@twin.org/data-json-ld';
7
- import { SchemaOrgDataTypes, SchemaOrgTypes } from '@twin.org/data-schema-org';
8
7
  import { ComparisonOperator, SortDirection, property, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
9
8
  import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
10
9
  import { IdentityConnectorFactory } from '@twin.org/identity-models';
11
- import { ImmutableStorageConnectorFactory } from '@twin.org/immutable-storage-models';
10
+ import { ImmutableStorageConnectorFactory, ImmutableStorageTypes } from '@twin.org/immutable-storage-models';
12
11
  import { VaultConnectorFactory } from '@twin.org/vault-models';
13
12
 
14
13
  /**
@@ -360,7 +359,6 @@ class ImmutableProofService {
360
359
  this._config = options?.config ?? {};
361
360
  this._assertionMethodId = this._config.assertionMethodId ?? "immutable-proof";
362
361
  this._proofConfigKeyId = this._config.proofConfigKeyId ?? "immutable-proof";
363
- SchemaOrgDataTypes.registerRedirects();
364
362
  this._processing = false;
365
363
  }
366
364
  /**
@@ -391,7 +389,7 @@ class ImmutableProofService {
391
389
  proofObjectHash: Converter.bytesToBase64(hash)
392
390
  };
393
391
  await this._proofStorage.set(proofEntity);
394
- this.startProcessingProofs();
392
+ this.startProcessingProofs(0);
395
393
  return new Urn(ImmutableProofService.NAMESPACE, id).toString();
396
394
  }
397
395
  catch (error) {
@@ -505,13 +503,9 @@ class ImmutableProofService {
505
503
  * @returns The model.
506
504
  * @internal
507
505
  */
508
- proofEntityToModel(proofEntity) {
506
+ proofEntityToJsonLd(proofEntity) {
509
507
  const model = {
510
- "@context": [
511
- ImmutableProofTypes.ContextRoot,
512
- SchemaOrgTypes.ContextRoot,
513
- DidContexts.ContextVCDataIntegrity
514
- ],
508
+ "@context": ImmutableProofTypes.ContextRoot,
515
509
  type: ImmutableProofTypes.ImmutableProof,
516
510
  id: proofEntity.id,
517
511
  userIdentity: proofEntity.userIdentity,
@@ -522,14 +516,16 @@ class ImmutableProofService {
522
516
  }
523
517
  /**
524
518
  * Start processing proofs.
519
+ * @param interval The interval to process proofs.
525
520
  * @returns Nothing.
526
521
  * @internal
527
522
  */
528
- startProcessingProofs() {
523
+ startProcessingProofs(interval) {
529
524
  if (!this._processing) {
525
+ this._processing = true;
530
526
  setTimeout(async () => {
531
527
  await this.processProofs();
532
- }, 0);
528
+ }, interval);
533
529
  }
534
530
  }
535
531
  /**
@@ -537,32 +533,48 @@ class ImmutableProofService {
537
533
  * @internal
538
534
  */
539
535
  async processProofs() {
540
- // Get the oldest pending proof, plus one more, we can then determine whether to
541
- // trigger another process after this one
542
- const pendingProofs = await this._proofStorage.query({
543
- property: "immutableStorageId",
544
- comparison: ComparisonOperator.Equals,
545
- value: undefined
546
- }, [
547
- {
548
- property: "dateCreated",
549
- sortDirection: SortDirection.Ascending
536
+ let remainingProofs = 0;
537
+ try {
538
+ // Get the oldest pending proof, plus one more, we can then determine whether to
539
+ // trigger another process after this one
540
+ const pendingProofs = await this._proofStorage.query({
541
+ property: "immutableStorageId",
542
+ comparison: ComparisonOperator.Equals,
543
+ value: undefined
544
+ }, [
545
+ {
546
+ property: "dateCreated",
547
+ sortDirection: SortDirection.Ascending
548
+ }
549
+ ], undefined, undefined, 2);
550
+ remainingProofs = pendingProofs.entities.length;
551
+ if (remainingProofs > 0) {
552
+ const proofEntity = pendingProofs.entities[0];
553
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
554
+ const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
555
+ // As we are adding the proof to the data we update its context
556
+ immutableProof["@context"] = [
557
+ ImmutableProofTypes.ContextRoot,
558
+ ImmutableStorageTypes.ContextRoot,
559
+ DidContexts.ContextVCDataIntegrity
560
+ ];
561
+ immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
562
+ if (Is.stringValue(immutableProof.proof.created)) {
563
+ proofEntity.dateCreated = immutableProof.proof.created;
564
+ }
565
+ const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
566
+ const immutableStoreResult = await this._immutableStorage.store(proofEntity.nodeIdentity, ObjectHelper.toBytes(compacted));
567
+ proofEntity.immutableStorageId = immutableStoreResult.id;
568
+ await this._proofStorage.set(proofEntity);
569
+ remainingProofs--;
550
570
  }
551
- ], undefined, undefined, 2);
552
- if (pendingProofs.entities.length > 0) {
553
- const proofEntity = pendingProofs.entities[0];
554
- const immutableProof = this.proofEntityToModel(proofEntity);
555
- const hashData = await this.generateHashData(proofEntity.nodeIdentity, immutableProof);
556
- immutableProof.proof = await this._identityConnector.createProof(proofEntity.nodeIdentity, `${proofEntity.nodeIdentity}#${this._assertionMethodId}`, hashData);
557
- proofEntity.dateCreated = immutableProof.proof.created ?? new Date(Date.now()).toISOString();
558
- const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
559
- proofEntity.immutableStorageId = await this._immutableStorage.store(proofEntity.nodeIdentity, ObjectHelper.toBytes(compacted));
560
- await this._proofStorage.set(proofEntity);
561
571
  }
562
- // If there are still remaining proofs, start the timer again
563
- this._processing = false;
564
- if (pendingProofs.entities.length > 1) {
565
- this.startProcessingProofs();
572
+ finally {
573
+ // If there are still remaining proofs, start the timer again
574
+ this._processing = false;
575
+ if (remainingProofs > 0) {
576
+ this.startProcessingProofs(100);
577
+ }
566
578
  }
567
579
  }
568
580
  /**
@@ -580,14 +592,15 @@ class ImmutableProofService {
580
592
  if (Is.empty(proofEntity)) {
581
593
  throw new NotFoundError(this.CLASS_NAME, "proofNotFound", id);
582
594
  }
583
- let proofModel = await this.proofEntityToModel(proofEntity);
595
+ let proofModel = await this.proofEntityToJsonLd(proofEntity);
584
596
  let verified = false;
585
597
  let failure = ImmutableProofFailure.NotIssued;
586
598
  if (Is.stringValue(proofEntity.immutableStorageId)) {
587
599
  failure = ImmutableProofFailure.ProofMissing;
588
- const immutableData = await this._immutableStorage.get(proofEntity.immutableStorageId);
589
- if (Is.uint8Array(immutableData)) {
590
- proofModel = ObjectHelper.fromBytes(immutableData);
600
+ const immutableResult = await this._immutableStorage.get(proofEntity.immutableStorageId);
601
+ if (Is.uint8Array(immutableResult.data)) {
602
+ proofModel = ObjectHelper.fromBytes(immutableResult.data);
603
+ proofModel.immutableReceipt = immutableResult.receipt;
591
604
  if (Is.object(proofModel.proof) && Is.object(proofObject)) {
592
605
  if (proofModel.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {
593
606
  failure = ImmutableProofFailure.CryptoSuiteMismatch;
@@ -624,7 +637,11 @@ class ImmutableProofService {
624
637
  * @internal
625
638
  */
626
639
  async generateHashData(nodeIdentity, immutableProof) {
627
- const canonicalDocument = JsonHelper.canonicalize(ObjectHelper.omit(immutableProof, ["proof"]));
640
+ // We hash the data for the proof with the proof or immutable receipt for the proof
641
+ // without these objects we can simplify the context
642
+ const object = ObjectHelper.omit(immutableProof, ["proof", "immutableReceipt"]);
643
+ object["@context"] = ImmutableProofTypes.ContextRoot;
644
+ const canonicalDocument = JsonHelper.canonicalize(object);
628
645
  const proofConfigKey = await this._vaultConnector.getKey(`${nodeIdentity}/${this._proofConfigKeyId}`);
629
646
  const proofConfigHash = Sha256.sum256(proofConfigKey.privateKey);
630
647
  const transformedDocumentHash = Sha256.sum256(Converter.utf8ToBytes(canonicalDocument));
@@ -1,5 +1,5 @@
1
1
  import { type IJsonLdNodeObject } from "@twin.org/data-json-ld";
2
- import { type IImmutableProofVerification, type IImmutableProof, type IImmutableProofComponent } from "@twin.org/immutable-proof-models";
2
+ import { type IImmutableProof, type IImmutableProofComponent, type IImmutableProofVerification } from "@twin.org/immutable-proof-models";
3
3
  import type { IImmutableProofServiceConfig } from "./models/IImmutableProofServiceConfig";
4
4
  /**
5
5
  * Class for performing immutable proof operations.
package/docs/changelog.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # @twin.org/immutable-proof-service - Changelog
2
2
 
3
- ## v0.0.1-next.3
3
+ ## v0.0.1-next.5
4
4
 
5
5
  - Initial Release
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/immutable-proof-service",
3
- "version": "0.0.1-next.3",
3
+ "version": "0.0.1-next.5",
4
4
  "description": "Immutable proof contract implementation and REST endpoint definitions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,7 +22,7 @@
22
22
  "@twin.org/entity": "next",
23
23
  "@twin.org/entity-storage-models": "next",
24
24
  "@twin.org/identity-models": "next",
25
- "@twin.org/immutable-proof-models": "0.0.1-next.3",
25
+ "@twin.org/immutable-proof-models": "0.0.1-next.5",
26
26
  "@twin.org/immutable-storage-models": "next",
27
27
  "@twin.org/nameof": "next",
28
28
  "@twin.org/standards-w3c-did": "next",