Skip to content

Commit f11184a

Browse files
committed
feat(artillery): enhance stress testing configurations and add new scripts
- Added new artillery commands for balance status and sign session key tests, improving testing capabilities. - Updated the PKP sign configuration to use a multi-endpoint processor for better flexibility. - Introduced a new balance status script to monitor account balances during tests. - Refactored existing scripts to include debug logging for HTTP responses, aiding in troubleshooting.
1 parent 0f31527 commit f11184a

File tree

7 files changed

+271
-16
lines changed

7 files changed

+271
-16
lines changed

e2e/artillery/configs/pkp-sign.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ config:
1616
- duration: 60
1717
arrivalRate: 5
1818
name: "Ramp Down"
19-
processor: "../src/processors/pkpSign.ts"
19+
processor: "../src/processors/multi-endpoints.ts"
2020

2121
scenarios:
2222
- name: "PKP Sign Stress Test"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
config:
2+
target: "dummy"
3+
phases:
4+
# Over 60s, ramp up to creating 50 vusers per second
5+
- duration: 60
6+
arrivalRate: 5
7+
# rampTo: 50
8+
rampTo: 10
9+
name: "Ramp Up"
10+
# Over 300s, create 50 vusers per second
11+
- duration: 300
12+
# arrivalRate: 50
13+
arrivalRate: 10
14+
name: "Sustained Sign Session Key"
15+
# Over 60s, ramp down to creating 5 vusers per second
16+
- duration: 60
17+
arrivalRate: 5
18+
name: "Ramp Down"
19+
processor: "../src/processors/multi-endpoints.ts"
20+
21+
scenarios:
22+
- name: "Sign Session Key Stress Test"
23+
weight: 100
24+
flow:
25+
26+
- function: "runSignSessionKeyTest"
27+
- think: 0.1
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { createLitClient } from "@lit-protocol/lit-client";
2+
import * as NetworkManager from "../../src/helper/NetworkManager";
3+
import * as AccountManager from '../src/AccountManager';
4+
5+
(async () => {
6+
7+
// 1. Setup network and chain client
8+
const networkModule = await NetworkManager.getLitNetworkModule();
9+
const publicClient = await NetworkManager.getViemPublicClient({ networkModule });
10+
const litClient = await createLitClient({ network: networkModule });
11+
12+
// 2. Get the master account
13+
const masterAccount = await AccountManager.getMasterAccount();
14+
15+
// every 5 seconds, check the balance of the master account
16+
setInterval(async () => {
17+
await AccountManager.getAccountDetails({
18+
accountLabel: "Master Account",
19+
account: masterAccount,
20+
publicClient,
21+
litClient,
22+
});
23+
}, 3000);
24+
25+
})();

e2e/artillery/src/init.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,21 @@ const LEDGER_MINIMUM_BALANCE = 10000;
8383
console.log('✅ Master Account PKP:', masterAccountPkp);
8484

8585
// create pkp auth context
86-
const masterAccountPkpAuthContext = await authManager.createPkpAuthContext({
87-
authData: masterAccountAuthData,
88-
pkpPublicKey: masterAccountPkp.publicKey,
89-
authConfig: {
90-
resources: [
91-
['pkp-signing', '*'],
92-
['lit-action-execution', '*'],
93-
['access-control-condition-decryption', '*'],
94-
],
95-
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
96-
},
97-
litClient: litClient,
98-
});
86+
// const masterAccountPkpAuthContext = await authManager.createPkpAuthContext({
87+
// authData: masterAccountAuthData,
88+
// pkpPublicKey: masterAccountPkp.publicKey,
89+
// authConfig: {
90+
// resources: [
91+
// ['pkp-signing', '*'],
92+
// ['lit-action-execution', '*'],
93+
// ['access-control-condition-decryption', '*'],
94+
// ],
95+
// expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
96+
// },
97+
// litClient: litClient,
98+
// });
9999

100-
console.log('✅ Master Account PKP Auth Context:', masterAccountPkpAuthContext);
100+
// console.log('✅ Master Account PKP Auth Context:', masterAccountPkpAuthContext);
101101

102102
// 6. create the auth context (this should be generated each time)
103103
// const masterAccountAuthContext = await authManager.createEoaAuthContext({
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import { createAuthManager, storagePlugins } from "@lit-protocol/auth";
2+
import { createLitClient } from "@lit-protocol/lit-client";
3+
import { z } from "zod";
4+
import * as StateManager from "../StateManager";
5+
import * as NetworkManager from "../../../src/helper/NetworkManager";
6+
import * as AccountManager from "../AccountManager";
7+
8+
// PKP Sign Result Schema
9+
const PkpSignResultSchema = z.object({
10+
signature: z.string().regex(/^0x[a-fA-F0-9]+$/, "Invalid hex signature"),
11+
verifyingKey: z.string().regex(/^0x[a-fA-F0-9]+$/, "Invalid hex verifying key"),
12+
signedData: z.string().regex(/^0x[a-fA-F0-9]+$/, "Invalid hex signed data"),
13+
recoveryId: z.number().int().min(0).max(3, "Recovery ID must be 0-3"),
14+
publicKey: z.string().regex(/^0x[a-fA-F0-9]+$/, "Invalid hex public key"),
15+
sigType: z.string().min(1, "Signature type cannot be empty"),
16+
});
17+
18+
// Global variables to cache expensive operations
19+
let litClient: any = null;
20+
let authManager: any = null;
21+
let masterAccountAuthContext: any = null;
22+
let networkModule: any = null;
23+
let masterAccount: any = null;
24+
25+
/**
26+
* Initialise shared resources once
27+
*/
28+
const initialiseSharedResources = async () => {
29+
if (!litClient) {
30+
console.log('🔧 Initializing shared resources...');
31+
32+
// Import network module
33+
networkModule = await NetworkManager.getLitNetworkModule();
34+
35+
// Create LitClient
36+
litClient = await createLitClient({ network: networkModule });
37+
38+
// Create AuthManager
39+
authManager = createAuthManager({
40+
storage: storagePlugins.localStorageNode({
41+
appName: 'artillery-testing-app',
42+
networkName: `${process.env['NETWORK']}-artillery`,
43+
storagePath: './lit-auth-artillery',
44+
}),
45+
});
46+
47+
console.log('✅ Shared resources initialised');
48+
}
49+
};
50+
51+
/**
52+
* Create auth context from stored state
53+
*/
54+
const createAuthContextFromState = async () => {
55+
if (!masterAccountAuthContext) {
56+
const state = await StateManager.readFile();
57+
58+
// Validate that master account authData and PKP exist
59+
if (!state.masterAccount.authData) {
60+
throw new Error('❌ Master account authData not found in state. Run init.ts first.');
61+
}
62+
63+
if (!state.masterAccount.pkp) {
64+
throw new Error('❌ Master account PKP not found in state. Run init.ts first.');
65+
}
66+
67+
// Get the master account from environment (same as init.ts)
68+
if (!masterAccount) {
69+
masterAccount = await AccountManager.getMasterAccount();
70+
}
71+
72+
// Create auth context for master account
73+
masterAccountAuthContext = await authManager.createEoaAuthContext({
74+
config: {
75+
account: masterAccount,
76+
},
77+
authConfig: {
78+
statement: 'I authorize the Lit Protocol to execute this Lit Action.',
79+
domain: 'example.com',
80+
resources: [
81+
['lit-action-execution', '*'],
82+
['pkp-signing', '*'],
83+
['access-control-condition-decryption', '*'],
84+
],
85+
capabilityAuthSigs: [],
86+
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
87+
},
88+
litClient: litClient,
89+
});
90+
}
91+
92+
return masterAccountAuthContext;
93+
};
94+
95+
/**
96+
* test the '/web/pkp/sign' endpoint
97+
*/
98+
export async function runPkpSignTest() {
99+
const startTime = Date.now();
100+
101+
try {
102+
// 1. Initialise shared resources (only happens once)
103+
await initialiseSharedResources();
104+
105+
// 2. Read state
106+
const state = await StateManager.readFile();
107+
108+
// Create auth context
109+
const authContext = await createAuthContextFromState();
110+
111+
// Perform pkpSign operation
112+
const result = await litClient.chain.ethereum.pkpSign({
113+
authContext: authContext,
114+
pubKey: state.masterAccount.pkp.publicKey,
115+
toSign: `Hello from Artillery! ${Date.now()}`, // Unique message per request
116+
});
117+
118+
// Validate the result using Zod schema
119+
const validatedResult = PkpSignResultSchema.parse(result);
120+
121+
const endTime = Date.now();
122+
const duration = endTime - startTime;
123+
124+
console.log(`✅ pkpSign successful in ${duration}ms`);
125+
console.log('✅ pkpSign result:', validatedResult);
126+
127+
// For Artillery, just return - no need to call next()
128+
return;
129+
130+
} catch (error) {
131+
const endTime = Date.now();
132+
const duration = endTime - startTime;
133+
134+
console.error(`❌ pkpSign failed in ${duration}ms:`, error instanceof Error ? error.message : String(error));
135+
136+
// Throw the error to let Artillery handle it
137+
throw error;
138+
}
139+
}
140+
141+
// test '/web/sign_session_key' endpoint
142+
export async function runSignSessionKeyTest() {
143+
144+
// ❗️ IT'S IMPORTANT TO SET THIS TO FALSE FOR TESTING
145+
const DELEGATION_AUTH_SIG_CACHE = false;
146+
147+
const startTime = Date.now();
148+
149+
try {
150+
// 1. initialise shared resources
151+
await initialiseSharedResources();
152+
153+
// 2. Read state
154+
const state = await StateManager.readFile();
155+
156+
const masterAccountPkpAuthContext = await authManager.createPkpAuthContext({
157+
authData: state.masterAccount.authData,
158+
pkpPublicKey: state.masterAccount.pkp.publicKey,
159+
authConfig: {
160+
resources: [
161+
['pkp-signing', '*'],
162+
['lit-action-execution', '*'],
163+
['access-control-condition-decryption', '*'],
164+
],
165+
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
166+
},
167+
litClient: litClient,
168+
cache: {
169+
delegationAuthSig: DELEGATION_AUTH_SIG_CACHE,
170+
}
171+
});
172+
173+
// console.log('✅ Master Account PKP Auth Context:', masterAccountPkpAuthContext);
174+
175+
} catch (error) {
176+
const endTime = Date.now();
177+
const duration = endTime - startTime;
178+
179+
console.error(`❌ signSessionKey failed in ${duration}ms:`, error instanceof Error ? error.message : String(error));
180+
181+
// Throw the error to let Artillery handle it
182+
throw error;
183+
}
184+
}

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
"auth-services": "cd packages/auth-services && bun run start",
2626
"test:e2e": "bun test ./e2e/src/e2e.spec.ts -t",
2727
"artillery:init": "bun run ./e2e/artillery/src/init.ts",
28-
"artillery:pkp-sign": "dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/pkp-sign.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'"
28+
"artillery:balance-status": "LOG_LEVEL=silent bun run ./e2e/artillery/src/balance-status.ts",
29+
"artillery:pkp-sign": "DEBUG_HTTP=true LOG_LEVEL=silent dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/pkp-sign.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'",
30+
"artillery:sign-session-key": "DEBUG_HTTP=true LOG_LEVEL=silent dotenvx run --env-file=.env -- sh -c 'artillery run ./e2e/artillery/configs/sign-session-key.yml ${ARTILLERY_KEY:+--record --key $ARTILLERY_KEY}'"
2931
},
3032
"private": true,
3133
"dependencies": {

packages/lit-client/src/lib/LitNodeClient/LitNodeApi/src/helper/sendNodeRequest.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,23 @@ export async function sendNodeRequest<T>(
7070

7171
const response = await fetch(_fullUrl, req);
7272

73+
// Only log response details when DEBUG_HTTP is enabled
74+
// Safely check for DEBUG_HTTP environment variable in both Node.js and browser
75+
let isDebugMode = false;
76+
try {
77+
isDebugMode = typeof process !== 'undefined' &&
78+
typeof process.env === 'object' &&
79+
process.env['DEBUG_HTTP'] === 'true';
80+
} catch (e) {
81+
// Ignore any errors - ensures browser compatibility
82+
isDebugMode = false;
83+
}
84+
85+
if (isDebugMode) {
86+
const timestamp = new Date().toISOString();
87+
console.log(`🔄 response at ${timestamp}`, response);
88+
}
89+
7390
const isJson = response.headers
7491
.get('content-type')
7592
?.includes('application/json');

0 commit comments

Comments
 (0)