@0xpolygonid/js-sdk 1.6.1 → 1.7.0

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.
Files changed (33) hide show
  1. package/README.md +3 -1
  2. package/dist/browser/esm/index.js +738 -491
  3. package/dist/browser/esm/index.js.map +1 -1
  4. package/dist/browser/umd/index.js +784 -531
  5. package/dist/browser/umd/index.js.map +1 -1
  6. package/dist/node/cjs/circuits/comparer.js +3 -3
  7. package/dist/node/cjs/credentials/credential-wallet.js +19 -2
  8. package/dist/node/cjs/credentials/index.js +1 -0
  9. package/dist/node/cjs/credentials/rhs.js +28 -15
  10. package/dist/node/cjs/credentials/status/credential-status-publisher.js +84 -0
  11. package/dist/node/cjs/credentials/utils.js +14 -1
  12. package/dist/node/cjs/identity/identity-wallet.js +57 -26
  13. package/dist/node/cjs/storage/blockchain/abi/CredentialStatusResolver.json +1 -1
  14. package/dist/node/cjs/storage/blockchain/index.js +1 -0
  15. package/dist/node/cjs/storage/blockchain/onchain-revocation.js +45 -5
  16. package/dist/node/esm/circuits/comparer.js +3 -3
  17. package/dist/node/esm/credentials/credential-wallet.js +20 -3
  18. package/dist/node/esm/credentials/index.js +1 -0
  19. package/dist/node/esm/credentials/rhs.js +26 -14
  20. package/dist/node/esm/credentials/status/credential-status-publisher.js +78 -0
  21. package/dist/node/esm/credentials/utils.js +12 -0
  22. package/dist/node/esm/identity/identity-wallet.js +52 -21
  23. package/dist/node/esm/storage/blockchain/abi/CredentialStatusResolver.json +1 -1
  24. package/dist/node/esm/storage/blockchain/index.js +1 -0
  25. package/dist/node/esm/storage/blockchain/onchain-revocation.js +45 -5
  26. package/dist/types/credentials/index.d.ts +1 -0
  27. package/dist/types/credentials/rhs.d.ts +11 -0
  28. package/dist/types/credentials/status/credential-status-publisher.d.ts +70 -0
  29. package/dist/types/credentials/utils.d.ts +2 -0
  30. package/dist/types/identity/identity-wallet.d.ts +42 -13
  31. package/dist/types/storage/blockchain/index.d.ts +1 -0
  32. package/dist/types/storage/blockchain/onchain-revocation.d.ts +7 -3
  33. package/package.json +1 -1
@@ -53,12 +53,12 @@ exports.QueryOperators = {
53
53
  };
54
54
  const allOperations = Object.values(exports.QueryOperators);
55
55
  exports.availableTypesOperators = new Map([
56
- [XSDNS.Boolean, [exports.QueryOperators.$eq, exports.QueryOperators.$ne]],
56
+ [XSDNS.Boolean, [exports.QueryOperators.$eq, exports.QueryOperators.$ne, exports.QueryOperators.$sd]],
57
57
  [XSDNS.Integer, allOperations],
58
58
  [XSDNS.NonNegativeInteger, allOperations],
59
59
  [XSDNS.PositiveInteger, allOperations],
60
- [XSDNS.Double, [exports.QueryOperators.$eq, exports.QueryOperators.$ne, exports.QueryOperators.$in, exports.QueryOperators.$nin]],
61
- [XSDNS.String, [exports.QueryOperators.$eq, exports.QueryOperators.$ne, exports.QueryOperators.$in, exports.QueryOperators.$nin]],
60
+ [XSDNS.Double, [exports.QueryOperators.$eq, exports.QueryOperators.$ne, exports.QueryOperators.$in, exports.QueryOperators.$nin, exports.QueryOperators.$sd]],
61
+ [XSDNS.String, [exports.QueryOperators.$eq, exports.QueryOperators.$ne, exports.QueryOperators.$in, exports.QueryOperators.$nin, exports.QueryOperators.$sd]],
62
62
  [XSDNS.DateTime, allOperations]
63
63
  ]);
64
64
  /**
@@ -83,7 +83,7 @@ class CredentialWallet {
83
83
  id: request.credentialSchema,
84
84
  type: verifiable_1.VerifiableConstants.JSON_SCHEMA_VALIDATOR
85
85
  };
86
- cr.credentialStatus = this.buildCredentialStatus(request);
86
+ cr.credentialStatus = this.buildCredentialStatus(request, issuer);
87
87
  return cr;
88
88
  };
89
89
  // if no credential status resolvers are provided
@@ -149,7 +149,7 @@ class CredentialWallet {
149
149
  * @param {CredentialRequest} request
150
150
  * @returns `CredentialStatus`
151
151
  */
152
- buildCredentialStatus(request) {
152
+ buildCredentialStatus(request, issuer) {
153
153
  const credentialStatus = {
154
154
  id: request.revocationOpts.id,
155
155
  type: request.revocationOpts.type,
@@ -168,6 +168,23 @@ class CredentialWallet {
168
168
  ? `${credentialStatus.id.replace(/\/$/, '')}/node?state=${request.revocationOpts.issuerState}`
169
169
  : `${credentialStatus.id.replace(/\/$/, '')}`
170
170
  };
171
+ case verifiable_1.CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023: {
172
+ const issuerId = js_iden3_core_1.DID.idFromDID(issuer);
173
+ const chainId = (0, js_iden3_core_1.getChainId)(js_iden3_core_1.DID.blockchainFromId(issuerId), js_iden3_core_1.DID.networkIdFromId(issuerId));
174
+ const searchParams = [
175
+ ['revocationNonce', request.revocationOpts.nonce?.toString() || ''],
176
+ ['contractAddress', `${chainId}:${request.revocationOpts.id}`],
177
+ ['state', request.revocationOpts.issuerState || '']
178
+ ]
179
+ .filter(([, value]) => Boolean(value))
180
+ .map(([key, value]) => `${key}=${value}`)
181
+ .join('&');
182
+ return {
183
+ ...credentialStatus,
184
+ // `[did]:[methodid]:[chain]:[network]:[id]/credentialStatus?(revocationNonce=value)&[contractAddress=[chainID]:[contractAddress]]&(state=issuerState)`
185
+ id: `${issuer.string()}/credentialStatus?${searchParams}`
186
+ };
187
+ }
171
188
  default:
172
189
  return credentialStatus;
173
190
  }
@@ -19,6 +19,7 @@ __exportStar(require("./status/reverse-sparse-merkle-tree"), exports);
19
19
  __exportStar(require("./status/sparse-merkle-tree"), exports);
20
20
  __exportStar(require("./status/resolver"), exports);
21
21
  __exportStar(require("./status/agent-revocation"), exports);
22
+ __exportStar(require("./status/credential-status-publisher"), exports);
22
23
  __exportStar(require("./status/utils"), exports);
23
24
  __exportStar(require("./credential-wallet"), exports);
24
25
  __exportStar(require("./rhs"), exports);
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pushHashesToRHS = void 0;
3
+ exports.getNodesRepresentation = exports.pushHashesToRHS = void 0;
4
4
  const js_merkletree_1 = require("@iden3/js-merkletree");
5
5
  const js_merkletree_2 = require("@iden3/js-merkletree");
6
6
  const js_merkletree_3 = require("@iden3/js-merkletree");
7
7
  const reverse_sparse_merkle_tree_1 = require("./status/reverse-sparse-merkle-tree");
8
+ const credential_status_publisher_1 = require("./status/credential-status-publisher");
9
+ const verifiable_1 = require("../verifiable");
8
10
  /**
9
11
  * Pushes identity state information to a reverse hash service.
10
12
  *
11
13
  * A reverse hash service (RHS) is a centralized or decentralized service for storing publicly available data about identity.
12
14
  * Such data are identity state and state of revocation tree and roots tree root tree.
13
15
  *
16
+ * @deprecated Use `pushHashesToReverseHashService` instead.
14
17
  * @param {Hash} state - current state of identity
15
18
  * @param {TreesModel} trees - current trees of identity (claims, revocation, rootOfRoots )
16
19
  * @param {string} rhsUrl - URL of service
@@ -18,6 +21,24 @@ const reverse_sparse_merkle_tree_1 = require("./status/reverse-sparse-merkle-tre
18
21
  * @returns void
19
22
  */
20
23
  async function pushHashesToRHS(state, trees, rhsUrl, revokedNonces) {
24
+ const nodes = await getNodesRepresentation(revokedNonces, trees, state);
25
+ const publisher = new credential_status_publisher_1.Iden3SmtRhsCredentialStatusPublisher();
26
+ await publisher.publish({
27
+ nodes,
28
+ credentialStatusType: verifiable_1.CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
29
+ rhsUrl: rhsUrl
30
+ });
31
+ }
32
+ exports.pushHashesToRHS = pushHashesToRHS;
33
+ /**
34
+ * Retrieves the representation of nodes for generating a proof.
35
+ *
36
+ * @param revokedNonces - An array of revoked nonces.
37
+ * @param trees - The TreesModel object containing the necessary trees.
38
+ * @param state - The hash of the state.
39
+ * @returns A Promise that resolves to an array of ProofNode objects.
40
+ */
41
+ async function getNodesRepresentation(revokedNonces, trees, state) {
21
42
  const nb = new NodesBuilder();
22
43
  if (revokedNonces) {
23
44
  await addRevocationNode(nb, trees, revokedNonces);
@@ -31,17 +52,9 @@ async function pushHashesToRHS(state, trees, rhsUrl, revokedNonces) {
31
52
  await trees.rootsTree.root()
32
53
  ]));
33
54
  }
34
- if (nb.nodes.length > 0) {
35
- await saveNodes(nb.nodes, rhsUrl);
36
- }
37
- }
38
- exports.pushHashesToRHS = pushHashesToRHS;
39
- async function saveNodes(nodes, nodeUrl) {
40
- const nodesJSON = nodes.map((n) => n.toJSON());
41
- const resp = await fetch(nodeUrl + '/node', { method: 'post', body: JSON.stringify(nodesJSON) });
42
- const status = resp.status;
43
- return status === 200;
55
+ return nb.nodes;
44
56
  }
57
+ exports.getNodesRepresentation = getNodesRepresentation;
45
58
  async function addRoRNode(nb, trees) {
46
59
  const currentRootsTree = trees.rootsTree;
47
60
  const claimsTree = trees.claimsTree;
@@ -66,8 +79,8 @@ class NodesBuilder {
66
79
  }
67
80
  async addKey(tree, nodeKey) {
68
81
  const { value: nodeValue, siblings } = await tree.get(nodeKey);
69
- const nodeKeyHash = (0, js_merkletree_1.newHashFromBigInt)(nodeKey);
70
- const nodeValueHash = (0, js_merkletree_1.newHashFromBigInt)(nodeValue);
82
+ const nodeKeyHash = js_merkletree_1.Hash.fromBigInt(nodeKey);
83
+ const nodeValueHash = js_merkletree_1.Hash.fromBigInt(nodeValue);
71
84
  const node = new js_merkletree_1.NodeLeaf(nodeKeyHash, nodeValueHash);
72
85
  const newNodes = await buildNodesUp(siblings, node);
73
86
  for (const n of newNodes) {
@@ -97,7 +110,7 @@ async function buildNodesUp(siblings, node) {
97
110
  nodes[index] = new reverse_sparse_merkle_tree_1.ProofNode();
98
111
  }
99
112
  nodes[sl].hash = prevHash;
100
- const hashOfOne = (0, js_merkletree_1.newHashFromBigInt)(BigInt(1));
113
+ const hashOfOne = js_merkletree_1.Hash.fromBigInt(BigInt(1));
101
114
  nodes[sl].children = [node.entry[0], node.entry[1], hashOfOne];
102
115
  const pathKey = node.entry[0];
103
116
  for (let i = sl - 1; i >= 0; i--) {
@@ -111,7 +124,7 @@ async function buildNodesUp(siblings, node) {
111
124
  nodes[i].children[0] = prevHash;
112
125
  nodes[i].children[1] = siblings[i];
113
126
  }
114
- nodes[i].hash = await (0, js_merkletree_3.hashElems)([nodes[i].children[0].bigInt(), nodes[i].children[1].bigInt()]);
127
+ nodes[i].hash = (0, js_merkletree_3.hashElems)([nodes[i].children[0].bigInt(), nodes[i].children[1].bigInt()]);
115
128
  prevHash = nodes[i].hash;
116
129
  }
117
130
  return nodes;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Iden3SmtRhsCredentialStatusPublisher = exports.Iden3OnchainSmtCredentialStatusPublisher = exports.CredentialStatusPublisherRegistry = void 0;
4
+ const verifiable_1 = require("../../verifiable");
5
+ /**
6
+ * Registry for managing credential status publishers.
7
+ */
8
+ class CredentialStatusPublisherRegistry {
9
+ constructor() {
10
+ this._publishers = new Map();
11
+ }
12
+ /**
13
+ * Registers one or more credential status publishers for a given type.
14
+ * @param type - The credential status type.
15
+ * @param publisher - One or more credential status publishers.
16
+ */
17
+ register(type, ...publisher) {
18
+ const publishers = this._publishers.get(type) ?? [];
19
+ publishers.push(...publisher);
20
+ this._publishers.set(type, publishers);
21
+ }
22
+ /**
23
+ * Retrieves the credential status publishers for a given type.
24
+ * @param type - The credential status type.
25
+ * @returns An array of credential status publishers or undefined if none are registered for the given type.
26
+ */
27
+ get(type) {
28
+ return this._publishers.get(type);
29
+ }
30
+ }
31
+ exports.CredentialStatusPublisherRegistry = CredentialStatusPublisherRegistry;
32
+ /**
33
+ * Implementation of the ICredentialStatusPublisher interface for publishing on-chain credential status.
34
+ */
35
+ class Iden3OnchainSmtCredentialStatusPublisher {
36
+ constructor(_storage) {
37
+ this._storage = _storage;
38
+ }
39
+ /**
40
+ * Publishes the credential status to the blockchain.
41
+ * @param params - The parameters for publishing the credential status.
42
+ */
43
+ async publish(params) {
44
+ if (![verifiable_1.CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023].includes(params.credentialStatusType)) {
45
+ throw new Error(`On-chain publishing is not supported for credential status type ${params.credentialStatusType}`);
46
+ }
47
+ const nodesBigInts = params.nodes.map((n) => n.children.map((c) => c.bigInt()));
48
+ const txPromise = this._storage.saveNodes(nodesBigInts);
49
+ if (params.onChain?.txCallback) {
50
+ const cb = params.onChain?.txCallback;
51
+ txPromise.then((receipt) => cb(receipt));
52
+ return;
53
+ }
54
+ await txPromise;
55
+ }
56
+ }
57
+ exports.Iden3OnchainSmtCredentialStatusPublisher = Iden3OnchainSmtCredentialStatusPublisher;
58
+ /**
59
+ * Implementation of the ICredentialStatusPublisher interface for publishing off-chain credential status.
60
+ */
61
+ class Iden3SmtRhsCredentialStatusPublisher {
62
+ /**
63
+ * Publishes the credential status to a specified node URL.
64
+ * @param params - The parameters for publishing the credential status.
65
+ * @param params.nodes - The proof nodes to be published.
66
+ * @param params.rhsUrl - The URL of the node to publish the credential status to.
67
+ * @returns A promise that resolves when the credential status is successfully published.
68
+ * @throws An error if the publishing fails.
69
+ */
70
+ async publish(params) {
71
+ if (![verifiable_1.CredentialStatusType.Iden3ReverseSparseMerkleTreeProof].includes(params.credentialStatusType)) {
72
+ throw new Error(`On-chain publishing is not supported for credential status type ${params.credentialStatusType}`);
73
+ }
74
+ const nodesJSON = params.nodes.map((n) => n.toJSON());
75
+ const resp = await fetch(params.rhsUrl + '/node', {
76
+ method: 'post',
77
+ body: JSON.stringify(nodesJSON)
78
+ });
79
+ if (resp.status !== 200) {
80
+ throw new Error(`Failed to publish credential status. Status: ${resp.status}`);
81
+ }
82
+ }
83
+ }
84
+ exports.Iden3SmtRhsCredentialStatusPublisher = Iden3SmtRhsCredentialStatusPublisher;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUserDIDFromCredential = void 0;
3
+ exports.getKMSIdByAuthCredential = exports.getUserDIDFromCredential = void 0;
4
4
  const js_iden3_core_1 = require("@iden3/js-iden3-core");
5
+ const js_crypto_1 = require("@iden3/js-crypto");
6
+ const kms_1 = require("../kms");
5
7
  /**
6
8
  * Retrieves the user DID from a given credential.
7
9
  * If the credential does not have a credentialSubject.id property, the issuer DID is returned.
@@ -21,3 +23,14 @@ const getUserDIDFromCredential = (issuerDID, credential) => {
21
23
  return js_iden3_core_1.DID.parse(credential.credentialSubject.id);
22
24
  };
23
25
  exports.getUserDIDFromCredential = getUserDIDFromCredential;
26
+ const getKMSIdByAuthCredential = (credential) => {
27
+ if (!credential.type.includes('AuthBJJCredential')) {
28
+ throw new Error("can't sign with not AuthBJJCredential credential");
29
+ }
30
+ const x = credential.credentialSubject['x'];
31
+ const y = credential.credentialSubject['y'];
32
+ const pb = new js_crypto_1.PublicKey([BigInt(x), BigInt(y)]);
33
+ const kp = (0, kms_1.keyPath)(kms_1.KmsKeyType.BabyJubJub, pb.hex());
34
+ return { type: kms_1.KmsKeyType.BabyJubJub, id: kp };
35
+ };
36
+ exports.getKMSIdByAuthCredential = getKMSIdByAuthCredential;
@@ -31,11 +31,11 @@ const js_merkletree_1 = require("@iden3/js-merkletree");
31
31
  const common_1 = require("./common");
32
32
  const uuid = __importStar(require("uuid"));
33
33
  const schema_processor_1 = require("../schema-processor");
34
- const mt_1 = require("../storage/entities/mt");
35
- const provider_helpers_1 = require("../kms/provider-helpers");
34
+ const storage_1 = require("../storage");
36
35
  const verifiable_1 = require("../verifiable");
37
36
  const credentials_1 = require("../credentials");
38
37
  const utils_1 = require("../utils");
38
+ const credential_status_publisher_1 = require("../credentials/status/credential-status-publisher");
39
39
  /**
40
40
  * @public
41
41
  * Wallet instance to manage the digital identity based on iden3 protocol
@@ -56,10 +56,19 @@ class IdentityWallet {
56
56
  * @param {ICredentialWallet} _credentialWallet - credential wallet instance to quickly access credential CRUD functionality
57
57
  * @public
58
58
  */
59
- constructor(_kms, _storage, _credentialWallet) {
59
+ constructor(_kms, _storage, _credentialWallet, _opts) {
60
60
  this._kms = _kms;
61
61
  this._storage = _storage;
62
62
  this._credentialWallet = _credentialWallet;
63
+ this._opts = _opts;
64
+ if (!_opts?.credentialStatusPublisherRegistry) {
65
+ this._credentialStatusPublisherRegistry = new credential_status_publisher_1.CredentialStatusPublisherRegistry();
66
+ this._credentialStatusPublisherRegistry.register(verifiable_1.CredentialStatusType.Iden3ReverseSparseMerkleTreeProof, new credential_status_publisher_1.Iden3SmtRhsCredentialStatusPublisher());
67
+ }
68
+ else {
69
+ this._credentialStatusPublisherRegistry = this._opts
70
+ ?.credentialStatusPublisherRegistry;
71
+ }
63
72
  }
64
73
  /**
65
74
  * {@inheritDoc IIdentityWallet.createIdentity}
@@ -78,8 +87,8 @@ class IdentityWallet {
78
87
  const authClaim = js_iden3_core_1.Claim.newClaim(schemaHash, js_iden3_core_1.ClaimOptions.withIndexDataInts(pubKey.p[0], pubKey.p[1]), js_iden3_core_1.ClaimOptions.withRevocationNonce(BigInt(0)));
79
88
  const revNonce = opts.revocationOpts.nonce ?? 0;
80
89
  authClaim.setRevocationNonce(BigInt(revNonce));
81
- await this._storage.mt.addToMerkleTree(tmpIdentifier, mt_1.MerkleTreeType.Claims, authClaim.hiHv().hi, authClaim.hiHv().hv);
82
- const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(tmpIdentifier, mt_1.MerkleTreeType.Claims);
90
+ await this._storage.mt.addToMerkleTree(tmpIdentifier, storage_1.MerkleTreeType.Claims, authClaim.hiHv().hi, authClaim.hiHv().hv);
91
+ const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(tmpIdentifier, storage_1.MerkleTreeType.Claims);
83
92
  const currentState = (0, js_merkletree_1.hashElems)([
84
93
  (await claimsTree.root()).bigInt(),
85
94
  js_merkletree_1.ZERO_HASH.bigInt(),
@@ -133,9 +142,10 @@ class IdentityWallet {
133
142
  coreClaim: authClaim
134
143
  });
135
144
  credential.proof = [mtpProof];
136
- if (opts.revocationOpts.type === verifiable_1.CredentialStatusType.Iden3ReverseSparseMerkleTreeProof) {
137
- await this.publishStateToRHS(did, opts.revocationOpts.id);
138
- }
145
+ await this.publishRevocationInfoByCredentialStatusType(did, opts.revocationOpts.type, {
146
+ rhsUrl: opts.revocationOpts.id,
147
+ onChain: opts.revocationOpts.onChain
148
+ });
139
149
  await this._storage.identity.saveIdentity({
140
150
  did: did.string(),
141
151
  state: currentState,
@@ -197,10 +207,11 @@ class IdentityWallet {
197
207
  }
198
208
  /** {@inheritDoc IIdentityWallet.getDIDTreeModel} */
199
209
  async getDIDTreeModel(did) {
200
- const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), mt_1.MerkleTreeType.Claims);
201
- const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), mt_1.MerkleTreeType.Revocations);
202
- const rootsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), mt_1.MerkleTreeType.Roots);
203
- const state = await (0, js_merkletree_1.hashElems)([
210
+ const didStr = did.string();
211
+ const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(didStr, storage_1.MerkleTreeType.Claims);
212
+ const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(didStr, storage_1.MerkleTreeType.Revocations);
213
+ const rootsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(didStr, storage_1.MerkleTreeType.Roots);
214
+ const state = (0, js_merkletree_1.hashElems)([
204
215
  (await claimsTree.root()).bigInt(),
205
216
  (await revocationTree.root()).bigInt(),
206
217
  (await rootsTree.root()).bigInt()
@@ -217,7 +228,7 @@ class IdentityWallet {
217
228
  const coreClaim = await this.getCoreClaimFromCredential(credential);
218
229
  // todo: Parser.parseClaim
219
230
  const treesModel = await this.getDIDTreeModel(did);
220
- const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), mt_1.MerkleTreeType.Claims);
231
+ const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), storage_1.MerkleTreeType.Claims);
221
232
  const claimsRoot = await treesModel.claimsTree.root();
222
233
  const rootOfRoots = await treesModel.rootsTree.root();
223
234
  const revocationRoot = await treesModel.revocationTree.root();
@@ -237,7 +248,7 @@ class IdentityWallet {
237
248
  const coreClaim = await this.getCoreClaimFromCredential(credential);
238
249
  const revNonce = coreClaim.getRevocationNonce();
239
250
  const treesModel = await this.getDIDTreeModel(did);
240
- const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), mt_1.MerkleTreeType.Revocations);
251
+ const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), storage_1.MerkleTreeType.Revocations);
241
252
  const claimsRoot = await treesModel.claimsTree.root();
242
253
  const rootOfRoots = await treesModel.rootsTree.root();
243
254
  const revocationRoot = await treesModel.revocationTree.root();
@@ -254,14 +265,14 @@ class IdentityWallet {
254
265
  }
255
266
  /** {@inheritDoc IIdentityWallet.sign} */
256
267
  async sign(message, credential) {
257
- const keyKMSId = this.getKMSIdByAuthCredential(credential);
268
+ const keyKMSId = (0, credentials_1.getKMSIdByAuthCredential)(credential);
258
269
  const payload = js_crypto_1.poseidon.hashBytes(message);
259
270
  const signature = await this._kms.sign(keyKMSId, js_iden3_core_1.BytesHelper.intToBytes(payload));
260
271
  return js_crypto_1.Signature.newFromCompressed(signature);
261
272
  }
262
273
  /** {@inheritDoc IIdentityWallet.signChallenge} */
263
274
  async signChallenge(challenge, credential) {
264
- const keyKMSId = this.getKMSIdByAuthCredential(credential);
275
+ const keyKMSId = (0, credentials_1.getKMSIdByAuthCredential)(credential);
265
276
  const signature = await this._kms.sign(keyKMSId, js_iden3_core_1.BytesHelper.intToBytes(challenge));
266
277
  return js_crypto_1.Signature.newFromCompressed(signature);
267
278
  }
@@ -358,11 +369,11 @@ class IdentityWallet {
358
369
  if (!coreClaim) {
359
370
  throw new Error('credential must have coreClaim representation in the signature proof');
360
371
  }
361
- await this._storage.mt.addToMerkleTree(issuerDID.string(), mt_1.MerkleTreeType.Claims, coreClaim.hIndex(), coreClaim.hValue());
372
+ await this._storage.mt.addToMerkleTree(issuerDID.string(), storage_1.MerkleTreeType.Claims, coreClaim.hIndex(), coreClaim.hValue());
362
373
  }
363
374
  const newIssuerTreeState = await this.getDIDTreeModel(issuerDID);
364
375
  const claimTreeRoot = await newIssuerTreeState.claimsTree.root();
365
- await this._storage.mt.addToMerkleTree(issuerDID.string(), mt_1.MerkleTreeType.Roots, claimTreeRoot.bigInt(), BigInt(0));
376
+ await this._storage.mt.addToMerkleTree(issuerDID.string(), storage_1.MerkleTreeType.Roots, claimTreeRoot.bigInt(), BigInt(0));
366
377
  const newIssuerTreeStateWithROR = await this.getDIDTreeModel(issuerDID);
367
378
  claimsRoot = await newIssuerTreeStateWithROR.claimsTree.root();
368
379
  rootOfRoots = await newIssuerTreeStateWithROR.rootsTree.root();
@@ -429,15 +440,35 @@ class IdentityWallet {
429
440
  rootsTree: treeState.rootsTree
430
441
  }, rhsURL, revokedNonces);
431
442
  }
432
- getKMSIdByAuthCredential(credential) {
433
- if (credential.type.indexOf('AuthBJJCredential') === -1) {
434
- throw new Error("can't sign with not AuthBJJCredential credential");
443
+ /** {@inheritDoc IIdentityWallet.publishRevocationInfoByCredentialStatusType} */
444
+ async publishRevocationInfoByCredentialStatusType(issuerDID, credentialStatusType, opts) {
445
+ const rhsPublishers = this._credentialStatusPublisherRegistry.get(credentialStatusType);
446
+ if (!rhsPublishers) {
447
+ throw new Error(`there is no registered publisher to save hash is not registered for ${credentialStatusType} is not registered`);
448
+ }
449
+ let nodes = [];
450
+ if (opts?.treeModel) {
451
+ nodes = await (0, credentials_1.getNodesRepresentation)(opts.revokedNonces, {
452
+ revocationTree: opts.treeModel.revocationTree,
453
+ claimsTree: opts.treeModel.claimsTree,
454
+ state: opts.treeModel.state,
455
+ rootsTree: opts.treeModel.rootsTree
456
+ }, opts.treeModel.state);
457
+ }
458
+ else {
459
+ const treeState = await this.getDIDTreeModel(issuerDID);
460
+ nodes = await (0, credentials_1.getNodesRepresentation)(opts?.revokedNonces, {
461
+ revocationTree: treeState.revocationTree,
462
+ claimsTree: treeState.claimsTree,
463
+ state: treeState.state,
464
+ rootsTree: treeState.rootsTree
465
+ }, treeState.state);
466
+ }
467
+ if (!nodes.length) {
468
+ return;
435
469
  }
436
- const x = credential.credentialSubject['x'];
437
- const y = credential.credentialSubject['y'];
438
- const pb = new js_crypto_1.PublicKey([BigInt(x), BigInt(y)]);
439
- const kp = (0, provider_helpers_1.keyPath)(kms_1.KmsKeyType.BabyJubJub, pb.hex());
440
- return { type: kms_1.KmsKeyType.BabyJubJub, id: kp };
470
+ const rhsPublishersTask = rhsPublishers.map((publisher) => publisher.publish({ nodes, ...opts, credentialStatusType, issuerDID }));
471
+ await Promise.all(rhsPublishersTask);
441
472
  }
442
473
  async getCoreClaimFromCredential(credential) {
443
474
  const coreClaimFromSigProof = credential.getCoreClaimFromProof(verifiable_1.ProofType.BJJSignature);
@@ -1 +1 @@
1
- [{ "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatus", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "structIOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatusByIdAndState", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "structIOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }]
1
+ [{ "inputs": [], "name": "MAX_SMT_DEPTH", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "key", "type": "uint256" }], "name": "getNode", "outputs": [{ "internalType": "uint256[]", "name": "", "type": "uint256[]" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatus", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "struct IOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatusByIdAndState", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "struct IOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256[][]", "name": "nodes", "type": "uint256[][]" }], "name": "saveNodes", "outputs": [], "stateMutability": "nonpayable", "type": "function" }]
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./state"), exports);
18
18
  __exportStar(require("./onchain-zkp-verifier"), exports);
19
+ __exportStar(require("./onchain-revocation"), exports);
@@ -22,9 +22,16 @@ class OnChainRevocationStorage {
22
22
  * @param {string} - onhcain contract address
23
23
  * @param {string} - rpc url to connect to the blockchain
24
24
  */
25
- constructor(config, contractAddress) {
26
- this.provider = new ethers_1.JsonRpcProvider(config.url);
27
- this.onchainContract = new ethers_1.Contract(contractAddress, CredentialStatusResolver_json_1.default, this.provider);
25
+ constructor(_config, contractAddress, _signer) {
26
+ this._config = _config;
27
+ this._signer = _signer;
28
+ this._provider = new ethers_1.JsonRpcProvider(_config.url);
29
+ let contract = new ethers_1.Contract(contractAddress, CredentialStatusResolver_json_1.default, this._provider);
30
+ if (this._signer) {
31
+ this._signer = this._signer.connect(this._provider);
32
+ contract = contract.connect(this._signer);
33
+ }
34
+ this._contract = contract;
28
35
  }
29
36
  /**
30
37
  * Get revocation status by issuerId, issuerState and nonce from the onchain.
@@ -32,7 +39,7 @@ class OnChainRevocationStorage {
32
39
  * @returns Promise<RevocationStatus>
33
40
  */
34
41
  async getRevocationStatusByIdAndState(issuerID, state, nonce) {
35
- const response = await this.onchainContract.getRevocationStatusByIdAndState(issuerID, state, nonce);
42
+ const response = await this._contract.getRevocationStatusByIdAndState(issuerID, state, nonce);
36
43
  const issuer = OnChainRevocationStorage.convertIssuerInfo(response.issuer);
37
44
  const mtp = OnChainRevocationStorage.convertSmtProofToProof(response.mtp);
38
45
  return {
@@ -46,7 +53,7 @@ class OnChainRevocationStorage {
46
53
  * @returns Promise<RevocationStatus>
47
54
  */
48
55
  async getRevocationStatus(issuerID, nonce) {
49
- const response = await this.onchainContract.getRevocationStatus(issuerID, nonce);
56
+ const response = await this._contract.getRevocationStatus(issuerID, nonce);
50
57
  const issuer = OnChainRevocationStorage.convertIssuerInfo(response.issuer);
51
58
  const mtp = OnChainRevocationStorage.convertSmtProofToProof(response.mtp);
52
59
  return {
@@ -54,6 +61,39 @@ class OnChainRevocationStorage {
54
61
  mtp
55
62
  };
56
63
  }
64
+ async saveNodes(payload) {
65
+ if (!this._signer) {
66
+ throw new Error('No signer provided');
67
+ }
68
+ const feeData = await this._provider.getFeeData();
69
+ const maxFeePerGas = this._config.maxFeePerGas
70
+ ? BigInt(this._config.maxFeePerGas)
71
+ : feeData.maxFeePerGas;
72
+ const maxPriorityFeePerGas = this._config.maxPriorityFeePerGas
73
+ ? BigInt(this._config.maxPriorityFeePerGas)
74
+ : feeData.maxPriorityFeePerGas;
75
+ const gasLimit = await this._contract.saveNodes.estimateGas(payload);
76
+ const txData = await this._contract.saveNodes.populateTransaction(payload);
77
+ const request = {
78
+ to: txData.to,
79
+ data: txData.data,
80
+ gasLimit,
81
+ maxFeePerGas,
82
+ maxPriorityFeePerGas
83
+ };
84
+ const tx = await this._signer.sendTransaction(request);
85
+ return tx.wait().then((txReceipt) => {
86
+ if (!txReceipt) {
87
+ throw new Error(`transaction: ${tx.hash} failed to mine`);
88
+ }
89
+ const status = txReceipt.status;
90
+ const txnHash = txReceipt.hash;
91
+ if (!status) {
92
+ throw new Error(`transaction: ${txnHash} failed to mine`);
93
+ }
94
+ return txReceipt;
95
+ });
96
+ }
57
97
  static convertIssuerInfo(issuer) {
58
98
  const [state, claimsTreeRoot, revocationTreeRoot, rootOfRoots] = issuer.map((i) => js_merkletree_1.Hash.fromBigInt(i).hex());
59
99
  return {
@@ -50,12 +50,12 @@ export const QueryOperators = {
50
50
  };
51
51
  const allOperations = Object.values(QueryOperators);
52
52
  export const availableTypesOperators = new Map([
53
- [XSDNS.Boolean, [QueryOperators.$eq, QueryOperators.$ne]],
53
+ [XSDNS.Boolean, [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$sd]],
54
54
  [XSDNS.Integer, allOperations],
55
55
  [XSDNS.NonNegativeInteger, allOperations],
56
56
  [XSDNS.PositiveInteger, allOperations],
57
- [XSDNS.Double, [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$in, QueryOperators.$nin]],
58
- [XSDNS.String, [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$in, QueryOperators.$nin]],
57
+ [XSDNS.Double, [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$in, QueryOperators.$nin, QueryOperators.$sd]],
58
+ [XSDNS.String, [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$in, QueryOperators.$nin, QueryOperators.$sd]],
59
59
  [XSDNS.DateTime, allOperations]
60
60
  ]);
61
61
  /**
@@ -1,4 +1,4 @@
1
- import { DID } from '@iden3/js-iden3-core';
1
+ import { DID, getChainId } from '@iden3/js-iden3-core';
2
2
  import { W3CCredential, VerifiableConstants, CredentialStatusType } from './../verifiable';
3
3
  import * as uuid from 'uuid';
4
4
  import { CredentialStatusResolverRegistry } from './status/resolver';
@@ -57,7 +57,7 @@ export class CredentialWallet {
57
57
  id: request.credentialSchema,
58
58
  type: VerifiableConstants.JSON_SCHEMA_VALIDATOR
59
59
  };
60
- cr.credentialStatus = this.buildCredentialStatus(request);
60
+ cr.credentialStatus = this.buildCredentialStatus(request, issuer);
61
61
  return cr;
62
62
  };
63
63
  // if no credential status resolvers are provided
@@ -123,7 +123,7 @@ export class CredentialWallet {
123
123
  * @param {CredentialRequest} request
124
124
  * @returns `CredentialStatus`
125
125
  */
126
- buildCredentialStatus(request) {
126
+ buildCredentialStatus(request, issuer) {
127
127
  const credentialStatus = {
128
128
  id: request.revocationOpts.id,
129
129
  type: request.revocationOpts.type,
@@ -142,6 +142,23 @@ export class CredentialWallet {
142
142
  ? `${credentialStatus.id.replace(/\/$/, '')}/node?state=${request.revocationOpts.issuerState}`
143
143
  : `${credentialStatus.id.replace(/\/$/, '')}`
144
144
  };
145
+ case CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023: {
146
+ const issuerId = DID.idFromDID(issuer);
147
+ const chainId = getChainId(DID.blockchainFromId(issuerId), DID.networkIdFromId(issuerId));
148
+ const searchParams = [
149
+ ['revocationNonce', request.revocationOpts.nonce?.toString() || ''],
150
+ ['contractAddress', `${chainId}:${request.revocationOpts.id}`],
151
+ ['state', request.revocationOpts.issuerState || '']
152
+ ]
153
+ .filter(([, value]) => Boolean(value))
154
+ .map(([key, value]) => `${key}=${value}`)
155
+ .join('&');
156
+ return {
157
+ ...credentialStatus,
158
+ // `[did]:[methodid]:[chain]:[network]:[id]/credentialStatus?(revocationNonce=value)&[contractAddress=[chainID]:[contractAddress]]&(state=issuerState)`
159
+ id: `${issuer.string()}/credentialStatus?${searchParams}`
160
+ };
161
+ }
145
162
  default:
146
163
  return credentialStatus;
147
164
  }
@@ -3,6 +3,7 @@ export * from './status/reverse-sparse-merkle-tree';
3
3
  export * from './status/sparse-merkle-tree';
4
4
  export * from './status/resolver';
5
5
  export * from './status/agent-revocation';
6
+ export * from './status/credential-status-publisher';
6
7
  export * from './status/utils';
7
8
  export * from './credential-wallet';
8
9
  export * from './rhs';