Skip to content

Commit debfd54

Browse files
committed
fix(test-suite): hard-cut main targets at simple acl
1 parent 8a9f40e commit debfd54

File tree

6 files changed

+86
-17
lines changed

6 files changed

+86
-17
lines changed

test-suite/fhevm/ARCHITECTURE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ This is the high-level shape of the Bun-based `fhevm-cli`.
55
```mermaid
66
flowchart TD
77
A["fhevm-cli up"] --> B["Resolve target"]
8-
B --> B1["latest-main: walk main SHAs until complete image set, but not before acfa977"]
8+
B --> B1["latest-main: walk main SHAs until complete image set, but not before 803f104"]
99
B --> B2["latest-release: latest stable release"]
10-
B --> B3["sha: exact repo-owned SHA, fail if any package tag is missing"]
10+
B --> B3["sha: exact repo-owned SHA on main, fail if any package tag is missing or if it predates 803f104"]
1111
B --> B4["devnet/testnet/mainnet: GitOps bundles"]
1212
B1 --> C["Lock resolved bundle"]
1313
B2 --> C

test-suite/fhevm/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ bun test
3838
## Targets
3939

4040
- `latest-release`: latest stable fhevm release plus checked-in companion defaults
41-
- `latest-main`: newest complete repo-owned main SHA bundle at or after the tenant-refactor floor (`acfa977`)
41+
- `latest-main`: newest complete repo-owned main SHA bundle at or after the simple-ACL floor (`803f104`)
4242
- `sha`: exact repo-owned SHA bundle plus `latest-release` companions
4343
- `devnet`
4444
- `testnet`
4545
- `mainnet`
4646

4747
Only `devnet`, `testnet`, and `mainnet` resolve from GitOps. Non-network targets do not.
4848
`latest-main` is intentionally modern-only; if the resolver cannot find a complete image set after the floor, it fails instead of walking into older protocol behavior.
49-
`sha` requires `--sha <git-sha>` and fails fast unless every repo-owned package is available at that 7-character SHA tag.
49+
`sha` requires `--sha <git-sha>` and fails fast unless every repo-owned package is available at that 7-character SHA tag, the SHA is on `main`, and it is at or after the simple-ACL floor.
5050

5151
## Pinning an Exact Version Bundle
5252

test-suite/fhevm/src/cli.test.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ const latestMainPackageResponses = (tag: string) =>
100100
);
101101

102102
describe("resolveTarget", () => {
103-
test("latest-main walks back to the first complete sha bundle after the tenant floor", async () => {
103+
test("latest-main walks back to the first complete sha bundle after the simple-acl floor", async () => {
104104
const gh = createGitHubClient(
105105
fakeRunner({
106106
"gh api repos/zama-ai/fhevm/commits?sha=main&per_page=100&page=1":
107107
JSON.stringify([
108108
{ sha: "1111111000000000000000000000000000000000" },
109-
{ sha: "acfa9775818406a119b53d2beb05a04742a49473" },
109+
{ sha: "803f1048727eabf6d8b3df618203e3c7dda77890" },
110110
{ sha: "2222222000000000000000000000000000000000" },
111111
]),
112112
...latestMainPackageResponses("1111111"),
@@ -118,13 +118,13 @@ describe("resolveTarget", () => {
118118
expect(bundle.env.CORE_VERSION).toBe("v0.13.0");
119119
});
120120

121-
test("latest-main rejects complete bundles older than the tenant floor", async () => {
121+
test("latest-main rejects complete bundles older than the simple-acl floor", async () => {
122122
const gh = createGitHubClient(
123123
fakeRunner({
124124
"gh api repos/zama-ai/fhevm/commits?sha=main&per_page=100&page=1":
125125
JSON.stringify([
126126
{ sha: "1111111000000000000000000000000000000000" },
127-
{ sha: "acfa9775818406a119b53d2beb05a04742a49473" },
127+
{ sha: "803f1048727eabf6d8b3df618203e3c7dda77890" },
128128
{ sha: "2222222000000000000000000000000000000000" },
129129
]),
130130
...latestMainPackageResponses("2222222"),
@@ -136,14 +136,52 @@ describe("resolveTarget", () => {
136136
});
137137

138138
test("sha resolves an explicit complete repo-owned image set", async () => {
139-
const gh = createGitHubClient(fakeRunner(latestMainPackageResponses("1234abc")));
139+
const gh = createGitHubClient(
140+
fakeRunner({
141+
"gh api repos/zama-ai/fhevm/commits?sha=main&per_page=100&page=1":
142+
JSON.stringify([
143+
{ sha: "1234abc999999999999999999999999999999999" },
144+
{ sha: "803f1048727eabf6d8b3df618203e3c7dda77890" },
145+
]),
146+
...latestMainPackageResponses("1234abc"),
147+
}),
148+
);
140149
const bundle = await resolveTarget("sha", gh, { sha: "1234abc999999999999999999999999999999999" });
141150
expect(bundle.lockName).toBe("sha-1234abc.json");
142151
expect(bundle.env.GATEWAY_VERSION).toBe("1234abc");
143152
expect(bundle.env.CORE_VERSION).toBe("v0.13.0");
144153
expect(bundle.sources).toContain("requested-sha=1234abc999999999999999999999999999999999");
145154
});
146155

156+
test("sha rejects commits older than the simple-acl floor", async () => {
157+
const gh = createGitHubClient(
158+
fakeRunner({
159+
"gh api repos/zama-ai/fhevm/commits?sha=main&per_page=100&page=1":
160+
JSON.stringify([
161+
{ sha: "803f1048727eabf6d8b3df618203e3c7dda77890" },
162+
{ sha: "1234abc999999999999999999999999999999999" },
163+
]),
164+
...latestMainPackageResponses("1234abc"),
165+
}),
166+
);
167+
await expect(resolveTarget("sha", gh, { sha: "1234abc" })).rejects.toThrow(
168+
"sha target 1234abc predates the simple-ACL cutover and is unsupported",
169+
);
170+
});
171+
172+
test("sha rejects non-main commits even if images exist", async () => {
173+
const gh = createGitHubClient(
174+
fakeRunner({
175+
"gh api repos/zama-ai/fhevm/commits?sha=main&per_page=100&page=1":
176+
JSON.stringify([{ sha: "803f1048727eabf6d8b3df618203e3c7dda77890" }]),
177+
...latestMainPackageResponses("1234abc"),
178+
}),
179+
);
180+
await expect(resolveTarget("sha", gh, { sha: "1234abc" })).rejects.toThrow(
181+
"sha target 1234abc is unsupported; only main commits at or after 803f104 are supported",
182+
);
183+
});
184+
147185
test("sha rejects missing repo-owned images", async () => {
148186
const responses = latestMainPackageResponses("1234abc");
149187
responses["gh api /orgs/zama-ai/packages/container/fhevm%2Fcoprocessor%2Fsns-worker/versions?per_page=100&page=1"] =
@@ -232,6 +270,10 @@ describe("runtime invariants", () => {
232270
["--tenant-api-key", "TENANT_API_KEY"],
233271
]);
234272
expect(compatPolicyForState(makeState("v0.11.0")).coprocessorArgs["transaction-sender"]).toEqual([
273+
["--multichain-acl-address", "MULTICHAIN_ACL_ADDRESS"],
274+
["--delegation-fallback-polling", "30"],
275+
["--delegation-max-retry", "100000"],
276+
["--retry-immediately-on-nonce-error", "2"],
235277
["--host-chain-url", "RPC_WS_URL"],
236278
]);
237279

test-suite/fhevm/src/compat.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ export type CompatPolicy = {
88
connectorEnv: Record<string, string>;
99
};
1010

11-
export const requiresMultichainAclAddress = (_state: Pick<State, "target" | "versions">) => true;
12-
1311
const COMPAT_PROFILES = {
1412
"legacy-coprocessor-api-keys": {
1513
coprocessorArgs: {
@@ -31,11 +29,23 @@ const COMPAT_PROFILES = {
3129
},
3230
connectorEnv: {},
3331
},
32+
"legacy-tx-sender-gateway-flags": {
33+
coprocessorArgs: {
34+
"transaction-sender": [
35+
["--multichain-acl-address", "MULTICHAIN_ACL_ADDRESS"],
36+
["--delegation-fallback-polling", "30"],
37+
["--delegation-max-retry", "100000"],
38+
["--retry-immediately-on-nonce-error", "2"],
39+
],
40+
},
41+
connectorEnv: {},
42+
},
3443
} as const satisfies Record<string, CompatPolicy>;
3544

3645
const COMPAT_RULES = {
3746
coprocessor: [
3847
{ before: [0, 12, 0] as CompatSemver, profile: "legacy-coprocessor-api-keys" },
48+
{ before: [0, 12, 0] as CompatSemver, profile: "legacy-tx-sender-gateway-flags" },
3949
{ before: [0, 11, 1] as CompatSemver, profile: "legacy-tx-sender-host-chain-url" },
4050
],
4151
connector: [{ before: [0, 11, 0] as CompatSemver, profile: "legacy-connector-chain-id" }],
@@ -63,6 +73,9 @@ const versionLt = (version: string, target: CompatSemver) => {
6373
return false;
6474
};
6575

76+
export const requiresMultichainAclAddress = (state: Pick<State, "versions">) =>
77+
versionLt(state.versions.env.COPROCESSOR_TX_SENDER_VERSION ?? "", [0, 12, 0]);
78+
6679
export const compatPolicyForState = (state: State): CompatPolicy => {
6780
const policy: CompatPolicy = { coprocessorArgs: {}, connectorEnv: {} };
6881
for (const rule of COMPAT_RULES.coprocessor) {

test-suite/fhevm/src/runtime.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { requiresMultichainAclAddress } from "./compat";
12
import path from "node:path";
23
import { parseArgs } from "node:util";
34

4-
import { requiresMultichainAclAddress } from "./compat";
55
import type {
66
Discovery,
77
InstanceOverride,

test-suite/fhevm/src/versions.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ const bundleFromFiles = async (client: GitHubClient, target: VersionTarget, file
304304

305305
const REPO_TAG = /^[0-9a-f]{7}$/;
306306
const SHA_REF = /^(?:[0-9a-f]{7}|[0-9a-f]{40})$/i;
307-
const LATEST_MAIN_MIN_SHA = "acfa9775818406a119b53d2beb05a04742a49473";
307+
const SIMPLE_ACL_MIN_SHA = "803f1048727eabf6d8b3df618203e3c7dda77890";
308308

309309
const repoPackageName = (pkg: string) => decodeURIComponent(pkg);
310310

@@ -322,6 +322,14 @@ const missingRepoPackages = (packageTags: Record<string, Set<string>>, tag: stri
322322

323323
const shortSha = (value: string) => value.toLowerCase().slice(0, 7);
324324

325+
const simpleAclFloor = (commits: string[]) => {
326+
const floor = commits.indexOf(SIMPLE_ACL_MIN_SHA);
327+
if (floor < 0) {
328+
throw new Error(`simple-acl floor ${SIMPLE_ACL_MIN_SHA} was not found in fetched main history`);
329+
}
330+
return floor;
331+
};
332+
325333
const presetBundle = (
326334
target: "latest-release" | "latest-main" | "sha",
327335
repoVersion: string,
@@ -378,14 +386,20 @@ export const resolveTarget = async (
378386
if (missing.length) {
379387
throw new Error(`Could not find a complete sha image set for ${tag}; missing: ${missing.join(", ")}`);
380388
}
389+
const commits = await client.mainCommits(1000);
390+
const floor = simpleAclFloor(commits);
391+
const index = commits.findIndex((sha) => sha.startsWith(tag));
392+
if (index < 0) {
393+
throw new Error(`sha target ${tag} is unsupported; only main commits at or after ${SIMPLE_ACL_MIN_SHA.slice(0, 7)} are supported`);
394+
}
395+
if (index > floor) {
396+
throw new Error(`sha target ${tag} predates the simple-ACL cutover and is unsupported`);
397+
}
381398
return presetBundle(target, tag, `sha-${tag}.json`, [`requested-sha=${requested.toLowerCase()}`]);
382399
}
383400
const packageTags = await repoPackageTags(client);
384401
const commits = await client.mainCommits(1000);
385-
const floor = commits.indexOf(LATEST_MAIN_MIN_SHA);
386-
if (floor < 0) {
387-
throw new Error(`latest-main floor ${LATEST_MAIN_MIN_SHA} was not found in fetched main history`);
388-
}
402+
const floor = simpleAclFloor(commits);
389403
const short = commits.slice(0, floor + 1).map((sha) => sha.slice(0, 7)).find((sha) =>
390404
Object.values(packageTags).every((set) => set.has(sha) && REPO_TAG.test(sha)),
391405
);

0 commit comments

Comments
 (0)