Skip to content

Commit 816852d

Browse files
authored
fix(bench): handle void worker-wallet returns in inclusion sweep (#24843)
## Problem Every point of the [Nightly Bench Inclusion Sweep](https://github.com/AztecProtocol/aztec-packages/actions/runs/29801774127) (1/5/10 TPS) failed identically, ~5ms into the `n_tps.test.ts` body, during `registerSponsoredFPC` setup: ``` SyntaxError: "undefined" is not valid JSON at JSON.parse (<anonymous>) at WorkerWallet.call (test-wallet/worker_wallet.ts:127) at registerSponsoredFPC (fixtures/setup.ts:821) ``` `WorkerWallet.call` unconditionally `JSON.parse`d the worker's transport response. But void-returning methods — `registerContract`, `registerContractClass` (both `output: z.void()` in `WalletSchema`) — return nothing, and `jsonStringify(undefined)` yields `undefined`, which arrives at the client as the JS value `undefined` over the structured-clone transport. `JSON.parse(undefined)` coerces to `JSON.parse("undefined")` and throws. The crash is in test setup, before any transactions are sent, so it is deterministic and independent of TPS — hence all three points failed the same way. The deployed network and the `6.0.0-nightly.20260721` image are not implicated. ## Fix Pass an `undefined` response straight to the method's schema (its `z.void()` output accepts `undefined`) instead of `JSON.parse`-ing it, and widen `callRaw`'s return type to `string | undefined`. ## Test Adds `worker_wallet.test.ts`, which builds a `WorkerWallet` over a stub transport that returns `undefined` and asserts `registerContract` / `registerContractClass` resolve. Verified red/green: against the old code it fails with the exact CI error (`"undefined" is not valid JSON`); with the fix it passes.
2 parents 60f0bb3 + fc2d744 commit 816852d

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { ContractArtifact } from '@aztec/stdlib/abi';
2+
import type { ContractInstancePreimage } from '@aztec/stdlib/contract';
3+
4+
import { WorkerWallet } from './worker_wallet.js';
5+
6+
describe('WorkerWallet', () => {
7+
// The private constructor spawns a worker; call() only touches the transport client, so we build the
8+
// instance directly with a stub client and never start a worker.
9+
const walletRespondingWith = (requestResult: unknown): WorkerWallet => {
10+
const client = { request: () => Promise.resolve(requestResult) };
11+
return Reflect.construct(WorkerWallet, [undefined, client]);
12+
};
13+
14+
// registerContract / registerContractClass return void, which the worker serializes as `undefined`.
15+
// Feeding that to JSON.parse throws `"undefined" is not valid JSON` — the crash that failed every
16+
// inclusion-sweep bench point during setup.
17+
it('resolves a void-returning method when the worker responds with undefined', async () => {
18+
const wallet = walletRespondingWith(undefined);
19+
await expect(wallet.registerContract({} as ContractInstancePreimage)).resolves.toBeUndefined();
20+
await expect(wallet.registerContractClass({} as ContractArtifact)).resolves.toBeUndefined();
21+
});
22+
});

yarn-project/end-to-end/src/test-wallet/worker_wallet.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,17 @@ export class WorkerWallet implements Wallet {
116116
return wallet;
117117
}
118118

119-
private async callRaw(fn: string, ...args: any[]): Promise<string> {
119+
private async callRaw(fn: string, ...args: any[]): Promise<string | undefined> {
120120
const argsJson = jsonStringify(args);
121-
return (await this.client.request({ fn, args: argsJson })) as string;
121+
return (await this.client.request({ fn, args: argsJson })) as string | undefined;
122122
}
123123

124124
private async call(fn: string, ...args: any[]): Promise<any> {
125125
const resultJson = await this.callRaw(fn, ...args);
126126
const methodSchema = (WorkerWalletSchema as ApiSchema)[fn];
127-
return getSchemaReturnType(methodSchema).parseAsync(JSON.parse(resultJson));
127+
// Void-returning methods (e.g. registerContract) serialize to `undefined` on the worker side, which
128+
// JSON.parse cannot handle; hand it straight to the schema, whose `z.void()` output accepts undefined.
129+
return getSchemaReturnType(methodSchema).parseAsync(resultJson === undefined ? undefined : JSON.parse(resultJson));
128130
}
129131

130132
getChainInfo(): Promise<ChainInfo> {

0 commit comments

Comments
 (0)