Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(la-sign-combine): add test cases #493

Merged
merged 3 commits into from
Jun 4, 2024
Merged
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: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ jobs:
run: yarn build:dev
- name: Run End to End Tests
if: steps.build.outputs.exit_code == 0
run: yarn test:local --filter=testUseEoaSessionSigsToExecuteJsSigning,testUseEoaSessionSigsToPkpSign,testUsePkpSessionSigsToExecuteJsSigning,testUsePkpSessionSigsToPkpSign,testUseValidLitActionCodeGeneratedSessionSigsToPkpSign,testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning,testDelegatingCapacityCreditsNFTToAnotherWalletToExecuteJs,testEthAuthSigToEncryptDecryptString --exclude=Parallel
run: yarn test:local --filter=testUseEoaSessionSigsToExecuteJsSigning,testUseEoaSessionSigsToPkpSign,testUsePkpSessionSigsToExecuteJsSigning,testUsePkpSessionSigsToPkpSign,testUseValidLitActionCodeGeneratedSessionSigsToPkpSign,testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning,testDelegatingCapacityCreditsNFTToAnotherWalletToExecuteJs,testEthAuthSigToEncryptDecryptString,testExecuteJsSignAndCombineEcdsa,testExecutJsDecryptAndCombine,testExecuteJsBroadcastAndCollect --exclude=Parallel
19 changes: 19 additions & 0 deletions local-tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ import { testPkpEthersWithLitActionSessionSigsToEthSignTypedData } from './tests
import { testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil';
import { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil';
import { testUseCustomAuthSessionSigsToPkpSignExecuteJs } from './tests/testUseCustomAuthSessionSigsToPkpSignExecuteJs';
import { testExecuteJsSignAndCombineEcdsa } from './tests/testExecuteJsSignAndCombineEcdsa';
import { testExecutJsDecryptAndCombine } from './tests/testExecuteJsDecryptAndCombine';
import { testExecuteJsBroadcastAndCollect } from './tests/testExecuteJsBroadcastAndCollect';

(async () => {
console.log('[𐬺🧪 Tinny𐬺] Running tests...');
Expand Down Expand Up @@ -200,6 +203,18 @@ import { testUseCustomAuthSessionSigsToPkpSignExecuteJs } from './tests/testUseC
},
};

const litActionCombiningTests = {
ecdsaSignAndCombine: {
testExecuteJsSignAndCombineEcdsa,
},
decryptAndCombine: {
testExecutJsDecryptAndCombine,
},
broadcastAndCombine: {
testExecuteJsBroadcastAndCollect,
},
};

const testConfig = {
tests: {
// testExample,
Expand All @@ -214,6 +229,10 @@ import { testUseCustomAuthSessionSigsToPkpSignExecuteJs } from './tests/testUseC
...pkpEthersTest.eoaSessionSigs,
...pkpEthersTest.pkpSessionSigs,
...pkpEthersTest.litActionSessionSigs,

...litActionCombiningTests.broadcastAndCombine,
...litActionCombiningTests.decryptAndCombine,
...litActionCombiningTests.ecdsaSignAndCombine,
},
devEnv,
};
Expand Down
45 changes: 45 additions & 0 deletions local-tests/tests/testExecuteJsBroadcastAndCollect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { LIT_TESTNET } from 'local-tests/setup/tinny-config';
import { AccessControlConditions } from 'local-tests/setup/accs/accs';
import { getLitActionSessionSigs } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';

/**
* Test Commands:
* ✅ NETWORK=cayenne yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
* ❌ NOT AVAILABLE IN MANZANO
* ✅ NETWORK=localchain yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
*
*/
export const testExecuteJsBroadcastAndCollect = async (
devEnv: TinnyEnvironment
) => {
devEnv.setUnavailable(LIT_TESTNET.MANZANO);

const alice = await devEnv.createRandomPerson();
// set access control conditions for encrypting and decrypting
const accs = AccessControlConditions.getEmvBasicAccessControlConditions({
userAddress: alice.authMethodOwnedPkp.ethAddress,
});

const litActionSessionSigs = await getLitActionSessionSigs(devEnv, alice);

const res = await devEnv.litNodeClient.executeJs({
sessionSigs: litActionSessionSigs,
code: `(async () => {
let rand = Math.floor(Math.random() * 100);
const resp = await Lit.Actions.broadcastAndCollect({
name: "temperature",
value: rand.toString(),
});
Lit.Actions.setResponse({
response: JSON.stringify(resp)
});
})();`,
jsParams: {},
});

const response = res.response;
if (!response) {
throw new Error('Should contained broadcast data');
}
};
83 changes: 83 additions & 0 deletions local-tests/tests/testExecuteJsDecryptAndCombine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { LIT_TESTNET } from 'local-tests/setup/tinny-config';
import * as LitJsSdk from '@lit-protocol/lit-node-client-nodejs';
import { ILitNodeClient, LitAbility } from '@lit-protocol/types';
import { AccessControlConditions } from 'local-tests/setup/accs/accs';
import {
LitAccessControlConditionResource,
LitActionResource,
} from '@lit-protocol/auth-helpers';
import { getLitActionSessionSigs } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { log } from '@lit-protocol/misc';
import * as accessControlConditions from '@lit-protocol/access-control-conditions';

/**
* Test Commands:
* ✅ NETWORK=cayenne yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
* ❌ NOT AVAILABLE IN MANZANO
* ✅ NETWORK=localchain yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
*
*/
export const testExecutJsDecryptAndCombine = async (
devEnv: TinnyEnvironment
) => {
devEnv.setUnavailable(LIT_TESTNET.MANZANO);

const alice = await devEnv.createRandomPerson();
// set access control conditions for encrypting and decrypting
const accs = AccessControlConditions.getEmvBasicAccessControlConditions({
userAddress: alice.authMethodOwnedPkp.ethAddress,
});

const litActionSessionSigs = await getLitActionSessionSigs(devEnv, alice);

const encryptRes = await LitJsSdk.encryptString(
{
accessControlConditions: accs,
dataToEncrypt: 'Hello world',
},
devEnv.litNodeClient as unknown as ILitNodeClient
);

log('encryptRes:', encryptRes);

// -- Expected output:
// {
// ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
// dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
// }

// -- assertions
if (!encryptRes.ciphertext) {
throw new Error(`Expected "ciphertext" in encryptRes`);
}

if (!encryptRes.dataToEncryptHash) {
throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
}

const res = await devEnv.litNodeClient.executeJs({
sessionSigs: litActionSessionSigs,
code: `(async () => {
const resp = await Lit.Actions.decryptAndCombine({
accessControlConditions,
ciphertext,
dataToEncryptHash,
authSig: null,
chain: 'ethereum',
});
Lit.Actions.setResponse({
response: resp
});
})();`,
jsParams: {
accessControlConditions: accs,
dataToEncryptHash: encryptRes.dataToEncryptHash,
ciphertext: encryptRes.ciphertext,
},
});

if (res.response !== 'Hello world') {
throw new Error('content does not match what was expected');
}
};
106 changes: 106 additions & 0 deletions local-tests/tests/testExecuteJsSignAndCombineEcdsa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { LIT_ENDPOINT_VERSION } from '@lit-protocol/constants';
import { LIT_TESTNET } from 'local-tests/setup/tinny-config';
import { getEoaSessionSigsWithCapacityDelegations } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';

/**
* ## Scenario:
* Testing unrestricted access to execute js code using a capacity delegation authSig without specific delegatee restrictions
* - Given: A capacity delegation authSig is created by the dApp owner
* - When: The authSig does not specifically restrict delegatees
* - And: Any user attempts to execute js code using the capacity from the capacity credits NFT
* - Then: The user should be able to sign with his/her PKP using the capacity without restrictions due to the absence of delegatee limits
*
*
* ## Test Commands:
* - ❌ Not supported in Cayenne, but session sigs would still work
* - ✅ NETWORK=manzano yarn test:local --filter=testUseCapacityDelegationAuthSigWithUnspecifiedCapacityTokenIdToExecuteJs
* - ✅ NETWORK=localchain yarn test:local --filter=testUseCapacityDelegationAuthSigWithUnspecifiedCapacityTokenIdToExecuteJs
*/
export const testExecuteJsSignAndCombineEcdsa = async (
devEnv: TinnyEnvironment
) => {
const alice = await devEnv.createRandomPerson();
const bob = await devEnv.createRandomPerson();

const appOwnersCapacityDelegationAuthSig = (
await devEnv.litNodeClient.createCapacityDelegationAuthSig({
dAppOwnerWallet: alice.wallet,
})
).capacityDelegationAuthSig;

// 3. Bob gets the capacity delegation authSig from somewhere and uses it to get session sigs
const bobsSessionSigs = await getEoaSessionSigsWithCapacityDelegations(
devEnv,
bob.wallet,
appOwnersCapacityDelegationAuthSig
);

// -- printing out the recaps from the session sigs
const bobsSingleSessionSig =
bobsSessionSigs[devEnv.litNodeClient.config.bootstrapUrls[0]];

console.log('bobsSingleSessionSig:', bobsSingleSessionSig);

const regex = /urn:recap:[\w+\/=]+/g;

const recaps = bobsSingleSessionSig.signedMessage.match(regex) || [];

recaps.forEach((r) => {
const encodedRecap = r.split(':')[2];
const decodedRecap = Buffer.from(encodedRecap, 'base64').toString();
console.log(decodedRecap);
});

// 4. Bob can now execute JS code using the capacity credits NFT
// 5. Bob can now execute JS code using the capacity credits NFT
const res = await devEnv.litNodeClient.executeJs({
sessionSigs: bobsSessionSigs,
code: `(async () => {
const sigShare = await LitActions.signAndCombineEcdsa({
toSign: dataToSign,
publicKey,
sigName: "sig",
});
Lit.Actions.setResponse({
response: sigShare
});
})();`,
jsParams: {
dataToSign: alice.loveLetter,
publicKey: bob.pkp.publicKey,
},
});

/**
Response format
{
"success": true,
"signedData": {},
"decryptedData": {},
"claimData": {},
"response": "{\"r\":\"026eede14267ca76064a7e22dbe6f9e44d786c7b5917b7d023f45ee4e84ce1ea47\",\"s\":\"22a6048bcb88d724d45bdb6161fefd151483f41d592d167e5c33f42e9fe6dac6\",\"v\":0}",
"logs": ""
}
*/

if (!res.response) {
throw new Error('Response not found, expecting signature in response');
}

const sig = JSON.parse(res.response as string);
console.log('signature returned as a response', sig);

if (!sig.r) {
throw new Error('invalid signature returned from lit action');
}

if (!sig.s) {
throw new Error('invalid signature returned from lit action');
}

if (!sig.v) {
throw new Error('invalid signature returned from lit action');
}
console.log('✅ testDelegatingCapacityCreditsNFTToAnotherWalletToExecuteJs');
};
Loading