Skip to content

Commit ea54ad4

Browse files
authored
fix: port bb socket startup retry to next (#24960)
## Summary Ports #24802 to `next`. This keeps the same behavior change from the merged v5 PR: - bb.js native socket startup now waits while the bb process remains alive, with a 60s wedged-process backstop instead of the old shared 5s socket/connect deadline. - bb startup failures are wrapped as retryable `ProvingError`s in bb-prover. - retryability is preserved when bb-prover re-wraps proof generation and verification failures. ## Conflict resolution The automatic cherry-pick conflicted because `barretenberg/ts/src/...` on the source branch has moved to `barretenberg/ts/bb.js/src/...` on `next`. Resolved by adapting the socket backend changes into the `bb.js` path and preserving `next`'s `createAsyncBackend` API shape, which returns `IMsgpackBackendAsync` rather than constructing a `Barretenberg` wrapper there. Added a small follow-up commit to satisfy the `next` lint rule for `destroy()`. Refs #24802 ## Verification - `git diff --check origin/next...HEAD` - `yarn formatting:fix` in `barretenberg/ts/bb.js` - `yarn test bb_backends/node/native_socket.test.ts --runInBand` in `barretenberg/ts/bb.js` Blocked locally: - `./bootstrap.sh build` in `barretenberg/ts/bb.js` passed formatting, then stopped at codegen because this checkout lacks `barretenberg/cpp/build/bin/bb`. - `JEST_MAX_WORKERS=1 yarn workspace @aztec/bb-prover test src/bb/bb_js_backend.test.ts` could not complete in this cold checkout without built workspace exports for `@aztec/bb.js`/`@aztec/foundation`. --- *Created by [claudebox](https://claudebox.work/v2/sessions/f03a66a010266d34/jobs/1) · group: `slackbot` · [Slack thread](https://aztecprotocol.slack.com/archives/C0AGN2WT3CP/p1784890226762699?thread_ts=1784890226.762699&cid=C0AGN2WT3CP)*
2 parents a4e87e4 + 8da21e8 commit ea54ad4

6 files changed

Lines changed: 227 additions & 201 deletions

File tree

barretenberg/ts/bb.js/src/bb_backends/node/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export async function createAsyncBackend(
2626
throw new Error('Native backend requires bb binary.');
2727
}
2828
logger(`Using native Unix socket backend: ${bbPath}`);
29-
return new BarretenbergNativeSocketAsyncBackend(bbPath, options.threads, options.logger, options.unref);
29+
return await BarretenbergNativeSocketAsyncBackend.new(bbPath, options.threads, options.logger, options.unref);
3030
}
3131

3232
case BackendType.NativeSharedMemory: {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { jest } from '@jest/globals';
2+
import * as fs from 'fs';
3+
import * as os from 'os';
4+
import * as path from 'path';
5+
6+
import { BarretenbergNativeSocketAsyncBackend } from './native_socket.js';
7+
8+
jest.setTimeout(30_000);
9+
10+
// Echo server speaking the bb msgpack socket protocol (4-byte LE length prefix), started after
11+
// an optional delay to simulate bb's startup time on a loaded machine.
12+
const ECHO_SERVER_JS = `
13+
const net = require('net');
14+
const socketPath = process.argv[2];
15+
const server = net.createServer(sock => {
16+
let buf = Buffer.alloc(0);
17+
sock.on('data', d => {
18+
buf = Buffer.concat([buf, d]);
19+
while (buf.length >= 4) {
20+
const len = buf.readUInt32LE(0);
21+
if (buf.length < 4 + len) break;
22+
const payload = buf.subarray(4, 4 + len);
23+
const out = Buffer.alloc(4);
24+
out.writeUInt32LE(payload.length, 0);
25+
sock.write(out);
26+
sock.write(payload);
27+
buf = buf.subarray(4 + len);
28+
}
29+
});
30+
});
31+
server.listen(socketPath);
32+
`;
33+
34+
// A fake bb binary: a bash script that optionally sleeps, then runs the echo server on the
35+
// socket path bb receives via `msgpack run --input <path>` ($4).
36+
function writeFakeBb(startupDelaySecs: number): string {
37+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fake-bb-'));
38+
const serverJs = path.join(dir, 'echo_server.cjs');
39+
fs.writeFileSync(serverJs, ECHO_SERVER_JS);
40+
const file = path.join(dir, 'bb');
41+
const sleep = startupDelaySecs > 0 ? `sleep ${startupDelaySecs}\n` : '';
42+
fs.writeFileSync(file, `#!/bin/bash\n${sleep}exec node ${serverJs} "$4"\n`, { mode: 0o755 });
43+
return file;
44+
}
45+
46+
function writeFakeBbScript(script: string): string {
47+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fake-bb-'));
48+
const file = path.join(dir, 'bb');
49+
fs.writeFileSync(file, script, { mode: 0o755 });
50+
return file;
51+
}
52+
53+
describe('BarretenbergNativeSocketAsyncBackend', () => {
54+
it('connects and echoes when bb starts promptly', async () => {
55+
const fakeBb = writeFakeBb(0);
56+
const backend = await BarretenbergNativeSocketAsyncBackend.new(fakeBb);
57+
const response = await backend.call(new Uint8Array([1, 2, 3, 4]));
58+
expect(response).toEqual(new Uint8Array([1, 2, 3, 4]));
59+
await backend.destroy();
60+
});
61+
62+
it('connects even when bb takes longer than 5s to create its socket', async () => {
63+
const fakeBb = writeFakeBb(7);
64+
const backend = await BarretenbergNativeSocketAsyncBackend.new(fakeBb);
65+
const response = await backend.call(new Uint8Array([42]));
66+
expect(response).toEqual(new Uint8Array([42]));
67+
await backend.destroy();
68+
});
69+
70+
it('fails with the exit cause when bb dies before creating its socket', async () => {
71+
const fakeBb = writeFakeBbScript(`#!/bin/bash\nexit 17\n`);
72+
await expect(BarretenbergNativeSocketAsyncBackend.new(fakeBb)).rejects.toThrow(
73+
/exited before socket connection was established \(code=17/,
74+
);
75+
});
76+
77+
it('fails with the spawn error when the bb binary does not exist', async () => {
78+
await expect(BarretenbergNativeSocketAsyncBackend.new('/nonexistent/bb-binary')).rejects.toThrow(
79+
/Native backend process error/,
80+
);
81+
});
82+
});

0 commit comments

Comments
 (0)