Skip to content

refactor(bbapi): adopt codegen-emitted dispatch; wire-typed handler boundary#23527

Open
charlielye wants to merge 1 commit into
cl/ipc-codegen-wire-typesfrom
cl/ipc-codegen-wire-types-bbapi
Open

refactor(bbapi): adopt codegen-emitted dispatch; wire-typed handler boundary#23527
charlielye wants to merge 1 commit into
cl/ipc-codegen-wire-typesfrom
cl/ipc-codegen-wire-types-bbapi

Conversation

@charlielye
Copy link
Copy Markdown
Contributor

Summary

Stacked on #23522#23499#23498#23497#23316.

api_msgpack.cpp's hand-rolled msgpack dispatch lambda (~80 LOC of length-prefix decode + NamedUnion convert + bbapi() call + error wrapping) is replaced by `make_bb_handler(request)` from the codegen-emitted bb_ipc_server.hpp. Same wire format, same in-process semantics — BBApiRequest is kept at server-function scope so IVC state is preserved across the call sequence (ChonkStart → ChonkLoad → ChonkAccumulate → ChonkProve).

Codegen wiring

Added C++ codegen step in `bbapi/CMakeLists.txt` (analogous to wsdb's). Emits `generated/bb_{types,ipc_client,ipc_server}.hpp` + `bb_ipc_client.cpp` from `bb_schema.json`. `bbapi_objects` gets ipc_runtime as a PUBLIC link dep since the generated headers include `ipc_runtime/ipc_server.hpp`.

Handler implementation

The codegen-emitted `make_bb_handler` template instantiates a dispatch table that calls `handle_(BBApiRequest&, wire::Cmd&&)` overloads. Two new files provide them:

  • `bbapi_handlers.hpp` — 60 non-template overload declarations (one per non-Shutdown command in bb_schema.json).
  • `bbapi_handlers.cpp` — 60 one-liner definitions:
    wire::FooResponse handle_foo(BBApiRequest& ctx, wire::Foo&& cmd) {
        return roundtrip<wire::FooResponse>(roundtrip<Foo>(cmd).execute(ctx));
    }

The wire types (from codegen) and domain types (`bbapi_*.hpp`) share a SERIALIZATION_FIELDS shape — same field names, msgpack-compatible field types (`Fr` packs as bin32 matching `bb::fr`; `GrumpkinPoint`/`Bn254G1Point`/etc. pack as {x, y} maps matching `affine_element`). So pack-then-unpack converts between them with no information loss. Slower than field-by-field copying (one extra pack+unpack pair per direction) but trivial to write and resistant to schema drift.

Test plan

  • `ninja bb bb-avm aztec-wsdb ipc_runtime_tests bbapi_tests api_tests` — clean
  • `./bin/bbapi_tests` — 30/30 tests pass (msgpack default-roundtrip suite covering CircuitProve, ChonkProve, all structural commands + CBind exception handling)
  • `./bin/ipc_runtime_tests` — 2 SHM tests pass
  • ipc-codegen cross-language matrix — 18/18 green
  • CI: bb-prover e2e + ivc-integration (live wire-format check)

What's deferred to PR-F

The hand-written types in `bbapi_{crypto,ecc,ecdsa,schnorr,chonk,ultra_honk,avm,srs}.hpp` still exist alongside the codegen-emitted wire types. PR-F will:

  • Replace each handler's `msgpack_roundtrip` with field-by-field wire→domain conversion
  • Delete the hand-written type definitions (keep utility funcs in `bbapi_shared.hpp` and the execute-method bodies, re-shaped as free functions)
  • Delete `bbapi_execute.{hpp,cpp}` (NamedUnion + visitor)
  • Update `c_bind.cpp` (the WASM CBIND entry point) and `ipc.bench.cpp` to use the codegen dispatch

That's a mechanical follow-up; this PR establishes the wire-typed handler boundary as the contract.

…oundary

api_msgpack.cpp's hand-rolled msgpack dispatch lambda (~80 LOC of
length-prefix decode + NamedUnion convert + bbapi() call + error
wrapping) is replaced by make_bb_handler<BBApiRequest>(request) from
the codegen-emitted bb_ipc_server.hpp. Same wire format, same in-process
semantics — BBApiRequest is kept at server-function scope so IVC state
(loaded_circuit_constraints, ivc_in_progress, etc.) is preserved across
the call sequence (ChonkStart → ChonkLoad → ChonkAccumulate → ChonkProve),
matching the bbapi() global_request convention.

C++ codegen step added for bb_schema.json
(barretenberg/cpp/src/barretenberg/bbapi/CMakeLists.txt). Same shape as
the wsdb side: add_custom_command emits generated/bb_{types,ipc_client,
ipc_server}.hpp and the codegen's msgpack_struct_map_impl.hpp (opted out
in barretenberg context via IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS).
bbapi_objects gets ipc_runtime as a PUBLIC link dependency since the
generated headers include ipc_runtime/ipc_server.hpp.

60 non-Shutdown commands need a non-template handle_<method> overload
for BBApiRequest so make_bb_handler<BBApiRequest>'s template instantiation
resolves to a concrete definition. Each handler is one line:
  return msgpack_roundtrip<wire::Resp>(
      msgpack_roundtrip<DomainCmd>(cmd).execute(ctx));
The wire and domain types share a SERIALIZATION_FIELDS shape (same field
names, msgpack-compatible field types — Fr packs as bin32 matching bb::fr;
nested point types pack as {x, y} maps in both versions), so a wire value
can be turned into its domain counterpart by pack-then-unpack. Slower
than field-by-field copying (two extra pack/unpack passes) but trivial
to write and resistant to schema drift — a follow-up can replace the
roundtrips with field-by-field conversions and delete the hand-written
domain types.

Verified:
- ninja bb bb-avm aztec-wsdb ipc_runtime_tests bbapi_tests api_tests
- ./bin/bbapi_tests → 30 tests pass (msgpack default-roundtrip suite +
  CBind exception-handling tests, covering CircuitProve, ChonkProve,
  all the structural commands).
- ./bin/ipc_runtime_tests → 2 SHM tests pass.
- ipc-codegen ./bootstrap.sh test → 18/18 cross-language matrix green.
- Wire format unchanged: bb.js and barretenberg-rs continue to talk to
  the same bb binary over the same msgpack bytes; only the C++ server-
  side decoder/encoder pair changes (from hand-rolled NamedUnion to
  codegen wire types + roundtrip-to-domain).

Followup (PR-F): drop the hand-written types in bbapi_*.hpp and inline
the per-field conversions into the handlers; delete bbapi_execute.cpp.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant