diff --git a/.changeset/stupid-deers-pull.md b/.changeset/stupid-deers-pull.md new file mode 100644 index 0000000..8d41100 --- /dev/null +++ b/.changeset/stupid-deers-pull.md @@ -0,0 +1,22 @@ +--- +"@zcloak/message": major +"@zcloak/verify": major +"@zcloak/vc": major +"@zcloak/login-did": major +"@zcloak/login-providers": major +"@zcloak/login-rpc": major +"@zcloak/login-rpc-defines": major +"@zcloak/login-verify": major +"@zcloak/ctype": major +"@zcloak/did": major +"@zcloak/did-resolver": major +"@zcloak/cross": major +"@zcloak/crypto": major +"@zcloak/keyring": major +"@zcloak/miden": major +"@zcloak/wasm": major +"@zcloak/wasm-asm": major +"@zcloak/wasm-bridge": major +--- + +[ upgrade to 2.0.0 ] diff --git a/.yarn/releases/yarn-4.0.0-rc.40.cjs b/.yarn/releases/yarn-4.0.0-rc.40.cjs old mode 100755 new mode 100644 diff --git a/package.json b/package.json index 4d5c7b9..2dd0292 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,9 @@ "test:one": "zcloak-dev-run-test --runInBand", "test:watch": "zcloak-dev-run-test --watch" }, + "dependencies": { + "web3": "^4.1.1" + }, "devDependencies": { "@types/jest": "^29.4.0", "@zcloak/dev": "^0.31.0", diff --git a/packages/message/src/decrypt/index.ts b/packages/message/src/decrypt/index.ts index 2fd15ba..78690cf 100644 --- a/packages/message/src/decrypt/index.ts +++ b/packages/message/src/decrypt/index.ts @@ -35,7 +35,19 @@ export function verifyMessageData(message: DecryptedMessage): void case 'Response_Approve_Attestation': assert(isVC(data), `Expected message data with msgType:${msgType} is VerifiableCredential object`); - assert(isSameUri(sender, data.issuer), 'Message sender is not the issuer of VerifiableCredential'); + + if (typeof data.issuer === 'object') { + assert( + data.issuer.some((issuer) => isSameUri(sender, issuer)), + 'Message sender is not the issuer of VerifiableCredential' + ); + } else if (typeof data.issuer === 'string') { + assert(isSameUri(sender, data.issuer), 'Message sender is not the issuer VerifiableCredential'); + } else { + const check: never = data.issuer; + + return check; + } break; @@ -73,7 +85,19 @@ export function verifyMessageData(message: DecryptedMessage): void case 'Send_issuedVC': assert(isVC(data), `Expected message data with msgType:${msgType} is VerifiableCredential object`); - assert(isSameUri(sender, data.issuer), 'Message sender is not the issuer of VerifiableCredential'); + + if (typeof data.issuer === 'object') { + assert( + data.issuer.some((issuer) => isSameUri(sender, issuer)), + 'Message sender is not the issuer of VerifiableCredential' + ); + } else if (typeof data.issuer === 'string') { + assert(isSameUri(sender, data.issuer), 'Message sender is not the issuer VerifiableCredential'); + } else { + const check: never = data.issuer; + + throw new Error(`Message sender type wrong, the wrong issuer is : ${check}`); + } break; diff --git a/packages/message/src/message.spec.ts b/packages/message/src/message.spec.ts index 62db3bd..b39b814 100644 --- a/packages/message/src/message.spec.ts +++ b/packages/message/src/message.spec.ts @@ -4,11 +4,12 @@ import type { CType } from '@zcloak/ctype/types'; import type { RawCredential } from '@zcloak/vc/types'; -import { alice, bob, testResolver } from 'test-support'; +import { alice, bob, charlie, testResolver } from 'test-support'; import { initCrypto } from '@zcloak/crypto'; import { getPublish } from '@zcloak/ctype'; import { Raw, VerifiableCredentialBuilder } from '@zcloak/vc'; +import { addProof } from '@zcloak/verify'; import { decryptMessage } from './decrypt'; import { encryptMessage } from './encrypt'; @@ -110,6 +111,55 @@ describe('message encrypt and decrypt', (): void => { }); describe('Send Extends msgType', () => { + it('Send vc to be add proof', async () => { + const vc = await VerifiableCredentialBuilder.fromRawCredential(rawCredential, ctype) + .setExpirationDate(null) + .build(alice, false); + + const message = await encryptMessage( + 'Extends_Request_Comfirmation', + vc, + alice, + bob.getKeyUrl('keyAgreement'), + undefined, + testResolver + ); + const decrypted = await decryptMessage(message, bob, testResolver); + + expect(decrypted.data).toEqual(vc); + }); + + it('Send multiAttester VC', async () => { + const vc = await VerifiableCredentialBuilder.fromRawCredential(rawCredential, ctype) + .setExpirationDate(null) + .build(alice, false); + + const message = await encryptMessage( + 'Extends_Request_Comfirmation', + vc, + alice, + bob.getKeyUrl('keyAgreement'), + undefined, + testResolver + ); + const decrypted = await decryptMessage(message, bob, testResolver); + const multiAttesterVC = await addProof(bob, decrypted.data); + + expect(multiAttesterVC.issuer).toEqual([alice.getDocument().id, bob.getDocument().id]); + + const messageSentToUser = await encryptMessage( + 'Extends_Response_Approve_Attestation message', + multiAttesterVC, + bob, + charlie.getKeyUrl('keyAgreement'), + undefined, + testResolver + ); + const decryptedMultiVC = await decryptMessage(messageSentToUser, charlie, testResolver); + + expect(decryptedMultiVC.data).toEqual(multiAttesterVC); + }); + it('Send string data', async () => { const message = await encryptMessage( 'Extends_send_string', diff --git a/packages/verify/src/vcVerify.spec.ts b/packages/verify/src/vcVerify.spec.ts index 9bd3218..690158d 100644 --- a/packages/verify/src/vcVerify.spec.ts +++ b/packages/verify/src/vcVerify.spec.ts @@ -4,10 +4,13 @@ import type { DidDocument } from '@zcloak/did-resolver/types'; import type { AnyJson, VerifiableCredential } from '@zcloak/vc/types'; -import { initCrypto } from '@zcloak/crypto'; -import { calcRoothash } from '@zcloak/vc'; +import { alice } from 'test-support'; -import { vcVerify, vcVerifyDigest } from './vcVerify'; +import { base58Decode, initCrypto } from '@zcloak/crypto'; +import { calcDigest, calcRoothash, DigestPayloadV2 } from '@zcloak/vc'; + +import { didVerify } from './didVerify'; +import { addProof, vcVerify, vcVerifyDigest } from './vcVerify'; const document1: DidDocument = { '@context': ['https://www.w3.org/ns/did/v1'], @@ -60,6 +63,32 @@ const document2: DidDocument = { capabilityDelegation: ['did:zk:0x565ee4a279Ad611010DF17082220987CcaD381fb#key-0'], service: [] }; +const document3: DidDocument = { + '@context': ['https://www.w3.org/ns/did/v1'], + version: '0', + id: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec', + controller: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec'], + verificationMethod: [ + { + id: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0', + controller: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec'], + type: 'EcdsaSecp256k1VerificationKey2019', + publicKeyMultibase: 'zupS5XUoHqKsBUHMAYqFNtUdzwNw7X3ML77Sh4CGUHNpx' + }, + { + id: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-1', + controller: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec'], + type: 'X25519KeyAgreementKey2019', + publicKeyMultibase: 'zCGHvcFKtP4pDzoTXWG7wLvT6fNRKMUUbmW8QuX8EQCVh' + } + ], + authentication: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0'], + assertionMethod: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0'], + keyAgreement: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-1'], + capabilityInvocation: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0'], + capabilityDelegation: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0'], + service: [] +}; const fullVC: VerifiableCredential = { '@context': ['https://www.w3.org/2018/credentials/v1'], @@ -103,6 +132,124 @@ const fullVC: VerifiableCredential = { ] }; +const fullVC2: VerifiableCredential = { + '@context': ['https://www.w3.org/2018/credentials/v1'], + version: '2', + ctype: '0xc08734bbd035fe0880ba6e469e40b160601a2389d0284f6255a5f0b395d2336c', + issuanceDate: 1693299183644, + credentialSubject: { name: 'zCloak', age: 19, birthday: '2022.10.31', isUser: true }, + issuer: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec'], + holder: 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1', + hasher: ['RescuePrime', 'Keccak256'], + digest: '0x115ab0958eca52ee2ef511a67079b419b8d57224f6457ded3ad117a2354e207a', + proof: [ + { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1693299183648, + verificationMethod: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0', + proofPurpose: 'assertionMethod', + proofValue: 'zJDsreYR36X2T1WggKwhRebve3PrzLpbSFmTCYz5mCV1DXbcQeDKqeE7eVxDKErAMe7GCuvpqxbpR6gdAb3F2d4hsu' + } + ], + credentialSubjectHashes: [ + '0xe2cc46a455caf6b78393d6b3a2fdf455f5542266f29fb3042a1e840cc2b86427', + '0xa0ea71dfa268c4277e455acd6a8a0b086c907f3caad43678e62ce9c0cf7bc0e8', + '0xb129e4db1e188ba554c295e5aa93ab0d0ade297e5cb4b710cee3ce1af4dc1c4a', + '0x6fe5621dc7ebaf818c6dae3afdada35a74676be85cbde5b4f9b074c76490a92d' + ], + credentialSubjectNonceMap: { + '0x88af5a7ba28c1de54ebd589dea81d30caa3f467646f6d714c0d2604599d63e1e': + '0x385e28cb8bcf5fdbd9011da8338d8a8852dabe5e441ab90676db5c4bf6957642', + '0x9ad57aefa90d9473f855c14221f330fe959a554b3d86c9d701db11c7559ce107': + '0x8f2924d768a2769bd65db828baa15a806627d808d379a16cd209de97736a6e10', + '0x2d2367a578506f669cfd4a744c08fd45315ad4ea3d248733957947cf00723662': + '0x85320040fcd44f06281535081364b4c5674ca946ae23e6a155ea0231e0cd1c39', + '0x6bc2ebdc9345c21f804ef735209993cb8e5b3755af0650c41aa164a9faf674bd': + '0x7450de9f08aca5030b3ddfd91de2416592951d4f2d3b76c7277b6d0c5debb236' + } +}; + +const fullVC3: VerifiableCredential = { + '@context': ['https://www.w3.org/2018/credentials/v1'], + version: '2', + ctype: '0xc08734bbd035fe0880ba6e469e40b160601a2389d0284f6255a5f0b395d2336c', + issuanceDate: 1693299329782, + credentialSubject: { name: 'zCloak', age: 19, birthday: '2022.10.31', isUser: true }, + issuer: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec'], + holder: 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1', + hasher: ['Keccak256', 'Keccak256'], + digest: '0x63c8827f7d7e7446772799ccfbc0ae0a57199b679a4ea3682951ccc5c418060d', + proof: [ + { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1693299329786, + verificationMethod: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0', + proofPurpose: 'assertionMethod', + proofValue: 'zJaNmsWPNQoJ1Gt58AotgQRoBvSoEibuAL6GBKvZ8fV5gbNCrXxBZkMyZFK6fUwUoFkZi2WZNNdMicwGzTPbzdH1Ep' + } + ], + credentialSubjectHashes: [ + '0x1537556bb6125c231e6e76ec1457b80bf43647fdd0de3f57c2bc3189da55617b', + '0x418070cd733fcab053b572eb37f4aea5686ec3485296eb2e517b622c9b59a112', + '0xd4be7b980fc8f5d53f99b5cfcfce5633827baff0be83f16f5290190864708f4b', + '0x4ddccf029950fee195bcd67df5a46986fea14ff00d47b5d3b9d1929c623c1f32' + ], + credentialSubjectNonceMap: { + '0x28cb5b00333a3266fa3d92f3426ad4ef1d20018b44dd64913578d43438b4051a': + '0xc9444e4d54f98aaa9076736432913113f0d6491321cc575ec751208d7f17fb7f', + '0x66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090': + '0x596e356de2ec14369f127afcba1c84441c658687ea9cff7a084af5f1490b8a50', + '0x7320ea69771c4eb8c89284d19ce63eb7a788f605b1f3509c17c6f47cc06cc404': + '0x8c3e7322bb5fa1421684356dfaa32625e849334fcc34122551b5f8440573c9a2', + '0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2': + '0xdc2737abd5c3a6bd9f10ec1211f6d6f973ff671d38f25c1003cd17efe5b44d70' + } +}; + +const multiAttesterVC: VerifiableCredential = { + '@context': ['https://www.w3.org/2018/credentials/v1'], + version: '2', + ctype: '0xc08734bbd035fe0880ba6e469e40b160601a2389d0284f6255a5f0b395d2336c', + issuanceDate: 1693299329782, + credentialSubject: { name: 'zCloak', age: 19, birthday: '2022.10.31', isUser: true }, + issuer: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec', 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1'], + holder: 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1', + hasher: ['Keccak256', 'Keccak256'], + digest: '0x63c8827f7d7e7446772799ccfbc0ae0a57199b679a4ea3682951ccc5c418060d', + proof: [ + { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1693299329786, + verificationMethod: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0', + proofPurpose: 'assertionMethod', + proofValue: 'zJaNmsWPNQoJ1Gt58AotgQRoBvSoEibuAL6GBKvZ8fV5gbNCrXxBZkMyZFK6fUwUoFkZi2WZNNdMicwGzTPbzdH1Ep' + }, + { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1693465100632, + verificationMethod: 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1#key-0', + proofPurpose: 'assertionMethod', + proofValue: 'zMM2jFmT4AdoepwHGNfqxjTxmemRsWpX4b4dVZyB6dLdWunBnLhTwLPYqsxF3nMfP11hQM3HUSLe3tMmiYVpYtCN16' + } + ], + credentialSubjectHashes: [ + '0x1537556bb6125c231e6e76ec1457b80bf43647fdd0de3f57c2bc3189da55617b', + '0x418070cd733fcab053b572eb37f4aea5686ec3485296eb2e517b622c9b59a112', + '0xd4be7b980fc8f5d53f99b5cfcfce5633827baff0be83f16f5290190864708f4b', + '0x4ddccf029950fee195bcd67df5a46986fea14ff00d47b5d3b9d1929c623c1f32' + ], + credentialSubjectNonceMap: { + '0x28cb5b00333a3266fa3d92f3426ad4ef1d20018b44dd64913578d43438b4051a': + '0xc9444e4d54f98aaa9076736432913113f0d6491321cc575ec751208d7f17fb7f', + '0x66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090': + '0x596e356de2ec14369f127afcba1c84441c658687ea9cff7a084af5f1490b8a50', + '0x7320ea69771c4eb8c89284d19ce63eb7a788f605b1f3509c17c6f47cc06cc404': + '0x8c3e7322bb5fa1421684356dfaa32625e849334fcc34122551b5f8440573c9a2', + '0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2': + '0xdc2737abd5c3a6bd9f10ec1211f6d6f973ff671d38f25c1003cd17efe5b44d70' + } +}; + const vcWithExpiration: VerifiableCredential = { '@context': ['https://www.w3.org/2018/credentials/v1'], version: '0', @@ -146,6 +293,43 @@ const vcWithExpiration: VerifiableCredential = { expirationDate: 1668362768974 }; +const oldvc: VerifiableCredential = { + '@context': ['https://www.w3.org/2018/credentials/v1'], + version: '1', + ctype: '0x2e0e5ba41f58ffdccb9dba906715b9142e40929d80896310906cde392862fc9e', + issuanceDate: 1684486317809, + credentialSubject: { Name: 'niubi', DateOfBirth: 737801428, Nationality: 156, RiskLevel: 6 }, + issuer: 'did:zk:0x0F6fDe944582dd316467288b374c0A2B1bF85FA3', + holder: 'did:zk:0x266006D511d5f1D439500F03C2Ec2393c56d2F60', + hasher: ['RescuePrimeOptimized', 'Keccak256'], + digest: '0x324c0deb43b9b378d8d0fcf4be10515de988071347cd318920a610ff26093a40', + proof: [ + { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1684486319027, + verificationMethod: 'did:zk:0x0F6fDe944582dd316467288b374c0A2B1bF85FA3#key-0', + proofPurpose: 'assertionMethod', + proofValue: 'zAP6hiSgycNjasu5kbVoSkEDskovCZqLRaGQxfCLo6bU18RVJrMYtuAyG9RBXJBFeTswDuvmsaUfVZ6S3zevkKzkwJ' + } + ], + credentialSubjectHashes: [ + '0xfc173d471bec19736002e054ae6e88529d2c27865db2501645512267a8472ee3', + '0x7510a76897e3c41c1b78d2bda7e627e47fa9914a4637e7fc82da1bcd7f8a7e19', + '0x6aa8322e8248cec1d4ad89f31b5f5939f21e20b92746fd21e2ad6d5dbb7e0d66', + '0x0b4d26948fea931e7fde139afda4e4bf12cd2d36fa939e268a627d51c420cd54' + ], + credentialSubjectNonceMap: { + '0x84bc66b0b72dfb3947cb8cc246812a198a1d71ad46e9b72bf8aea55efa43fa56': + '0xddbc2f87addd89883bc5d6c6fe2796e78706d57bd5de7c88ae0eeda5edbd9e5f', + '0xa3da24bd5605af8b631ef43c92e492d59030017db07b36d4efa7ebf970ae4159': + '0x4f5f413e553c2449a1aef70d9f1ecafe6ddceb3676dd3f6e51dd16158fafdacf', + '0x747e81e49d695483a90dc5193bfbce117649f242c629937926ce312ad8586561': + '0xcb82110b48c35a914d632684b0432210fbe7afd65083059779c7ab141122e62a', + '0x4c106f339d6f5e9b85bdf2b211fb6999e231aa62d66af41d6e8147be7a8ba305': + '0x8bda7aead48651accfcae1a8f81c90a0a390ca4982c275202d65035505c7f75b' + } +}; + describe('vc verify', (): void => { beforeAll(async (): Promise => { await initCrypto(); @@ -156,6 +340,14 @@ describe('vc verify', (): void => { expect(await vcVerify(fullVC, document1)).toBe(true); }); + it('vc verify with version 2, without keccak256', async (): Promise => { + expect(await vcVerify(fullVC2, document3)).toBe(true); + }); + + it('vc verify with version 2, with keccak256', async (): Promise => { + expect(await vcVerify(fullVC3, document3)).toBe(true); + }); + it('vc verify with expiration', async (): Promise => { // it is expirate expect(await vcVerify(vcWithExpiration, document2)).toBe(false); @@ -247,23 +439,123 @@ describe('vc verify', (): void => { ) ).toBe(true); }); - }); - describe('verify vc with digest', (): void => { - it('vc verify without expiration', async (): Promise => { + it('vc verify old vc', async (): Promise => { + expect(await vcVerify(oldvc)).toBe(true); + }); + + describe('verify vc with digest', (): void => { + it('vc verify without expiration', async (): Promise => { + expect( + await vcVerifyDigest( + { + ...fullVC, + credentialSubject: calcRoothash( + fullVC.credentialSubject as AnyJson, + fullVC.hasher[0], + fullVC.version, + fullVC.credentialSubjectNonceMap || {} + ).rootHash, + credentialSubjectNonceMap: {}, + credentialSubjectHashes: [] + }, + document1 + ) + ).toBe(true); + }); + }); + + it('vc verify with version 2, without keccak256, add Proof', async (): Promise => { + const addProofVC = await addProof(alice, fullVC2); + + expect(addProofVC.issuer).toEqual([ + 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec', + 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1' + ]); + expect(addProofVC.proof[1].verificationMethod).toEqual('did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1#key-0'); + expect(await vcVerify(addProofVC)).toBe(true); expect( - await vcVerifyDigest( - { - ...fullVC, - credentialSubject: calcRoothash( - fullVC.credentialSubject as AnyJson, - fullVC.hasher[0], - fullVC.credentialSubjectNonceMap || {} - ).rootHash, - credentialSubjectNonceMap: {}, - credentialSubjectHashes: [] - }, - document1 + await didVerify( + addProofVC.digest, + base58Decode(addProofVC.proof[0].proofValue), + addProofVC.proof[0].type, + addProofVC.proof[0].verificationMethod + ) + ).toBe(true); + expect( + await didVerify( + addProofVC.digest, + base58Decode(addProofVC.proof[1].proofValue), + addProofVC.proof[1].type, + addProofVC.proof[1].verificationMethod + ) + ).toBe(true); + }); + + it('vc verify with version 2, with keccak256, add Proof', async (): Promise => { + const addProofVC = await addProof(alice, fullVC3); + + expect(addProofVC.issuer).toEqual([ + 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec', + 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1' + ]); + expect(addProofVC.proof[1].verificationMethod).toEqual('did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1#key-0'); + expect(await vcVerify(addProofVC)).toBe(true); + expect( + await didVerify( + addProofVC.digest, + base58Decode(addProofVC.proof[0].proofValue), + addProofVC.proof[0].type, + addProofVC.proof[0].verificationMethod + ) + ).toBe(true); + expect( + await didVerify( + addProofVC.digest, + base58Decode(addProofVC.proof[1].proofValue), + addProofVC.proof[1].type, + addProofVC.proof[1].verificationMethod + ) + ).toBe(true); + }); + + it('vc verify with version 2, with steps', async (): Promise => { + expect(await vcVerify(multiAttesterVC)).toBe(true); + // console.log(await vcVerify(multiAttesterVC)); + const rootHash = calcRoothash( + multiAttesterVC.credentialSubject as AnyJson, + multiAttesterVC.hasher[0], + '2', + multiAttesterVC.credentialSubjectNonceMap + ); + const payload: DigestPayloadV2 = { + rootHash: rootHash.rootHash, + holder: multiAttesterVC.holder, + expirationDate: multiAttesterVC.expirationDate, + issuanceDate: multiAttesterVC.issuanceDate, + ctype: multiAttesterVC.ctype + }; + + // console.log(payload); + const digest = calcDigest(multiAttesterVC.version, payload, multiAttesterVC.hasher[1]); + + expect(digest.digest).toEqual(multiAttesterVC.digest); + + expect( + await didVerify( + digest.digest, + base58Decode(multiAttesterVC.proof[0].proofValue), + multiAttesterVC.proof[0].type, + multiAttesterVC.proof[0].verificationMethod + ) + ).toBe(true); + + expect( + await didVerify( + digest.digest, + base58Decode(multiAttesterVC.proof[1].proofValue), + multiAttesterVC.proof[1].type, + multiAttesterVC.proof[1].verificationMethod ) ).toBe(true); }); diff --git a/packages/verify/src/vcVerify.ts b/packages/verify/src/vcVerify.ts index c5f0d3b..49addf4 100644 --- a/packages/verify/src/vcVerify.ts +++ b/packages/verify/src/vcVerify.ts @@ -8,10 +8,11 @@ import type { VerifiableCredential } from '@zcloak/vc/types'; import { assert, bufferToU8a, isHex, u8aConcat, u8aToHex } from '@polkadot/util'; -import { calcRoothash, makeMerkleTree } from '@zcloak/vc'; +import { Did } from '@zcloak/did'; +import { calcRoothash, makeMerkleTree, VerifiableCredentialBuilder } from '@zcloak/vc'; import { HASHER } from '@zcloak/vc/hasher'; import { isPublicVC, isVC } from '@zcloak/vc/is'; -import { rlpEncode, signedVCMessage } from '@zcloak/vc/utils'; +import { encodeAsSol, rlpEncode, signedVCMessage } from '@zcloak/vc/utils'; import { digestVerify } from './digestVerify'; import { proofVerify } from './proofVerify'; @@ -22,7 +23,7 @@ async function verifyShared( rootHash: HexString, resolverOrDidDocument?: DidResolver | DidDocument ): Promise { - assert(isVC(vc), 'input `vc` is not a VerifiableCredential'); + assert(isVC(vc), "input 'vc' is not a VerifiableCredential"); const { ctype, digest, expirationDate, hasher, holder, issuanceDate, proof, version } = vc; @@ -43,9 +44,27 @@ async function verifyShared( hasher[1] ); - const message = version === '1' ? signedVCMessage(digest, version) : digest; + let message: Uint8Array | HexString; + + if (version === '1') { + message = signedVCMessage(digest, version); + } else if (version === '0' || version === '2') { + message = digest; + } else { + const check: never = version; + + throw new Error(`The VC Version is invalid : ${check}`); + } + + let proofValid = true; - const proofValid = await proofVerify(message, proof[0], resolverOrDidDocument); + for (const item of proof) { + proofValid = await proofVerify(message, item, resolverOrDidDocument); + + if (!proofValid) { + return false; + } + } return digestValid && proofValid; } @@ -81,7 +100,7 @@ export async function vcVerify( let rootHash: HexString; if (isPublicVC(vc)) { - rootHash = calcRoothash(vc.credentialSubject, vc.hasher[0]).rootHash; + rootHash = calcRoothash(vc.credentialSubject, vc.hasher[0], vc.version).rootHash; } else { const { credentialSubject, credentialSubjectHashes, credentialSubjectNonceMap, hasher } = vc; @@ -90,8 +109,23 @@ export async function vcVerify( rootHash = u8aToHex(bufferToU8a(tree.getRoot())); for (const value of Object.values(credentialSubject)) { - const encode = u8aToHex(rlpEncode(value, hasher[0])); - const hash = u8aToHex(HASHER[hasher[0]](u8aConcat(encode, credentialSubjectNonceMap[encode]))); + let encoded: HexString; + + if (vc.version === '2') { + if (hasher[0] === 'Keccak256') { + encoded = encodeAsSol(value); + } else { + encoded = u8aToHex(rlpEncode(value, hasher[0])); + } + } else if (vc.version === '0' || vc.version === '1') { + encoded = u8aToHex(rlpEncode(value, hasher[0])); + } else { + const check: never = vc.version; + + throw new Error(`VC Version invalid, the wrong VC Version is ${check}`); + } + + const hash = u8aToHex(HASHER[hasher[0]](u8aConcat(encoded, credentialSubjectNonceMap[encoded]))); if (!credentialSubjectHashes.includes(hash)) return false; } @@ -137,3 +171,39 @@ export async function vcVerifyDigest( return verifyShared(vc, rootHash, resolverOrDidDocument); } + +/** + * since @2.0.0 + * @param issuer + * @param vc + * @returns + */ +export async function addProof( + issuer: Did, + vc: VerifiableCredential, + resolverOrDidDocument?: DidResolver +): Promise> { + const existedIssuer = vc.issuer; + const existedProof = vc.proof; + const exitedDigest = vc.digest; + + assert(vc.version === '2', 'Only version2 support addProof'); + + // Must have proof + assert(existedIssuer.length > 0 && existedProof.length > 0, 'field issuer or proof is empty'); + + const vcVerifyResult = await vcVerify(vc, resolverOrDidDocument); + + assert(vcVerifyResult, 'The VC is invalid'); + + // addProof available since vc@2.0.0 + const version = '2'; + const proof = await VerifiableCredentialBuilder._signDigest(issuer, exitedDigest, version); + const modifiedVC: VerifiableCredential = { + ...vc, + issuer: [...existedIssuer, issuer.id] as any, + proof: [...existedProof, proof] + }; + + return modifiedVC; +} diff --git a/packages/verify/src/vpVerify.spec.ts b/packages/verify/src/vpVerify.spec.ts index a133c8f..b5c89f2 100644 --- a/packages/verify/src/vpVerify.spec.ts +++ b/packages/verify/src/vpVerify.spec.ts @@ -9,6 +9,7 @@ import { initCrypto, randomAsHex } from '@zcloak/crypto'; import { getPublish } from '@zcloak/ctype/publish'; import { Did } from '@zcloak/did'; import { Raw, VerifiableCredentialBuilder, VerifiablePresentationBuilder } from '@zcloak/vc'; +import { VerifiablePresentation } from '@zcloak/vc/types'; import { vpVerify } from './vpVerify'; @@ -19,11 +20,60 @@ const CONTENTS1 = { isUser: true }; +const vp1: VerifiablePresentation = { + '@context': ['https://www.w3.org/2018/credentials/v1'], + version: '1', + type: ['VP_SelectiveDisclosure'], + verifiableCredential: [ + { + '@context': ['https://www.w3.org/2018/credentials/v1'], + version: '2', + ctype: '0xab82151238ca0dbe9e343caf2b1042650d9a977b29ad7180c3a14e5df537ef40', + issuanceDate: 1693300491044, + credentialSubject: { isUser: true }, + issuer: ['did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec'], + holder: 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1', + hasher: ['Keccak256', 'Keccak256'], + digest: '0xcaf72e5ad65c8fe8d489346b3aed6152e8f02b8487fe16dd7037ec66943f4db4', + proof: [ + { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1693300491046, + verificationMethod: 'did:zk:0x57E7b664aaa7C895878DdCa5790526B9659350Ec#key-0', + proofPurpose: 'assertionMethod', + proofValue: 'z7BbcEoiUpyQKmJ1soNNX6MicHzPpJUcGXLQ65QWYZFY9eArHUPmh4Kgf1D9EsLJbjGYDQpGxGcuA98etPsyXh82C8' + } + ], + credentialSubjectHashes: [ + '0x1e00eee4ae14ff270e57b4c20c43a287bf5ea34828069650d3c4edc4790d2535', + '0x68500dbd64b29d43a580cf437c0eeb899e2d76ebb06e9fc4565f83d76708509e', + '0xaa4831bd6cd6adaab67ab872dd606c41bad95814e201d168e92c45c2b41a8724', + '0x6d7154b2efb83c39a5cf81ade1ec18509435c573211301ef3cd45957619d4121' + ], + credentialSubjectNonceMap: { + '0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2': + '0x7e40f40af672df4c16ee00317cac4a1b6ab62b68efeecd18940e041472765fc7' + } + } + ], + id: '0xbf881c79f3385dca051fbfb367a2fccd86ca28b9dba87b35d47c0d8cece24167', + proof: { + type: 'EcdsaSecp256k1SignatureEip191', + created: 1693300491047, + verificationMethod: 'did:zk:0x11f8b77F34FCF14B7095BF5228Ac0606324E82D1', + proofPurpose: 'controller', + proofValue: 'zLFLYALJPDUK9LE69LKBnc4FV2ov7cTj7PX6ykYNsdLBDcoux1FW3Q3eeXRoou8EWhnf8xHG1V3waTTC61ezb25Jz3', + challenge: '0x6ef8cf2355352b0fafd4b1a4b719520a7f2cdd5e10fe27ddd0353955d154f3f5' + }, + hasher: ['Keccak256'] +}; + describe('VerifiablePresentation', (): void => { const holder: Did = alice; const issuer1: Did = bob; let ctype: CType; let rawCtype: Raw; + let rawCtype2: Raw; beforeAll(async (): Promise => { await initCrypto(); @@ -56,6 +106,13 @@ describe('VerifiablePresentation', (): void => { ctype, hashType: 'RescuePrime' }); + + rawCtype2 = new Raw({ + contents: CONTENTS1, + owner: holder.id, + ctype, + hashType: 'Keccak256' + }); }); describe('VerifiablePresentation single vc', (): void => { @@ -98,4 +155,48 @@ describe('VerifiablePresentation', (): void => { expect(await vpVerify(vp, testResolver)).toBe(true); }); }); + describe('VerifiablePresentation single vc with Version2 keccak256', (): void => { + it('verify vp with VPType: VP', async (): Promise => { + const vc = await VerifiableCredentialBuilder.fromRawCredential(rawCtype2.toRawCredential(), ctype) + .setExpirationDate(null) + .build(issuer1); + + const vpBuilder = new VerifiablePresentationBuilder(holder); + + const challenge = randomAsHex(); + const vp = await vpBuilder.addVC(vc, 'VP').build(undefined, challenge); + + expect(await vpVerify(vp, testResolver)).toBe(true); + }); + + it('create ctype vp with VPType: VP_Digest', async (): Promise => { + const vc = await VerifiableCredentialBuilder.fromRawCredential(rawCtype2.toRawCredential(), ctype) + .setExpirationDate(null) + .build(issuer1); + + const vpBuilder = new VerifiablePresentationBuilder(holder); + + const challenge = randomAsHex(); + const vp = await vpBuilder.addVC(vc, 'VP_Digest').build(undefined, challenge); + + expect(await vpVerify(vp, testResolver)).toBe(true); + }); + + it('verify vp with VPType: VP_SelectiveDisclosure', async (): Promise => { + const vc = await VerifiableCredentialBuilder.fromRawCredential(rawCtype2.toRawCredential(), ctype) + .setExpirationDate(null) + .build(issuer1); + + const vpBuilder = new VerifiablePresentationBuilder(holder); + + const challenge = randomAsHex(); + const vp = await vpBuilder.addVC(vc, 'VP_SelectiveDisclosure', ['isUser']).build(undefined, challenge); + + expect(await vpVerify(vp, testResolver)).toBe(true); + }); + + it('verify vp with VPType: VP_SelectiveDisclosure with exist VP', async (): Promise => { + expect(await vpVerify(vp1, testResolver)).toBe(true); + }); + }); }); diff --git a/protocol/vc/package.json b/protocol/vc/package.json index 5ddbc04..5a86f51 100644 --- a/protocol/vc/package.json +++ b/protocol/vc/package.json @@ -24,7 +24,9 @@ "@zcloak/crypto": "workspace:^", "@zcloak/ctype": "workspace:^", "@zcloak/did": "workspace:^", - "merkletreejs": "^0.3.9" + "@zcloak/did-resolver": "workspace:^", + "merkletreejs": "^0.3.9", + "web3": "^4.1.1" }, "devDependencies": { "@zcloak/did-resolver": "workspace:^" diff --git a/protocol/vc/src/credential/index.spec.ts b/protocol/vc/src/credential/index.spec.ts index 7c433cc..2ea9a0b 100644 --- a/protocol/vc/src/credential/index.spec.ts +++ b/protocol/vc/src/credential/index.spec.ts @@ -20,6 +20,12 @@ const CONTENTS = { birthday: '2022.10.31', isUser: true }; +const CONTENTS2 = { + name: 'zCloak', + age: -120, + birthday: '2022.10.31', + isUser: true +}; describe('VerifiableCredential', (): void => { let holder: Did; @@ -30,7 +36,6 @@ describe('VerifiableCredential', (): void => { await initCrypto(); holder = alice; issuer = bob; - ctype = await getPublish( { title: 'Test', @@ -110,7 +115,7 @@ describe('VerifiableCredential', (): void => { digestHashType: 'Keccak256' }); - const vc = await vcBuilder.build(issuer); + const vc = await vcBuilder.build(issuer, false); expect(isPrivateVC(vc)).toBe(true); @@ -120,7 +125,7 @@ describe('VerifiableCredential', (): void => { ctype: ctype.$id, issuanceDate: now, credentialSubject: CONTENTS, - issuer: issuer.id, + issuer: [issuer.id], holder: holder.id, hasher: ['RescuePrime', 'Keccak256'], proof: [ @@ -137,7 +142,7 @@ describe('VerifiableCredential', (): void => { contents: CONTENTS, owner: holder.id, ctype, - hashType: 'RescuePrime' + hashType: 'Keccak256' }); const now = Date.now(); @@ -153,19 +158,18 @@ describe('VerifiableCredential', (): void => { digestHashType: 'Keccak256' }); - const vc = await vcBuilder.build(issuer); + const vc = await vcBuilder.build(issuer, false); expect(isPrivateVC(vc)).toBe(true); - expect(vc).toMatchObject({ '@context': DEFAULT_CONTEXT, version: DEFAULT_VC_VERSION, ctype: ctype.$id, issuanceDate: now, credentialSubject: CONTENTS, - issuer: issuer.id, + issuer: [issuer.id], holder: holder.id, - hasher: ['RescuePrime', 'Keccak256'], + hasher: ['Keccak256', 'Keccak256'], proof: [ { type: 'EcdsaSecp256k1SignatureEip191', @@ -196,9 +200,9 @@ describe('VerifiableCredential', (): void => { digestHashType: 'Keccak256' }); - const vc = await vcBuilder.build(issuer); + const vc = await vcBuilder.build(issuer, true); - expect(isPrivateVC(vc)).toBe(true); + expect(isPrivateVC(vc)).toBe(false); expect(vc).toMatchObject({ '@context': DEFAULT_CONTEXT, @@ -206,7 +210,7 @@ describe('VerifiableCredential', (): void => { ctype: ctype.$id, issuanceDate: now, credentialSubject: CONTENTS, - issuer: issuer.id, + issuer: [issuer.id], holder: holder.id, hasher: ['RescuePrimeOptimized', 'Keccak256'], proof: [ @@ -217,6 +221,48 @@ describe('VerifiableCredential', (): void => { ] }); }); + it('build VC from RawCredential negtive number', async (): Promise => { + const raw = new Raw({ + contents: CONTENTS2, + owner: holder.id, + ctype, + hashType: 'Keccak256' + }); + + const now = Date.now(); + + const vcBuilder = VerifiableCredentialBuilder.fromRawCredential(raw.toRawCredential('Keccak256'), ctype) + .setExpirationDate(null) + .setIssuanceDate(now); + + expect(vcBuilder).toMatchObject({ + raw, + '@context': DEFAULT_CONTEXT, + issuanceDate: now, + digestHashType: 'Keccak256' + }); + + const vc = await vcBuilder.build(issuer, true); + + expect(isPrivateVC(vc)).toBe(false); + + expect(vc).toMatchObject({ + '@context': DEFAULT_CONTEXT, + version: DEFAULT_VC_VERSION, + ctype: ctype.$id, + issuanceDate: now, + credentialSubject: CONTENTS2, + issuer: [issuer.id], + holder: holder.id, + hasher: ['Keccak256', 'Keccak256'], + proof: [ + { + type: 'EcdsaSecp256k1SignatureEip191', + proofPurpose: 'assertionMethod' + } + ] + }); + }); }); describe('PublicVerifiableCredential', () => { @@ -256,7 +302,7 @@ describe('VerifiableCredential', (): void => { ctype: ctype.$id, issuanceDate: now, credentialSubject: CONTENTS, - issuer: issuer.id, + issuer: [issuer.id], holder: holder.id, hasher: ['RescuePrime', 'Keccak256'], proof: [ diff --git a/protocol/vc/src/credential/vc.ts b/protocol/vc/src/credential/vc.ts index f01f121..5bab232 100644 --- a/protocol/vc/src/credential/vc.ts +++ b/protocol/vc/src/credential/vc.ts @@ -11,6 +11,7 @@ import { assert } from '@polkadot/util'; import { base58Encode } from '@zcloak/crypto'; +// import { vcVerify } from '@zcloak/verify/vcVerify'; import { DEFAULT_CONTEXT, DEFAULT_VC_VERSION } from '../defaults'; import { calcDigest, DigestPayload } from '../digest'; import { isRawCredential } from '../is'; @@ -78,6 +79,8 @@ export class VerifiableCredentialBuilder { this.raw = raw; } + public async build(issuer: Did, isPublic?: boolean): Promise>; + /** * Build to [[PublicVerifiableCredential]] */ @@ -86,9 +89,16 @@ export class VerifiableCredentialBuilder { /** * Build to [[PrivateVerifiableCredential]] */ - public async build(issuer: Did, isPublic?: false): Promise>; + public async build(issuer: Did, isPublic: false): Promise>; - public async build(issuer: Did, isPublic?: boolean): Promise> { + /** + * + * @param issuer this is Did type, because we need to sign vc to fulfill the proof field + * @param isPublic + * @param moreIssuers this is only DidUrl type, because we just add them to the issuer field( not proof field) + * @returns + */ + public async build(issuer: Did, isPublic = false): Promise> { assert(this.raw.checkSubject(), `Subject check failed when use ctype ${this.raw.ctype}`); if ( @@ -101,9 +111,9 @@ export class VerifiableCredentialBuilder { let rootHashResult: RootHashResult; if (isPublic) { - rootHashResult = calcRoothash(this.raw.contents, this.raw.hashType); + rootHashResult = calcRoothash(this.raw.contents, this.raw.hashType, this.version); } else { - rootHashResult = calcRoothash(this.raw.contents, this.raw.hashType, {}); + rootHashResult = calcRoothash(this.raw.contents, this.raw.hashType, this.version, {}); } const digestPayload: DigestPayload = { @@ -116,15 +126,17 @@ export class VerifiableCredentialBuilder { const { digest, type: digestHashType } = calcDigest(this.version, digestPayload, this.digestHashType); - const proof = await this._signDigest(issuer, digest, this.version); + const proof = await VerifiableCredentialBuilder._signDigest(issuer, digest, this.version); + // NOTE: at this moment, the first proof is fullfiled, this maybe not enough because of multiple issuers + // Use addIssuerProof() to add more proofs let vc: VerifiableCredential = { '@context': this['@context'], version: this.version, ctype: this.raw.ctype.$id, issuanceDate: this.issuanceDate, credentialSubject: this.raw.contents, - issuer: issuer.id, + issuer: [issuer.id], holder: this.raw.owner, hasher: [rootHashResult.type, digestHashType], digest, @@ -205,13 +217,17 @@ export class VerifiableCredentialBuilder { } // sign digest by did, the signed message is `concat('CredentialVersionedDigest', version, digest)` - private async _signDigest(did: Did, digest: HexString, version: VerifiableCredentialVersion): Promise { + public static async _signDigest(did: Did, digest: HexString, version: VerifiableCredentialVersion): Promise { let message: Uint8Array | HexString; if (version === '1') { message = signedVCMessage(digest, version); - } else { + } else if (version === '0' || version === '2') { message = digest; + } else { + const check: never = version; + + throw new Error(`VC Version invalid, the wrong VC Version is ${check}`); } const signDidUrl: DidUrl = did.getKeyUrl('assertionMethod'); diff --git a/protocol/vc/src/defaults.ts b/protocol/vc/src/defaults.ts index 10be0bc..235b4cd 100644 --- a/protocol/vc/src/defaults.ts +++ b/protocol/vc/src/defaults.ts @@ -9,7 +9,7 @@ import type { VerifiablePresentationVersion } from './types'; -export const DEFAULT_VC_VERSION: VerifiableCredentialVersion = '1'; +export const DEFAULT_VC_VERSION: VerifiableCredentialVersion = '2'; export const DEFAULT_VP_VERSION: VerifiablePresentationVersion = '1'; diff --git a/protocol/vc/src/digest.spec.ts b/protocol/vc/src/digest.spec.ts index 4b57f91..c300551 100644 --- a/protocol/vc/src/digest.spec.ts +++ b/protocol/vc/src/digest.spec.ts @@ -46,7 +46,7 @@ describe('digest', (): void => { isUser: true }; - const { rootHash } = calcRoothash(input, 'Blake32to1', { + const { rootHash } = calcRoothash(input, 'Blake32to1', '1', { '0x6b90277e3f4ab97b83b3fc61ecffa4ec063f70d7255233ef5afdf418dcec3b75': '0x25807968a4c5f3ce2f116c5914991c97e33020408146406a36e4fa4826dd6c7d', '0x1300000000000000000000000000000000000000000000000000000000000000': diff --git a/protocol/vc/src/digest.ts b/protocol/vc/src/digest.ts index 5a20d2f..242b939 100644 --- a/protocol/vc/src/digest.ts +++ b/protocol/vc/src/digest.ts @@ -33,6 +33,9 @@ export interface DigestPayloadV0 { ctype: HexString; } +/** + * @deprecated + */ export interface DigestPayloadV1 extends DigestPayloadV0 { /** * @since `@zcloak/vc@1.0.0` and `VerifiableCredential.version is 1` @@ -41,9 +44,18 @@ export interface DigestPayloadV1 extends DigestPayloadV0 { issuanceDate: number; } +/** + * @since `@zcloak/vc@2.0.0` + */ +export interface DigestPayloadV2 extends DigestPayloadV0 { + issuanceDate: number; +} + export type DigestPayload = Version extends '0' ? DigestPayloadV0 - : DigestPayloadV1; + : Version extends '1' + ? DigestPayloadV1 + : DigestPayloadV2; /** * @name calcDigest @@ -72,7 +84,7 @@ export function calcDigest( numberToU8a(payload.expirationDate || 0), payload.ctype ); - } else { + } else if (version === '1') { encoded = u8aConcat( payload.rootHash, encodeDidUrl(payload.holder), @@ -80,6 +92,18 @@ export function calcDigest( numberToU8a(payload.expirationDate || 0), payload.ctype ); + } else if (version === '2') { + encoded = u8aConcat( + payload.rootHash, + encodeDidUrl(payload.holder), + numberToU8a((payload as DigestPayload<'2'>).issuanceDate), + numberToU8a(payload.expirationDate || 0), + payload.ctype + ); + } else { + const check: never = version; + + throw new Error(`VC Version invalid, the vcVersionCheckResult is ${check}`); } return { diff --git a/protocol/vc/src/is.ts b/protocol/vc/src/is.ts index 678a5d2..230d4c2 100644 --- a/protocol/vc/src/is.ts +++ b/protocol/vc/src/is.ts @@ -15,6 +15,7 @@ import { isArray, isHex, isJsonObject, isNull, isNumber, isString, isUndefined } import { isBase32, isBase58, isBase64 } from '@zcloak/crypto'; import { isDidUrl } from '@zcloak/did/utils'; +import { parseDid } from '@zcloak/did-resolver/parseDid'; import { ALL_HASH_TYPES, ALL_SIG_TYPES, ALL_VP_TYPES } from './defaults'; @@ -61,6 +62,49 @@ export function isProof(input: unknown): input is Proof { ); } +/** + * @name isAttesterMapping + * @description + * check the `attester` is the same in [[Proof]] + */ +export function isAttesterMapping(issuer: unknown, proof: unknown): boolean { + if (isProof(proof)) { + const issuerInProof = parseDid(proof.verificationMethod).did; + + return issuer === issuerInProof; + } else return false; +} + +/** + * @name isAttesterProof + * @description + * check the Proof is qualified or not + */ +export function isAttesterProof(issuer: unknown, proof: unknown): boolean { + // version 0 & version 1, only one attester and one proof + if (typeof issuer === 'string' && isArray(proof) && proof.length === 1) { + return isAttesterMapping(issuer, proof[0]); + } else if (isArray(issuer) && isArray(proof) && issuer.length === proof.length) { + const check = issuer.every((issuer, index) => isAttesterMapping(issuer, proof[index])); + + return check; + } else { + return false; + } +} + +export function isAttester(value: unknown, version: unknown): boolean { + if (typeof value === 'string' && (version === '0' || version === '1')) { + return isDidUrl(value); + } else if (isArray(value) && value.length !== 0 && version === '2') { + const check = value.every(isDidUrl); + + return check; + } else { + return false; + } +} + /** * @name isRawCredential * @description @@ -118,10 +162,10 @@ export function isVC(input: unknown): input is VerifiableCredential { isString(input.version) && isNumber(input.issuanceDate) && (isUndefined(input.expirationDate) || isNull(input.expirationDate) || isNumber(input.expirationDate)) && - isDidUrl(input.issuer) && + isAttester(input.issuer, input.version) && isHex(input.digest) && isArray(input.proof) && - !input.proof.map((p) => isProof(p)).includes(false) && + isAttesterProof(input.issuer, input.proof) && isHex(input.ctype) && (isJsonObject(input.credentialSubject) || isHex(input.credentialSubject)) && isDidUrl(input.holder) && diff --git a/protocol/vc/src/rootHash.spec.ts b/protocol/vc/src/rootHash.spec.ts index 779f4df..00374f7 100644 --- a/protocol/vc/src/rootHash.spec.ts +++ b/protocol/vc/src/rootHash.spec.ts @@ -1,9 +1,12 @@ // Copyright 2021-2023 zcloak authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { HexString } from '@polkadot/util/types'; + import { initCrypto } from '@zcloak/crypto'; import { calcRoothash } from './rootHash'; +import { encodeAsSol } from './utils'; describe('calcRoothash', (): void => { beforeAll(async (): Promise => { @@ -19,7 +22,7 @@ describe('calcRoothash', (): void => { isUser: true }; - const { rootHash } = calcRoothash(input, 'RescuePrime', { + const { rootHash } = calcRoothash(input, 'RescuePrime', '1', { '0x88af5a7ba28c1de54ebd589dea81d30caa3f467646f6d714c0d2604599d63e1e': '0x357d50aac640931f9976477de30b3b476be4a14ae367b045496670d7a23c457d', '0x9ad57aefa90d9473f855c14221f330fe959a554b3d86c9d701db11c7559ce107': @@ -42,7 +45,7 @@ describe('calcRoothash', (): void => { types: ['1', '2', '5'] }; - const { rootHash } = calcRoothash(input, 'RescuePrime', { + const { rootHash } = calcRoothash(input, 'RescuePrime', '1', { '0x88af5a7ba28c1de54ebd589dea81d30caa3f467646f6d714c0d2604599d63e1e': '0x42ecebd0acae94843f906a9fe69e5c672c60d8d688b71aa85948d8e60becf082', '0x9ad57aefa90d9473f855c14221f330fe959a554b3d86c9d701db11c7559ce107': @@ -67,7 +70,7 @@ describe('calcRoothash', (): void => { types: ['1', '2', '5'] }; - const { rootHash } = calcRoothash(input, 'RescuePrime'); + const { rootHash } = calcRoothash(input, 'RescuePrime', '1'); expect(rootHash).toEqual('0x9579c93741b6979500bca88dcb104da424c2c3bb0e2fa85f13d76cd00637e46f'); }); @@ -82,7 +85,7 @@ describe('calcRoothash', (): void => { isUser: true }; - const { rootHash } = calcRoothash(input, 'Blake32to1', { + const { rootHash } = calcRoothash(input, 'Blake32to1', '1', { '0x6b90277e3f4ab97b83b3fc61ecffa4ec063f70d7255233ef5afdf418dcec3b75': '0x25807968a4c5f3ce2f116c5914991c97e33020408146406a36e4fa4826dd6c7d', '0x1300000000000000000000000000000000000000000000000000000000000000': @@ -106,7 +109,7 @@ describe('calcRoothash', (): void => { isUser: true }; - const { rootHash } = calcRoothash(input, 'RescuePrimeOptimized', { + const { rootHash } = calcRoothash(input, 'RescuePrimeOptimized', '1', { '0x011eed5f2e2321069b83e2bdd38c790948231cd1d49ed6c4dd09bb0f16b0661c': '0xfd766e5717ae2ae09abee1268d6a653dc50c2067d9efd665e7b52d8f0f597d2b', '0x7f8a33bf3f50ca9b84d1dc5561c8f71d48d6256763fd8d0f5e5e902dce5dfb88': @@ -120,4 +123,63 @@ describe('calcRoothash', (): void => { expect(rootHash).toEqual('0x2cbd72a75cf5797fb6893b222a45de60eaa2ddf2e5d435d67e5ed8067efb76e3'); }); }); + + describe('calcContentAsSolidity', () => { + it('calcRoothash', (): void => { + const input = { + name: 'zCloak', + age: 111, + number_array: [11, 12, 13], + isUser: true, + string_array: ['zCloak', 'database'] + }; + const values = Object.values(input); + const encodedClaimHashes: HexString[] = values.map((values) => encodeAsSol(values)); + + expect(encodedClaimHashes).toEqual([ + '0x28cb5b00333a3266fa3d92f3426ad4ef1d20018b44dd64913578d43438b4051a', + '0x39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e12711', + '0x8d20824cd86ad1c5673537a4b5d1ee68bd9265b7d357e82bc76483ae879322c2', + '0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2', + '0x69ab0c29dcf9256886435d72272bceee1f0a0b2cee41865d3b56f9726e7fe0a3' + ]); + }); + }); + + describe('calc Roothash with version 2', () => { + it('calcRoothash', (): void => { + const input = { + name: 'zCloak', + age: 111, + number_array: [11, 12, 13], + isUser: true, + string_array: ['zCloak', 'database'] + }; + const values = Object.values(input); + const encodedClaimHashes: HexString[] = values.map((values) => encodeAsSol(values)); + + expect(encodedClaimHashes).toEqual([ + '0x28cb5b00333a3266fa3d92f3426ad4ef1d20018b44dd64913578d43438b4051a', + '0x39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e12711', + '0x8d20824cd86ad1c5673537a4b5d1ee68bd9265b7d357e82bc76483ae879322c2', + '0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2', + '0x69ab0c29dcf9256886435d72272bceee1f0a0b2cee41865d3b56f9726e7fe0a3' + ]); + + const { rootHash } = calcRoothash(input, 'Keccak256', '2', { + '0x28cb5b00333a3266fa3d92f3426ad4ef1d20018b44dd64913578d43438b4051a': + '0xcd769c703ecfdc6798d56711af8b3a7918973524db6c6c0901209fd396f3a61b', + '0x39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e12711': + '0xc5bd9417c2dd820e8c074086acb0e1a785c5f9aa59022ca74606f4f6f32338bb', + '0x8d20824cd86ad1c5673537a4b5d1ee68bd9265b7d357e82bc76483ae879322c2': + '0x9895d1010a3c7ae796bfdb2bff52febcfb21d8c71a0fb465a02d8a2a0ad857bd', + '0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2': + '0xddb361f768d83f2f8eabd4f51517adb8d92aef33ce627127311bad01bac41710', + '0x69ab0c29dcf9256886435d72272bceee1f0a0b2cee41865d3b56f9726e7fe0a3': + '0x51c09e0512047698103565fc9c2aca963eb3af6cf99b9201fc6be1331e4649e5' + }); + + expect(rootHash).toEqual('0x8e94d639398a25f0484ba8f40feff5e694b084164118af84ffece25c68be4342'); + }); + }); }); diff --git a/protocol/vc/src/rootHash.ts b/protocol/vc/src/rootHash.ts index 12e043c..f9a1b48 100644 --- a/protocol/vc/src/rootHash.ts +++ b/protocol/vc/src/rootHash.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { HexString } from '@zcloak/crypto/types'; -import type { AnyJson, HashType } from './types'; +import type { AnyJson, HashType, VerifiableCredentialVersion } from './types'; import { assert, bufferToU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util'; import { MerkleTree } from 'merkletreejs'; @@ -10,7 +10,7 @@ import { MerkleTree } from 'merkletreejs'; import { randomAsHex } from '@zcloak/crypto'; import { HASHER } from './hasher'; -import { rlpEncode } from './utils'; +import { encodeAsSol, rlpEncode } from './utils'; export type RootHashResult = { rootHash: HexString; @@ -71,7 +71,7 @@ export function rootHashFromMerkle( * @description * calc rootHash with supplied `input` and `hashType`. Returns [[RootHashResult]]. */ -export function calcRoothash(input: AnyJson, hashType: HashType): RootHashResult; +export function calcRoothash(input: AnyJson, hashType: HashType, version: VerifiableCredentialVersion): RootHashResult; /** * @name calcRoothash * @summary calc rootHash from any json. @@ -83,16 +83,33 @@ export function calcRoothash(input: AnyJson, hashType: HashType): RootHashResult export function calcRoothash( input: AnyJson, hashType: HashType, + version: VerifiableCredentialVersion, nonceMap: Record ): RootHashResult; export function calcRoothash( input: AnyJson, hashType: HashType, + version: VerifiableCredentialVersion, nonceMap?: Record ): RootHashResult { const values = Object.values(input); - const encoded: HexString[] = values.map((value) => rlpEncode(value, hashType)).map((value) => u8aToHex(value)); + let encoded: HexString[] = []; + + // if the version is `2` and the hash in merkletree is Keccak256, we assume this vc aims to be used on chain. + if (version === '2') { + if (hashType === 'Keccak256') { + encoded = values.map((values) => encodeAsSol(values)); + } else { + encoded = values.map((value) => rlpEncode(value, hashType)).map((value) => u8aToHex(value)); + } + } else if (version === '0' || version === '1') { + encoded = values.map((value) => rlpEncode(value, hashType)).map((value) => u8aToHex(value)); + } else { + const check: never = version; + + throw new Error(`VC Version invalid, the wrong VC Version is ${check}`); + } if (nonceMap) { for (const encode of encoded) { diff --git a/protocol/vc/src/types.ts b/protocol/vc/src/types.ts index 324d3d3..4b9c3e7 100644 --- a/protocol/vc/src/types.ts +++ b/protocol/vc/src/types.ts @@ -27,7 +27,7 @@ export type HashType = export type VerifiablePresentationType = 'VP' | 'VP_Digest' | 'VP_SelectiveDisclosure'; -export type VerifiableCredentialVersion = '0' | '1'; +export type VerifiableCredentialVersion = '0' | '1' | '2'; export type VerifiablePresentationVersion = '0' | '1'; @@ -52,7 +52,7 @@ interface PublicVerifiableCredential extends RawCredential { version: VerifiableCredentialVersion; issuanceDate: number; expirationDate?: number; - issuer: DidUrl; + issuer: DidUrl[] | DidUrl; digest: HexString; proof: Proof[]; } @@ -62,7 +62,7 @@ interface PrivateVerifiableCredential extends Omit { verifiableCredential: [ { ...vc, - credentialSubject: calcRoothash(CONTENTS1, vc.hasher[0], vc.credentialSubjectNonceMap).rootHash, + credentialSubject: calcRoothash(CONTENTS1, vc.hasher[0], vc.version, vc.credentialSubjectNonceMap).rootHash, credentialSubjectHashes: [], credentialSubjectNonceMap: {} } @@ -260,13 +260,15 @@ describe('VerifiablePresentation', (): void => { verifiableCredential: [ { ...vc1, - credentialSubject: calcRoothash(CONTENTS2, vc1.hasher[0], vc1.credentialSubjectNonceMap).rootHash, + credentialSubject: calcRoothash(CONTENTS2, vc1.hasher[0], vc1.version, vc1.credentialSubjectNonceMap) + .rootHash, credentialSubjectHashes: [], credentialSubjectNonceMap: {} }, { ...vc2, - credentialSubject: calcRoothash(CONTENTS2, vc2.hasher[0], vc2.credentialSubjectNonceMap).rootHash, + credentialSubject: calcRoothash(CONTENTS2, vc2.hasher[0], vc2.version, vc2.credentialSubjectNonceMap) + .rootHash, credentialSubjectHashes: [], credentialSubjectNonceMap: {} } @@ -362,7 +364,8 @@ describe('VerifiablePresentation', (): void => { verifiableCredential: [ { ...vc1, - credentialSubject: calcRoothash(CONTENTS1, vc1.hasher[0], vc1.credentialSubjectNonceMap).rootHash, + credentialSubject: calcRoothash(CONTENTS1, vc1.hasher[0], vc1.version, vc1.credentialSubjectNonceMap) + .rootHash, credentialSubjectHashes: [], credentialSubjectNonceMap: {} }, diff --git a/protocol/vc/src/vp.ts b/protocol/vc/src/vp.ts index 4b1cd08..b4f360d 100644 --- a/protocol/vc/src/vp.ts +++ b/protocol/vc/src/vp.ts @@ -21,7 +21,7 @@ import { DEFAULT_CONTEXT, DEFAULT_VP_HASH_TYPE, DEFAULT_VP_VERSION } from './def import { HASHER } from './hasher'; import { isPublicVC, isVC } from './is'; import { calcRoothash } from './rootHash'; -import { rlpEncode, signedVPMessage } from './utils'; +import { encodeAsSol, rlpEncode, signedVPMessage } from './utils'; // @internal // transform private Verifiable Credential by [[VerifiablePresentationType]] @@ -48,16 +48,34 @@ function transformVC( for (const key of selectedAttributes) { vc.credentialSubject[key] = subject[key]; - const encode = u8aToHex(rlpEncode(subject[key], vc.hasher[0])); + let encode: HexString; + + if (vc.version === '2') { + if (vc.hasher[0] === 'Keccak256') { + encode = encodeAsSol(subject[key]); + } else { + encode = u8aToHex(rlpEncode(subject[key], vc.hasher[0])); + } + } else if (vc.version === '0' || vc.version === '1') { + encode = u8aToHex(rlpEncode(subject[key], vc.hasher[0])); + } else { + const check: never = vc.version; + + throw new Error(`VC Version invalid, the wrong VC Version is ${check}`); + } vc.credentialSubjectNonceMap[encode] = nonceMap[encode]; } - } else { - const { rootHash } = calcRoothash(vc.credentialSubject, vc.hasher[0], vc.credentialSubjectNonceMap); + } else if (type === 'VP_Digest') { + const { rootHash } = calcRoothash(vc.credentialSubject, vc.hasher[0], vc.version, vc.credentialSubjectNonceMap); vc.credentialSubject = rootHash; vc.credentialSubjectHashes = []; vc.credentialSubjectNonceMap = {}; + } else { + const check: never = type; + + throw new Error(`VP Type invalid, the invalid VP type is: ${check}`); } return vc; diff --git a/yarn.lock b/yarn.lock index 045f9ac..0d5dc0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:^1.8.8": + version: 1.9.4 + resolution: "@adraffy/ens-normalize@npm:1.9.4" + checksum: f8e00455f9c81b02b051715fbf38f6d4975ad1ca4b94e6773fac607ec4974a63d5a30846bd6e61d447e3890f606dfdc3b3a64468a28d38f1f5647756e28d88ee + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -1799,6 +1806,228 @@ __metadata: languageName: node linkType: hard +"@ethereumjs/rlp@npm:^4.0.1": + version: 4.0.1 + resolution: "@ethereumjs/rlp@npm:4.0.1" + bin: + rlp: bin/rlp + checksum: 641fd88603d38cc891b9596e70cccd0937dcecaa5753a53a590cad09163ef6e0808bd032f03efbb38b0cbe8c34a0b03b526ef9e478a5e3e79dc0a23379e398ab + languageName: node + linkType: hard + +"@ethersproject/abi@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abi@npm:5.7.0" + dependencies: + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: d280355626314f5acb1a3c2e81328d27ddafd0ac9fdeeba496de26a6a53c39102076ebd7d74c38362d2a26e5fcc911759d64c4a446e10cc01216eef6220288d6 + languageName: node + linkType: hard + +"@ethersproject/abstract-provider@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abstract-provider@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/networks": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + checksum: dd46b5444090a32afa967f507091d04ea9e65d555a24744b728e134449e50e5c60419b1c03720eb934d556ab7fe30b8790f98cb4a8f2d0dc2e188c6966bf147f + languageName: node + linkType: hard + +"@ethersproject/abstract-signer@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abstract-signer@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + checksum: b97eda8abf6584efe2628456b8933fef9e212ba0e2cdc86e84b303bdc5401f88f9b785c9f123b8fb961dbc809dbe4a0f710ee63c67b79b7f96341d28d9650ee4 + languageName: node + linkType: hard + +"@ethersproject/address@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/address@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + checksum: 40d3fc40e075709fef5c986eece2ce21a81803d6fd8c009ae8866de1e50522fa76788771cdd0bc2fb1efc00710caee9c7501a9853844eef8d7a80e7c257414e3 + languageName: node + linkType: hard + +"@ethersproject/base64@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/base64@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + checksum: 920573265a668c4d356b8aa031d2be00901ff16d8d74412a5d4bf5a191af03fae83307e5f9c398ad1e29f9de80bac867b05aa23b942fbc02ea574372e8ffa6dd + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bignumber@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + bn.js: "npm:^5.2.1" + checksum: 666c8155b98881ac220c15152c24d0e8036c814d036b4105f0d60252777d9582d5d539a34ac41d16d90e28ac89e4816db7478ef2b8e27f793156dcbf4d8a5d4e + languageName: node + linkType: hard + +"@ethersproject/bytes@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bytes@npm:5.7.0" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 65d987c3e7057fcab2407c84dc79341b2e633364532262c635333bf6bb85bf244e2515ab5b582c06407f75b58fe90433b77af9161fa26819ca99fee9026743bc + languageName: node + linkType: hard + +"@ethersproject/constants@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/constants@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + checksum: 1e64c19be14deb69f0c1532c62b24d6d3e8a99df7412004ade36dd5d257a763ff06da9b8729172b7b86aa3d24e59202280d5df3a63dd9860f91109f6fa2356d9 + languageName: node + linkType: hard + +"@ethersproject/hash@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/hash@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: a4ea4262760273d657c677447fab9668204061de7f376b27996945efd7926ff96fa7b4227a80b60c626e3f76bee39bc948d0e91f8614af9bc7b4b4a639be4c0b + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/keccak256@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + js-sha3: "npm:0.8.0" + checksum: a0cace980f416a5395c3b9fed0a87e73fae6ebb1bf49e25b099670f75ea779d8e458e853bd7f3624ef08b2c098cc5fb7c13952dd0ed790ccf5f1bb879213f0ce + languageName: node + linkType: hard + +"@ethersproject/logger@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/logger@npm:5.7.0" + checksum: 41ef0d49aad3677c36d0e79a6e2346ec13cf378cc6a042cfbc0d76aca6bce0b9f7362cb3fa4d60572e2e24df12edc378e5d8bbf1e33f8234c142e09552c87f8a + languageName: node + linkType: hard + +"@ethersproject/networks@npm:^5.7.0": + version: 5.7.1 + resolution: "@ethersproject/networks@npm:5.7.1" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 5495b6a83a896366e8268da5e790898c5f7812fa6c395d3dffb89c2534a46e7cebaec07c6ae526f342843b482eb0e028013cea7f4e7bb8a266c8d6e22d114bda + languageName: node + linkType: hard + +"@ethersproject/properties@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/properties@npm:5.7.0" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 776f2d63f4b0ad04934d34db1b35c974f77e8beaec124d8fd267794fcdc0845c6a57ad8398b0637144a1bb57e5e2552bdbb76f9919c3919ec58e9bf2e5d008c3 + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/rlp@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + checksum: 41ff1717ee483131747ee3b625a7b78df981d221421e824b818dd598139571598e1cde7a00f40a927d08e8352537f7411685eaa9a004bcb78315b4beb9a16c33 + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/signing-key@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + bn.js: "npm:^5.2.1" + elliptic: "npm:6.5.4" + hash.js: "npm:1.1.7" + checksum: 53bf8187e47537f3715a9c50836b10ecd05feb7448cfe865b44b6e2776eb14a716accdca4b60465cdf814fbfe06a7d3c405448d4c448fe96c9d89e5dadddbaaf + languageName: node + linkType: hard + +"@ethersproject/strings@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/strings@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + checksum: 9f6e514c6bbbb9ecd7f567a92884c6ed5eb5d14bc60ac91e04bb2ad74e2bab52cb94b14ba875a4495a0f0d2a76babd842d226442e71537ad83606795691f7f16 + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/transactions@npm:5.7.0" + dependencies: + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/signing-key": "npm:^5.7.0" + checksum: 28ed8fefaad0c5689518393eed5bd65abd7d202ba4d0182f06cf21dddecff51738ae9164aac1f86ff7eac634483dd4265a7d21d81cc0fd478724cac326575e44 + languageName: node + linkType: hard + +"@ethersproject/web@npm:^5.7.0": + version: 5.7.1 + resolution: "@ethersproject/web@npm:5.7.1" + dependencies: + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: 916275c181114ddadaa063d83d1b34817f0fdf996f0b79ddc6204c281883119c095469592babacba4386ec7fa0e1c1ab689d0a56ca267c342fb8f36dc8a7ebff + languageName: node + linkType: hard + "@gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -2319,6 +2548,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.1.0, @noble/curves@npm:~1.1.0": + version: 1.1.0 + resolution: "@noble/curves@npm:1.1.0" + dependencies: + "@noble/hashes": "npm:1.3.1" + checksum: 87153bd4ec6cb58cfeba223933c7859d250613ba382421bd7d244280ef4ce08672f790750cd900f27d1dd09a650b3f736c08133fdd5c196587b8c461f86098be + languageName: node + linkType: hard + "@noble/hashes@npm:1.1.2": version: 1.1.2 resolution: "@noble/hashes@npm:1.1.2" @@ -2333,6 +2571,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.1": + version: 1.3.1 + resolution: "@noble/hashes@npm:1.3.1" + checksum: 69a6d561379bab638dd4608a6780c1f1ac3385505d7a1117040eb672d2633877bd6b06f45145ff915fe9196668c39863aee192f2cdfa546c013f4223e30bb108 + languageName: node + linkType: hard + "@noble/hashes@npm:^1.2.0": version: 1.3.0 resolution: "@noble/hashes@npm:1.3.0" @@ -2340,6 +2585,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.1": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: 1743313a088b484a7c37bcf21f7a69a9740bc32f9fa6ee15720e0f9a6e01e7ecad91bd75a37c17fe613269c1dcbdc1b8797e3de5ec52dd4488229089b0819bdd + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:^1.7.1": version: 1.7.1 resolution: "@noble/secp256k1@npm:1.7.1" @@ -3001,6 +3253,34 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.1.0": + version: 1.1.3 + resolution: "@scure/base@npm:1.1.3" + checksum: 6863158a2a8ed76da6f6bfdb028a9d55e4d277afc317165e861c9e1500403200f3e15db455b711949b7da3a0cd53ae05f8f0a038a8221c0200d4cc190e75aad3 + languageName: node + linkType: hard + +"@scure/bip32@npm:1.3.1": + version: 1.3.1 + resolution: "@scure/bip32@npm:1.3.1" + dependencies: + "@noble/curves": "npm:~1.1.0" + "@noble/hashes": "npm:~1.3.1" + "@scure/base": "npm:~1.1.0" + checksum: 37816766f4f07d6b03b5d2017c9bb2fb7fbe2e303ef07c85f8262319fd1a0b3fa0b9085720dfdb07661680f85269ce62e3f7c814d7283c925a0674eb0f594007 + languageName: node + linkType: hard + +"@scure/bip39@npm:1.2.1": + version: 1.2.1 + resolution: "@scure/bip39@npm:1.2.1" + dependencies: + "@noble/hashes": "npm:~1.3.0" + "@scure/base": "npm:~1.1.0" + checksum: a4a1145249a93d4a945581cb29f80b8747e675acb1e5c10e52c550f6686115aab692718f1a87b1fe84d45297cb3861e386d288fa525a4c69b8d2a393343433d5 + languageName: node + linkType: hard + "@settlemint/merkle-tools@npm:^1.0.7": version: 1.0.7 resolution: "@settlemint/merkle-tools@npm:1.0.7" @@ -3553,6 +3833,15 @@ __metadata: languageName: node linkType: hard +"@types/ws@npm:8.5.3": + version: 8.5.3 + resolution: "@types/ws@npm:8.5.3" + dependencies: + "@types/node": "npm:*" + checksum: 079fdee163d7cb86d59e5379d2ea6511ba6a46210af420320a4bd52b04b06f86d2c3acc89289f5eae16c8815a562faada8c717fd55a4888c8a5a5f8ce1420112 + languageName: node + linkType: hard + "@types/ws@npm:^8.5.1": version: 8.5.4 resolution: "@types/ws@npm:8.5.4" @@ -4204,6 +4493,7 @@ __metadata: "@zcloak/did": "workspace:^" "@zcloak/did-resolver": "workspace:^" merkletreejs: "npm:^0.3.9" + web3: "npm:^4.1.1" languageName: unknown linkType: soft @@ -6072,6 +6362,15 @@ __metadata: languageName: node linkType: hard +"crc-32@npm:^1.2.2": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: 3412e2f46a8ef7616a1bcd3e656cd075549ae125ab3a965e874d287a5dfda1114b3cc13891007f00ddeef74e1f19a0266fa48871217ac1b3f53f7b5cf1167f70 + languageName: node + linkType: hard + "create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": version: 1.2.0 resolution: "create-hash@npm:1.2.0" @@ -6829,7 +7128,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.5.2, elliptic@npm:^6.5.4": +"elliptic@npm:6.5.4, elliptic@npm:^6.5.2, elliptic@npm:^6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -7617,6 +7916,18 @@ __metadata: languageName: node linkType: hard +"ethereum-cryptography@npm:^2.0.0": + version: 2.1.2 + resolution: "ethereum-cryptography@npm:2.1.2" + dependencies: + "@noble/curves": "npm:1.1.0" + "@noble/hashes": "npm:1.3.1" + "@scure/bip32": "npm:1.3.1" + "@scure/bip39": "npm:1.2.1" + checksum: 689ec9d4f686b628d69895a70b382fe17bd0d46cf52b6538e6fabe64a6bc6e96f1ebea9b491892ed86331e90e198c3ee7917314c02fcdd504e856c1e1fc576b4 + languageName: node + linkType: hard + "ethereumjs-abi@npm:^0.6.8": version: 0.6.8 resolution: "ethereumjs-abi@npm:0.6.8" @@ -8906,7 +9217,7 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": +"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": version: 1.1.7 resolution: "hash.js@npm:1.1.7" dependencies: @@ -9304,7 +9615,7 @@ __metadata: languageName: node linkType: hard -"is-arguments@npm:^1.1.1": +"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1": version: 1.1.1 resolution: "is-arguments@npm:1.1.1" dependencies: @@ -9437,6 +9748,15 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.0.10 + resolution: "is-generator-function@npm:1.0.10" + dependencies: + has-tostringtag: "npm:^1.0.0" + checksum: 5ddb05cd61c043348eaee42bd003d52fa2307827dd1690e6cdb6b205a6b62750f4e41d34d0a6a84793dda6dc6b147405e0ba349e631996beea00631302e36294 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -9675,6 +9995,15 @@ __metadata: languageName: node linkType: hard +"is-typed-array@npm:^1.1.3": + version: 1.1.12 + resolution: "is-typed-array@npm:1.1.12" + dependencies: + which-typed-array: "npm:^1.1.11" + checksum: bbc1e04914affd083808bb10a49b30e59106367560b5a20a696f277f47cd1a96263eda2bc5193811f8cb5677e247865bd8f77863864b2db687d956f059509e5d + languageName: node + linkType: hard + "is-typedarray@npm:^1.0.0, is-typedarray@npm:~1.0.0": version: 1.0.0 resolution: "is-typedarray@npm:1.0.0" @@ -9780,6 +10109,15 @@ __metadata: languageName: node linkType: hard +"isomorphic-ws@npm:^5.0.0": + version: 5.0.0 + resolution: "isomorphic-ws@npm:5.0.0" + peerDependencies: + ws: "*" + checksum: 4c07f7c2fc49e6157adaf8c1563ec135796c66730f119243fec5e0ddb904ab3a9089aefe6a8f70fa6d349ad9585c4b9a5dbdb3147671825fba7b4a5322f9fc99 + languageName: node + linkType: hard + "isstream@npm:~0.1.2": version: 0.1.2 resolution: "isstream@npm:0.1.2" @@ -10327,7 +10665,7 @@ __metadata: languageName: node linkType: hard -"js-sha3@npm:^0.8.0": +"js-sha3@npm:0.8.0, js-sha3@npm:^0.8.0": version: 0.8.0 resolution: "js-sha3@npm:0.8.0" checksum: f7ae73fb14080ea094e95c7401eea57468bde1df93441052b3e9823af1f7a61e814b0f61610212249b8499adedbe92199cbb467cfca799b5003d17701427c994 @@ -13212,6 +13550,7 @@ __metadata: "@zcloak/dev": "npm:^0.31.0" fs-extra: "npm:^11.1.0" rlp: "npm:^3.0.0" + web3: "npm:^4.1.1" bin: build-wasm: scripts/build-wasm.js install-build-deps: scripts/install-build-deps.js @@ -14869,6 +15208,19 @@ __metadata: languageName: node linkType: hard +"util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: "npm:^2.0.3" + is-arguments: "npm:^1.0.4" + is-generator-function: "npm:^1.0.7" + is-typed-array: "npm:^1.1.3" + which-typed-array: "npm:^1.1.2" + checksum: b64a6d3e8ab48037b0f3fb38b6df96e180ab8c430d49386be8444fa2402f26450239bc1fd13aa29c02f3165be380f01aaf88eadb284e77f14df63664a5536e92 + languageName: node + linkType: hard + "utils-merge@npm:1.0.1": version: 1.0.1 resolution: "utils-merge@npm:1.0.1" @@ -14993,6 +15345,206 @@ __metadata: languageName: node linkType: hard +"web3-core@npm:^4.1.1": + version: 4.1.1 + resolution: "web3-core@npm:4.1.1" + dependencies: + web3-errors: "npm:^1.1.1" + web3-eth-iban: "npm:^4.0.5" + web3-providers-http: "npm:^4.0.5" + web3-providers-ipc: "npm:^4.0.5" + web3-providers-ws: "npm:^4.0.5" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + dependenciesMeta: + web3-providers-ipc: + optional: true + checksum: 31891b5139ac1780da2591064c8d945cd7d94bd802df24e3d70cf4da08f031f60e54273e5890033ca7d5182d2178a67d8106507d00b25acf6757f98674ccf2d1 + languageName: node + linkType: hard + +"web3-errors@npm:^1.1.1": + version: 1.1.1 + resolution: "web3-errors@npm:1.1.1" + dependencies: + web3-types: "npm:^1.1.1" + checksum: 4bfa993aa4b452ef346aff2d946261cfa0af6741aa5a9f3bbf96fa8f6d857a4c6113dbae56292d5a74bed10e7c08aa56bd0dfd4e6bca30b5c29da201b9ceae5a + languageName: node + linkType: hard + +"web3-eth-abi@npm:^4.1.1": + version: 4.1.1 + resolution: "web3-eth-abi@npm:4.1.1" + dependencies: + "@ethersproject/abi": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + checksum: 09fdb6ebcfd292cc046014e4ae22aa166dba8c132730c30d4f5eae4fb5b3674f5063c88b4e8b864c88b06b8eda864188636ff72f5de230eb75e1954e49f4f88f + languageName: node + linkType: hard + +"web3-eth-accounts@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-eth-accounts@npm:4.0.5" + dependencies: + "@ethereumjs/rlp": "npm:^4.0.1" + crc-32: "npm:^1.2.2" + ethereum-cryptography: "npm:^2.0.0" + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: bd0c1b4420fa477c8c6eba033cf0fb73dc04633ddf45e8f18850bc470bdcb3a6788928922735001b71546531b1ef67c75d15fc8428740b0c23aeea60eb1f5209 + languageName: node + linkType: hard + +"web3-eth-contract@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-eth-contract@npm:4.0.5" + dependencies: + web3-core: "npm:^4.1.1" + web3-errors: "npm:^1.1.1" + web3-eth: "npm:^4.1.1" + web3-eth-abi: "npm:^4.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: be48c33941aee1f28b46154d578ca5f199d227bda2615e6e5751bc71dff19308e0ca9fe0ca0c8edd2b05ab6b5bd832c9a18c779bd69c468157b0658fcf90afb8 + languageName: node + linkType: hard + +"web3-eth-ens@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-eth-ens@npm:4.0.5" + dependencies: + "@adraffy/ens-normalize": "npm:^1.8.8" + web3-core: "npm:^4.1.1" + web3-errors: "npm:^1.1.1" + web3-eth: "npm:^4.1.1" + web3-eth-contract: "npm:^4.0.5" + web3-net: "npm:^4.0.5" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: 6aebbd8c67bf3537168ffd219cccc28f8fd3944538ed0076aa7f8c09d252d34879635eaeb0720f07fd7315150c509bfbd8a382ba9f67f4581131374a81737c08 + languageName: node + linkType: hard + +"web3-eth-iban@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-eth-iban@npm:4.0.5" + dependencies: + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: 829503f1e94b69243fb07bd9c074f640115dad6156d9f6a95d78cfe22ea529b23de6570f16f2c8e421ea05f16cab6ddcc8d4bce09f170e5da71b580a2af6432b + languageName: node + linkType: hard + +"web3-eth-personal@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-eth-personal@npm:4.0.5" + dependencies: + web3-core: "npm:^4.1.1" + web3-eth: "npm:^4.1.1" + web3-rpc-methods: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: b04e50022b3bdf2291115fdfa759d2d819c0c07a2c53f98e362e71829eb9d8766192e94ea31cc47db3c3480671d83d7b36e1cc7b5b199d04c3c4b5c05816681d + languageName: node + linkType: hard + +"web3-eth@npm:^4.1.1": + version: 4.1.1 + resolution: "web3-eth@npm:4.1.1" + dependencies: + setimmediate: "npm:^1.0.5" + web3-core: "npm:^4.1.1" + web3-errors: "npm:^1.1.1" + web3-eth-abi: "npm:^4.1.1" + web3-eth-accounts: "npm:^4.0.5" + web3-net: "npm:^4.0.5" + web3-providers-ws: "npm:^4.0.5" + web3-rpc-methods: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: 78911ecc7e667225b4442e0251ef7acb30ff7059a3c20f2a3187b0218bab8430f42f72a8b5abf930b768190fb0b3a254c922812662974c1e04b911a85cb9c2d5 + languageName: node + linkType: hard + +"web3-net@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-net@npm:4.0.5" + dependencies: + web3-core: "npm:^4.1.1" + web3-rpc-methods: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + checksum: a0bac3119c880ea0b7a4a10e10cc88a25ceed85be77415567feac891ae10b3f443affb4a388817b1074d8924c5290e71bc7ebe061d4805220451d413ed6ed527 + languageName: node + linkType: hard + +"web3-providers-http@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-providers-http@npm:4.0.5" + dependencies: + cross-fetch: "npm:^3.1.5" + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + checksum: f46abd42e423b8e2eb8aa5be46238388ef008443c9598f44db14038df604acab06906f8199c96aaa122818e66525f9ec3f5ec7b4c757cbbe131431110ec9d331 + languageName: node + linkType: hard + +"web3-providers-ipc@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-providers-ipc@npm:4.0.5" + dependencies: + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + checksum: 9dc1859754bce6c460861ef3d226154ae3360abf2c0380f39de495b9455ec7eef76a6ab277bb72b196a4eff70d49f55e922c6786759a0d0d3364cfa05384efe7 + languageName: node + linkType: hard + +"web3-providers-ws@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-providers-ws@npm:4.0.5" + dependencies: + "@types/ws": "npm:8.5.3" + isomorphic-ws: "npm:^5.0.0" + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + ws: "npm:^8.8.1" + checksum: 15786a7b67b66affb2cac633b1bf0f788a381b84f58555d138ab2a1b0567e5227d830ba873f57e48622015ba1a6089d4fa8f23e46e3f8a5788bc8f558c104dec + languageName: node + linkType: hard + +"web3-rpc-methods@npm:^1.1.1": + version: 1.1.1 + resolution: "web3-rpc-methods@npm:1.1.1" + dependencies: + web3-core: "npm:^4.1.1" + web3-types: "npm:^1.1.1" + web3-validator: "npm:^2.0.1" + checksum: da096bed37e08c123a95882a7d026b2ea30da794d38145cf0a887dbf657d8dc9d52c93af828333d5b0f40ec0889373166d06ac2e4e85282ebc2693692ea5b77b + languageName: node + linkType: hard + +"web3-types@npm:^1.1.1": + version: 1.1.1 + resolution: "web3-types@npm:1.1.1" + checksum: 132cf6b684941003623ea76e81ad70478f8ec014e56e4d44a59aa0b903a76bdc771c34086427029a6ef57ecce6112c8a5fdc86fe0961c33ce663d1dd1cb5841b + languageName: node + linkType: hard + "web3-utils@npm:^1.3.4": version: 1.9.0 resolution: "web3-utils@npm:1.9.0" @@ -15008,6 +15560,55 @@ __metadata: languageName: node linkType: hard +"web3-utils@npm:^4.0.5": + version: 4.0.5 + resolution: "web3-utils@npm:4.0.5" + dependencies: + ethereum-cryptography: "npm:^2.0.0" + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-validator: "npm:^2.0.1" + checksum: 69bb8b3eb60b430559fa6c6f56a166433fc30584514b82d1290d41df2b95b30eefd056bac1e4ca776cd65636cd34bfd3e07bf1a1ab540c2064c6d78f6886803e + languageName: node + linkType: hard + +"web3-validator@npm:^2.0.1": + version: 2.0.1 + resolution: "web3-validator@npm:2.0.1" + dependencies: + ethereum-cryptography: "npm:^2.0.0" + util: "npm:^0.12.5" + web3-errors: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + zod: "npm:^3.21.4" + checksum: 008d64498533f90fa7ceb75007f23516a4b975934ed24f35c66be71b6e7e2aebfd079e22a68e1436ca45ddfb690e8afcda016da9cb98520d36ff9f3276f63323 + languageName: node + linkType: hard + +"web3@npm:^4.1.1": + version: 4.1.1 + resolution: "web3@npm:4.1.1" + dependencies: + web3-core: "npm:^4.1.1" + web3-errors: "npm:^1.1.1" + web3-eth: "npm:^4.1.1" + web3-eth-abi: "npm:^4.1.1" + web3-eth-accounts: "npm:^4.0.5" + web3-eth-contract: "npm:^4.0.5" + web3-eth-ens: "npm:^4.0.5" + web3-eth-iban: "npm:^4.0.5" + web3-eth-personal: "npm:^4.0.5" + web3-net: "npm:^4.0.5" + web3-providers-http: "npm:^4.0.5" + web3-providers-ws: "npm:^4.0.5" + web3-rpc-methods: "npm:^1.1.1" + web3-types: "npm:^1.1.1" + web3-utils: "npm:^4.0.5" + web3-validator: "npm:^2.0.1" + checksum: 907e02d4ae666b97f3db16e2f4500d5b98e50bc82e789dff7802878e0d1f46ef571aaf5205e28522fc22073f714f7465b1ea7c9ee8d8e40ceced246dec074252 + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" @@ -15293,6 +15894,19 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.2": + version: 1.1.11 + resolution: "which-typed-array@npm:1.1.11" + dependencies: + available-typed-arrays: "npm:^1.0.5" + call-bind: "npm:^1.0.2" + for-each: "npm:^0.3.3" + gopd: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.0" + checksum: b1ba153cb37bb901c64012e256666d5a3e9ad915a1e0f12fd0c8d128f5158a88a85520d28f432ea658393f66f3520684d3c315ceedac8d348a4af067663efaaa + languageName: node + linkType: hard + "which-typed-array@npm:^1.1.9": version: 1.1.9 resolution: "which-typed-array@npm:1.1.9" @@ -15612,3 +16226,10 @@ __metadata: checksum: 63eceacd482622afd71290541a9823a0e5eed88a6b58a5d136a5fb8151ed4d1549c80f28d74d4ad351582f9890635d49e6cf70f8d3cc64948640f839f6a37c70 languageName: node linkType: hard + +"zod@npm:^3.21.4": + version: 3.22.2 + resolution: "zod@npm:3.22.2" + checksum: b6158a49b57cb2f6454789005f9989db4df0dbe213186d3356be56c8ea01a5bc8c9c9af7795ef2156539526bf350e0fd351b0ecb8e1bcff5a6511b1b40293ed0 + languageName: node + linkType: hard