Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions local-tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import { testFailBatchGeneratePrivateKeysAtomic } from './tests/wrapped-keys/tes

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();
Expand Down Expand Up @@ -174,6 +175,7 @@ setLitActionsCodeToLocal();
testUseEoaSessionSigsToEncryptDecryptFile,
testUseEoaSessionSigsToEncryptDecryptZip,
testUseEoaSessionSigsToRequestSingleResponse,
testUseTriaAuthAndWrappedKeysSessionSigsGen,
};

const pkpSessionSigsTests = {
Expand Down
112 changes: 112 additions & 0 deletions local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
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';
import { api } 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
* ✅ 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
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...`);
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..
const { litActionCode, litActionIpfsCid } = api.getLitActionCodeOrCidCommon(
'triaAuthAndBatchGenerateEncryptedKeys'
);

// -- 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({
pkpPublicKey: pkp.publicKey,
ipfsId: hashOfLitActionCode,
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: triaAuthMethod,
});

console.log('results:', results);
};
1 change: 1 addition & 0 deletions local-tests/tests/wrapped-keys/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {

const emptyLitActionRepositoryCommon: LitActionCodeRepositoryCommon = {
batchGenerateEncryptedKeys: '',
triaAuthAndBatchGenerateEncryptedKeys: '',
};

const emptyLitActionRepository: LitActionCodeRepository = {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export function parseCustomResources(nodeResponses: any) {
return nodeResponses.values
.map((item: any) => {
return {
signedMessage: item.siweMessage,
};
})
.map((v: any, i: number) => {
const signedMessage = v.signedMessage;
const urnLine = signedMessage.match(/urn:recap:[\w\d]+/)![0];

const authContext = JSON.parse(atob(urnLine.split(':')[2])).att[
'lit-resolvedauthcontext://*'
]['Auth/Auth'][0]['auth_context'];

const extractedCustomAuthResource = authContext[
'customAuthResource'
].slice(8, -2);
const customAuthResources = extractedCustomAuthResource.replace(
/\\"/g,
'"'
);
let result;

try {
result = JSON.parse(customAuthResources);
} catch (e) {
result = extractedCustomAuthResource;
}

return {
customAuthResources: result,
// authContext,
};
})
.find((item: any) => item.customAuthResources !== 'undefined')
.customAuthResources;
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
findMostCommonResponse,
formatSessionSigs,
hexPrefixed,
leastCommonString,
log,
logError,
logErrorWithRequestId,
Expand Down Expand Up @@ -76,6 +77,7 @@ import { parsePkpSignResponse } from './helpers/parse-pkp-sign-response';
import { processLitActionResponseStrategy } from './helpers/process-lit-action-response-strategy';
import { removeDoubleQuotes } from './helpers/remove-double-quotes';
import { blsSessionSigVerify } from './helpers/validate-bls-session-sig';
import { parseCustomResources } from './helpers/parseCustomResources';

import type {
AuthCallback,
Expand Down Expand Up @@ -1880,18 +1882,35 @@ export class LitNodeClientNodeJs
});

// -- resolve promises
const numberToResolve = params?.handleAllResponses
? this.connectedNodes.size
: this.config.minNodeCount;
log(
`[signSessionKey] number of node promises to resolve:`,
numberToResolve
);

let res;
try {
res = await this.handleNodePromises(
nodePromises,
requestId,
this.config.minNodeCount
numberToResolve
);
log('signSessionKey node promises:', res);
} catch (e) {
throw new Error(`Error when handling node promises: ${e}`);
}

// -- parse that custom thing
let customAuthResources;

try {
customAuthResources = parseCustomResources(res);
} catch (e) {
log(`Failed to parse custom resources, not a problem.`);
}

logWithRequestId(requestId, 'handleNodePromises res:', res);

// -- case: promises rejected
Expand Down Expand Up @@ -1993,10 +2012,13 @@ export class LitNodeClientNodeJs
);
}

const commonStringStrategy =
params?.strategy === 'mostCommon' ? mostCommonString : leastCommonString;

const blsSignedData: BlsResponseData[] =
validatedSignedDataList as BlsResponseData[];

const sigType = mostCommonString(blsSignedData.map((s) => s.curveType));
const sigType = commonStringStrategy(blsSignedData.map((s) => s.curveType));
log(`[signSessionKey] sigType:`, sigType);

const signatureShares = getBlsSignatures(blsSignedData);
Expand All @@ -2013,10 +2035,12 @@ export class LitNodeClientNodeJs
const publicKey = removeHexPrefix(params.pkpPublicKey);
log(`[signSessionKey] publicKey:`, publicKey);

const dataSigned = mostCommonString(blsSignedData.map((s) => s.dataSigned));
const dataSigned = commonStringStrategy(
blsSignedData.map((s) => s.dataSigned)
);
log(`[signSessionKey] dataSigned:`, dataSigned);

const mostCommonSiweMessage = mostCommonString(
const mostCommonSiweMessage = commonStringStrategy(
blsSignedData.map((s) => s.siweMessage)
);

Expand All @@ -2035,6 +2059,9 @@ export class LitNodeClientNodeJs
derivedVia: 'lit.bls',
signedMessage,
address: computeAddress(hexPrefixed(publicKey)),
...(customAuthResources && {
customAuthResources: customAuthResources,
}),
},
pkpPublicKey: publicKey,
};
Expand Down Expand Up @@ -2318,6 +2345,10 @@ export class LitNodeClientNodeJs
litActionIpfsId: props.litActionIpfsId,
}),
...(props.jsParams && { jsParams: props.jsParams }),

...(params.handleAllResponses && {
handleAllResponses: params.handleAllResponses,
}),
});

return response.authSig;
Expand Down
17 changes: 17 additions & 0 deletions packages/misc/src/lib/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,23 @@ export const mostCommonString = (arr: Array<any>): any => {
.pop();
};

/**
*
* Find the element that occurs the least in an array
*
* @param { Array<any> } arr
* @returns { any } the element that appeared the least
*/
export const leastCommonString = (arr: Array<any>): any => {
return arr
.sort(
(a: any, b: any) =>
arr.filter((v: any) => v === b).length -
arr.filter((v: any) => v === a).length
)
.pop();
};

export const findMostCommonResponse = (responses: Array<object>): object => {
const result: { [key: string]: any } = {};

Expand Down
13 changes: 13 additions & 0 deletions packages/types/src/lib/ILitNodeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
RejectedNodePromises,
SendNodeCommand,
SuccessNodePromises,
GetLitActionSessionSigs,
SessionSigsMap,
} from './interfaces';
import { ILitResource, ISessionCapabilityObject } from './models';
import { SupportedJsonRequests } from './types';
Expand Down Expand Up @@ -227,4 +229,15 @@ export interface ILitNodeClient {
generateSessionCapabilityObjectWithWildcards(
litResources: ILitResource[]
): Promise<ISessionCapabilityObject>;

/**
* 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<SessionSigsMap>;
}
21 changes: 18 additions & 3 deletions packages/types/src/lib/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,9 @@ export interface CreateCustomAuthMethodRequest {
// pub auth_sig: Option<AuthSigItem>,
// pub siwe_message: String,
// }
export interface SignSessionKeyProp extends LitActionSdkParams {
export interface SignSessionKeyProp
extends LitActionSdkParams,
RespondHandling {
/**
* The serialized session key pair to sign. If not provided, a session key pair will be fetched from localStorge or generated.
*/
Expand Down Expand Up @@ -1910,7 +1912,8 @@ export interface SignerLike {

export interface GetPkpSessionSigs
extends CommonGetSessionSigsProps,
LitActionSdkParams {
LitActionSdkParams,
RespondHandling {
pkpPublicKey: string;

/**
Expand Down Expand Up @@ -1943,7 +1946,19 @@ export type GetLitActionSessionSigs = CommonGetSessionSigsProps &
})
) & {
ipfsOptions?: IpfsOptions;
};
} & RespondHandling;

export interface RespondHandling {
/**
* Whether to handle all responses or threshold/minNodeCount responses
*/
handleAllResponses?: boolean;

/**
* Strategy to handle responses
*/
strategy?: ResponseStrategy;
}

export interface SessionKeyCache {
value: SessionKeyPair;
Expand Down
1 change: 1 addition & 0 deletions packages/wrapped-keys-lit-actions/esbuild.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ module.exports = {
'./src/lib/self-executing-actions/ethereum/generateEncryptedEthereumPrivateKey.js',
'./src/lib/self-executing-actions/common/exportPrivateKey.js',
'./src/lib/self-executing-actions/common/batchGenerateEncryptedKeys.js',
'./src/lib/self-executing-actions/common/triaAuthAndBatchGenerateEncryptedKeys.js',
],
bundle: true,
minify: true,
Expand Down
Loading
Loading