Skip to content

Commit 24381ec

Browse files
feat: Vincent Wrapped Keys
- Renamed `decryptVincentWrappedKey` -> `exportPrivateKey` to match existing wrapped keys SDK terminology - Resolved `TS80009` errors by removing `@Typedef` from tsdocs - Updated APIs for `evmContractConditions` - Updated APIs for `delegatorAddress` both in inputs and returned outputs from storage backend - Added explicit exported types for exportPrivateKey inputs and outputs (now matches our existing APIs structures) - Removed unused sessionSigs helper code from the api layer - Removed unused getDecryptedKeyToSingleNode - Renamed `delegateeSessionSigs` arg in generate methods to `delegatorSessionSigs`, since only delegators are allowed to generate sessionSigs per current spec - Paramaterized `evmContractConditions` in `getSolanaKeyPair()` -- this is now stored along with other wrapped key metadata and should _not_ be assumed to be static. - Updated REST API paths and arguments in `service-client` to match current paths - Removed unused devDependency on @lit-protocol/lit-node-client (we only use its type) - Use `removeSaltFromDecryptedKey()` in all places where we need to remove salt from the decrypted key (both exporting and inside of helper for solana wrapped keypair composition) - Updated `exportPrivateKey` API to match existing wrapped key behaviour patterns -- it now fetches the encrypted wrapped key from the storage backend using the `id` instead of expecting the consumer to use the service-client directly to fetch it
1 parent 628ba81 commit 24381ec

24 files changed

+315
-355
lines changed

packages/libs/wrapped-keys/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
{
22
"name": "@lit-protocol/vincent-wrapped-keys",
3-
"version": "0.1.0",
3+
"version": "0.6.0",
44
"publishConfig": {
55
"access": "public"
66
},
77
"dependencies": {
8+
"@lit-protocol/auth-helpers": "^8.0.2",
89
"@lit-protocol/constants": "^7.3.0",
910
"@lit-protocol/types": "^7.2.3",
1011
"@lit-protocol/vincent-contracts-sdk": "workspace:*",
@@ -25,6 +26,7 @@
2526
}
2627
},
2728
"devDependencies": {
29+
"@lit-protocol/lit-node-client": "^7.2.3",
2830
"@types/semver": "^7.7.0",
2931
"chokidar-cli": "^3.0.0",
3032
"ipfs-only-hash": "^4.0.0",

packages/libs/wrapped-keys/src/index.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { SupportedNetworks } from './lib/service-client/types';
1+
import type {
2+
SupportedNetworks,
3+
StoreKeyParams,
4+
StoreKeyBatchParams,
5+
} from './lib/service-client/types';
26
import type {
37
GetEncryptedKeyDataParams,
48
GeneratePrivateKeyParams,
@@ -16,6 +20,8 @@ import type {
1620
BatchGeneratePrivateKeysResult,
1721
Network,
1822
KeyType,
23+
ExportPrivateKeyParams,
24+
ExportPrivateKeyResult,
1925
} from './lib/types';
2026

2127
import {
@@ -25,7 +31,7 @@ import {
2531
listEncryptedKeyMetadata,
2632
batchGeneratePrivateKeys,
2733
storeEncryptedKeyBatch,
28-
getVincentRegistryAccessControlCondition,
34+
exportPrivateKey,
2935
} from './lib/api';
3036
import { CHAIN_YELLOWSTONE, LIT_PREFIX, NETWORK_SOLANA, KEYTYPE_ED25519 } from './lib/constants';
3137
import { getSolanaKeyPairFromWrappedKey } from './lib/lit-actions-client';
@@ -44,7 +50,7 @@ export const api = {
4450
storeEncryptedKey,
4551
storeEncryptedKeyBatch,
4652
batchGeneratePrivateKeys,
47-
getVincentRegistryAccessControlCondition,
53+
exportPrivateKey,
4854
litActionHelpers: {
4955
getSolanaKeyPairFromWrappedKey,
5056
},
@@ -68,4 +74,8 @@ export {
6874
BatchGeneratePrivateKeysResult,
6975
Network,
7076
KeyType,
77+
StoreKeyParams,
78+
StoreKeyBatchParams,
79+
ExportPrivateKeyParams,
80+
ExportPrivateKeyResult,
7181
};

packages/libs/wrapped-keys/src/lib/api/batch-generate-private-keys.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { getVincentWrappedKeysAccs } from '@lit-protocol/vincent-contracts-sdk';
2+
13
import type {
24
BatchGeneratePrivateKeysParams,
35
BatchGeneratePrivateKeysResult,
@@ -7,7 +9,7 @@ import type {
79
import { batchGenerateKeysWithLitAction } from '../lit-actions-client';
810
import { getLitActionCommonCid } from '../lit-actions-client/utils';
911
import { storePrivateKeyBatch } from '../service-client';
10-
import { getKeyTypeFromNetwork, getVincentRegistryAccessControlCondition } from './utils';
12+
import { getKeyTypeFromNetwork } from './utils';
1113

1214
/**
1315
* Generates multiple random private keys inside a Lit Action for Vincent delegators,
@@ -26,7 +28,7 @@ export async function batchGeneratePrivateKeys(
2628
): Promise<BatchGeneratePrivateKeysResult> {
2729
const { jwtToken, delegatorAddress, litNodeClient } = params;
2830

29-
const allowDelegateeToDecrypt = await getVincentRegistryAccessControlCondition({
31+
const vincentWrappedKeysAccs = await getVincentWrappedKeysAccs({
3032
delegatorAddress,
3133
});
3234

@@ -35,14 +37,16 @@ export async function batchGeneratePrivateKeys(
3537
const actionResults = await batchGenerateKeysWithLitAction({
3638
...params,
3739
litActionIpfsCid,
38-
accessControlConditions: [allowDelegateeToDecrypt],
40+
evmContractConditions: vincentWrappedKeysAccs,
3941
});
4042

41-
const keyParamsBatch = actionResults.map((keyData) => {
43+
const keyParamsBatch = actionResults.map((keyData, index) => {
4244
const { generateEncryptedPrivateKey } = keyData;
4345
return {
4446
...generateEncryptedPrivateKey,
4547
keyType: getKeyTypeFromNetwork('solana'),
48+
delegatorAddress,
49+
evmContractConditions: actionResults[index].generateEncryptedPrivateKey.evmContractConditions,
4650
};
4751
});
4852

@@ -56,17 +60,17 @@ export async function batchGeneratePrivateKeys(
5660
const {
5761
generateEncryptedPrivateKey: { memo, publicKey },
5862
} = actionResult;
59-
const id = ids[index]; // Result of writes is in same order as provided
63+
const id = ids[index]; // Result of writes is returned in the same order as provided
6064

6165
const signature = actionResult.signMessage?.signature;
6266

6367
return {
6468
...(signature ? { signMessage: { signature } } : {}),
6569
generateEncryptedPrivateKey: {
70+
delegatorAddress,
6671
memo,
6772
id,
6873
generatedPublicKey: publicKey,
69-
delegatorAddress,
7074
},
7175
};
7276
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { ExportPrivateKeyParams, ExportPrivateKeyResult } from '../types';
2+
3+
import { fetchPrivateKey } from '../service-client';
4+
import { removeSaltFromDecryptedKey } from '../utils';
5+
6+
export const exportPrivateKey = async ({
7+
litNodeClient,
8+
delegatorSessionSigs,
9+
jwtToken,
10+
id,
11+
delegatorAddress,
12+
}: ExportPrivateKeyParams): Promise<ExportPrivateKeyResult> => {
13+
const storedKeyMetadata = await fetchPrivateKey({
14+
delegatorAddress,
15+
id,
16+
jwtToken,
17+
litNetwork: litNodeClient.config.litNetwork,
18+
});
19+
20+
const {
21+
ciphertext,
22+
dataToEncryptHash,
23+
evmContractConditions,
24+
publicKey,
25+
keyType,
26+
litNetwork,
27+
memo,
28+
} = storedKeyMetadata;
29+
30+
const { decryptedData } = await litNodeClient.decrypt({
31+
sessionSigs: delegatorSessionSigs,
32+
ciphertext: ciphertext,
33+
dataToEncryptHash: dataToEncryptHash,
34+
evmContractConditions: JSON.parse(evmContractConditions),
35+
chain: 'ethereum',
36+
});
37+
38+
return {
39+
decryptedPrivateKey: removeSaltFromDecryptedKey(new TextDecoder().decode(decryptedData)),
40+
delegatorAddress,
41+
id,
42+
publicKey,
43+
keyType,
44+
litNetwork,
45+
memo,
46+
};
47+
};

packages/libs/wrapped-keys/src/lib/api/generate-private-key.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { getVincentWrappedKeysAccs } from '@lit-protocol/vincent-contracts-sdk';
2+
13
import type { GeneratePrivateKeyParams, GeneratePrivateKeyResult } from '../types';
24

35
import { generateKeyWithLitAction } from '../lit-actions-client';
46
import { getLitActionCid } from '../lit-actions-client/utils';
57
import { storePrivateKey } from '../service-client';
6-
import { getKeyTypeFromNetwork, getVincentRegistryAccessControlCondition } from './utils';
8+
import { getKeyTypeFromNetwork } from './utils';
79

810
/**
911
* Generates a random private key inside a Lit Action for Vincent delegators,
@@ -22,17 +24,18 @@ export async function generatePrivateKey(
2224
): Promise<GeneratePrivateKeyResult> {
2325
const { delegatorAddress, jwtToken, network, litNodeClient, memo } = params;
2426

25-
const allowDelegateeToDecrypt = await getVincentRegistryAccessControlCondition({
27+
const vincentWrappedKeysAccs = await getVincentWrappedKeysAccs({
2628
delegatorAddress,
2729
});
2830

2931
const litActionIpfsCid = getLitActionCid(network, 'generateEncryptedKey');
3032

31-
const { ciphertext, dataToEncryptHash, publicKey } = await generateKeyWithLitAction({
32-
...params,
33-
litActionIpfsCid,
34-
accessControlConditions: [allowDelegateeToDecrypt],
35-
});
33+
const { ciphertext, dataToEncryptHash, publicKey, evmContractConditions } =
34+
await generateKeyWithLitAction({
35+
...params,
36+
litActionIpfsCid,
37+
evmContractConditions: vincentWrappedKeysAccs,
38+
});
3639

3740
const { id } = await storePrivateKey({
3841
jwtToken,
@@ -42,6 +45,8 @@ export async function generatePrivateKey(
4245
keyType: getKeyTypeFromNetwork(network),
4346
dataToEncryptHash,
4447
memo,
48+
delegatorAddress,
49+
evmContractConditions,
4550
},
4651
litNetwork: litNodeClient.config.litNetwork,
4752
});

packages/libs/wrapped-keys/src/lib/api/index.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,5 @@ export { listEncryptedKeyMetadata } from './list-encrypted-key-metadata';
44
export { getEncryptedKey } from './get-encrypted-key';
55
export { storeEncryptedKey } from './store-encrypted-key';
66
export { storeEncryptedKeyBatch } from './store-encrypted-key-batch';
7-
export {
8-
getKeyTypeFromNetwork,
9-
getFirstSessionSig,
10-
getVincentRegistryAccessControlCondition,
11-
} from './utils';
7+
export { getKeyTypeFromNetwork } from './utils';
8+
export { exportPrivateKey } from './export-private-key';

packages/libs/wrapped-keys/src/lib/api/store-encrypted-key-batch.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { storePrivateKeyBatch } from '../service-client';
1818
export async function storeEncryptedKeyBatch(
1919
params: StoreEncryptedKeyBatchParams,
2020
): Promise<StoreEncryptedKeyBatchResult> {
21-
const { jwtToken, litNodeClient, keyBatch } = params;
21+
const { jwtToken, litNodeClient, keyBatch, delegatorAddress } = params;
2222

2323
const storedKeyMetadataBatch: StoreKeyBatchParams['storedKeyMetadataBatch'] = keyBatch.map(
2424
({
@@ -27,15 +27,24 @@ export async function storeEncryptedKeyBatch(
2727
memo,
2828
dataToEncryptHash,
2929
ciphertext,
30+
evmContractConditions,
3031
}): Pick<
3132
StoredKeyData,
32-
'publicKey' | 'keyType' | 'dataToEncryptHash' | 'ciphertext' | 'memo'
33+
| 'publicKey'
34+
| 'keyType'
35+
| 'dataToEncryptHash'
36+
| 'ciphertext'
37+
| 'memo'
38+
| 'delegatorAddress'
39+
| 'evmContractConditions'
3340
> => ({
3441
publicKey,
3542
memo,
3643
dataToEncryptHash,
3744
ciphertext,
3845
keyType,
46+
delegatorAddress,
47+
evmContractConditions,
3948
}),
4049
);
4150

packages/libs/wrapped-keys/src/lib/api/store-encrypted-key.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@ export async function storeEncryptedKey(
1515
): Promise<StoreEncryptedKeyResult> {
1616
const { jwtToken, litNodeClient } = params;
1717

18-
const { publicKey, keyType, dataToEncryptHash, ciphertext, memo } = params;
18+
const {
19+
publicKey,
20+
keyType,
21+
dataToEncryptHash,
22+
ciphertext,
23+
memo,
24+
delegatorAddress,
25+
evmContractConditions,
26+
} = params;
1927

2028
return storePrivateKey({
2129
storedKeyMetadata: {
@@ -24,6 +32,8 @@ export async function storeEncryptedKey(
2432
dataToEncryptHash,
2533
ciphertext,
2634
memo,
35+
delegatorAddress,
36+
evmContractConditions,
2737
},
2838
jwtToken,
2939
litNetwork: litNodeClient.config.litNetwork,
Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
import { ethers } from 'ethers';
2-
3-
import type { AuthSig, SessionSigsMap, AccsEVMParams } from '@lit-protocol/types';
4-
5-
import { LIT_RPC } from '@lit-protocol/constants';
6-
import {
7-
VINCENT_DIAMOND_CONTRACT_ADDRESS_PROD,
8-
getPkpTokenId,
9-
COMBINED_ABI,
10-
} from '@lit-protocol/vincent-contracts-sdk';
11-
121
import type { KeyType, Network } from '../types';
132

14-
import { CHAIN_YELLOWSTONE, NETWORK_SOLANA } from '../constants';
3+
import { NETWORK_SOLANA } from '../constants';
154

165
/**
176
* Returns the key type for the given network
@@ -27,80 +16,3 @@ export function getKeyTypeFromNetwork(network: Network): KeyType {
2716
throw new Error(`Network not implemented ${network}`);
2817
}
2918
}
30-
31-
/**
32-
*
33-
* Extracts the first SessionSig from the SessionSigsMap since we only pass a single SessionSig to the AWS endpoint
34-
*
35-
* @param pkpSessionSigs - The PKP sessionSigs (map) used to associate the PKP with the generated private key
36-
*
37-
* @returns { AuthSig } - The first SessionSig from the map
38-
*/
39-
export function getFirstSessionSig(pkpSessionSigs: SessionSigsMap): AuthSig {
40-
const sessionSigsEntries = Object.entries(pkpSessionSigs);
41-
42-
if (sessionSigsEntries.length === 0) {
43-
throw new Error(`Invalid pkpSessionSigs, length zero: ${JSON.stringify(pkpSessionSigs)}`);
44-
}
45-
46-
const [[, sessionSig]] = sessionSigsEntries;
47-
return sessionSig;
48-
}
49-
50-
/**
51-
* Creates access control condition to validate Vincent delegatee authorization
52-
* via the Vincent registry contract's isDelegateePermitted method
53-
*
54-
* This function creates an ACC utilize the Vincent Delegatee's address derived from the inner Auth Sig of the provided Session Signatures,
55-
* the delegator's PKP token ID derived from the provided delegator's address, and the IPFS CID of the executing Lit Action.
56-
*
57-
* @returns AccsEVMParams - Access control condition for Vincent registry validation
58-
*/
59-
export async function getVincentRegistryAccessControlCondition({
60-
delegatorAddress,
61-
}: {
62-
delegatorAddress: string;
63-
}): Promise<AccsEVMParams> {
64-
if (!ethers.utils.isAddress(delegatorAddress)) {
65-
throw new Error(`delegatorAddress is not a valid Ethereum Address: ${delegatorAddress}`);
66-
}
67-
68-
const delegatorPkpTokenId = (
69-
await getPkpTokenId({
70-
pkpEthAddress: delegatorAddress,
71-
signer: ethers.Wallet.createRandom().connect(
72-
new ethers.providers.StaticJsonRpcProvider(LIT_RPC.CHRONICLE_YELLOWSTONE),
73-
),
74-
})
75-
).toString();
76-
77-
const contractInterface = new ethers.utils.Interface(COMBINED_ABI.fragments);
78-
const fragment = contractInterface.getFunction('isDelegateePermitted');
79-
80-
const functionAbi = {
81-
type: 'function',
82-
name: fragment.name,
83-
inputs: fragment.inputs.map((input) => ({
84-
name: input.name,
85-
type: input.type,
86-
})),
87-
outputs: fragment.outputs?.map((output) => ({
88-
name: output.name,
89-
type: output.type,
90-
})),
91-
stateMutability: fragment.stateMutability,
92-
};
93-
94-
return {
95-
contractAddress: VINCENT_DIAMOND_CONTRACT_ADDRESS_PROD,
96-
functionAbi,
97-
chain: CHAIN_YELLOWSTONE,
98-
functionName: 'isDelegateePermitted',
99-
functionParams: [':userAddress', delegatorPkpTokenId, ':currentActionIpfsId'],
100-
returnValueTest: {
101-
key: 'isPermitted',
102-
comparator: '=',
103-
value: 'true',
104-
},
105-
};
106-
}

0 commit comments

Comments
 (0)