Skip to content

Commit 7fb2610

Browse files
authored
Merge pull request #2620 from privacy-scaling-explorations/feat/coordinator/tests-in-github
feat: coordinator tests in GitHub
2 parents 38c76f2 + 0b0bd93 commit 7fb2610

File tree

19 files changed

+505
-309
lines changed

19 files changed

+505
-309
lines changed

.github/workflows/coordinator.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Coordinator
2+
3+
on:
4+
push:
5+
branches: [dev]
6+
pull_request:
7+
8+
env:
9+
NODE_OPTIONS: "--max-old-space-size=8192"
10+
TTL: ${{ vars.COORDINATOR_TTL }}
11+
LIMIT: ${{ vars.COORDINATOR_LIMIT }}
12+
COORDINATOR_PUBLIC_KEY_PATH: ${{ vars.COORDINATOR_PUBLIC_KEY_PATH }}
13+
COORDINATOR_PRIVATE_KEY_PATH: ${{ vars.COORDINATOR_PRIVATE_KEY_PATH }}
14+
COORDINATOR_MACI_PRIVATE_KEY: ${{ secrets.COORDINATOR_MACI_PRIVATE_KEY }}
15+
COORDINATOR_TALLY_ZKEY_NAME: ${{ vars.COORDINATOR_TALLY_ZKEY_NAME }}
16+
COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME: ${{ vars.COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME }}
17+
COORDINATOR_POLL_JOINING_ZKEY_NAME: ${{ vars.COORDINATOR_POLL_JOINING_ZKEY_NAME }}
18+
COORDINATOR_POLL_JOINED_ZKEY_NAME: ${{ vars.COORDINATOR_POLL_JOINED_ZKEY_NAME }}
19+
COORDINATOR_RAPIDSNARK_EXE: ${{ vars.COORDINATOR_RAPIDSNARK_EXE }}
20+
COORDINATOR_ZKEY_PATH: ${{ vars.COORDINATOR_ZKEY_PATH }}
21+
COORDINATOR_RPC_URL: ${{ secrets.COORDINATOR_RPC_URL }}
22+
COORDINATOR_ADDRESSES: ${{ vars.COORDINATOR_ADDRESSES }}
23+
COORDINATOR_ALLOWED_ORIGINS: ${{ vars.COORDINATOR_ALLOWED_ORIGINS }}
24+
COORDINATOR_PORT: ${{ vars.COORDINATOR_PORT }}
25+
SUBGRAPH_NAME: ${{ vars.COORDINATOR_SUBGRAPH_NAME }}
26+
SUBGRAPH_PROVIDER_URL: ${{ vars.COORDINATOR_SUBGRAPH_PROVIDER_URL }}
27+
SUBGRAPH_DEPLOY_KEY: ${{ secrets.COORDINATOR_SUBGRAPH_DEPLOY_KEY }}
28+
SUBGRAPH_FOLDER: ${{ vars.COORDINATOR_SUBGRAPH_FOLDER }}
29+
ZERODEV_BUNDLER_RPC_OP_SEPOLIA: ${{ secrets.COORDINATOR_ZERODEV_BUNDLER_RPC_OP_SEPOLIA }}
30+
TEST_PRIVATE_KEY: ${{ secrets.COORDINATOR_TEST_PRIVATE_KEY }}
31+
PRIVATE_KEY: ${{ secrets.COORDINATOR_TEST_PRIVATE_KEY }}
32+
33+
concurrency:
34+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
35+
cancel-in-progress: true
36+
37+
jobs:
38+
build-and-test:
39+
runs-on: ubuntu-22.04
40+
41+
steps:
42+
- uses: actions/checkout@v4
43+
- uses: pnpm/action-setup@v4
44+
with:
45+
version: 9
46+
47+
- name: Use Node.js 20
48+
uses: actions/setup-node@v4
49+
with:
50+
node-version: 20
51+
cache: "pnpm"
52+
53+
- name: Install dependencies
54+
run: |
55+
sudo apt-get update
56+
sudo apt-get install --yes \
57+
build-essential \
58+
libgmp-dev \
59+
libsodium-dev \
60+
nasm \
61+
nlohmann-json3-dev
62+
63+
- name: Install
64+
run: |
65+
pnpm install --frozen-lockfile --prefer-offline
66+
67+
- name: Build
68+
run: |
69+
unset TEST_PRIVATE_KEY // avoid errors when building contracts
70+
unset PRIVATE_KEY // avoid errors when building contracts
71+
pnpm run build
72+
73+
- name: Download rapidsnark (1c137)
74+
run: |
75+
mkdir -p ~/rapidsnark/build
76+
wget -qO ~/rapidsnark/build/prover https://maci-devops-zkeys.s3.ap-northeast-2.amazonaws.com/rapidsnark-linux-amd64-1c137
77+
chmod +x ~/rapidsnark/build/prover
78+
79+
- name: Download zkeys
80+
run: |
81+
pnpm download-zkeys:test:coordinator
82+
83+
- name: Generate RSA Keypair
84+
working-directory: apps/coordinator
85+
run: |
86+
pnpm run generate-keypair
87+
88+
- name: Run tests
89+
working-directory: apps/coordinator
90+
run: |
91+
pnpm run test
92+
93+
- name: Run E2E tests
94+
working-directory: apps/coordinator
95+
run: |
96+
pnpm run test:e2e

apps/coordinator/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
NODE_OPTIONS="--max-old-space-size=8192"
2+
DOTENV_CONFIG_DEBUG="false"
13
# Rate limit configuation
24
TTL=60000
35
LIMIT=10

apps/coordinator/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"run:node": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));'",
2323
"start": "pnpm run run:node ./ts/main.ts",
2424
"start:prod": "pnpm run run:node build/ts/main.js",
25-
"test": "jest --testPathIgnorePatterns=e2e.deploy.test.ts --testPathIgnorePatterns=e2e.test.ts --forceExit",
25+
"test": "jest --testPathIgnorePatterns=tests/ --forceExit",
2626
"test:coverage": "jest --coverage --forceExit",
2727
"test:e2e": "jest ./tests/*.test.ts --forceExit --runInBand",
2828
"types": "tsc -p tsconfig.json --noEmit",

apps/coordinator/tests/e2e.aa.test.ts

Lines changed: 0 additions & 126 deletions
This file was deleted.

apps/coordinator/tests/e2e.deploy.test.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Keypair } from "@maci-protocol/domainobjs";
2-
import { ContractStorage, isArm, joinPoll, signup, sleep } from "@maci-protocol/sdk";
2+
import { ContractStorage, isArm, joinPoll, signup, sleepUntil } from "@maci-protocol/sdk";
33
import { ValidationPipe, type INestApplication } from "@nestjs/common";
44
import { Test } from "@nestjs/testing";
55
import dotenv from "dotenv";
@@ -110,11 +110,18 @@ describe("E2E Deployment Tests", () => {
110110
});
111111
});
112112
});
113+
113114
afterEach(() => {
114115
socket.disconnect();
115116
});
116117

117118
// run tests
119+
test("should use OP Sepolia RPC in E2E", async () => {
120+
const network = await signer.provider?.getNetwork();
121+
122+
expect(network?.name).toBe(ESupportedNetworks.OPTIMISM_SEPOLIA);
123+
});
124+
118125
test("should return true in the health check", async () => {
119126
const response = await fetch(`${TEST_URL}/health/check`, { method: "GET" });
120127
const body = (await response.json()) as IHealthCheckResponse;
@@ -154,14 +161,14 @@ describe("E2E Deployment Tests", () => {
154161
});
155162

156163
test("should deploy MACI correctly", async () => {
157-
const config = testMaciDeploymentConfig;
158-
config.VerifyingKeysRegistry.args.stateTreeDepth = config.VerifyingKeysRegistry.args.stateTreeDepth.toString();
159-
config.VerifyingKeysRegistry.args.pollStateTreeDepth =
160-
config.VerifyingKeysRegistry.args.pollStateTreeDepth.toString();
161-
config.VerifyingKeysRegistry.args.tallyProcessingStateTreeDepth =
162-
config.VerifyingKeysRegistry.args.tallyProcessingStateTreeDepth.toString();
163-
config.VerifyingKeysRegistry.args.voteOptionTreeDepth =
164-
config.VerifyingKeysRegistry.args.voteOptionTreeDepth.toString();
164+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.stateTreeDepth =
165+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.stateTreeDepth.toString();
166+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.pollStateTreeDepth =
167+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.pollStateTreeDepth.toString();
168+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.tallyProcessingStateTreeDepth =
169+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.tallyProcessingStateTreeDepth.toString();
170+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.voteOptionTreeDepth =
171+
testMaciDeploymentConfig.VerifyingKeysRegistry.args.voteOptionTreeDepth.toString();
165172

166173
const response = await fetch(`${TEST_URL}/deploy/maci`, {
167174
method: "POST",
@@ -171,7 +178,7 @@ describe("E2E Deployment Tests", () => {
171178
},
172179
body: JSON.stringify({
173180
chain: CHAIN,
174-
config,
181+
config: testMaciDeploymentConfig,
175182
} as IDeployMaciArgs),
176183
});
177184

@@ -187,12 +194,11 @@ describe("E2E Deployment Tests", () => {
187194
});
188195

189196
test("should deploy a poll correctly", async () => {
190-
const config = testPollDeploymentConfig;
191-
config.voteOptions = config.voteOptions.toString();
197+
testPollDeploymentConfig.voteOptions = testPollDeploymentConfig.voteOptions.toString();
192198

193199
const startDate = Math.floor(Date.now() / 1000) + pollStartDateExtraSeconds;
194-
config.startDate = startDate;
195-
config.endDate = startDate + pollDuration;
200+
testPollDeploymentConfig.startDate = startDate;
201+
testPollDeploymentConfig.endDate = startDate + pollDuration;
196202

197203
const response = await fetch(`${TEST_URL}/deploy/poll`, {
198204
method: "POST",
@@ -202,10 +208,11 @@ describe("E2E Deployment Tests", () => {
202208
},
203209
body: JSON.stringify({
204210
chain: CHAIN,
205-
config,
211+
config: testPollDeploymentConfig,
206212
} as IDeployPollArgs),
207213
});
208214
const body = (await response.json()) as { pollId: string };
215+
209216
expect(response.status).toBe(201);
210217
expect(body.pollId).toBeDefined();
211218

@@ -214,7 +221,8 @@ describe("E2E Deployment Tests", () => {
214221
});
215222

216223
test("should allow voting on a poll", async () => {
217-
await sleep(pollStartDateExtraSeconds * 1000);
224+
await sleepUntil(testPollDeploymentConfig.startDate * 1000);
225+
218226
for (let i = 0; i < NUM_USERS; i += 1) {
219227
const keypairUser = new Keypair();
220228
const userPublicKey = keypairUser.publicKey.serialize();
@@ -285,7 +293,8 @@ describe("E2E Deployment Tests", () => {
285293
});
286294

287295
test("should merge correctly", async () => {
288-
await sleep(pollDuration * 1000);
296+
await sleepUntil((testPollDeploymentConfig.endDate + 5) * 1000); // 5 seconds of grace time after the poll end date
297+
289298
const response = await fetch(`${TEST_URL}/proof/merge`, {
290299
method: "POST",
291300
headers: {

apps/coordinator/tests/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ export const rechargeGasIfNeeded = async (
4747
const publicClient = getPublicClient(ESupportedNetworks.OPTIMISM_SEPOLIA);
4848
const balance = await publicClient.getBalance({ address });
4949
const balanceAsEther = formatEther(balance);
50+
5051
if (balanceAsEther <= minimumValueOfEther) {
5152
const testAccount = privateKeyToAccount(process.env.TEST_PRIVATE_KEY! as Hex);
5253
const walletClient = createWalletClient({
5354
chain: optimismSepolia,
5455
transport: http(),
5556
});
57+
5658
await walletClient.sendTransaction({
5759
account: testAccount,
5860
to: address,

apps/coordinator/ts/common/__tests__/common.test.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,8 @@ describe("common", () => {
6161
});
6262

6363
describe("getRpcUrl", () => {
64-
test("should return the correct RPCUrl for optimism-sepolia", () => {
65-
const rpcUrl = getRpcUrl(ESupportedNetworks.OPTIMISM_SEPOLIA);
66-
expect(rpcUrl).toBeDefined();
67-
expect(rpcUrl).toContain("https://opt-sepolia.g.alchemy.com/v2/");
68-
});
69-
70-
test("should return the correct RPCUrl for sepolia", () => {
71-
const rpcUrl = getRpcUrl(ESupportedNetworks.ETHEREUM_SEPOLIA);
72-
expect(rpcUrl).toBeDefined();
73-
expect(rpcUrl).toContain("https://eth-sepolia.g.alchemy.com/v2/");
74-
});
75-
7664
test("should throw when given an unsupported network", () => {
77-
expect(() => getRpcUrl(ESupportedNetworks.GNOSIS_CHAIN)).toThrow(ErrorCodes.UNSUPPORTED_NETWORK.toString());
65+
expect(() => getRpcUrl("Unsupported" as ESupportedNetworks)).toThrow(ErrorCodes.UNSUPPORTED_NETWORK.toString());
7866
});
7967

8068
test("should throw when COORDINATOR_RPC_URL is not set", () => {

0 commit comments

Comments
 (0)