From d2309b0c0d8aa547c6b3e9386e61c9ae0aab8018 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 17:13:36 +0100 Subject: [PATCH 01/10] feat(script): add `sync` script to sync lit action to ipfs --- packages/wrapped-keys-lit-actions/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/wrapped-keys-lit-actions/package.json b/packages/wrapped-keys-lit-actions/package.json index e3420fbc4c..5417b0589c 100644 --- a/packages/wrapped-keys-lit-actions/package.json +++ b/packages/wrapped-keys-lit-actions/package.json @@ -24,7 +24,8 @@ "genReact": false }, "scripts": { - "generate-lit-actions": "yarn node ./esbuild.config.js" + "generate-lit-actions": "yarn node ./esbuild.config.js", + "sync": "yarn node sync-actions-to-ipfs.js" }, "version": "6.9.0", "main": "./dist/src/index.js", From 2489cfd3225b3b79500eab8a22f6efa29010c2d3 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 17:13:59 +0100 Subject: [PATCH 02/10] feat(interface): add `getLitActionSessionSigs` interface --- packages/types/src/lib/ILitNodeClient.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/types/src/lib/ILitNodeClient.ts b/packages/types/src/lib/ILitNodeClient.ts index 0f8b3646b0..5a4e2e5bc0 100644 --- a/packages/types/src/lib/ILitNodeClient.ts +++ b/packages/types/src/lib/ILitNodeClient.ts @@ -18,6 +18,8 @@ import { RejectedNodePromises, SendNodeCommand, SuccessNodePromises, + GetLitActionSessionSigs, + SessionSigsMap, } from './interfaces'; import { ILitResource, ISessionCapabilityObject } from './models'; import { SupportedJsonRequests } from './types'; @@ -227,4 +229,16 @@ export interface ILitNodeClient { generateSessionCapabilityObjectWithWildcards( litResources: ILitResource[] ): Promise; + + /** + * Retrieves session signatures specifically for Lit Actions. + * Unlike `getPkpSessionSigs`, this function requires either `litActionCode` or `litActionIpfsId`, and `jsParams` must be provided. + * + * @param params - The parameters required for retrieving the session signatures. + * @returns A promise that resolves with the session signatures. + */ + getLitActionSessionSigs( + params: GetLitActionSessionSigs + ): Promise + } From 49045974a2c67182ed997f23b14511bfaf9c8745 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 18:10:50 +0100 Subject: [PATCH 03/10] test(wip): add testUseTriaAuthAndWrappedKeysSessionSigsGen --- local-tests/test.ts | 4 + ...UseTriaAuthAndWrappedKeysSessionSigsGen.ts | 122 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts diff --git a/local-tests/test.ts b/local-tests/test.ts index 431460344b..21bc0e52bc 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -108,6 +108,7 @@ import { testBatchGeneratePrivateKeys } from './tests/wrapped-keys/testBatchGene import { setLitActionsCodeToLocal } from './tests/wrapped-keys/util'; import { testUseEoaSessionSigsToRequestSingleResponse } from './tests/testUseEoaSessionSigsToRequestSingleResponse'; +import { testUseTriaAuthAndWrappedKeysSessionSigsGen } from './tests/testUseTriaAuthAndWrappedKeysSessionSigsGen'; // Use the current LIT action code to test against setLitActionsCodeToLocal(); @@ -171,7 +172,10 @@ setLitActionsCodeToLocal(); testUseEoaSessionSigsToEncryptDecryptString, testUseEoaSessionSigsToEncryptDecryptFile, testUseEoaSessionSigsToEncryptDecryptZip, + + // single node execution testUseEoaSessionSigsToRequestSingleResponse, + testUseTriaAuthAndWrappedKeysSessionSigsGen }; const pkpSessionSigsTests = { diff --git a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts new file mode 100644 index 0000000000..4b82ae2551 --- /dev/null +++ b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts @@ -0,0 +1,122 @@ +import { LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers'; +import { log } from '@lit-protocol/misc'; +import { LitAbility } from '@lit-protocol/types'; +import { getLitActionSessionSigs, getLitActionSessionSigsUsingIpfsId } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; + +/** + * Test Commands: + * ✅ NETWORK=datil-dev yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen + * ✅ NETWORK=datil-test yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen + * ✅ NETWORK=datil yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen + */ +export const testUseTriaAuthAndWrappedKeysSessionSigsGen = + async (devEnv: TinnyEnvironment) => { + + const alice = await devEnv.createRandomPerson(); + + // -- Start + + // -- mint a pkp + console.log(`🔄 Minting new PKP...`); + const pkpMintRes = await devEnv.contractsClient.pkpNftContractUtils.write.mint(); + const pkp = pkpMintRes.pkp; + console.log(` ✅ PKP minted:`); + console.log(` - Token ID: ${pkp.tokenId}`); + console.log(` - Public Key: ${pkp.publicKey}`); + console.log(` - ETH Address: ${pkp.ethAddress}`); + + // -- mint capacity token + console.log(`🔄 Minting Capacity Credits NFT...`); + const capacityTokenId = ( + await devEnv.contractsClient.mintCapacityCreditsNFT({ + requestsPerKilosecond: 10, + daysUntilUTCMidnightExpiration: 1, + }) + ).capacityTokenIdStr; + console.log(` ✅ Capacity Credits NFT minted:`); + + // -- create capacity delegation auth sig + console.log(`🔄 Creating Capacity Delegation AuthSig...`); + const authSigResponse = await devEnv.litNodeClient.createCapacityDelegationAuthSig({ + dAppOwnerWallet: alice.wallet, + capacityTokenId, + delegateeAddresses: [pkp.ethAddress], + uses: "1", + }); + const capacityDelegationAuthSig = authSigResponse.capacityDelegationAuthSig; + console.log(` ✅ Capacity Delegation AuthSig created:`); + console.log(` - AuthSig: ${JSON.stringify(capacityDelegationAuthSig)}`); + console.log(` - Uses: 1`); + console.log(` - Delegatee Address: ${pkp.ethAddress}`); + console.log(` - Capacity Token ID: ${capacityTokenId}`); + + // -- Get the lit action code.. + + + process.exit(); + + const litActionSessionSigs = await devEnv.litNodeClient.getLitActionSessionSigs({ + pkpPublicKey: alice.authMethodOwnedPkp.publicKey, + expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), // 10 mins expiry + resourceAbilityRequests: [ + { + resource: new LitPKPResource("*"), + ability: LitAbility.PKPSigning, + }, + { + resource: new LitActionResource("*"), + ability: LitAbility.LitActionExecution, + }, + ], + litActionCode: Buffer.from(` + // Works with an AuthSig AuthMethod + if (Lit.Auth.authMethodContexts.some(e => e.authMethodType === 1)) { + LitActions.setResponse({ response: "true" }); + } else { + LitActions.setResponse({ response: "false" }); + } + `).toString("base64"), + jsParams: { + magicNumber: 42, + }, + capabilityAuthSigs: [capacityDelegationAuthSig], + }); + + // const litActionSessionSigs = await getLitActionSessionSigs(devEnv, alice) + + console.log("litActionSessionSigs:", litActionSessionSigs); + process.exit(); + + // -- Remove below + // const litActionSessionSigs = await getLitActionSessionSigsUsingIpfsId( + // devEnv, + // alice, + // [ + // { + // resource: new LitPKPResource('*'), + // ability: LitAbility.PKPSigning, + // }, + // { + // resource: new LitActionResource('*'), + // ability: LitAbility.LitActionExecution, + // }, + // ] + // ); + + // const res = await devEnv.litNodeClient.executeJs({ + // sessionSigs: litActionSessionSigs, + // code: `(async () => { + // const sigShare = await LitActions.signEcdsa({ + // toSign: dataToSign, + // publicKey, + // sigName: "sig", + // }); + // })();`, + // jsParams: { + // dataToSign: alice.loveLetter, + // publicKey: alice.authMethodOwnedPkp.publicKey, + // }, + // }); + + }; From eb44e7cc4e3b85ddfda38ed937c351d0daf6d900 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 18:50:03 +0100 Subject: [PATCH 04/10] feat(wip): add tria batch gen key function --- local-tests/test.ts | 2 +- ...UseTriaAuthAndWrappedKeysSessionSigsGen.ts | 156 +++++++++--------- local-tests/tests/wrapped-keys/util.ts | 2 + packages/types/src/lib/ILitNodeClient.ts | 3 +- .../esbuild.config.js | 3 + .../wrapped-keys-lit-actions/src/index.ts | 6 + .../tria_batchGenerateEncryptedKeys.js | 149 +++++++++++++++++ packages/wrapped-keys-lit-actions/test.ts | 21 +++ packages/wrapped-keys/src/index.ts | 3 + .../tria-batch-generate-private-keys.ts | 75 +++++++++ packages/wrapped-keys/src/lib/api/index.ts | 4 + .../lib/lit-actions-client/code-repository.ts | 11 +- .../src/lib/lit-actions-client/constants.ts | 1 + .../src/lib/lit-actions-client/types.ts | 12 +- 14 files changed, 364 insertions(+), 84 deletions(-) create mode 100644 packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js create mode 100644 packages/wrapped-keys-lit-actions/test.ts create mode 100644 packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts diff --git a/local-tests/test.ts b/local-tests/test.ts index 21bc0e52bc..a96b93ce87 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -175,7 +175,7 @@ setLitActionsCodeToLocal(); // single node execution testUseEoaSessionSigsToRequestSingleResponse, - testUseTriaAuthAndWrappedKeysSessionSigsGen + testUseTriaAuthAndWrappedKeysSessionSigsGen, }; const pkpSessionSigsTests = { diff --git a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts index 4b82ae2551..77c6e5d7d1 100644 --- a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts +++ b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts @@ -1,7 +1,10 @@ import { LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers'; import { log } from '@lit-protocol/misc'; import { LitAbility } from '@lit-protocol/types'; -import { getLitActionSessionSigs, getLitActionSessionSigsUsingIpfsId } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs'; +import { + getLitActionSessionSigs, + getLitActionSessionSigsUsingIpfsId, +} from 'local-tests/setup/session-sigs/get-lit-action-session-sigs'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; /** @@ -10,113 +13,116 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; * ✅ NETWORK=datil-test yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen * ✅ NETWORK=datil yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen */ -export const testUseTriaAuthAndWrappedKeysSessionSigsGen = - async (devEnv: TinnyEnvironment) => { +export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( + devEnv: TinnyEnvironment +) => { + const alice = await devEnv.createRandomPerson(); - const alice = await devEnv.createRandomPerson(); + // -- Start - // -- Start + // -- mint a pkp + console.log(`🔄 Minting new PKP...`); + const pkpMintRes = + await devEnv.contractsClient.pkpNftContractUtils.write.mint(); + const pkp = pkpMintRes.pkp; + console.log(` ✅ PKP minted:`); + console.log(` - Token ID: ${pkp.tokenId}`); + console.log(` - Public Key: ${pkp.publicKey}`); + console.log(` - ETH Address: ${pkp.ethAddress}`); - // -- mint a pkp - console.log(`🔄 Minting new PKP...`); - const pkpMintRes = await devEnv.contractsClient.pkpNftContractUtils.write.mint(); - const pkp = pkpMintRes.pkp; - console.log(` ✅ PKP minted:`); - console.log(` - Token ID: ${pkp.tokenId}`); - console.log(` - Public Key: ${pkp.publicKey}`); - console.log(` - ETH Address: ${pkp.ethAddress}`); + // -- mint capacity token + console.log(`🔄 Minting Capacity Credits NFT...`); + const capacityTokenId = ( + await devEnv.contractsClient.mintCapacityCreditsNFT({ + requestsPerKilosecond: 10, + daysUntilUTCMidnightExpiration: 1, + }) + ).capacityTokenIdStr; + console.log(` ✅ Capacity Credits NFT minted:`); - // -- mint capacity token - console.log(`🔄 Minting Capacity Credits NFT...`); - const capacityTokenId = ( - await devEnv.contractsClient.mintCapacityCreditsNFT({ - requestsPerKilosecond: 10, - daysUntilUTCMidnightExpiration: 1, - }) - ).capacityTokenIdStr; - console.log(` ✅ Capacity Credits NFT minted:`); - - // -- create capacity delegation auth sig - console.log(`🔄 Creating Capacity Delegation AuthSig...`); - const authSigResponse = await devEnv.litNodeClient.createCapacityDelegationAuthSig({ + // -- create capacity delegation auth sig + console.log(`🔄 Creating Capacity Delegation AuthSig...`); + const authSigResponse = + await devEnv.litNodeClient.createCapacityDelegationAuthSig({ dAppOwnerWallet: alice.wallet, capacityTokenId, delegateeAddresses: [pkp.ethAddress], - uses: "1", + uses: '1', }); - const capacityDelegationAuthSig = authSigResponse.capacityDelegationAuthSig; - console.log(` ✅ Capacity Delegation AuthSig created:`); - console.log(` - AuthSig: ${JSON.stringify(capacityDelegationAuthSig)}`); - console.log(` - Uses: 1`); - console.log(` - Delegatee Address: ${pkp.ethAddress}`); - console.log(` - Capacity Token ID: ${capacityTokenId}`); - - // -- Get the lit action code.. + const capacityDelegationAuthSig = authSigResponse.capacityDelegationAuthSig; + console.log(` ✅ Capacity Delegation AuthSig created:`); + console.log(` - AuthSig: ${JSON.stringify(capacityDelegationAuthSig)}`); + console.log(` - Uses: 1`); + console.log(` - Delegatee Address: ${pkp.ethAddress}`); + console.log(` - Capacity Token ID: ${capacityTokenId}`); + // -- Get the lit action code.. - process.exit(); + process.exit(); - const litActionSessionSigs = await devEnv.litNodeClient.getLitActionSessionSigs({ + const litActionSessionSigs = + await devEnv.litNodeClient.getLitActionSessionSigs({ pkpPublicKey: alice.authMethodOwnedPkp.publicKey, expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), // 10 mins expiry resourceAbilityRequests: [ { - resource: new LitPKPResource("*"), + resource: new LitPKPResource('*'), ability: LitAbility.PKPSigning, }, { - resource: new LitActionResource("*"), + resource: new LitActionResource('*'), ability: LitAbility.LitActionExecution, }, ], - litActionCode: Buffer.from(` + litActionCode: Buffer.from( + ` // Works with an AuthSig AuthMethod if (Lit.Auth.authMethodContexts.some(e => e.authMethodType === 1)) { LitActions.setResponse({ response: "true" }); } else { LitActions.setResponse({ response: "false" }); } - `).toString("base64"), + ` + ).toString('base64'), jsParams: { magicNumber: 42, }, capabilityAuthSigs: [capacityDelegationAuthSig], }); - // const litActionSessionSigs = await getLitActionSessionSigs(devEnv, alice) - - console.log("litActionSessionSigs:", litActionSessionSigs); - process.exit(); + // const litActionSessionSigs = await getLitActionSessionSigs(devEnv, alice) - // -- Remove below - // const litActionSessionSigs = await getLitActionSessionSigsUsingIpfsId( - // devEnv, - // alice, - // [ - // { - // resource: new LitPKPResource('*'), - // ability: LitAbility.PKPSigning, - // }, - // { - // resource: new LitActionResource('*'), - // ability: LitAbility.LitActionExecution, - // }, - // ] - // ); + console.log('litActionSessionSigs:', litActionSessionSigs); + process.exit(); - // const res = await devEnv.litNodeClient.executeJs({ - // sessionSigs: litActionSessionSigs, - // code: `(async () => { - // const sigShare = await LitActions.signEcdsa({ - // toSign: dataToSign, - // publicKey, - // sigName: "sig", - // }); - // })();`, - // jsParams: { - // dataToSign: alice.loveLetter, - // publicKey: alice.authMethodOwnedPkp.publicKey, - // }, - // }); + // -- Remove below + // const litActionSessionSigs = await getLitActionSessionSigsUsingIpfsId( + // devEnv, + // alice, + // [ + // { + // resource: new LitPKPResource('*'), + // ability: LitAbility.PKPSigning, + // }, + // { + // resource: new LitActionResource('*'), + // ability: LitAbility.LitActionExecution, + // }, + // ] + // ); - }; + // const res = await devEnv.litNodeClient.executeJs({ + // sessionSigs: litActionSessionSigs, + // code: `(async () => { + // const sigShare = await LitActions.signEcdsa({ + // toSign: dataToSign, + // publicKey, + // sigName: "sig", + // }); + // })();`, + // jsParams: { + // dataToSign: alice.loveLetter, + // publicKey: alice.authMethodOwnedPkp.publicKey, + // }, + // }); +}; diff --git a/local-tests/tests/wrapped-keys/util.ts b/local-tests/tests/wrapped-keys/util.ts index 4f3573fe33..c20a9087dd 100644 --- a/local-tests/tests/wrapped-keys/util.ts +++ b/local-tests/tests/wrapped-keys/util.ts @@ -15,6 +15,8 @@ import type { const emptyLitActionRepositoryCommon: LitActionCodeRepositoryCommon = { batchGenerateEncryptedKeys: '', + + tria_batchGenerateEncryptedKeys: '', }; const emptyLitActionRepository: LitActionCodeRepository = { diff --git a/packages/types/src/lib/ILitNodeClient.ts b/packages/types/src/lib/ILitNodeClient.ts index 5a4e2e5bc0..dcee100d72 100644 --- a/packages/types/src/lib/ILitNodeClient.ts +++ b/packages/types/src/lib/ILitNodeClient.ts @@ -239,6 +239,5 @@ export interface ILitNodeClient { */ getLitActionSessionSigs( params: GetLitActionSessionSigs - ): Promise - + ): Promise; } diff --git a/packages/wrapped-keys-lit-actions/esbuild.config.js b/packages/wrapped-keys-lit-actions/esbuild.config.js index 7b0ba54732..b442a0f8ef 100644 --- a/packages/wrapped-keys-lit-actions/esbuild.config.js +++ b/packages/wrapped-keys-lit-actions/esbuild.config.js @@ -58,6 +58,9 @@ module.exports = { './src/lib/ethereum/generateEncryptedEthereumPrivateKey.js', './src/lib/common/exportPrivateKey.js', './src/lib/common/batchGenerateEncryptedKeys.js', + + // bespoke + './src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js', ], bundle: true, minify: true, diff --git a/packages/wrapped-keys-lit-actions/src/index.ts b/packages/wrapped-keys-lit-actions/src/index.ts index 8ca684ec8c..13f6fd8699 100644 --- a/packages/wrapped-keys-lit-actions/src/index.ts +++ b/packages/wrapped-keys-lit-actions/src/index.ts @@ -12,6 +12,9 @@ import type { LitActionCodeRepositoryCommon, } from '@lit-protocol/wrapped-keys'; +// bespoke +import * as tria_batchGenerateEncryptedKeys from './generated/common/bespoke/tria_batchGenerateEncryptedKeys'; + const litActionRepository: LitActionCodeRepository = { signTransaction: { evm: signTransactionWithEthereumEncryptedKey.code, @@ -33,6 +36,9 @@ const litActionRepository: LitActionCodeRepository = { const litActionRepositoryCommon: LitActionCodeRepositoryCommon = { batchGenerateEncryptedKeys: batchGenerateEncryptedKeys.code, + + // bespoke + tria_batchGenerateEncryptedKeys: tria_batchGenerateEncryptedKeys.code, }; export { diff --git a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js new file mode 100644 index 0000000000..8824d5362f --- /dev/null +++ b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js @@ -0,0 +1,149 @@ +const { encryptPrivateKey } = require('./../internal/encryptKey'); +const { + generateEthereumPrivateKey, +} = require('../../ethereum/internal/generatePrivateKey'); +const { + signMessageEthereumKey, +} = require('../../ethereum/internal/signMessage'); +const { + generateSolanaPrivateKey, +} = require('../../solana/internal/generatePrivateKey'); +const { signMessageSolanaKey } = require('../../solana/internal/signMessage'); + +/* "TRIA" global accessControlConditions, actions, Lit*/ + +async function processEthereumAction(action) { + const { network, generateKeyParams } = action; + const messageToSign = action.signMessageParams?.messageToSign; + + const ethereumKey = generateEthereumPrivateKey(); + + const [generatedPrivateKey, messageSignature] = await Promise.all([ + encryptPrivateKey({ + accessControlConditions, + publicKey: ethereumKey.publicKey, + privateKey: ethereumKey.privateKey, + }), + messageToSign + ? signMessageEthereumKey({ + messageToSign: messageToSign, + privateKey: ethereumKey.privateKey, + }) + : Promise.resolve(), + ]); + + return { + network, + generateEncryptedPrivateKey: { + ...generatedPrivateKey, + memo: generateKeyParams.memo, + }, + ...(messageSignature + ? { signMessage: { signature: messageSignature } } + : {}), + }; +} + +async function processSolanaAction(action) { + const { network, generateKeyParams } = action; + + const messageToSign = action.signMessageParams?.messageToSign; + + const solanaKey = generateSolanaPrivateKey(); + + const [generatedPrivateKey, messageSignature] = await Promise.all([ + encryptPrivateKey({ + accessControlConditions, + publicKey: solanaKey.publicKey, + privateKey: solanaKey.privateKey, + }), + messageToSign + ? signMessageSolanaKey({ + messageToSign: messageToSign, + privateKey: solanaKey.privateKey, + }) + : Promise.resolve(), + ]); + + return { + network, + generateEncryptedPrivateKey: { + ...generatedPrivateKey, + memo: generateKeyParams.memo, + }, + ...(messageSignature + ? { signMessage: { signature: messageSignature } } + : {}), + }; +} + +async function processActions(actions) { + return Promise.all( + actions.map(async (action, ndx) => { + const { network } = action; + + if (network === 'evm') { + return await processEthereumAction(action, ndx); + } else if (network === 'solana') { + return await processSolanaAction(action, ndx); + } else { + // Just in case :tm: + throw new Error(`Invalid network for action[${ndx}]: ${network}`); + } + }) + ); +} + +function validateParams(actions) { + if (!actions) { + throw new Error('Missing required field: actions'); + } + + if (!actions.length) { + throw new Error('No actions provided (empty array?)'); + } + + actions.forEach((action, ndx) => { + if (!['evm', 'solana'].includes(action.network)) { + throw new Error( + `Invalid field: actions[${ndx}].network: ${action.network}` + ); + } + + if (!action.generateKeyParams) { + throw new Error( + `Missing required field: actions[${ndx}].generateKeyParams` + ); + } + + if (!action.generateKeyParams?.memo) { + throw new Error( + `Missing required field: actions[${ndx}].generateKeyParams.memo` + ); + } + + if (action.signMessageParams && !action.signMessageParams?.messageToSign) { + throw new Error( + `Missing required field: actions[${ndx}].signMessageParams.messageToSign` + ); + } + }); +} + +(async () => { + try { + validateParams(actions); + + const batchGeneratePrivateKeysActionResult = await processActions(actions); + + Lit.Actions.setResponse({ + response: JSON.stringify(batchGeneratePrivateKeysActionResult), + }); + + // 1. Generate both EVM and solana private keys + // 2. Run appropriate signMessage for each key _and_ encrypt the keys for persistence to wrapped-keys backend + // 3. Return results for both signMessage ops and both encrypted key payloads for persistence + } catch (err) { + Lit.Actions.setResponse({ response: `Error: ${err.message}` }); + } +})(); diff --git a/packages/wrapped-keys-lit-actions/test.ts b/packages/wrapped-keys-lit-actions/test.ts new file mode 100644 index 0000000000..52d9138ede --- /dev/null +++ b/packages/wrapped-keys-lit-actions/test.ts @@ -0,0 +1,21 @@ +// const ansonTestCredential = { "authMethod": { "authMethodType": "0xf8d39b7f3ec30f4bd2e45e0d545c83f64f8364a2c53765ca42ccf9bf7cde3482", "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiNjcwZmVhM2EtOWQ5Yi00NzIyLWEwYWEtYTRkZDlmMTY2ZjM5IiwiZW1haWwiOiJhbnNvbkBsaXRwcm90b2NvbC5jb20iLCJpYXQiOjE3Mjg2NTg1NTUsImV4cCI6MTcyOTI2MzM1NX0.JyXdgpN_ioqPq0kfeSHaA9hh7NZEyP_gBGQ5415kKyY", "userOauthId": "anson@litprotocol.com", "userKey": "anson@litprotocol.com" }, "pubKey": "0x04d168bedc060af4f7e7dc4d84e8c7bd8b3e8c4aa98ebecd2fcd2982a8ef72f799b87611e71d6b04d5b0ee9195c621a827e2ffb529742d809fe366648f48e6b1f5" }; + +// const url = 'https://api.development.tria.so/api/v1/user/info'; +// const response = await fetch(url, { +// method: 'GET', +// headers: { +// Authorization: `Bearer ${ansonTestCredential.authMethod.accessToken}`, +// }, +// }); + +// // { +// // success: true, +// // userInfo: { +// // uuid: "xxxxxxxx-yyyy-zzzz-aaaa-bbbbbbbbbbbb", +// // email: "xxx@xxx.com", +// // iat: 1728658555, +// // exp: 1729263355, +// // }, +// // } +// const data = await response.json(); +// console.log('data', data); diff --git a/packages/wrapped-keys/src/index.ts b/packages/wrapped-keys/src/index.ts index ea0b95d524..797dada407 100644 --- a/packages/wrapped-keys/src/index.ts +++ b/packages/wrapped-keys/src/index.ts @@ -8,6 +8,9 @@ import { storeEncryptedKey, listEncryptedKeyMetadata, batchGeneratePrivateKeys, + + // bespoke + triaBatchGeneratePrivateKeys, } from './lib/api'; import { CHAIN_ETHEREUM, diff --git a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts new file mode 100644 index 0000000000..b0635d2a33 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts @@ -0,0 +1,75 @@ +import { getKeyTypeFromNetwork } from './../utils'; +import { batchGenerateKeysWithLitAction } from '../../lit-actions-client'; +import { getLitActionCodeOrCidCommon } from '../../lit-actions-client/utils'; +import { storePrivateKey } from '../../service-client'; +import { + BatchGeneratePrivateKeysActionResult, + BatchGeneratePrivateKeysParams, + BatchGeneratePrivateKeysResult, +} from '../../types'; +import { + getFirstSessionSig, + getPkpAccessControlCondition, + getPkpAddressFromSessionSig, +} from '../../utils'; + +/** + * TODO: Document batch behaviour + * @param { BatchGeneratePrivateKeysParams } params Parameters to use for generating keys and optionally signing messages + * + * @returns { Promise } - The generated keys and, optionally, signed messages + */ +export async function triaBatchGeneratePrivateKeys( + params: BatchGeneratePrivateKeysParams +): Promise { + const { pkpSessionSigs, litNodeClient } = params; + + const sessionSig = getFirstSessionSig(pkpSessionSigs); + const pkpAddress = getPkpAddressFromSessionSig(sessionSig); + + const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); + + const { litActionCode, litActionIpfsCid } = getLitActionCodeOrCidCommon( + 'batchGenerateEncryptedKeys' + ); + + const actionResults = await batchGenerateKeysWithLitAction({ + ...params, + litActionIpfsCid: litActionCode ? undefined : litActionIpfsCid, + litActionCode: litActionCode ? litActionCode : undefined, + accessControlConditions: [allowPkpAddressToDecrypt], + pkpSessionSigs, + }); + + const results = await Promise.all( + actionResults.map( + async (result): Promise => { + const { generateEncryptedPrivateKey, network } = result; + + const signature = result.signMessage?.signature; + + const { id } = await storePrivateKey({ + sessionSig, + storedKeyMetadata: { + ...generateEncryptedPrivateKey, + keyType: getKeyTypeFromNetwork(network), + pkpAddress, + }, + litNetwork: litNodeClient.config.litNetwork, + }); + + return { + ...(signature ? { signMessage: { signature } } : {}), + generateEncryptedPrivateKey: { + memo: generateEncryptedPrivateKey.memo, + id, + generatedPublicKey: generateEncryptedPrivateKey.publicKey, + pkpAddress, + }, + }; + } + ) + ); + + return { pkpAddress, results }; +} diff --git a/packages/wrapped-keys/src/lib/api/index.ts b/packages/wrapped-keys/src/lib/api/index.ts index d13292a017..c2ad1b823c 100644 --- a/packages/wrapped-keys/src/lib/api/index.ts +++ b/packages/wrapped-keys/src/lib/api/index.ts @@ -7,6 +7,7 @@ import { listEncryptedKeyMetadata } from './list-encrypted-key-metadata'; import { signMessageWithEncryptedKey } from './sign-message-with-encrypted-key'; import { signTransactionWithEncryptedKey } from './sign-transaction-with-encrypted-key'; import { storeEncryptedKey } from './store-encrypted-key'; +import { triaBatchGeneratePrivateKeys } from './bespoke/tria-batch-generate-private-keys'; export { listEncryptedKeyMetadata, @@ -18,4 +19,7 @@ export { storeEncryptedKey, getEncryptedKey, batchGeneratePrivateKeys, + + // bespoke + triaBatchGeneratePrivateKeys, }; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts b/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts index 54363e47a2..2323d99a5c 100644 --- a/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts +++ b/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts @@ -53,11 +53,9 @@ function assertIsLitActionRepositoryEntry( ): asserts entry is LitActionCodeRepositoryEntry { if ( typeof entry !== 'object' || - !entry || - // @ts-expect-error assert function - ('evm' in entry && typeof entry.evm !== 'string') || - // @ts-expect-error assert function - ('solana' in entry && typeof entry.solana !== 'string') || + entry === null || // Ensure entry is not null + ('evm' in entry && typeof (entry as any).evm !== 'string') || + ('solana' in entry && typeof (entry as any).solana !== 'string') || Object.keys(entry).some((key) => !['evm', 'solana'].includes(key)) ) { throw new Error( @@ -89,6 +87,9 @@ function setLitActionsCode(repository: LitActionCodeRepositoryInput) { */ const litActionCodeRepositoryCommon: LitActionCodeRepositoryCommon = { batchGenerateEncryptedKeys: '', + + // bespoke + tria_batchGenerateEncryptedKeys: '', }; function assertIsLitActionKeyCommon( diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts b/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts index 83360f84fc..7b4304c12a 100644 --- a/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts +++ b/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts @@ -21,6 +21,7 @@ const LIT_ACTION_CID_REPOSITORY: LitCidRepository = Object.freeze({ const LIT_ACTION_CID_REPOSITORY_COMMON: LitCidRepositoryCommon = Object.freeze({ batchGenerateEncryptedKeys: 'QmR8Zs7ctSEctxBrSnAYhMXFXCC1ub8K1xvMn5Js3NCSAA', + tria_batchGenerateEncryptedKeys: 'xxx', }); export { LIT_ACTION_CID_REPOSITORY, LIT_ACTION_CID_REPOSITORY_COMMON }; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/types.ts b/packages/wrapped-keys/src/lib/lit-actions-client/types.ts index bda28ecd57..ce87c80680 100644 --- a/packages/wrapped-keys/src/lib/lit-actions-client/types.ts +++ b/packages/wrapped-keys/src/lib/lit-actions-client/types.ts @@ -6,7 +6,17 @@ export type LitActionType = | 'generateEncryptedKey' | 'exportPrivateKey'; -export type LitActionTypeCommon = 'batchGenerateEncryptedKeys'; +export type LitActionTypeCommon = + | 'batchGenerateEncryptedKeys' + | BespokeLitActionTypes; + +export type BespokeLitActionTypes = Tria_LitActionTypeCommon; +// | Foo_LitActionTypeCommon +// | Bar_LitActionTypeCommon + +export type Tria_LitActionTypeCommon = 'tria_batchGenerateEncryptedKeys'; +// export type Foo_LitActionTypeCommon = 'FooBatchGenerateEncryptedKeys'; +// export type Bar_LitActionTypeCommon = 'BarBatchGenerateEncryptedKeys'; export type LitCidRepositoryEntry = Readonly>; From 60ec3db3da0199065bc61b5aca28e8813d4d0444 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 21:01:34 +0100 Subject: [PATCH 05/10] feat: add session sigs resource parser --- packages/misc/src/index.ts | 7 +- .../lib/helper/session-sigs-reader.test.ts | 73 +++++++- .../src/lib/helper/session-sigs-reader.ts | 166 ++++++++++++++++++ 3 files changed, 244 insertions(+), 2 deletions(-) diff --git a/packages/misc/src/index.ts b/packages/misc/src/index.ts index 88be5e3cc5..bb180364ca 100644 --- a/packages/misc/src/index.ts +++ b/packages/misc/src/index.ts @@ -2,5 +2,10 @@ export * from './lib/misc'; export { validateSessionSig, validateSessionSigs, + parseSignedMessage, } from './lib/helper/session-sigs-validator'; -export { formatSessionSigs } from './lib/helper/session-sigs-reader'; +export { + formatSessionSigs, + formatSessionSigsJSON, + getResourcesFromSessionSigs +} from './lib/helper/session-sigs-reader'; diff --git a/packages/misc/src/lib/helper/session-sigs-reader.test.ts b/packages/misc/src/lib/helper/session-sigs-reader.test.ts index dc34aab025..aee39f95ac 100644 --- a/packages/misc/src/lib/helper/session-sigs-reader.test.ts +++ b/packages/misc/src/lib/helper/session-sigs-reader.test.ts @@ -1,4 +1,4 @@ -import { formatSessionSigs } from './session-sigs-reader'; +import { formatSessionSigs, formatSessionSigsJSON } from './session-sigs-reader'; describe('formatSessionSigs', () => { it('should format session signatures correctly', () => { @@ -81,3 +81,74 @@ describe('formatSessionSigs', () => { expect(formattedSessionSigs).toBe(expectedOutput); }); }); + + +describe('formatSessionSigsJson', () => { + + const sessionSigs = { + 'https://178.162.172.88:443': { + sig: 'd8d1311def1e6bfa2dd8ec79fee7f7ba3e770e1b0f2841c13db2a3196febf47b857c48575fd8f2a478c0364cffa9d478f0b0479c784b04f010f0f6fc97a61f09', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://178.162.172.88:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://104.245.147.218:443': { + sig: 'f4133963d987cebb05d889488865237e28ee29d86e5de7f0f08b07eb246c6e614a8ac2042431ad5cb8944f9583556838fdfe8d200ba86e620a5351d37119b705', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://104.245.147.218:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://184.107.182.142:443': { + sig: 'ae98fca36a1059cd5cbe7578ff94f777cb89e5fb642f8e5e709328e8a2753768925bf203650fcde83a8691e6e2bee1dc80b6fd71714a1c5d1d7f06d6356b1a0a', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://184.107.182.142:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://23.82.129.77:443': { + sig: 'e666f0bac0633a2d262e252cfa5d7746084f32a9c75e79a8ed9781a73fde1767c999d1e7898432f3653867ef182a17f013810c5b2d85e87ab0695b7b5cf63b0c', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://23.82.129.77:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://199.115.115.103:443': { + sig: '887bfe8581c9e50915638d796c10da8560e2a76f29dd83283efb0654ca6375add37dec073ef25ec74dfd9215ad4a37b3bfdf407579fe987154fabd95bff20b0f', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://199.115.115.103:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://207.244.66.41:443': { + sig: '37f4e81fb4a410335b322331f49d43a02d38c893042e2a580fcffe781ea17db7ad0b2d83f36afdeb84968d4901f4a47eef02484ed14adbb301c45fc8937bf400', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://207.244.66.41:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://173.208.0.151:443': { + sig: '12496182e7b323943bcea9e0e342d6caee961137c9852dc063ac46ee20705b3f8a70e144249f3fe04d290bf7318f43d1cb641d472894954cdc8f784d333b5300', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://173.208.0.151:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + }, + 'https://207.244.90.225:443': { + sig: 'da675ce1b939511714116c73c32dec32db60abc42fa596cf4a82e4eeddc4531d85fb15758e4c78db83f990a892f07782a825e459022817d4098a65b736e9d900', + derivedVia: 'litSessionSignViaNacl', + signedMessage: `{"sessionKey":"09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0","resourceAbilityRequests":[{"resource":{"resource":"*","resourcePrefix":"lit-pkp"},"ability":"pkp-signing"},{"resource":{"resource":"*","resourcePrefix":"lit-litaction"},"ability":"lit-action-execution"}],"capabilities":[{"sig":"{\\"ProofOfPossession\\":\\"838cf437fa58c2bb7e5c183bd2b184e4ed9da595bdb9bffa34019ca9b47e93f64b83d464eb9237297a829d1aa333560b0d6c55910631334bd9249cc826f8dcbf202f5f2d7d1ec67ec894a0b36b616cabb74f3e582e8b37089b9abdabbfa17e0d\\"}","algo":"LIT_BLS","derivedVia":"lit.bls","signedMessage":"litprotocol.com wants you to sign in with your Ethereum account:\\n0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166\\n\\nLit Protocol PKP session signature I further authorize the stated URI to perform the following actions on my behalf: I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. I further authorize the stated URI to perform the following actions on my behalf: (1) 'Threshold': 'Execution' for 'lit-litaction://*'. (2) 'Threshold': 'Signing' for 'lit-pkp://*'. (3) 'Auth': 'Auth' for 'lit-resolvedauthcontext://*'.\\n\\nURI: lit:session:09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0\\nVersion: 1\\nChain ID: 1\\nNonce: 0x244bc2b37cf85c94f37206c2ca0769db6bd353f2795f5b6894829068ad8c8542\\nIssued At: 2024-10-11T18:59:23Z\\nExpiration Time: 2024-10-12T18:59:52.424Z\\nResources:\\n- urn:recap:eyJhdHQiOnsibGl0LWxpdGFjdGlvbjovLyoiOnsiVGhyZXNob2xkL0V4ZWN1dGlvbiI6W3t9XX0sImxpdC1wa3A6Ly8qIjp7IlRocmVzaG9sZC9TaWduaW5nIjpbe31dfSwibGl0LXJlc29sdmVkYXV0aGNvbnRleHQ6Ly8qIjp7IkF1dGgvQXV0aCI6W3siYXV0aF9jb250ZXh0Ijp7ImFjdGlvbklwZnNJZHMiOlsiUW1kNWliQ1JvOURoRW5qY21mQnNNVTZxUkJDdk1DWnc1a0I3b1N2Q2E3aVhEUiJdLCJhdXRoTWV0aG9kQ29udGV4dHMiOltdLCJhdXRoU2lnQWRkcmVzcyI6bnVsbCwiY3VzdG9tQXV0aFJlc291cmNlIjoiKHRydWUsICdBbnl0aGluZyB5b3VyIHdhbnQgdG8gdXNlIGluIGV4ZWN1dGVKcycpIiwicmVzb3VyY2VzIjpbXX19XX19LCJwcmYiOltdfQ","address":"0xa19355DD0C6aDfD02a0F8C2B70A26DF4cECea166"}],"issuedAt":"2024-10-11T18:59:53.489Z","expiration":"2024-10-12T18:59:52.424Z","nodeAddress":"https://207.244.90.225:443"}`, + address: '09f07199ad48addc9b582cd4d1dd29014c61706b665474a5d10ee3903b2571a0', + algo: 'ed25519' + } + }; + + it('should format session signatures correctly', () => { + const formattedSessionSigsJson = formatSessionSigsJSON(JSON.stringify(sessionSigs)); + + + console.log('formattedSessionSigsJson', formattedSessionSigsJson); + + }); +}) \ No newline at end of file diff --git a/packages/misc/src/lib/helper/session-sigs-reader.ts b/packages/misc/src/lib/helper/session-sigs-reader.ts index 84e05f9d04..034f2fdca3 100644 --- a/packages/misc/src/lib/helper/session-sigs-reader.ts +++ b/packages/misc/src/lib/helper/session-sigs-reader.ts @@ -1,4 +1,39 @@ import { parseSignedMessage } from './session-sigs-validator'; +interface SessionInfo { + requestTime: string; + outerExpiration: { + issuedAt: string; + expiration: string; + duration: string; + status: string; + }; + capabilities: Array<{ + type: string; + issuedAt: string; + expiration: string; + duration: string; + status: string; + resources: { + att: Record>; + prf: string[]; + }; + }>; +} + +interface ResolvedAuthContext { + auth_context: { + actionIpfsIds: string[]; + authMethodContexts: any[]; + authSigAddress: any; + customAuthResource: string; + resources: any[]; + } +} +interface ProcessedSessionInfo { + att?: any; + customAuthSource?: string; + error?: string; +} function formatDuration(start: Date, end: Date): string { const diff = end.getTime() - start.getTime(); @@ -89,3 +124,134 @@ export function formatSessionSigs( return result; } + +function decodeBase64(str: string): string { + try { + return atob(str); + } catch (e) { + console.error('Error decoding base64:', e); + return str; + } +} + +export function formatSessionSigsJSON( + sessionSigs: string, + currentTime: Date = new Date() +): SessionInfo[] { + const parsedSigs = JSON.parse(sessionSigs); + const currentDate = new Date(currentTime); + const results: SessionInfo[] = []; + + Object.entries(parsedSigs).forEach(([nodeKey, nodeValue]: [string, any]) => { + let signedMessage; + + try { + signedMessage = JSON.parse(nodeValue.signedMessage); + } catch (error: unknown) { + const errorMessage = + error instanceof Error ? error.message : 'Unknown error'; + console.error(`Invalid JSON format for signedMessage in node ${nodeKey}: ${errorMessage}`); + return; // Skip this node and continue with the next one + } + + let result: SessionInfo = { + requestTime: currentDate.toISOString(), + outerExpiration: { + issuedAt: '', + expiration: '', + duration: '', + status: '', + }, + capabilities: [], + }; + + // Outer expiration + let issuedAt, expiration; + try { + issuedAt = new Date(signedMessage.issuedAt); + expiration = new Date(signedMessage.expiration); + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : 'Unknown error'; + console.error(`Error parsing issuedAt or expiration in node ${nodeKey}: ${errorMessage}`); + return; // Skip this node and continue with the next one + } + + result.outerExpiration = { + issuedAt: issuedAt.toISOString(), + expiration: expiration.toISOString(), + duration: formatDuration(issuedAt, expiration), + status: formatStatus(expiration, currentDate), + }; + + // Capabilities + signedMessage.capabilities.forEach((cap: any) => { + const capType = cap.derivedVia; + const parsedCapMessage = parseSignedMessage(cap.signedMessage); + + const capIssuedAt = new Date(parsedCapMessage['Issued At'] || ''); + const capExpiration = new Date(parsedCapMessage['Expiration Time'] || ''); + const capResources = parsedCapMessage['- urn'] || ''; + + const encodedStr = (capResources as string).split('recap:')[1]; + const decodedData = decodeBase64(encodedStr); + + let jsonDecodedData; + + try { + jsonDecodedData = JSON.parse(decodedData); + } catch (e) { + console.error('Error parsing JSON:', e); + jsonDecodedData = decodedData; + } + + result.capabilities.push({ + type: capType, + issuedAt: capIssuedAt.toISOString(), + expiration: capExpiration.toISOString(), + duration: formatDuration(capIssuedAt, capExpiration), + status: formatStatus(capExpiration, currentDate), + resources: jsonDecodedData, + }); + }); + + results.push(result); + }); + + return results; +} + +export function getResourcesFromSessionSigs(sessionSigs: string): ProcessedSessionInfo[] { + + const formattedSessionSigs = formatSessionSigsJSON(sessionSigs); + + return formattedSessionSigs.map((sessionInfo): ProcessedSessionInfo => { + const result: ProcessedSessionInfo = {}; + + const capabilities = sessionInfo.capabilities; + const litBlsCapability = capabilities.find((c) => c.type === 'lit.bls'); + + if (litBlsCapability && litBlsCapability.resources) { + const litBlsResources = litBlsCapability.resources; + const resolvedAuthContextKey = Object.keys(litBlsResources.att).find((k) => k.startsWith('lit-resolvedauthcontext')); + + if (resolvedAuthContextKey) { + const resolvedAuthContextObject = litBlsResources.att[resolvedAuthContextKey]; + if (resolvedAuthContextObject['Auth/Auth'] && resolvedAuthContextObject['Auth/Auth'][0]) { + const resolvedAuthContext = resolvedAuthContextObject['Auth/Auth'][0] as unknown as ResolvedAuthContext; + result.att = litBlsResources.att; + result.customAuthSource = resolvedAuthContext.auth_context.customAuthResource; + } else { + result.error = "No Auth/Auth data found in resolvedAuthContextObject"; + } + } else { + result.error = "No lit-resolvedauthcontext key found in resources"; + } + } else { + result.error = "No lit.bls capability found or no resources in the capability"; + } + + return result; + }); +} + From 9548dd8cb005df814b88b23fc5072a0a0336b2c4 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 21:03:58 +0100 Subject: [PATCH 06/10] wip --- ...UseTriaAuthAndWrappedKeysSessionSigsGen.ts | 45 +++++ .../testTriaBatchGeneratePrivateKeys.ts | 180 +++++++++++++++++ package.json | 1 + .../tria_batchGenerateEncryptedKeys.js | 40 ++-- packages/wrapped-keys/src/index.ts | 8 + .../tria-batch-generate-private-keys.ts | 164 ++++++++++----- .../bespoke/tria-batch-generate-keys.ts | 101 ++++++++++ tsconfig.json | 17 +- yarn.lock | 187 +++++++++++++++++- 9 files changed, 669 insertions(+), 74 deletions(-) create mode 100644 local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts create mode 100644 packages/wrapped-keys/src/lib/lit-actions-client/bespoke/tria-batch-generate-keys.ts diff --git a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts index 77c6e5d7d1..0d76929916 100644 --- a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts +++ b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts @@ -6,7 +6,12 @@ import { getLitActionSessionSigsUsingIpfsId, } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { api, utils } from '@lit-protocol/wrapped-keys'; +import Hash from "typestub-ipfs-only-hash"; +import { AuthMethodScope } from '@lit-protocol/constants'; + +const { triaBatchGeneratePrivateKeys, exportPrivateKey } = api; /** * Test Commands: * ✅ NETWORK=datil-dev yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen @@ -57,6 +62,46 @@ export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( console.log(` - Capacity Token ID: ${capacityTokenId}`); // -- Get the lit action code.. + const { litActionCode, litActionIpfsCid } = utils.getLitActionCodeOrCidCommon( + 'tria_batchGenerateEncryptedKeys' + ); + + // -- detect which one we got + const hashOfLitActionCode = litActionCode + ? await Hash.of(Buffer.from(litActionCode)) + : litActionIpfsCid; + console.log(` ✅ Lit Action Code IPFS CID: ${hashOfLitActionCode}`); + + console.log(`🔄 Adding permitted action...`); + const permitTx = await devEnv.contractsClient.addPermittedAction({ + ipfsId: hashOfLitActionCode, + pkpTokenId: pkp.tokenId, + authMethodScopes: [AuthMethodScope.SignAnything] + }); + console.log(` ✅ Permitted action added:`); + console.log(` - Transaction Hash: ${permitTx.transactionHash}`); + + const solanaMessageToSign = 'This is a test solana message'; + const evmMessageToSign = 'This is a test evm message'; + + const { results } = await triaBatchGeneratePrivateKeys({ + ipfsId: hashOfLitActionCode, + pkpPublicKey: pkp.publicKey, + actions: [ + { + network: 'evm', + signMessageParams: { messageToSign: evmMessageToSign }, + generateKeyParams: { memo: 'Test evm key' }, + }, + { + network: 'solana', + signMessageParams: { messageToSign: solanaMessageToSign }, + generateKeyParams: { memo: 'Test solana key' }, + }, + ], + litNodeClient: devEnv.litNodeClient, + }); + process.exit(); diff --git a/local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts b/local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts new file mode 100644 index 0000000000..b9b3e03826 --- /dev/null +++ b/local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts @@ -0,0 +1,180 @@ +import { log } from '@lit-protocol/misc'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; +import nacl from 'tweetnacl'; +import bs58 from 'bs58'; +import { ethers } from 'ethers'; +import { BatchGeneratePrivateKeysActionResult } from '../../../packages/wrapped-keys/src/lib/types'; +import { triaBatchGeneratePrivateKeys } from 'packages/wrapped-keys/src/lib/api'; + +async function verifySolanaSignature( + solanaResult: BatchGeneratePrivateKeysActionResult, + solanaMessageToSign +) { + const { + signMessage: { signature }, + generateEncryptedPrivateKey: { generatedPublicKey }, + } = solanaResult; + const signatureIsValidForPublicKey = nacl.sign.detached.verify( + Buffer.from(solanaMessageToSign), + bs58.decode(signature), + bs58.decode(generatedPublicKey) + ); + + console.log({ signatureIsValidForPublicKey, signature }); + if (!signatureIsValidForPublicKey) { + throw new Error( + `signature: ${signature} doesn't validate for the Solana public key: ${generatedPublicKey}` + ); + } +} +async function verifyEvmSignature(evmResult, messageToSign) { + function verifyMessageSignature() { + try { + return ethers.utils.verifyMessage( + messageToSign, + evmResult.signMessage.signature + ); + } catch (err) { + throw new Error( + `When validating signed Ethereum message is valid: ${err.message}` + ); + } + } + + const walletAddress = ethers.utils.computeAddress( + evmResult.generateEncryptedPrivateKey.generatedPublicKey + ); + + const recoveredAddress = verifyMessageSignature(); + + console.log({ + recoveredAddress, + walletAddress, + signature: evmResult.signMessage.signature, + }); + if (recoveredAddress !== walletAddress) { + throw new Error( + "Recovered address from verifyMessage doesn't match the wallet address" + ); + } +} + +/** + * Test Commands: + * ✅ NETWORK=datil-dev yarn test:local --filter=testTriaBatchGeneratePrivateKeys + * ✅ NETWORK=datil-test yarn test:local --filter=testTriaBatchGeneratePrivateKeys + * ✅ NETWORK=localchain yarn test:local --filter=testTriaBatchGeneratePrivateKeys + */ +export const testTriaBatchGeneratePrivateKeys = async ( + devEnv: TinnyEnvironment +) => { + const alice = await devEnv.createRandomPerson(); + + const TEN_MINUTES_EXPIRY = new Date( + Date.now() + 1000 * 60 * 10 + ).toISOString(); + + // const litActionSessionSigs = devEnv.litNodeClient.getLitActionSessionSigs({ + + // pkpPublicKey: alice.authMethodOwnedPkp.publicKey, + // resourceAbilityRequests: [ + // { + // resource: new LitPKPResource('*'), + // ability: LitAbility.PKPSigning, + // }, + // { + // resource: new LitActionResource('*'), + // ability: LitAbility.LitActionExecution, + // }, + // ], + // jsParams: { + // actions: [ + // { + // network: 'evm', + // signMessageParams: { messageToSign: evmMessageToSign }, + // generateKeyParams: { memo: 'Test evm key' }, + // }, + // { + // network: 'solana', + // signMessageParams: { messageToSign: solanaMessageToSign }, + // generateKeyParams: { memo: 'Test solana key' }, + // }, + // ], + // authMethod: { + // accessToken: ansonTestCredential.authMethod.accessToken, + // authMethodType: ansonTestCredential.authMethod.authMethodType, + // } + // } + // }) + + try { + // const pkpSessionSigsSigning = await getPkpSessionSigs( + // devEnv, + // alice, + // null, + // TEN_MINUTES_EXPIRY + // ); + + const solanaMessageToSign = 'This is a test solana message'; + const evmMessageToSign = 'This is a test evm message'; + const { results } = await triaBatchGeneratePrivateKeys({ + actions: [ + { + network: 'evm', + signMessageParams: { messageToSign: evmMessageToSign }, + generateKeyParams: { memo: 'Test evm key' }, + }, + { + network: 'solana', + signMessageParams: { messageToSign: solanaMessageToSign }, + generateKeyParams: { memo: 'Test solana key' }, + }, + ], + litNodeClient: devEnv.litNodeClient, + authMethod: { + accessToken: ansonTestCredential.authMethod.accessToken, + authMethodType: ansonTestCredential.authMethod.authMethodType, + }, + publicKey: alice.authMethodOwnedPkp.publicKey, + // publicKey: ansonTestCredential.pubKey, + // accessControlConditions: [] // would be done in the Lit Action + }); + + if (results.length !== 2) { + throw new Error( + `Incorrect # of results; expected 2, got ${results.length}` + ); + } + + if ( + results[0].generateEncryptedPrivateKey.memo !== 'Test evm key' || + results[1].generateEncryptedPrivateKey.memo !== 'Test solana key' + ) { + throw new Error( + 'Results not in order sent; expected evm as first result, solana as second' + ); + } + + if ( + !results[0].signMessage.signature || + !results[1].signMessage.signature + ) { + throw new Error('Missing message signature in response'); + } + + console.log('solana verify sig'); + await verifySolanaSignature(results[1], solanaMessageToSign); + + console.log('evm verify sig'); + await verifyEvmSignature(results[0], evmMessageToSign); + console.log('results', results); + + log('✅ testBatchGenerateEncryptedKeys'); + } catch (err) { + console.log(err.message, err, err.stack); + throw err; + } finally { + devEnv.releasePrivateKeyFromUser(alice); + } +}; diff --git a/package.json b/package.json index fad1755fd2..7a947b8eda 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "tslib": "^2.3.0", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", + "typestub-ipfs-only-hash": "^4.0.0", "uint8arrays": "^4.0.3" }, "devDependencies": { diff --git a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js index 8824d5362f..def8981fdb 100644 --- a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js +++ b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js @@ -130,20 +130,28 @@ function validateParams(actions) { }); } -(async () => { - try { - validateParams(actions); - - const batchGeneratePrivateKeysActionResult = await processActions(actions); - - Lit.Actions.setResponse({ - response: JSON.stringify(batchGeneratePrivateKeysActionResult), - }); +// (async () => { +// try { +// validateParams(actions); + +// const batchGeneratePrivateKeysActionResult = await processActions(actions); + +// Lit.Actions.setResponse({ +// response: JSON.stringify(batchGeneratePrivateKeysActionResult), +// }); + +// // 1. Generate both EVM and solana private keys +// // 2. Run appropriate signMessage for each key _and_ encrypt the keys for persistence to wrapped-keys backend +// // 3. Return results for both signMessage ops and both encrypted key payloads for persistence +// } catch (err) { +// Lit.Actions.setResponse({ response: `Error: ${err.message}` }); +// } +// })(); + +const go = async () => { + LitActions.setResponse({ + response: "(true, 'Something else is here!')", + }); +}; - // 1. Generate both EVM and solana private keys - // 2. Run appropriate signMessage for each key _and_ encrypt the keys for persistence to wrapped-keys backend - // 3. Return results for both signMessage ops and both encrypted key payloads for persistence - } catch (err) { - Lit.Actions.setResponse({ response: `Error: ${err.message}` }); - } -})(); +go(); diff --git a/packages/wrapped-keys/src/index.ts b/packages/wrapped-keys/src/index.ts index 797dada407..b5fef315dd 100644 --- a/packages/wrapped-keys/src/index.ts +++ b/packages/wrapped-keys/src/index.ts @@ -29,6 +29,7 @@ import { LitActionCodeRepositoryCommon, LitActionCodeRepositoryEntry, } from './lib/lit-actions-client/types'; +import { getLitActionCodeOrCidCommon } from './lib/lit-actions-client/utils'; import type { SupportedNetworks } from './lib/service-client/types'; import type { @@ -74,6 +75,9 @@ export const api = { signTransactionWithEncryptedKey, storeEncryptedKey, batchGeneratePrivateKeys, + + // bespoke + triaBatchGeneratePrivateKeys, }; export const config = { @@ -81,6 +85,10 @@ export const config = { setLitActionsCodeCommon, }; +export const utils = { + getLitActionCodeOrCidCommon +} + export { ApiParamsSupportedNetworks, BaseApiParams, diff --git a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts index b0635d2a33..8b6601fa42 100644 --- a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts +++ b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts @@ -12,6 +12,20 @@ import { getPkpAccessControlCondition, getPkpAddressFromSessionSig, } from '../../utils'; +import { LitAbility, LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers'; +import { SessionSigsMap } from '@lit-protocol/types'; +import { formatSessionSigsJSON, getResourcesFromSessionSigs } from '@lit-protocol/misc'; + +// resolvedAuthContext: { +// auth_context: { +// actionIpfsIds: [ 'Qmd5ibCRo9DhEnjcmfBsMU6qRBCvMCZw5kB7oSvCa7iXDR' ], +// authMethodContexts: [], +// authSigAddress: null, +// customAuthResource: "(true, 'Anything your want to use in executeJs')", +// resources: [] +// } +// } + /** * TODO: Document batch behaviour @@ -20,56 +34,104 @@ import { * @returns { Promise } - The generated keys and, optionally, signed messages */ export async function triaBatchGeneratePrivateKeys( - params: BatchGeneratePrivateKeysParams + params: Omit & { + pkpPublicKey: string | `0x${string}`; + ipfsId: string | `Qm${string}`; + } ): Promise { - const { pkpSessionSigs, litNodeClient } = params; - - const sessionSig = getFirstSessionSig(pkpSessionSigs); - const pkpAddress = getPkpAddressFromSessionSig(sessionSig); - - const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); - - const { litActionCode, litActionIpfsCid } = getLitActionCodeOrCidCommon( - 'batchGenerateEncryptedKeys' - ); - - const actionResults = await batchGenerateKeysWithLitAction({ - ...params, - litActionIpfsCid: litActionCode ? undefined : litActionIpfsCid, - litActionCode: litActionCode ? litActionCode : undefined, - accessControlConditions: [allowPkpAddressToDecrypt], - pkpSessionSigs, - }); - - const results = await Promise.all( - actionResults.map( - async (result): Promise => { - const { generateEncryptedPrivateKey, network } = result; - - const signature = result.signMessage?.signature; - - const { id } = await storePrivateKey({ - sessionSig, - storedKeyMetadata: { - ...generateEncryptedPrivateKey, - keyType: getKeyTypeFromNetwork(network), - pkpAddress, - }, - litNetwork: litNodeClient.config.litNetwork, - }); - - return { - ...(signature ? { signMessage: { signature } } : {}), - generateEncryptedPrivateKey: { - memo: generateEncryptedPrivateKey.memo, - id, - generatedPublicKey: generateEncryptedPrivateKey.publicKey, - pkpAddress, - }, - }; - } - ) - ); - - return { pkpAddress, results }; + + // -- validate + if (!params.litNodeClient) { + throw new Error(`Error: litNodeClient is required`); + } + if (!params.pkpPublicKey) { + throw new Error(`Error: pkpPublicKey is required`); + } + if (!params.ipfsId) { + throw new Error(`Error: ipfsId is required`); + } + + // const sessionSig = getFirstSessionSig(pkpSessionSigs); + // const pkpAddress = getPkpAddressFromSessionSig(sessionSig); + + // const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); + + // const { litActionCode, litActionIpfsCid } = getLitActionCodeOrCidCommon( + // 'tria_batchGenerateEncryptedKeys' + // ); + + // Here we should use getLitActionSessionSigs rather than executeJs + console.log(`🔄 Getting Lit Action Session Sigs`); + let litActionSessionSigs: SessionSigsMap; + + try { + litActionSessionSigs = await params.litNodeClient.getLitActionSessionSigs({ + pkpPublicKey: params.pkpPublicKey, + resourceAbilityRequests: [ + { + resource: new LitPKPResource('*'), + ability: LitAbility.PKPSigning, + }, + { + resource: new LitActionResource('*'), + ability: LitAbility.LitActionExecution, + }, + ], + litActionIpfsId: params.ipfsId, + jsParams: {}, + }); + } catch (e) { + throw new Error(`Error getting Lit Action Session Sigs: ${e}`); + } + + console.log("litActionSessionSigs:", litActionSessionSigs); + + const sessionSigsResources = getResourcesFromSessionSigs(JSON.stringify(litActionSessionSigs)); + + console.log("sessionSigsResources:", sessionSigsResources); + + process.exit(); + + // // This is the original code + // const actionResults = await batchGenerateKeysWithLitAction({ + // ...params, + // litActionIpfsCid: litActionCode ? undefined : litActionIpfsCid, + // litActionCode: litActionCode ? litActionCode : undefined, + // accessControlConditions: [allowPkpAddressToDecrypt], + // pkpSessionSigs, + // }); + + // const results = await Promise.all( + // actionResults.map( + // async (result): Promise => { + // const { generateEncryptedPrivateKey, network } = result; + + // const signature = result.signMessage?.signature; + + // const { id } = await storePrivateKey({ + // sessionSig, + // storedKeyMetadata: { + // ...generateEncryptedPrivateKey, + // keyType: getKeyTypeFromNetwork(network), + // pkpAddress, + // }, + // litNetwork: litNodeClient.config.litNetwork, + // }); + + // return { + // ...(signature ? { signMessage: { signature } } : {}), + // generateEncryptedPrivateKey: { + // memo: generateEncryptedPrivateKey.memo, + // id, + // generatedPublicKey: generateEncryptedPrivateKey.publicKey, + // pkpAddress, + // }, + // }; + // } + // ) + // ); + + // return { pkpAddress, results }; + + return { pkpAddress: '', results: [] }; } diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/bespoke/tria-batch-generate-keys.ts b/packages/wrapped-keys/src/lib/lit-actions-client/bespoke/tria-batch-generate-keys.ts new file mode 100644 index 0000000000..ab8f521af8 --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/bespoke/tria-batch-generate-keys.ts @@ -0,0 +1,101 @@ +import { GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK } from '@lit-protocol/constants'; +import { AccessControlConditions } from '@lit-protocol/types'; + +import { postLitActionValidation } from '../utils'; +import { BatchGeneratePrivateKeysParams, Network } from '../../types'; + +import { LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers'; +import { LitAbility, LitResourceAbilityRequest } from '@lit-protocol/types'; +import { formatSessionSigsJSON, parseSignedMessage } from '@lit-protocol/misc'; + +interface BatchGeneratePrivateKeysWithLitActionParams + extends BatchGeneratePrivateKeysParams { + accessControlConditions: AccessControlConditions; + litActionIpfsCid?: string; + litActionCode?: string; +} + +interface GeneratePrivateKeyLitActionResult { + ciphertext: string; + dataToEncryptHash: string; + publicKey: string; + memo: string; +} + +interface BatchGeneratePrivateKeysWithLitActionResult { + network: Network; + signMessage?: { signature: string }; + generateEncryptedPrivateKey: GeneratePrivateKeyLitActionResult; +} + +export async function triaBatchGenerateKeysWithLitActionSessionSigs( + args: Omit & { + authMethod: { + accessToken: string | `eyJ${string}`; + authMethodType: string | `0x${string}`; + }, + publicKey: string; + } +): Promise { + + // print all the params out + // console.log("args:", args); + // process.exit(); + + const sessionSigs = await args.litNodeClient.getLitActionSessionSigs({ + pkpPublicKey: args.publicKey, + resourceAbilityRequests: [ + { + resource: new LitPKPResource('*'), + ability: LitAbility.PKPSigning, + }, + { + resource: new LitActionResource('*'), + ability: LitAbility.LitActionExecution, + }, + ], + litActionCode: args.litActionCode ? + Buffer.from(args.litActionCode).toString('base64') : + undefined, + + // @ts-ignore - this is a test + litActionIpfsCid: args.litActionIpfsCid ? + undefined : + args.litActionIpfsCid, + + jsParams: { + publicKey: args.publicKey, + sigName: 'tria-batch-generate-keys-combined-sig', + actions: args.actions, + authMethod: { + accessToken: args.authMethod.accessToken, + authMethodType: args.authMethod.authMethodType, + } + } + }); + + console.log("sessionSigs:", sessionSigs); + + const parsedSignedMessage = formatSessionSigsJSON(JSON.stringify(sessionSigs)); + + console.log("parsedSignedMessage:", parsedSignedMessage); + process.exit(); + + // const result = await litNodeClient.executeJs({ + // useSingleNode: true, + // sessionSigs: pkpSessionSigs, + // ipfsId: litActionIpfsCid, + // code: litActionCode, + // jsParams: { + // actions, + // accessControlConditions, + // }, + // ipfsOptions: { + // overwriteCode: + // GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK[litNodeClient.config.litNetwork], + // }, + // }); + + // const response = postLitActionValidation(result); + // return JSON.parse(response); +} diff --git a/tsconfig.json b/tsconfig.json index d79d1c4238..e8f4e19b50 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,15 +10,24 @@ "importHelpers": true, "target": "ES2020", "module": "ES2020", - "lib": ["ES2020", "dom", "ES2021.String"], + "lib": [ + "ES2020", + "dom", + "ES2021.String" + ], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "paths": { - "@lit-protocol/*": ["packages/*/src"] + "@lit-protocol/*": [ + "packages/*/src" + ] } }, - "exclude": ["node_modules", "tmp"] -} + "exclude": [ + "node_modules", + "tmp" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index bd29e4cc9b..5a933819e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3594,6 +3594,11 @@ "@motionone/dom" "^10.16.4" tslib "^2.3.1" +"@multiformats/base-x@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== + "@multiformats/murmur3@^2.0.0": version "2.1.8" resolved "https://registry.yarnpkg.com/@multiformats/murmur3/-/murmur3-2.1.8.tgz#81c1c15b6391109f3febfca4b3205196615a04e9" @@ -9294,6 +9299,16 @@ cids@^0.7.1: multicodec "^1.0.0" multihashes "~0.4.15" +cids@^1.0.0, cids@^1.1.5, cids@^1.1.6: + version "1.1.9" + resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" + integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== + dependencies: + multibase "^4.0.1" + multicodec "^3.0.1" + multihashes "^4.0.1" + uint8arrays "^3.0.0" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -11401,7 +11416,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -err-code@^3.0.1: +err-code@^3.0.0, err-code@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920" integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== @@ -14078,6 +14093,14 @@ h3@^1.10.2, h3@^1.11.1: uncrypto "^0.1.3" unenv "^1.9.0" +hamt-sharding@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-2.0.1.tgz#f45686d0339e74b03b233bee1bde9587727129b6" + integrity sha512-vnjrmdXG9dDs1m/H4iJ6z0JFI2NtgsW5keRkTcM85NGak69Mkf5PHUqBz+Xs0T4sg0ppvj9O5EGAJo40FTxmmA== + dependencies: + sparse-array "^1.3.1" + uint8arrays "^3.0.0" + hamt-sharding@^3.0.0: version "3.0.6" resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-3.0.6.tgz#3643107a3021af66ac95684aec87b196add5ba57" @@ -14843,6 +14866,15 @@ interface-blockstore@^4.0.0: interface-store "^3.0.0" multiformats "^11.0.0" +interface-ipld-format@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interface-ipld-format/-/interface-ipld-format-1.0.1.tgz#bee39c70c584a033e186ff057a2be89f215963e3" + integrity sha512-WV/ar+KQJVoQpqRDYdo7YPGYIUHJxCuOEhdvsRpzLqoOIVCqPKdMMYmsLL1nCRsF3yYNio+PAJbCKiv6drrEAg== + dependencies: + cids "^1.1.6" + multicodec "^3.0.1" + multihashes "^4.0.2" + interface-store@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-3.0.4.tgz#670d95ef45f3b7061d154c3cbfaf39a538167ad7" @@ -14903,6 +14935,14 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +ipfs-only-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ipfs-only-hash/-/ipfs-only-hash-4.0.0.tgz#b3bd60a244d9eb7394961aa9d812a2e5ac7c04d6" + integrity sha512-TE1DZCvfw8i3gcsTq3P4TFx3cKFJ3sluu/J3XINkJhIN9OwJgNMqKA+WnKx6ByCb1IoPXsTp1KM7tupElb6SyA== + dependencies: + ipfs-unixfs-importer "^7.0.1" + meow "^9.0.0" + ipfs-unixfs-importer@12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-12.0.1.tgz#316a52d8a793e9e006b1ee43edc50b83e00ef306" @@ -14924,6 +14964,34 @@ ipfs-unixfs-importer@12.0.1: uint8arraylist "^2.3.3" uint8arrays "^4.0.2" +ipfs-unixfs-importer@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-7.0.3.tgz#b850e831ca9647d589ef50bc33421f65bab7bba6" + integrity sha512-qeFOlD3AQtGzr90sr5Tq1Bi8pT5Nr2tSI8z310m7R4JDYgZc6J1PEZO3XZQ8l1kuGoqlAppBZuOYmPEqaHcVQQ== + dependencies: + bl "^5.0.0" + cids "^1.1.5" + err-code "^3.0.1" + hamt-sharding "^2.0.0" + ipfs-unixfs "^4.0.3" + ipld-dag-pb "^0.22.2" + it-all "^1.0.5" + it-batch "^1.0.8" + it-first "^1.0.6" + it-parallel-batch "^1.0.9" + merge-options "^3.0.4" + multihashing-async "^2.1.0" + rabin-wasm "^0.1.4" + uint8arrays "^2.1.2" + +ipfs-unixfs@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-4.0.3.tgz#7c43e5726052ade4317245358ac541ef3d63d94e" + integrity sha512-hzJ3X4vlKT8FQ3Xc4M1szaFVjsc1ZydN+E4VQ91aXxfpjFn9G2wsMo1EFdAXNq/BUnN5dgqIOMP5zRYr3DTsAw== + dependencies: + err-code "^3.0.1" + protobufjs "^6.10.2" + ipfs-unixfs@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-9.0.1.tgz#d06e688e07ef4ce08d610337ba2fe8c143c386e7" @@ -14932,6 +15000,19 @@ ipfs-unixfs@^9.0.0: err-code "^3.0.1" protobufjs "^7.0.0" +ipld-dag-pb@^0.22.2: + version "0.22.3" + resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.22.3.tgz#6d5af28b5752236a5cb0e0a1888c87dd733b55cd" + integrity sha512-dfG5C5OVAR4FEP7Al2CrHWvAyIM7UhAQrjnOYOIxXGQz5NlEj6wGX0XQf6Ru6or1na6upvV3NQfstapQG8X2rg== + dependencies: + cids "^1.0.0" + interface-ipld-format "^1.0.0" + multicodec "^3.0.1" + multihashing-async "^2.0.0" + protobufjs "^6.10.2" + stable "^0.1.8" + uint8arrays "^2.0.5" + iron-webcrypto@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz#aa60ff2aa10550630f4c0b11fd2442becdb35a6f" @@ -15632,21 +15713,43 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +it-all@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335" + integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A== + it-all@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-all/-/it-all-2.0.1.tgz#45d530ecf6e13fb81d7ba583cdfd55ffdb376b05" integrity sha512-9UuJcCRZsboz+HBQTNOau80Dw+ryGaHYFP/cPYzFBJBFcfDathMYnhHk4t52en9+fcyDGPTdLB+lFc1wzQIroA== +it-batch@^1.0.8, it-batch@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-1.0.9.tgz#7e95aaacb3f9b1b8ca6c8b8367892171d6a5b37f" + integrity sha512-7Q7HXewMhNFltTsAMdSz6luNhyhkhEtGGbYek/8Xb/GiqYMtwUmopE1ocPSiJKKp3rM4Dt045sNFoUu+KZGNyA== + it-batch@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-2.0.1.tgz#a0822be9b18743c41d8525835f788a7f297ba41f" integrity sha512-2gWFuPzamh9Dh3pW+OKjc7UwJ41W4Eu2AinVAfXDMfrC5gXfm3b1TF+1UzsygBUgKBugnxnGP+/fFRyn+9y1mQ== +it-first@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/it-first/-/it-first-1.0.7.tgz#a4bef40da8be21667f7d23e44dae652f5ccd7ab1" + integrity sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g== + it-first@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-first/-/it-first-2.0.1.tgz#75d66b254c385ae3a1906def060a69006a437cef" integrity sha512-noC1oEQcWZZMUwq7VWxHNLML43dM+5bviZpfmkxkXlvBe60z7AFRqpZSga9uQBo792jKv9otnn1IjA4zwgNARw== +it-parallel-batch@^1.0.9: + version "1.0.11" + resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-1.0.11.tgz#f889b4e1c7a62ef24111dbafbaaa010b33d00f69" + integrity sha512-UWsWHv/kqBpMRmyZJzlmZeoAMA0F3SZr08FBdbhtbe+MtoEBgr/ZUAKrnenhXCBrsopy76QjRH2K/V8kNdupbQ== + dependencies: + it-batch "^1.0.9" + it-parallel-batch@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-2.0.1.tgz#23eb07bbeb73521253d7c8a1566b53137103077c" @@ -17781,6 +17884,24 @@ meow@^8.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -18264,6 +18385,13 @@ multibase@^0.7.0: base-x "^3.0.8" buffer "^5.5.0" +multibase@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" + integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== + dependencies: + "@multiformats/base-x" "^4.0.1" + multibase@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" @@ -18287,6 +18415,14 @@ multicodec@^1.0.0: buffer "^5.6.0" varint "^5.0.0" +multicodec@^3.0.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" + integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== + dependencies: + uint8arrays "^3.0.0" + varint "^6.0.0" + multiformats@^11.0.0, multiformats@^11.0.2: version "11.0.2" resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-11.0.2.tgz#b14735efc42cd8581e73895e66bebb9752151b60" @@ -18316,6 +18452,27 @@ multihashes@^0.4.15, multihashes@~0.4.15: multibase "^0.7.0" varint "^5.0.0" +multihashes@^4.0.1, multihashes@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" + integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== + dependencies: + multibase "^4.0.1" + uint8arrays "^3.0.0" + varint "^5.0.2" + +multihashing-async@^2.0.0, multihashing-async@^2.1.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843" + integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg== + dependencies: + blakejs "^1.1.0" + err-code "^3.0.0" + js-sha3 "^0.8.0" + multihashes "^4.0.1" + murmurhash3js-revisited "^3.0.0" + uint8arrays "^3.0.0" + multimatch@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6" @@ -20324,7 +20481,7 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== -protobufjs@^6.8.8, protobufjs@~6.11.2, protobufjs@~6.11.3: +protobufjs@^6.10.2, protobufjs@^6.8.8, protobufjs@~6.11.2, protobufjs@~6.11.3: version "6.11.4" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== @@ -22245,6 +22402,11 @@ ssri@^9.0.0, ssri@^9.0.1: dependencies: minipass "^3.1.1" +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -23489,6 +23651,13 @@ typescript@~5.3.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +typestub-ipfs-only-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typestub-ipfs-only-hash/-/typestub-ipfs-only-hash-4.0.0.tgz#12e7d0e13947884b5b7d8091b9a17073fdf71d2d" + integrity sha512-HKLePX0XiPiyqoueSfvCLL9SIzvKBXjASaRoR0yk/gUbbK7cqejU6/tjhihwmzBCvWbx5aMQ2LYsYIpMK7Ikpg== + dependencies: + ipfs-only-hash "^4.0.0" + u2f-api@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" @@ -23518,6 +23687,13 @@ uint8arrays@3.1.0: dependencies: multiformats "^9.4.2" +uint8arrays@^2.0.5, uint8arrays@^2.1.2: + version "2.1.10" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" + integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== + dependencies: + multiformats "^9.4.2" + uint8arrays@^3.0.0, uint8arrays@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" @@ -24031,11 +24207,16 @@ valtio@1.11.0: proxy-compare "2.5.1" use-sync-external-store "1.2.0" -varint@^5.0.0: +varint@^5.0.0, varint@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + varuint-bitcoin@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92" From 92c2b851aeefed455b683c5ebd33cb554009cd9e Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 21:05:04 +0100 Subject: [PATCH 07/10] wip: delete testTriaBatchGeneratePrivateKeys --- .../testTriaBatchGeneratePrivateKeys.ts | 180 ------------------ 1 file changed, 180 deletions(-) delete mode 100644 local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts diff --git a/local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts b/local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts deleted file mode 100644 index b9b3e03826..0000000000 --- a/local-tests/tests/wrapped-keys/testTriaBatchGeneratePrivateKeys.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { log } from '@lit-protocol/misc'; -import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import nacl from 'tweetnacl'; -import bs58 from 'bs58'; -import { ethers } from 'ethers'; -import { BatchGeneratePrivateKeysActionResult } from '../../../packages/wrapped-keys/src/lib/types'; -import { triaBatchGeneratePrivateKeys } from 'packages/wrapped-keys/src/lib/api'; - -async function verifySolanaSignature( - solanaResult: BatchGeneratePrivateKeysActionResult, - solanaMessageToSign -) { - const { - signMessage: { signature }, - generateEncryptedPrivateKey: { generatedPublicKey }, - } = solanaResult; - const signatureIsValidForPublicKey = nacl.sign.detached.verify( - Buffer.from(solanaMessageToSign), - bs58.decode(signature), - bs58.decode(generatedPublicKey) - ); - - console.log({ signatureIsValidForPublicKey, signature }); - if (!signatureIsValidForPublicKey) { - throw new Error( - `signature: ${signature} doesn't validate for the Solana public key: ${generatedPublicKey}` - ); - } -} -async function verifyEvmSignature(evmResult, messageToSign) { - function verifyMessageSignature() { - try { - return ethers.utils.verifyMessage( - messageToSign, - evmResult.signMessage.signature - ); - } catch (err) { - throw new Error( - `When validating signed Ethereum message is valid: ${err.message}` - ); - } - } - - const walletAddress = ethers.utils.computeAddress( - evmResult.generateEncryptedPrivateKey.generatedPublicKey - ); - - const recoveredAddress = verifyMessageSignature(); - - console.log({ - recoveredAddress, - walletAddress, - signature: evmResult.signMessage.signature, - }); - if (recoveredAddress !== walletAddress) { - throw new Error( - "Recovered address from verifyMessage doesn't match the wallet address" - ); - } -} - -/** - * Test Commands: - * ✅ NETWORK=datil-dev yarn test:local --filter=testTriaBatchGeneratePrivateKeys - * ✅ NETWORK=datil-test yarn test:local --filter=testTriaBatchGeneratePrivateKeys - * ✅ NETWORK=localchain yarn test:local --filter=testTriaBatchGeneratePrivateKeys - */ -export const testTriaBatchGeneratePrivateKeys = async ( - devEnv: TinnyEnvironment -) => { - const alice = await devEnv.createRandomPerson(); - - const TEN_MINUTES_EXPIRY = new Date( - Date.now() + 1000 * 60 * 10 - ).toISOString(); - - // const litActionSessionSigs = devEnv.litNodeClient.getLitActionSessionSigs({ - - // pkpPublicKey: alice.authMethodOwnedPkp.publicKey, - // resourceAbilityRequests: [ - // { - // resource: new LitPKPResource('*'), - // ability: LitAbility.PKPSigning, - // }, - // { - // resource: new LitActionResource('*'), - // ability: LitAbility.LitActionExecution, - // }, - // ], - // jsParams: { - // actions: [ - // { - // network: 'evm', - // signMessageParams: { messageToSign: evmMessageToSign }, - // generateKeyParams: { memo: 'Test evm key' }, - // }, - // { - // network: 'solana', - // signMessageParams: { messageToSign: solanaMessageToSign }, - // generateKeyParams: { memo: 'Test solana key' }, - // }, - // ], - // authMethod: { - // accessToken: ansonTestCredential.authMethod.accessToken, - // authMethodType: ansonTestCredential.authMethod.authMethodType, - // } - // } - // }) - - try { - // const pkpSessionSigsSigning = await getPkpSessionSigs( - // devEnv, - // alice, - // null, - // TEN_MINUTES_EXPIRY - // ); - - const solanaMessageToSign = 'This is a test solana message'; - const evmMessageToSign = 'This is a test evm message'; - const { results } = await triaBatchGeneratePrivateKeys({ - actions: [ - { - network: 'evm', - signMessageParams: { messageToSign: evmMessageToSign }, - generateKeyParams: { memo: 'Test evm key' }, - }, - { - network: 'solana', - signMessageParams: { messageToSign: solanaMessageToSign }, - generateKeyParams: { memo: 'Test solana key' }, - }, - ], - litNodeClient: devEnv.litNodeClient, - authMethod: { - accessToken: ansonTestCredential.authMethod.accessToken, - authMethodType: ansonTestCredential.authMethod.authMethodType, - }, - publicKey: alice.authMethodOwnedPkp.publicKey, - // publicKey: ansonTestCredential.pubKey, - // accessControlConditions: [] // would be done in the Lit Action - }); - - if (results.length !== 2) { - throw new Error( - `Incorrect # of results; expected 2, got ${results.length}` - ); - } - - if ( - results[0].generateEncryptedPrivateKey.memo !== 'Test evm key' || - results[1].generateEncryptedPrivateKey.memo !== 'Test solana key' - ) { - throw new Error( - 'Results not in order sent; expected evm as first result, solana as second' - ); - } - - if ( - !results[0].signMessage.signature || - !results[1].signMessage.signature - ) { - throw new Error('Missing message signature in response'); - } - - console.log('solana verify sig'); - await verifySolanaSignature(results[1], solanaMessageToSign); - - console.log('evm verify sig'); - await verifyEvmSignature(results[0], evmMessageToSign); - console.log('results', results); - - log('✅ testBatchGenerateEncryptedKeys'); - } catch (err) { - console.log(err.message, err, err.stack); - throw err; - } finally { - devEnv.releasePrivateKeyFromUser(alice); - } -}; From 92245d460f9ab7c88eeeefb87866c38c3639e192 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 22:19:45 +0100 Subject: [PATCH 08/10] wip: combined lit action --- ...UseTriaAuthAndWrappedKeysSessionSigsGen.ts | 9 +- .../tria_batchGenerateEncryptedKeys.js | 145 +++++++++++++++++- packages/wrapped-keys-lit-actions/test.ts | 21 --- .../tria-batch-generate-private-keys.ts | 42 +++-- 4 files changed, 177 insertions(+), 40 deletions(-) delete mode 100644 packages/wrapped-keys-lit-actions/test.ts diff --git a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts index 0d76929916..0c4c4b4b91 100644 --- a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts +++ b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts @@ -24,6 +24,11 @@ export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( const alice = await devEnv.createRandomPerson(); // -- Start + const triaAuthMethod = { + // authMethodId: '', <-- Tria's managing this by permitting auth method to the user id + authMethodType: process.env.TRIA_AUTHMETHOD_TYPE, + accessToken: process.env.TRIA_ACCESS_TOKEN, + }; // -- mint a pkp console.log(`🔄 Minting new PKP...`); @@ -85,8 +90,8 @@ export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( const evmMessageToSign = 'This is a test evm message'; const { results } = await triaBatchGeneratePrivateKeys({ - ipfsId: hashOfLitActionCode, pkpPublicKey: pkp.publicKey, + ipfsId: hashOfLitActionCode, actions: [ { network: 'evm', @@ -100,8 +105,10 @@ export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( }, ], litNodeClient: devEnv.litNodeClient, + authMethod: triaAuthMethod, }); + console.log("results:", results); process.exit(); diff --git a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js index def8981fdb..76b3ac3bfb 100644 --- a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js +++ b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js @@ -11,7 +11,6 @@ const { const { signMessageSolanaKey } = require('../../solana/internal/signMessage'); /* "TRIA" global accessControlConditions, actions, Lit*/ - async function processEthereumAction(action) { const { network, generateKeyParams } = action; const messageToSign = action.signMessageParams?.messageToSign; @@ -94,16 +93,43 @@ async function processActions(actions) { ); } -function validateParams(actions) { - if (!actions) { +/** + * - jsParams: Expected data type: Object (e.g., "{ authMethod: { accessToken: '...', authMethodType: '...' }, publicKey: '...', actions: [...] }") + * + * This parameter is an object containing the following properties: + * - authMethod + * - publicKey + * - actions: Array of action objects, each containing network and key generation params. + * + */ +function validateJsParams(jsParams) { + if (!jsParams.authMethod) { + throw new Error('Missing required field: authMethod'); + } + if (!jsParams.publicKey) { + throw new Error('Missing required field: publicKey'); + } + if (!jsParams.accessControlConditions) { + throw new Error('Missing required field: accessControlConditions'); + } + const { accessToken, authMethodType } = jsParams.authMethod; + + if (!accessToken) { + throw new Error('Missing required field: authMethod.accessToken'); + } + if (!authMethodType) { + throw new Error('Missing required field: authMethod.authMethodType'); + } + + if (!jsParams.actions) { throw new Error('Missing required field: actions'); } - if (!actions.length) { + if (!jsParams.actions.length) { throw new Error('No actions provided (empty array?)'); } - actions.forEach((action, ndx) => { + jsParams.actions.forEach((action, ndx) => { if (!['evm', 'solana'].includes(action.network)) { throw new Error( `Invalid field: actions[${ndx}].network: ${action.network}` @@ -149,9 +175,114 @@ function validateParams(actions) { // })(); const go = async () => { - LitActions.setResponse({ - response: "(true, 'Something else is here!')", + // ========== Tria's Logic ========== + // Lit Action:: Prepare jsParams + const jsParams = { + authMethod: { + accessToken: authMethod.accessToken, + authMethodType: authMethod.authMethodType, + }, + publicKey: publicKey, + actions: actions, + accessControlConditions: accessControlConditions, + }; + + validateJsParams(jsParams); + + // ========== Tria's Logic ========== + + // Authentication + const url = 'https://api.development.tria.so/api/v1/user/info'; + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${jsParams.authMethod.accessToken}`, + }, }); + const data = await response.json(); + console.log('data', data); + + if (!data.success) { + Lit.Actions.setResponse({ + response: JSON.stringify({ + success: false, + message: 'Authentication Failed', + }), + }); + return; + } + + // Authorization:: Prepare params + // -- 1. get the authMethodId from unique identify from the response + const authMethodId = `${ethers.utils.keccak256( + ethers.utils.toUtf8Bytes(data.userInfo.uuid) + )}`; + console.log('Computed AuthMethodId', authMethodId); + + // -- 2. get the PKP token id + const tokenId = Lit.Actions.pubkeyToTokenId({ + publicKey: jsParams.publicKey, + }); + console.log('tokenId', tokenId); + + // -- 3. get the permitted auth methods of the PKP token id + const permittedAuthMethods = await Lit.Actions.getPermittedAuthMethods({ + tokenId, + }); + console.log('permittedAuthMethods', permittedAuthMethods); + + // -- 4. only get where authMethod that's equal to the authMethod Id + const permittedAuthMethod = permittedAuthMethods.find( + (method) => method.id === authMethodId + ); + console.log('permittedAuthMethod', permittedAuthMethod); + + // TODO: Uncomment this block to enable Authorization + // Authorization:: Failed Authentication and Authorization + // if ( + // !permittedAuthMethod || + // permittedAuthMethod.auth_method_type !== jsParams.authMethod.authMethodType + // ) { + // Lit.Actions.setResponse({ + // response: JSON.stringify({ + // success: false, + // message: 'Authorization Failed', + // }), + // }); + // return; + // } + + // LitActions.setResponse({ + // response: `(true, ${JSON.stringify({ + // returnedData: data, + // logs: { + // authMethodId, + // tokenId, + // permittedAuthMethods, + // permittedAuthMethod, + // actions: jsParams.actions, + // batchGeneratePrivateKeysActionResult, + // }, + // })})`, + // }); + + try { + const batchGeneratePrivateKeysActionResult = await processActions( + jsParams.actions + ); + + Lit.Actions.setResponse({ + response: JSON.stringify( + `(true, ${JSON.stringify(batchGeneratePrivateKeysActionResult)})` + ), + }); + + // 1. Generate both EVM and solana private keys + // 2. Run appropriate signMessage for each key _and_ encrypt the keys for persistence to wrapped-keys backend + // 3. Return results for both signMessage ops and both encrypted key payloads for persistence + } catch (err) { + Lit.Actions.setResponse({ response: `Error: ${err.message}` }); + } }; go(); diff --git a/packages/wrapped-keys-lit-actions/test.ts b/packages/wrapped-keys-lit-actions/test.ts deleted file mode 100644 index 52d9138ede..0000000000 --- a/packages/wrapped-keys-lit-actions/test.ts +++ /dev/null @@ -1,21 +0,0 @@ -// const ansonTestCredential = { "authMethod": { "authMethodType": "0xf8d39b7f3ec30f4bd2e45e0d545c83f64f8364a2c53765ca42ccf9bf7cde3482", "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiNjcwZmVhM2EtOWQ5Yi00NzIyLWEwYWEtYTRkZDlmMTY2ZjM5IiwiZW1haWwiOiJhbnNvbkBsaXRwcm90b2NvbC5jb20iLCJpYXQiOjE3Mjg2NTg1NTUsImV4cCI6MTcyOTI2MzM1NX0.JyXdgpN_ioqPq0kfeSHaA9hh7NZEyP_gBGQ5415kKyY", "userOauthId": "anson@litprotocol.com", "userKey": "anson@litprotocol.com" }, "pubKey": "0x04d168bedc060af4f7e7dc4d84e8c7bd8b3e8c4aa98ebecd2fcd2982a8ef72f799b87611e71d6b04d5b0ee9195c621a827e2ffb529742d809fe366648f48e6b1f5" }; - -// const url = 'https://api.development.tria.so/api/v1/user/info'; -// const response = await fetch(url, { -// method: 'GET', -// headers: { -// Authorization: `Bearer ${ansonTestCredential.authMethod.accessToken}`, -// }, -// }); - -// // { -// // success: true, -// // userInfo: { -// // uuid: "xxxxxxxx-yyyy-zzzz-aaaa-bbbbbbbbbbbb", -// // email: "xxx@xxx.com", -// // iat: 1728658555, -// // exp: 1729263355, -// // }, -// // } -// const data = await response.json(); -// console.log('data', data); diff --git a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts index 8b6601fa42..da45d75e51 100644 --- a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts +++ b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts @@ -15,16 +15,7 @@ import { import { LitAbility, LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers'; import { SessionSigsMap } from '@lit-protocol/types'; import { formatSessionSigsJSON, getResourcesFromSessionSigs } from '@lit-protocol/misc'; - -// resolvedAuthContext: { -// auth_context: { -// actionIpfsIds: [ 'Qmd5ibCRo9DhEnjcmfBsMU6qRBCvMCZw5kB7oSvCa7iXDR' ], -// authMethodContexts: [], -// authSigAddress: null, -// customAuthResource: "(true, 'Anything your want to use in executeJs')", -// resources: [] -// } -// } +import { computeAddress } from 'ethers/lib/utils'; /** @@ -37,6 +28,10 @@ export async function triaBatchGeneratePrivateKeys( params: Omit & { pkpPublicKey: string | `0x${string}`; ipfsId: string | `Qm${string}`; + authMethod: { + authMethodType: string | `0x${string}`; + accessToken: string | `eyJ${string}`; + } } ): Promise { @@ -60,10 +55,35 @@ export async function triaBatchGeneratePrivateKeys( // 'tria_batchGenerateEncryptedKeys' // ); + let pkpPubKey = params.pkpPublicKey; + + if (pkpPubKey.startsWith('0x')) { + pkpPubKey = pkpPubKey.slice(2); + } + const pkpPubkeyBuffer = Buffer.from(pkpPubKey, 'hex'); + + const pkpEthAddress = computeAddress(pkpPubkeyBuffer); + + console.log("pkpEthAddress:", pkpEthAddress); + + const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpEthAddress); + // Here we should use getLitActionSessionSigs rather than executeJs console.log(`🔄 Getting Lit Action Session Sigs`); let litActionSessionSigs: SessionSigsMap; + const _jsParams = { + authMethod: { + accessToken: params.authMethod.accessToken, + authMethodType: params.authMethod.authMethodType, + }, + actions: params.actions, + publicKey: params.pkpPublicKey, + accessControlConditions: [allowPkpAddressToDecrypt], + }; + + console.log("_jsParams:", _jsParams); + try { litActionSessionSigs = await params.litNodeClient.getLitActionSessionSigs({ pkpPublicKey: params.pkpPublicKey, @@ -78,7 +98,7 @@ export async function triaBatchGeneratePrivateKeys( }, ], litActionIpfsId: params.ipfsId, - jsParams: {}, + jsParams: _jsParams, }); } catch (e) { throw new Error(`Error getting Lit Action Session Sigs: ${e}`); From e1c5de87ace420916504f0d2f47be8ff4fecef30 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 22:42:15 +0100 Subject: [PATCH 09/10] can see the parsed results --- ...UseTriaAuthAndWrappedKeysSessionSigsGen.ts | 68 ------------------- .../tria_batchGenerateEncryptedKeys.js | 64 +++++++---------- 2 files changed, 25 insertions(+), 107 deletions(-) diff --git a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts index 0c4c4b4b91..688b7f27a7 100644 --- a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts +++ b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts @@ -109,72 +109,4 @@ export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( }); console.log("results:", results); - - process.exit(); - - const litActionSessionSigs = - await devEnv.litNodeClient.getLitActionSessionSigs({ - pkpPublicKey: alice.authMethodOwnedPkp.publicKey, - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), // 10 mins expiry - resourceAbilityRequests: [ - { - resource: new LitPKPResource('*'), - ability: LitAbility.PKPSigning, - }, - { - resource: new LitActionResource('*'), - ability: LitAbility.LitActionExecution, - }, - ], - litActionCode: Buffer.from( - ` - // Works with an AuthSig AuthMethod - if (Lit.Auth.authMethodContexts.some(e => e.authMethodType === 1)) { - LitActions.setResponse({ response: "true" }); - } else { - LitActions.setResponse({ response: "false" }); - } - ` - ).toString('base64'), - jsParams: { - magicNumber: 42, - }, - capabilityAuthSigs: [capacityDelegationAuthSig], - }); - - // const litActionSessionSigs = await getLitActionSessionSigs(devEnv, alice) - - console.log('litActionSessionSigs:', litActionSessionSigs); - process.exit(); - - // -- Remove below - // const litActionSessionSigs = await getLitActionSessionSigsUsingIpfsId( - // devEnv, - // alice, - // [ - // { - // resource: new LitPKPResource('*'), - // ability: LitAbility.PKPSigning, - // }, - // { - // resource: new LitActionResource('*'), - // ability: LitAbility.LitActionExecution, - // }, - // ] - // ); - - // const res = await devEnv.litNodeClient.executeJs({ - // sessionSigs: litActionSessionSigs, - // code: `(async () => { - // const sigShare = await LitActions.signEcdsa({ - // toSign: dataToSign, - // publicKey, - // sigName: "sig", - // }); - // })();`, - // jsParams: { - // dataToSign: alice.loveLetter, - // publicKey: alice.authMethodOwnedPkp.publicKey, - // }, - // }); }; diff --git a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js index 76b3ac3bfb..3e6f20103f 100644 --- a/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js +++ b/packages/wrapped-keys-lit-actions/src/lib/common/bespoke/tria_batchGenerateEncryptedKeys.js @@ -10,7 +10,20 @@ const { } = require('../../solana/internal/generatePrivateKey'); const { signMessageSolanaKey } = require('../../solana/internal/signMessage'); -/* "TRIA" global accessControlConditions, actions, Lit*/ +// =========== Global Variables (JsParams) =========== +// Lit Action:: Prepare jsParams +const jsParams = { + authMethod: { + accessToken: authMethod.accessToken, + authMethodType: authMethod.authMethodType, + }, + publicKey: publicKey, + actions: actions, + accessControlConditions: accessControlConditions, +}; + +validateJsParams(jsParams); + async function processEthereumAction(action) { const { network, generateKeyParams } = action; const messageToSign = action.signMessageParams?.messageToSign; @@ -156,26 +169,7 @@ function validateJsParams(jsParams) { }); } -// (async () => { -// try { -// validateParams(actions); - -// const batchGeneratePrivateKeysActionResult = await processActions(actions); - -// Lit.Actions.setResponse({ -// response: JSON.stringify(batchGeneratePrivateKeysActionResult), -// }); - -// // 1. Generate both EVM and solana private keys -// // 2. Run appropriate signMessage for each key _and_ encrypt the keys for persistence to wrapped-keys backend -// // 3. Return results for both signMessage ops and both encrypted key payloads for persistence -// } catch (err) { -// Lit.Actions.setResponse({ response: `Error: ${err.message}` }); -// } -// })(); - const go = async () => { - // ========== Tria's Logic ========== // Lit Action:: Prepare jsParams const jsParams = { authMethod: { @@ -252,29 +246,21 @@ const go = async () => { // return; // } - // LitActions.setResponse({ - // response: `(true, ${JSON.stringify({ - // returnedData: data, - // logs: { - // authMethodId, - // tokenId, - // permittedAuthMethods, - // permittedAuthMethod, - // actions: jsParams.actions, - // batchGeneratePrivateKeysActionResult, - // }, - // })})`, - // }); - + // -- Perform runOnce wrapped-keys actions try { - const batchGeneratePrivateKeysActionResult = await processActions( - jsParams.actions + let res = await Lit.Actions.runOnce( + { waitForResponse: true, name: 'tria-auth-and-wrapped-keys' }, + async () => { + const batchGeneratePrivateKeysActionResult = await processActions( + jsParams.actions + ); + + return JSON.stringify(batchGeneratePrivateKeysActionResult); + } ); Lit.Actions.setResponse({ - response: JSON.stringify( - `(true, ${JSON.stringify(batchGeneratePrivateKeysActionResult)})` - ), + response: JSON.stringify(`(true, ${res})`), }); // 1. Generate both EVM and solana private keys From be8ce96bec66a4e3151b0b6f16eeed888eaa83e8 Mon Sep 17 00:00:00 2001 From: Anson Date: Fri, 11 Oct 2024 23:15:07 +0100 Subject: [PATCH 10/10] wip parsing --- .../api/bespoke/tria-batch-generate-private-keys.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts index da45d75e51..c5375bfabf 100644 --- a/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts +++ b/packages/wrapped-keys/src/lib/api/bespoke/tria-batch-generate-private-keys.ts @@ -110,6 +110,18 @@ export async function triaBatchGeneratePrivateKeys( console.log("sessionSigsResources:", sessionSigsResources); + // select a random resource from the array + const firstResource = sessionSigsResources[0]; + + if (!firstResource.customAuthSource) { + throw new Error(`Error: customAuthSource is required`); + } + + // remove "(true, from the beginning of the string and )" at the end of the string + const customAuthSource = firstResource.customAuthSource.slice(8, -2); + console.log("customAuthSource:", customAuthSource); + + process.exit(); // // This is the original code