From c3f2207894b65d3a0a0685971f824b71ef9678d1 Mon Sep 17 00:00:00 2001 From: Charlie <5764343+charlielye@users.noreply.github.com> Date: Fri, 22 May 2026 23:31:25 +0000 Subject: [PATCH] refactor(wsdb): drop parallel domain types; handlers operate on wire types Eliminates the dual type hierarchy that's been sitting under wsdb: - generated/wsdb_types.hpp (codegen wire types: POD, schema-driven) - wsdb_commands.hpp / wsdb_execute.cpp (hand-written domain types with identical fields but semantic typedefs and execute() methods) After this change there's just one type system per command. Handlers in wsdb_handlers.cpp take wire types directly, convert fields to/from domain types at the entry/exit boundary, call the existing world_state APIs, and return wire response types. The codegen's --server emission becomes the dispatch entry point; wsdb_ipc_server.cpp shrinks to construction + make_wsdb_handler + server->run. Codegen changes (ipc-codegen/src/cpp_codegen.ts): - Emit Fr as a `struct Fr { std::array bytes; }` plus an explicit `msgpack::adaptor::pack` / `convert` specialization that packs as msgpack `bin` (matching the schema's ["fr","bin32"] alias, matching bb::fr's wire bytes, matching what Rust's serialize_bytes and TS's msgpackr already produce). The default std::array adapter packs as `array` which would have produced wire-incompatible bytes the moment any consumer used wire types as the encoder. - convert also accepts `array` on the read side for forward compatibility with msgpack producers that don't emit `bin`. Codegen-emitted msgpack_struct_map_impl.hpp now opts out when IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS is predefined (barretenberg's serialize/msgpack.hpp sets it). Otherwise both barretenberg's framework adaptor and the codegen's bundled one partially-specialize `msgpack::adaptor::convert` on overlapping concepts in the same TU, producing "ambiguous partial specializations" errors. CMakeLists: wsdb codegen now passes --server (emitting generated/wsdb_ipc_server.hpp) and the aztec-wsdb target compiles wsdb_handlers.cpp instead of wsdb_execute.cpp. The AVM's wsdb_ipc_merkle_db now uses the same shared wire-convert helpers (wsdb_wire_convert.hpp) instead of its own private copies. Net diff: +846 / -1194. Same dispatch logic, smaller surface, single source of truth for command/response shapes (wsdb_schema.json). --- .../src/barretenberg/serialize/msgpack.hpp | 10 + .../vm2/simulation/dbs/wsdb_ipc_merkle_db.cpp | 56 +- .../cpp/src/barretenberg/wsdb/CMakeLists.txt | 7 +- .../cpp/src/barretenberg/wsdb/cli.cpp | 16 +- .../src/barretenberg/wsdb/wsdb_commands.hpp | 536 ------------------ .../src/barretenberg/wsdb/wsdb_execute.cpp | 414 -------------- .../src/barretenberg/wsdb/wsdb_execute.hpp | 115 ---- .../src/barretenberg/wsdb/wsdb_handlers.cpp | 506 +++++++++++++++++ .../src/barretenberg/wsdb/wsdb_handlers.hpp | 55 ++ .../src/barretenberg/wsdb/wsdb_ipc_server.cpp | 78 +-- .../src/barretenberg/wsdb/wsdb_request.hpp | 18 + .../barretenberg/wsdb/wsdb_wire_convert.hpp | 140 +++++ ipc-codegen/src/cpp_codegen.ts | 76 ++- .../templates/cpp/msgpack_struct_map_impl.hpp | 13 +- 14 files changed, 846 insertions(+), 1194 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_commands.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.hpp create mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.cpp create mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.hpp create mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_request.hpp create mode 100644 barretenberg/cpp/src/barretenberg/wsdb/wsdb_wire_convert.hpp diff --git a/barretenberg/cpp/src/barretenberg/serialize/msgpack.hpp b/barretenberg/cpp/src/barretenberg/serialize/msgpack.hpp index d93896bf3215..55e025f1cedb 100644 --- a/barretenberg/cpp/src/barretenberg/serialize/msgpack.hpp +++ b/barretenberg/cpp/src/barretenberg/serialize/msgpack.hpp @@ -1,4 +1,14 @@ #pragma once + +// Opt out of ipc-codegen's bundled struct-map msgpack adaptor: barretenberg +// ships an equivalent under msgpack_impl/struct_map_impl.hpp with overlapping +// partial specialisations on the same primary template. Predefining this +// guard means any codegen-emitted msgpack_struct_map_impl.hpp pulled into the +// same TU yields to the framework's adaptor instead of fighting it. +#ifndef IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS +#define IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS +#endif + /* Minimal header for declaring msgpack fields. This should be included as "barretenberg/serialize/msgpack.hpp" unless a translation wants to use msgpack for bindings, then "barretenberg/serialize/cbind.hpp" should be included. diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/dbs/wsdb_ipc_merkle_db.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/dbs/wsdb_ipc_merkle_db.cpp index 27323c442ef6..f596fc87c9e9 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/dbs/wsdb_ipc_merkle_db.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/dbs/wsdb_ipc_merkle_db.cpp @@ -3,59 +3,19 @@ #include "barretenberg/common/log.hpp" #include "barretenberg/serialize/msgpack.hpp" #include "barretenberg/serialize/msgpack_impl.hpp" +#include "barretenberg/wsdb/wsdb_wire_convert.hpp" #include namespace bb::avm2::simulation { -// --------------------------------------------------------------------------- -// Wire <-> Domain conversion helpers -// -// ipc-codegen emits a wire-typed client (std::array for field -// elements, primitive ints for enums, plain structs for domain types). This -// translation unit owns the inline conversions to/from barretenberg's domain -// types so the public interface stays unchanged. -// --------------------------------------------------------------------------- - -namespace { - -inline ::Fr fr_to_wire(const bb::fr& d) -{ - ::Fr r{}; - bb::fr::serialize_to_buffer(d, r.data()); - return r; -} - -inline bb::fr fr_from_wire(const ::Fr& w) -{ - return bb::fr::serialize_from_buffer(w.data()); -} - -inline std::vector fr_vec_from_wire(const std::vector<::Fr>& wire) -{ - std::vector result; - result.reserve(wire.size()); - for (const auto& w : wire) { - result.push_back(fr_from_wire(w)); - } - return result; -} - -inline wsdb::wire::WorldStateRevision revision_to_wire(const world_state::WorldStateRevision& r) -{ - return wsdb::wire::WorldStateRevision{ - .forkId = r.forkId, - .blockNumber = r.blockNumber, - .includeUncommitted = r.includeUncommitted, - }; -} - -inline uint32_t tree_id_to_wire(MerkleTreeId id) -{ - return static_cast(id); -} - -} // anonymous namespace +// Wire <-> domain conversion helpers are shared with the server handlers +// (see wsdb_handlers.cpp) so both sides use the same encoding boundary. +using bb::wsdb::fr_from_wire; +using bb::wsdb::fr_to_wire; +using bb::wsdb::fr_vec_from_wire; +using bb::wsdb::revision_to_wire; +using bb::wsdb::tree_id_to_wire; // --------------------------------------------------------------------------- // Helpers diff --git a/barretenberg/cpp/src/barretenberg/wsdb/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/wsdb/CMakeLists.txt index 240816e3d495..3971ead8cc9d 100644 --- a/barretenberg/cpp/src/barretenberg/wsdb/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/wsdb/CMakeLists.txt @@ -9,6 +9,7 @@ if(NOT(FUZZING) AND NOT(WASM)) set(WSDB_GEN_OUTPUTS ${WSDB_GEN_DIR}/wsdb_ipc_client.cpp ${WSDB_GEN_DIR}/wsdb_ipc_client.hpp + ${WSDB_GEN_DIR}/wsdb_ipc_server.hpp ${WSDB_GEN_DIR}/wsdb_types.hpp ${WSDB_GEN_DIR}/msgpack_struct_map_impl.hpp ) @@ -24,11 +25,11 @@ if(NOT(FUZZING) AND NOT(WASM)) --schema ${WSDB_SCHEMA} --lang cpp --out ${WSDB_GEN_DIR} - --client + --client --server --cpp-namespace bb::wsdb --prefix Wsdb DEPENDS ${WSDB_SCHEMA} ${IPC_CODEGEN_SRC} - COMMENT "Generating WSDB IPC client from wsdb_schema.json" + COMMENT "Generating WSDB IPC client + server from wsdb_schema.json" VERBATIM ) add_library( @@ -48,7 +49,7 @@ if(NOT(FUZZING) AND NOT(WASM)) aztec-wsdb main.cpp cli.cpp - wsdb_execute.cpp + wsdb_handlers.cpp wsdb_ipc_server.cpp ) target_link_libraries( diff --git a/barretenberg/cpp/src/barretenberg/wsdb/cli.cpp b/barretenberg/cpp/src/barretenberg/wsdb/cli.cpp index 7f9fd1899886..384688ee300e 100644 --- a/barretenberg/cpp/src/barretenberg/wsdb/cli.cpp +++ b/barretenberg/cpp/src/barretenberg/wsdb/cli.cpp @@ -2,7 +2,7 @@ #include "barretenberg/common/log.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/serialize/msgpack.hpp" -#include "barretenberg/wsdb/wsdb_execute.hpp" +#include "barretenberg/world_state/world_state.hpp" #include "barretenberg/wsdb/wsdb_ipc_server.hpp" #include "barretenberg/bb/deps/cli11.hpp" @@ -19,15 +19,15 @@ using namespace bb::crypto::merkle_tree; namespace { -struct WsdbApi { - WsdbCommand commands; - WsdbCommandResponse responses; - SERIALIZATION_FIELDS(commands, responses); -}; - +// Wire-format schema authority is barretenberg/cpp/src/barretenberg/wsdb/ +// wsdb_schema.json — that's what every language's codegen consumes. The +// `msgpack schema` subcommand kept the old NamedUnion-derived dump as a +// secondary introspection path; it's now redundant, so we just point at +// the canonical source. std::string get_wsdb_schema_as_json() { - return msgpack_schema_to_string(WsdbApi{}); + return "{\"note\":\"Wire format authority is " + "barretenberg/cpp/src/barretenberg/wsdb/wsdb_schema.json.\"}"; } } // namespace diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_commands.hpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_commands.hpp deleted file mode 100644 index 5ccf8cc760bc..000000000000 --- a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_commands.hpp +++ /dev/null @@ -1,536 +0,0 @@ -#pragma once -/** - * @file wsdb_commands.hpp - * @brief NamedUnion command structs for the aztec-wsdb world state database API. - * - * Each command follows the bbapi pattern: - * - static constexpr MSGPACK_SCHEMA_NAME for NamedUnion dispatch - * - Nested Response struct with its own MSGPACK_SCHEMA_NAME - * - Request fields with SERIALIZATION_FIELDS - * - execute(WsdbRequest&) && method (implemented in wsdb_execute.cpp) - */ - -#include "barretenberg/crypto/merkle_tree/hash_path.hpp" -#include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" -#include "barretenberg/crypto/merkle_tree/response.hpp" -#include "barretenberg/crypto/merkle_tree/types.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/serialize/msgpack.hpp" -#include "barretenberg/world_state/fork.hpp" -#include "barretenberg/world_state/types.hpp" -#include -#include -#include -#include - -namespace bb::wsdb { - -using namespace bb::world_state; -using namespace bb::crypto::merkle_tree; - -// Forward declaration -struct WsdbRequest; - -// --------------------------------------------------------------------------- -// Tree info / state queries -// --------------------------------------------------------------------------- - -struct WsdbGetTreeInfo { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetTreeInfo"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetTreeInfoResponse"; - MerkleTreeId treeId; - fr root; - index_t size; - uint32_t depth; - SERIALIZATION_FIELDS(treeId, root, size, depth); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision); - bool operator==(const WsdbGetTreeInfo&) const = default; -}; - -struct WsdbGetStateReference { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetStateReference"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetStateReferenceResponse"; - StateReference state; - SERIALIZATION_FIELDS(state); - bool operator==(const Response&) const = default; - }; - WorldStateRevision revision; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(revision); - bool operator==(const WsdbGetStateReference&) const = default; -}; - -struct WsdbGetInitialStateReference { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetInitialStateReference"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetInitialStateReferenceResponse"; - StateReference state; - SERIALIZATION_FIELDS(state); - bool operator==(const Response&) const = default; - }; - Response execute(WsdbRequest& request) &&; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const WsdbGetInitialStateReference&) const = default; -}; - -// --------------------------------------------------------------------------- -// Leaf queries -// --------------------------------------------------------------------------- - -struct WsdbGetLeafValue { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetLeafValue"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetLeafValueResponse"; - // Polymorphic: Fr, NullifierLeafValue, or PublicDataLeafValue serialized as bytes - std::optional> value; - SERIALIZATION_FIELDS(value); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - index_t leafIndex; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, leafIndex); - bool operator==(const WsdbGetLeafValue&) const = default; -}; - -struct WsdbGetLeafPreimage { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetLeafPreimage"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetLeafPreimageResponse"; - // Serialized indexed leaf (NullifierLeafValue or PublicDataLeafValue) - std::optional> preimage; - SERIALIZATION_FIELDS(preimage); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - index_t leafIndex; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, leafIndex); - bool operator==(const WsdbGetLeafPreimage&) const = default; -}; - -struct WsdbGetSiblingPath { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetSiblingPath"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetSiblingPathResponse"; - fr_sibling_path path; - SERIALIZATION_FIELDS(path); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - index_t leafIndex; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, leafIndex); - bool operator==(const WsdbGetSiblingPath&) const = default; -}; - -struct WsdbGetBlockNumbersForLeafIndices { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetBlockNumbersForLeafIndices"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetBlockNumbersForLeafIndicesResponse"; - std::vector> blockNumbers; - SERIALIZATION_FIELDS(blockNumbers); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - std::vector leafIndices; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, leafIndices); - bool operator==(const WsdbGetBlockNumbersForLeafIndices&) const = default; -}; - -// --------------------------------------------------------------------------- -// Leaf search operations -// --------------------------------------------------------------------------- - -struct WsdbFindLeafIndices { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFindLeafIndices"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFindLeafIndicesResponse"; - std::vector> indices; - SERIALIZATION_FIELDS(indices); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - // Polymorphic leaves: each leaf is serialized as bytes - std::vector> leaves; - index_t startIndex; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, leaves, startIndex); - bool operator==(const WsdbFindLeafIndices&) const = default; -}; - -struct WsdbFindLowLeaf { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFindLowLeaf"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFindLowLeafResponse"; - bool alreadyPresent; - index_t index; - SERIALIZATION_FIELDS(alreadyPresent, index); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - fr key; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, key); - bool operator==(const WsdbFindLowLeaf&) const = default; -}; - -struct WsdbFindSiblingPaths { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFindSiblingPaths"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFindSiblingPathsResponse"; - std::vector> paths; - SERIALIZATION_FIELDS(paths); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - WorldStateRevision revision; - // Polymorphic leaves - std::vector> leaves; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, revision, leaves); - bool operator==(const WsdbFindSiblingPaths&) const = default; -}; - -// --------------------------------------------------------------------------- -// Tree mutation operations -// --------------------------------------------------------------------------- - -struct WsdbAppendLeaves { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbAppendLeaves"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbAppendLeavesResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - // Polymorphic leaves - std::vector> leaves; - Fork::Id forkId{ CANONICAL_FORK_ID }; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, leaves, forkId); - bool operator==(const WsdbAppendLeaves&) const = default; -}; - -struct WsdbBatchInsert { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbBatchInsert"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbBatchInsertResponse"; - // Serialized BatchInsertionResult - std::vector result; - SERIALIZATION_FIELDS(result); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - std::vector> leaves; - uint32_t subtreeDepth; - Fork::Id forkId{ CANONICAL_FORK_ID }; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, leaves, subtreeDepth, forkId); - bool operator==(const WsdbBatchInsert&) const = default; -}; - -struct WsdbSequentialInsert { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbSequentialInsert"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbSequentialInsertResponse"; - // Serialized SequentialInsertionResult - std::vector result; - SERIALIZATION_FIELDS(result); - bool operator==(const Response&) const = default; - }; - MerkleTreeId treeId; - std::vector> leaves; - Fork::Id forkId{ CANONICAL_FORK_ID }; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(treeId, leaves, forkId); - bool operator==(const WsdbSequentialInsert&) const = default; -}; - -struct WsdbUpdateArchive { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbUpdateArchive"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbUpdateArchiveResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - StateReference blockStateRef; - bb::fr blockHeaderHash; - Fork::Id forkId{ CANONICAL_FORK_ID }; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(blockStateRef, blockHeaderHash, forkId); - bool operator==(const WsdbUpdateArchive&) const = default; -}; - -// --------------------------------------------------------------------------- -// Transaction operations -// --------------------------------------------------------------------------- - -struct WsdbCommit { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCommit"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCommitResponse"; - WorldStateStatusFull status; - SERIALIZATION_FIELDS(status); - bool operator==(const Response&) const = default; - }; - Response execute(WsdbRequest& request) &&; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const WsdbCommit&) const = default; -}; - -struct WsdbRollback { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRollback"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRollbackResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - Response execute(WsdbRequest& request) &&; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const WsdbRollback&) const = default; -}; - -// --------------------------------------------------------------------------- -// Block synchronization -// --------------------------------------------------------------------------- - -struct WsdbSyncBlock { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbSyncBlock"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbSyncBlockResponse"; - WorldStateStatusFull status; - SERIALIZATION_FIELDS(status); - bool operator==(const Response&) const = default; - }; - block_number_t blockNumber; - StateReference blockStateRef; - bb::fr blockHeaderHash; - std::vector paddedNoteHashes; - std::vector paddedL1ToL2Messages; - std::vector paddedNullifiers; - std::vector publicDataWrites; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(blockNumber, - blockStateRef, - blockHeaderHash, - paddedNoteHashes, - paddedL1ToL2Messages, - paddedNullifiers, - publicDataWrites); - bool operator==(const WsdbSyncBlock&) const = default; -}; - -// --------------------------------------------------------------------------- -// Fork management -// --------------------------------------------------------------------------- - -struct WsdbCreateFork { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCreateFork"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCreateForkResponse"; - uint64_t forkId; - SERIALIZATION_FIELDS(forkId); - bool operator==(const Response&) const = default; - }; - bool latest; - block_number_t blockNumber; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(latest, blockNumber); - bool operator==(const WsdbCreateFork&) const = default; -}; - -struct WsdbDeleteFork { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbDeleteFork"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbDeleteForkResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - uint64_t forkId; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(forkId); - bool operator==(const WsdbDeleteFork&) const = default; -}; - -// --------------------------------------------------------------------------- -// Block management -// --------------------------------------------------------------------------- - -struct WsdbFinalizeBlocks { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFinalizeBlocks"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbFinalizeBlocksResponse"; - WorldStateStatusSummary status; - SERIALIZATION_FIELDS(status); - bool operator==(const Response&) const = default; - }; - block_number_t toBlockNumber; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(toBlockNumber); - bool operator==(const WsdbFinalizeBlocks&) const = default; -}; - -struct WsdbUnwindBlocks { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbUnwindBlocks"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbUnwindBlocksResponse"; - WorldStateStatusFull status; - SERIALIZATION_FIELDS(status); - bool operator==(const Response&) const = default; - }; - block_number_t toBlockNumber; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(toBlockNumber); - bool operator==(const WsdbUnwindBlocks&) const = default; -}; - -struct WsdbRemoveHistoricalBlocks { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRemoveHistoricalBlocks"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRemoveHistoricalBlocksResponse"; - WorldStateStatusFull status; - SERIALIZATION_FIELDS(status); - bool operator==(const Response&) const = default; - }; - block_number_t toBlockNumber; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(toBlockNumber); - bool operator==(const WsdbRemoveHistoricalBlocks&) const = default; -}; - -// --------------------------------------------------------------------------- -// Status -// --------------------------------------------------------------------------- - -struct WsdbGetStatus { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetStatus"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbGetStatusResponse"; - WorldStateStatusSummary status; - SERIALIZATION_FIELDS(status); - bool operator==(const Response&) const = default; - }; - Response execute(WsdbRequest& request) &&; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const WsdbGetStatus&) const = default; -}; - -// --------------------------------------------------------------------------- -// Checkpoint operations -// --------------------------------------------------------------------------- - -struct WsdbCreateCheckpoint { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCreateCheckpoint"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCreateCheckpointResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - uint64_t forkId; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(forkId); - bool operator==(const WsdbCreateCheckpoint&) const = default; -}; - -struct WsdbCommitCheckpoint { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCommitCheckpoint"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCommitCheckpointResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - uint64_t forkId; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(forkId); - bool operator==(const WsdbCommitCheckpoint&) const = default; -}; - -struct WsdbRevertCheckpoint { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRevertCheckpoint"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRevertCheckpointResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - uint64_t forkId; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(forkId); - bool operator==(const WsdbRevertCheckpoint&) const = default; -}; - -struct WsdbCommitAllCheckpoints { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCommitAllCheckpoints"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCommitAllCheckpointsResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - uint64_t forkId; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(forkId); - bool operator==(const WsdbCommitAllCheckpoints&) const = default; -}; - -struct WsdbRevertAllCheckpoints { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRevertAllCheckpoints"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbRevertAllCheckpointsResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - uint64_t forkId; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(forkId); - bool operator==(const WsdbRevertAllCheckpoints&) const = default; -}; - -// --------------------------------------------------------------------------- -// Database operations -// --------------------------------------------------------------------------- - -struct WsdbCopyStores { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCopyStores"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbCopyStoresResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - std::string dstPath; - std::optional compact; - Response execute(WsdbRequest& request) &&; - SERIALIZATION_FIELDS(dstPath, compact); - bool operator==(const WsdbCopyStores&) const = default; -}; - -// --------------------------------------------------------------------------- -// Lifecycle -// --------------------------------------------------------------------------- - -struct WsdbShutdown { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbShutdown"; - struct Response { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbShutdownResponse"; - void msgpack(auto&& pack_fn) { pack_fn(); } - bool operator==(const Response&) const = default; - }; - void msgpack(auto&& pack_fn) { pack_fn(); } - Response execute(WsdbRequest& request) &&; - bool operator==(const WsdbShutdown&) const = default; -}; - -} // namespace bb::wsdb diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.cpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.cpp deleted file mode 100644 index 5a6282b9de8f..000000000000 --- a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.cpp +++ /dev/null @@ -1,414 +0,0 @@ -#include "barretenberg/wsdb/wsdb_execute.hpp" -#include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" -#include "barretenberg/crypto/merkle_tree/response.hpp" -#include "barretenberg/world_state/world_state.hpp" -#include -#include - -namespace bb::wsdb { - -using namespace bb::world_state; -using namespace bb::crypto::merkle_tree; - -// --------------------------------------------------------------------------- -// Helper: serialize a value to msgpack bytes -// --------------------------------------------------------------------------- - -template static std::vector serialize_to_msgpack(const T& value) -{ - msgpack::sbuffer buf; - msgpack::pack(buf, value); - return std::vector(buf.data(), buf.data() + buf.size()); -} - -// --------------------------------------------------------------------------- -// Helper: deserialize leaves from raw bytes based on tree type -// --------------------------------------------------------------------------- - -template -static std::vector deserialize_leaves(const std::vector>& raw_leaves) -{ - std::vector leaves; - leaves.reserve(raw_leaves.size()); - for (const auto& raw : raw_leaves) { - auto unpacked = msgpack::unpack(reinterpret_cast(raw.data()), raw.size()); - LeafType leaf; - unpacked.get().convert(leaf); - leaves.push_back(std::move(leaf)); - } - return leaves; -} - -// --------------------------------------------------------------------------- -// Top-level dispatch -// --------------------------------------------------------------------------- - -WsdbCommandResponse wsdb(WsdbRequest& request, WsdbCommand&& command) -{ - return execute(request, std::move(command)); -} - -// --------------------------------------------------------------------------- -// Tree info / state queries -// --------------------------------------------------------------------------- - -WsdbGetTreeInfo::Response WsdbGetTreeInfo::execute(WsdbRequest& request) && -{ - auto info = request.world_state.get_tree_info(revision, treeId); - return Response{ .treeId = treeId, .root = info.meta.root, .size = info.meta.size, .depth = info.meta.depth }; -} - -WsdbGetStateReference::Response WsdbGetStateReference::execute(WsdbRequest& request) && -{ - auto state = request.world_state.get_state_reference(revision); - return Response{ .state = state }; -} - -WsdbGetInitialStateReference::Response WsdbGetInitialStateReference::execute(WsdbRequest& request) && -{ - auto state = request.world_state.get_initial_state_reference(); - return Response{ .state = state }; -} - -// --------------------------------------------------------------------------- -// Leaf queries -// --------------------------------------------------------------------------- - -WsdbGetLeafValue::Response WsdbGetLeafValue::execute(WsdbRequest& request) && -{ - switch (treeId) { - case MerkleTreeId::NOTE_HASH_TREE: - case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: - case MerkleTreeId::ARCHIVE: { - auto leaf = request.world_state.get_leaf(revision, treeId, leafIndex); - if (!leaf.has_value()) { - return Response{ .value = std::nullopt }; - } - return Response{ .value = serialize_to_msgpack(leaf.value()) }; - } - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto leaf = request.world_state.get_leaf(revision, treeId, leafIndex); - if (!leaf.has_value()) { - return Response{ .value = std::nullopt }; - } - return Response{ .value = serialize_to_msgpack(leaf.value()) }; - } - case MerkleTreeId::NULLIFIER_TREE: { - auto leaf = request.world_state.get_leaf(revision, treeId, leafIndex); - if (!leaf.has_value()) { - return Response{ .value = std::nullopt }; - } - return Response{ .value = serialize_to_msgpack(leaf.value()) }; - } - default: - throw std::runtime_error("Unsupported tree type for get_leaf_value"); - } -} - -WsdbGetLeafPreimage::Response WsdbGetLeafPreimage::execute(WsdbRequest& request) && -{ - switch (treeId) { - case MerkleTreeId::NULLIFIER_TREE: { - auto leaf = request.world_state.get_indexed_leaf(revision, treeId, leafIndex); - if (!leaf.has_value()) { - return Response{ .preimage = std::nullopt }; - } - return Response{ .preimage = serialize_to_msgpack(leaf.value()) }; - } - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto leaf = request.world_state.get_indexed_leaf(revision, treeId, leafIndex); - if (!leaf.has_value()) { - return Response{ .preimage = std::nullopt }; - } - return Response{ .preimage = serialize_to_msgpack(leaf.value()) }; - } - default: - throw std::runtime_error("Unsupported tree type for get_leaf_preimage"); - } -} - -WsdbGetSiblingPath::Response WsdbGetSiblingPath::execute(WsdbRequest& request) && -{ - fr_sibling_path path = request.world_state.get_sibling_path(revision, treeId, leafIndex); - return Response{ .path = path }; -} - -WsdbGetBlockNumbersForLeafIndices::Response WsdbGetBlockNumbersForLeafIndices::execute(WsdbRequest& request) && -{ - Response response; - request.world_state.get_block_numbers_for_leaf_indices(revision, treeId, leafIndices, response.blockNumbers); - return response; -} - -// --------------------------------------------------------------------------- -// Leaf search operations -// --------------------------------------------------------------------------- - -WsdbFindLeafIndices::Response WsdbFindLeafIndices::execute(WsdbRequest& request) && -{ - Response response; - switch (treeId) { - case MerkleTreeId::NOTE_HASH_TREE: - case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: - case MerkleTreeId::ARCHIVE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.find_leaf_indices(revision, treeId, typed_leaves, response.indices, startIndex); - break; - } - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.find_leaf_indices( - revision, treeId, typed_leaves, response.indices, startIndex); - break; - } - case MerkleTreeId::NULLIFIER_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.find_leaf_indices( - revision, treeId, typed_leaves, response.indices, startIndex); - break; - } - default: - throw std::runtime_error("Unsupported tree type for find_leaf_indices"); - } - return response; -} - -WsdbFindLowLeaf::Response WsdbFindLowLeaf::execute(WsdbRequest& request) && -{ - auto low_leaf_info = request.world_state.find_low_leaf_index(revision, treeId, key); - return Response{ .alreadyPresent = low_leaf_info.is_already_present, .index = low_leaf_info.index }; -} - -WsdbFindSiblingPaths::Response WsdbFindSiblingPaths::execute(WsdbRequest& request) && -{ - Response response; - switch (treeId) { - case MerkleTreeId::NOTE_HASH_TREE: - case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: - case MerkleTreeId::ARCHIVE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.find_sibling_paths(revision, treeId, typed_leaves, response.paths); - break; - } - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.find_sibling_paths(revision, treeId, typed_leaves, response.paths); - break; - } - case MerkleTreeId::NULLIFIER_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.find_sibling_paths(revision, treeId, typed_leaves, response.paths); - break; - } - default: - throw std::runtime_error("Unsupported tree type for find_sibling_paths"); - } - return response; -} - -// --------------------------------------------------------------------------- -// Tree mutation operations -// --------------------------------------------------------------------------- - -WsdbAppendLeaves::Response WsdbAppendLeaves::execute(WsdbRequest& request) && -{ - switch (treeId) { - case MerkleTreeId::NOTE_HASH_TREE: - case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: - case MerkleTreeId::ARCHIVE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.append_leaves(treeId, typed_leaves, forkId); - break; - } - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.append_leaves(treeId, typed_leaves, forkId); - break; - } - case MerkleTreeId::NULLIFIER_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - request.world_state.append_leaves(treeId, typed_leaves, forkId); - break; - } - default: - throw std::runtime_error("Unsupported tree type for append_leaves"); - } - return Response{}; -} - -WsdbBatchInsert::Response WsdbBatchInsert::execute(WsdbRequest& request) && -{ - switch (treeId) { - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - auto result = request.world_state.batch_insert_indexed_leaves( - treeId, typed_leaves, subtreeDepth, forkId); - return Response{ .result = serialize_to_msgpack(result) }; - } - case MerkleTreeId::NULLIFIER_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - auto result = request.world_state.batch_insert_indexed_leaves( - treeId, typed_leaves, subtreeDepth, forkId); - return Response{ .result = serialize_to_msgpack(result) }; - } - default: - throw std::runtime_error("Unsupported tree type for batch_insert"); - } -} - -WsdbSequentialInsert::Response WsdbSequentialInsert::execute(WsdbRequest& request) && -{ - switch (treeId) { - case MerkleTreeId::PUBLIC_DATA_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - auto result = request.world_state.insert_indexed_leaves(treeId, typed_leaves, forkId); - return Response{ .result = serialize_to_msgpack(result) }; - } - case MerkleTreeId::NULLIFIER_TREE: { - auto typed_leaves = deserialize_leaves(leaves); - auto result = request.world_state.insert_indexed_leaves(treeId, typed_leaves, forkId); - return Response{ .result = serialize_to_msgpack(result) }; - } - default: - throw std::runtime_error("Unsupported tree type for sequential_insert"); - } -} - -WsdbUpdateArchive::Response WsdbUpdateArchive::execute(WsdbRequest& request) && -{ - request.world_state.update_archive(blockStateRef, blockHeaderHash, forkId); - return Response{}; -} - -// --------------------------------------------------------------------------- -// Transaction operations -// --------------------------------------------------------------------------- - -WsdbCommit::Response WsdbCommit::execute(WsdbRequest& request) && -{ - WorldStateStatusFull status; - request.world_state.commit(status); - return Response{ .status = status }; -} - -WsdbRollback::Response WsdbRollback::execute(WsdbRequest& request) && -{ - request.world_state.rollback(); - return Response{}; -} - -// --------------------------------------------------------------------------- -// Block synchronization -// --------------------------------------------------------------------------- - -WsdbSyncBlock::Response WsdbSyncBlock::execute(WsdbRequest& request) && -{ - WorldStateStatusFull status = request.world_state.sync_block( - blockStateRef, blockHeaderHash, paddedNoteHashes, paddedL1ToL2Messages, paddedNullifiers, publicDataWrites); - return Response{ .status = status }; -} - -// --------------------------------------------------------------------------- -// Fork management -// --------------------------------------------------------------------------- - -WsdbCreateFork::Response WsdbCreateFork::execute(WsdbRequest& request) && -{ - std::optional block = latest ? std::nullopt : std::optional(blockNumber); - uint64_t id = request.world_state.create_fork(block); - return Response{ .forkId = id }; -} - -WsdbDeleteFork::Response WsdbDeleteFork::execute(WsdbRequest& request) && -{ - request.world_state.delete_fork(forkId); - return Response{}; -} - -// --------------------------------------------------------------------------- -// Block management -// --------------------------------------------------------------------------- - -WsdbFinalizeBlocks::Response WsdbFinalizeBlocks::execute(WsdbRequest& request) && -{ - WorldStateStatusSummary status = request.world_state.set_finalized_blocks(toBlockNumber); - return Response{ .status = status }; -} - -WsdbUnwindBlocks::Response WsdbUnwindBlocks::execute(WsdbRequest& request) && -{ - WorldStateStatusFull status = request.world_state.unwind_blocks(toBlockNumber); - return Response{ .status = status }; -} - -WsdbRemoveHistoricalBlocks::Response WsdbRemoveHistoricalBlocks::execute(WsdbRequest& request) && -{ - WorldStateStatusFull status = request.world_state.remove_historical_blocks(toBlockNumber); - return Response{ .status = status }; -} - -// --------------------------------------------------------------------------- -// Status -// --------------------------------------------------------------------------- - -WsdbGetStatus::Response WsdbGetStatus::execute(WsdbRequest& request) && -{ - WorldStateStatusSummary status; - request.world_state.get_status_summary(status); - return Response{ .status = status }; -} - -// --------------------------------------------------------------------------- -// Checkpoint operations -// --------------------------------------------------------------------------- - -WsdbCreateCheckpoint::Response WsdbCreateCheckpoint::execute(WsdbRequest& request) && -{ - request.world_state.checkpoint(forkId); - return Response{}; -} - -WsdbCommitCheckpoint::Response WsdbCommitCheckpoint::execute(WsdbRequest& request) && -{ - request.world_state.commit_checkpoint(forkId); - return Response{}; -} - -WsdbRevertCheckpoint::Response WsdbRevertCheckpoint::execute(WsdbRequest& request) && -{ - request.world_state.revert_checkpoint(forkId); - return Response{}; -} - -WsdbCommitAllCheckpoints::Response WsdbCommitAllCheckpoints::execute(WsdbRequest& request) && -{ - request.world_state.commit_all_checkpoints_to(forkId, 0); - return Response{}; -} - -WsdbRevertAllCheckpoints::Response WsdbRevertAllCheckpoints::execute(WsdbRequest& request) && -{ - request.world_state.revert_all_checkpoints_to(forkId, 0); - return Response{}; -} - -// --------------------------------------------------------------------------- -// Database operations -// --------------------------------------------------------------------------- - -WsdbCopyStores::Response WsdbCopyStores::execute(WsdbRequest& request) && -{ - request.world_state.copy_stores(dstPath, compact.value_or(false)); - return Response{}; -} - -// --------------------------------------------------------------------------- -// Lifecycle -// --------------------------------------------------------------------------- - -WsdbShutdown::Response WsdbShutdown::execute(WsdbRequest& /* request */) && -{ - return Response{}; -} - -} // namespace bb::wsdb diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.hpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.hpp deleted file mode 100644 index 20de7d738c4c..000000000000 --- a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_execute.hpp +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once -/** - * @file wsdb_execute.hpp - * @brief WsdbCommand NamedUnion, WsdbRequest context, and dispatch function. - */ - -#include "barretenberg/common/named_union.hpp" -#include "barretenberg/world_state/world_state.hpp" -#include "barretenberg/wsdb/wsdb_commands.hpp" - -namespace bb::wsdb { - -/** - * @brief Context passed to each command's execute() method, providing access to the WorldState. - */ -struct WsdbRequest { - world_state::WorldState& world_state; -}; - -/** - * @brief Error response returned when a command fails. - */ -struct WsdbErrorResponse { - static constexpr const char MSGPACK_SCHEMA_NAME[] = "WsdbErrorResponse"; - std::string message; - SERIALIZATION_FIELDS(message); - bool operator==(const WsdbErrorResponse&) const = default; -}; - -/** - * @brief Union of all wsdb commands (request types). - */ -using WsdbCommand = NamedUnion; - -/** - * @brief Union of all wsdb response types. - */ -using WsdbCommandResponse = NamedUnion; - -/** - * @brief Execute a wsdb command using the visitor pattern. - */ -inline WsdbCommandResponse execute(WsdbRequest& request, WsdbCommand&& command) -{ - return std::move(command).visit([&request](auto&& cmd) -> WsdbCommandResponse { - using CmdType = std::decay_t; - return std::forward(cmd).execute(request); - }); -} - -/** - * @brief Top-level wsdb API entry point. Takes a WsdbRequest and dispatches the command. - */ -WsdbCommandResponse wsdb(WsdbRequest& request, WsdbCommand&& command); - -} // namespace bb::wsdb diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.cpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.cpp new file mode 100644 index 000000000000..505ffe5ee6ff --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.cpp @@ -0,0 +1,506 @@ +/** + * @file wsdb_handlers.cpp + * @brief Per-command handlers consumed by the codegen-emitted server dispatch. + * + * Each handler matches the signature declared by generated/wsdb_ipc_server.hpp + * but as a non-template overload for `WsdbRequest` so the codegen's + * `make_wsdb_handler` instantiation resolves to these + * definitions via overload resolution (preferred over the unspecialized + * template). + * + * Wire <-> domain conversion happens at the entry/exit of each handler via + * the helpers in wsdb_wire_convert.hpp. Field-element-bearing or status- + * struct-bearing responses use msgpack roundtrip when wire/domain shapes + * are isomorphic (cheaper than writing field-by-field copies). + */ +#include "barretenberg/wsdb/wsdb_handlers.hpp" +#include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" +#include "barretenberg/crypto/merkle_tree/response.hpp" +#include "barretenberg/world_state/world_state.hpp" +#include "barretenberg/wsdb/generated/wsdb_ipc_server.hpp" +#include "barretenberg/wsdb/wsdb_wire_convert.hpp" + +#include +#include + +namespace bb::wsdb { + +using namespace bb::world_state; +using namespace bb::crypto::merkle_tree; + +// --------------------------------------------------------------------------- +// Helper: serialize a value to msgpack bytes (for opaque-blob wire fields). +// --------------------------------------------------------------------------- + +template static std::vector serialize_to_msgpack(const T& value) +{ + msgpack::sbuffer buf; + msgpack::pack(buf, value); + return std::vector(buf.data(), buf.data() + buf.size()); +} + +// --------------------------------------------------------------------------- +// Helper: deserialize typed leaves from raw msgpack bytes per leaf. +// --------------------------------------------------------------------------- + +template +static std::vector deserialize_leaves(const std::vector>& raw_leaves) +{ + std::vector leaves; + leaves.reserve(raw_leaves.size()); + for (const auto& raw : raw_leaves) { + auto unpacked = msgpack::unpack(reinterpret_cast(raw.data()), raw.size()); + LeafType leaf; + unpacked.get().convert(leaf); + leaves.push_back(std::move(leaf)); + } + return leaves; +} + +// --------------------------------------------------------------------------- +// Tree info / state queries +// --------------------------------------------------------------------------- + +wire::WsdbGetTreeInfoResponse handle_get_tree_info(WsdbRequest& ctx, wire::WsdbGetTreeInfo&& cmd) +{ + auto info = ctx.world_state.get_tree_info(revision_from_wire(cmd.revision), tree_id_from_wire(cmd.treeId)); + return wire::WsdbGetTreeInfoResponse{ + .treeId = cmd.treeId, + .root = fr_to_wire(info.meta.root), + .size = info.meta.size, + .depth = info.meta.depth, + }; +} + +wire::WsdbGetStateReferenceResponse handle_get_state_reference(WsdbRequest& ctx, wire::WsdbGetStateReference&& cmd) +{ + auto state = ctx.world_state.get_state_reference(revision_from_wire(cmd.revision)); + return wire::WsdbGetStateReferenceResponse{ .state = state_reference_to_wire(state) }; +} + +wire::WsdbGetInitialStateReferenceResponse handle_get_initial_state_reference(WsdbRequest& ctx, + wire::WsdbGetInitialStateReference&&) +{ + auto state = ctx.world_state.get_initial_state_reference(); + return wire::WsdbGetInitialStateReferenceResponse{ .state = state_reference_to_wire(state) }; +} + +// --------------------------------------------------------------------------- +// Leaf queries +// --------------------------------------------------------------------------- + +wire::WsdbGetLeafValueResponse handle_get_leaf_value(WsdbRequest& ctx, wire::WsdbGetLeafValue&& cmd) +{ + auto revision = revision_from_wire(cmd.revision); + auto tree_id = tree_id_from_wire(cmd.treeId); + auto leaf_index = static_cast(cmd.leafIndex); + + switch (tree_id) { + case MerkleTreeId::NOTE_HASH_TREE: + case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: + case MerkleTreeId::ARCHIVE: { + auto leaf = ctx.world_state.get_leaf(revision, tree_id, leaf_index); + if (!leaf.has_value()) { + return wire::WsdbGetLeafValueResponse{ .value = std::nullopt }; + } + return wire::WsdbGetLeafValueResponse{ .value = serialize_to_msgpack(leaf.value()) }; + } + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto leaf = ctx.world_state.get_leaf(revision, tree_id, leaf_index); + if (!leaf.has_value()) { + return wire::WsdbGetLeafValueResponse{ .value = std::nullopt }; + } + return wire::WsdbGetLeafValueResponse{ .value = serialize_to_msgpack(leaf.value()) }; + } + case MerkleTreeId::NULLIFIER_TREE: { + auto leaf = ctx.world_state.get_leaf(revision, tree_id, leaf_index); + if (!leaf.has_value()) { + return wire::WsdbGetLeafValueResponse{ .value = std::nullopt }; + } + return wire::WsdbGetLeafValueResponse{ .value = serialize_to_msgpack(leaf.value()) }; + } + default: + throw std::runtime_error("Unsupported tree type for get_leaf_value"); + } +} + +wire::WsdbGetLeafPreimageResponse handle_get_leaf_preimage(WsdbRequest& ctx, wire::WsdbGetLeafPreimage&& cmd) +{ + auto revision = revision_from_wire(cmd.revision); + auto tree_id = tree_id_from_wire(cmd.treeId); + auto leaf_index = static_cast(cmd.leafIndex); + + switch (tree_id) { + case MerkleTreeId::NULLIFIER_TREE: { + auto leaf = ctx.world_state.get_indexed_leaf(revision, tree_id, leaf_index); + if (!leaf.has_value()) { + return wire::WsdbGetLeafPreimageResponse{ .preimage = std::nullopt }; + } + return wire::WsdbGetLeafPreimageResponse{ .preimage = serialize_to_msgpack(leaf.value()) }; + } + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto leaf = ctx.world_state.get_indexed_leaf(revision, tree_id, leaf_index); + if (!leaf.has_value()) { + return wire::WsdbGetLeafPreimageResponse{ .preimage = std::nullopt }; + } + return wire::WsdbGetLeafPreimageResponse{ .preimage = serialize_to_msgpack(leaf.value()) }; + } + default: + throw std::runtime_error("Unsupported tree type for get_leaf_preimage"); + } +} + +wire::WsdbGetSiblingPathResponse handle_get_sibling_path(WsdbRequest& ctx, wire::WsdbGetSiblingPath&& cmd) +{ + fr_sibling_path path = ctx.world_state.get_sibling_path( + revision_from_wire(cmd.revision), tree_id_from_wire(cmd.treeId), static_cast(cmd.leafIndex)); + return wire::WsdbGetSiblingPathResponse{ .path = fr_vec_to_wire(path) }; +} + +wire::WsdbGetBlockNumbersForLeafIndicesResponse handle_get_block_numbers_for_leaf_indices( + WsdbRequest& ctx, wire::WsdbGetBlockNumbersForLeafIndices&& cmd) +{ + std::vector leaf_indices; + leaf_indices.reserve(cmd.leafIndices.size()); + for (auto i : cmd.leafIndices) { + leaf_indices.push_back(static_cast(i)); + } + std::vector> block_numbers; + ctx.world_state.get_block_numbers_for_leaf_indices( + revision_from_wire(cmd.revision), tree_id_from_wire(cmd.treeId), leaf_indices, block_numbers); + std::vector> wire_block_numbers; + wire_block_numbers.reserve(block_numbers.size()); + for (const auto& bn : block_numbers) { + wire_block_numbers.push_back(bn); + } + return wire::WsdbGetBlockNumbersForLeafIndicesResponse{ .blockNumbers = std::move(wire_block_numbers) }; +} + +// --------------------------------------------------------------------------- +// Leaf search operations +// --------------------------------------------------------------------------- + +wire::WsdbFindLeafIndicesResponse handle_find_leaf_indices(WsdbRequest& ctx, wire::WsdbFindLeafIndices&& cmd) +{ + auto revision = revision_from_wire(cmd.revision); + auto tree_id = tree_id_from_wire(cmd.treeId); + auto start_index = static_cast(cmd.startIndex); + + std::vector> indices; + switch (tree_id) { + case MerkleTreeId::NOTE_HASH_TREE: + case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: + case MerkleTreeId::ARCHIVE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.find_leaf_indices(revision, tree_id, typed_leaves, indices, start_index); + break; + } + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.find_leaf_indices(revision, tree_id, typed_leaves, indices, start_index); + break; + } + case MerkleTreeId::NULLIFIER_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.find_leaf_indices(revision, tree_id, typed_leaves, indices, start_index); + break; + } + default: + throw std::runtime_error("Unsupported tree type for find_leaf_indices"); + } + std::vector> wire_indices; + wire_indices.reserve(indices.size()); + for (const auto& i : indices) { + wire_indices.push_back(i.has_value() ? std::optional(static_cast(*i)) : std::nullopt); + } + return wire::WsdbFindLeafIndicesResponse{ .indices = std::move(wire_indices) }; +} + +wire::WsdbFindLowLeafResponse handle_find_low_leaf(WsdbRequest& ctx, wire::WsdbFindLowLeaf&& cmd) +{ + auto low_leaf_info = ctx.world_state.find_low_leaf_index( + revision_from_wire(cmd.revision), tree_id_from_wire(cmd.treeId), fr_from_wire(cmd.key)); + return wire::WsdbFindLowLeafResponse{ + .alreadyPresent = low_leaf_info.is_already_present, + .index = static_cast(low_leaf_info.index), + }; +} + +wire::WsdbFindSiblingPathsResponse handle_find_sibling_paths(WsdbRequest& ctx, wire::WsdbFindSiblingPaths&& cmd) +{ + auto revision = revision_from_wire(cmd.revision); + auto tree_id = tree_id_from_wire(cmd.treeId); + std::vector> paths; + switch (tree_id) { + case MerkleTreeId::NOTE_HASH_TREE: + case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: + case MerkleTreeId::ARCHIVE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.find_sibling_paths(revision, tree_id, typed_leaves, paths); + break; + } + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.find_sibling_paths(revision, tree_id, typed_leaves, paths); + break; + } + case MerkleTreeId::NULLIFIER_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.find_sibling_paths(revision, tree_id, typed_leaves, paths); + break; + } + default: + throw std::runtime_error("Unsupported tree type for find_sibling_paths"); + } + std::vector> wire_paths; + wire_paths.reserve(paths.size()); + for (const auto& p : paths) { + if (!p.has_value()) { + wire_paths.push_back(std::nullopt); + continue; + } + wire_paths.push_back(wire::SiblingPathAndIndex{ + .index = static_cast(p->index), + .path = fr_vec_to_wire(p->path), + }); + } + return wire::WsdbFindSiblingPathsResponse{ .paths = std::move(wire_paths) }; +} + +// --------------------------------------------------------------------------- +// Tree mutation operations +// --------------------------------------------------------------------------- + +wire::WsdbAppendLeavesResponse handle_append_leaves(WsdbRequest& ctx, wire::WsdbAppendLeaves&& cmd) +{ + auto tree_id = tree_id_from_wire(cmd.treeId); + switch (tree_id) { + case MerkleTreeId::NOTE_HASH_TREE: + case MerkleTreeId::L1_TO_L2_MESSAGE_TREE: + case MerkleTreeId::ARCHIVE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.append_leaves(tree_id, typed_leaves, cmd.forkId); + break; + } + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.append_leaves(tree_id, typed_leaves, cmd.forkId); + break; + } + case MerkleTreeId::NULLIFIER_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + ctx.world_state.append_leaves(tree_id, typed_leaves, cmd.forkId); + break; + } + default: + throw std::runtime_error("Unsupported tree type for append_leaves"); + } + return wire::WsdbAppendLeavesResponse{}; +} + +wire::WsdbBatchInsertResponse handle_batch_insert(WsdbRequest& ctx, wire::WsdbBatchInsert&& cmd) +{ + auto tree_id = tree_id_from_wire(cmd.treeId); + switch (tree_id) { + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + auto result = ctx.world_state.batch_insert_indexed_leaves( + tree_id, typed_leaves, cmd.subtreeDepth, cmd.forkId); + return wire::WsdbBatchInsertResponse{ .result = serialize_to_msgpack(result) }; + } + case MerkleTreeId::NULLIFIER_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + auto result = ctx.world_state.batch_insert_indexed_leaves( + tree_id, typed_leaves, cmd.subtreeDepth, cmd.forkId); + return wire::WsdbBatchInsertResponse{ .result = serialize_to_msgpack(result) }; + } + default: + throw std::runtime_error("Unsupported tree type for batch_insert"); + } +} + +wire::WsdbSequentialInsertResponse handle_sequential_insert(WsdbRequest& ctx, wire::WsdbSequentialInsert&& cmd) +{ + auto tree_id = tree_id_from_wire(cmd.treeId); + switch (tree_id) { + case MerkleTreeId::PUBLIC_DATA_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + auto result = ctx.world_state.insert_indexed_leaves(tree_id, typed_leaves, cmd.forkId); + return wire::WsdbSequentialInsertResponse{ .result = serialize_to_msgpack(result) }; + } + case MerkleTreeId::NULLIFIER_TREE: { + auto typed_leaves = deserialize_leaves(cmd.leaves); + auto result = ctx.world_state.insert_indexed_leaves(tree_id, typed_leaves, cmd.forkId); + return wire::WsdbSequentialInsertResponse{ .result = serialize_to_msgpack(result) }; + } + default: + throw std::runtime_error("Unsupported tree type for sequential_insert"); + } +} + +wire::WsdbUpdateArchiveResponse handle_update_archive(WsdbRequest& ctx, wire::WsdbUpdateArchive&& cmd) +{ + ctx.world_state.update_archive( + state_reference_from_wire(cmd.blockStateRef), fr_from_wire(cmd.blockHeaderHash), cmd.forkId); + return wire::WsdbUpdateArchiveResponse{}; +} + +// --------------------------------------------------------------------------- +// Transaction operations +// --------------------------------------------------------------------------- + +wire::WsdbCommitResponse handle_commit(WsdbRequest& ctx, wire::WsdbCommit&&) +{ + WorldStateStatusFull status; + ctx.world_state.commit(status); + return wire::WsdbCommitResponse{ + .status = msgpack_roundtrip_to_wire(status), + }; +} + +wire::WsdbRollbackResponse handle_rollback(WsdbRequest& ctx, wire::WsdbRollback&&) +{ + ctx.world_state.rollback(); + return wire::WsdbRollbackResponse{}; +} + +// --------------------------------------------------------------------------- +// Block synchronization +// --------------------------------------------------------------------------- + +wire::WsdbSyncBlockResponse handle_sync_block(WsdbRequest& ctx, wire::WsdbSyncBlock&& cmd) +{ + auto block_state_ref = state_reference_from_wire(cmd.blockStateRef); + auto block_header_hash = fr_from_wire(cmd.blockHeaderHash); + auto padded_note_hashes = fr_vec_from_wire(cmd.paddedNoteHashes); + auto padded_l1_to_l2_messages = fr_vec_from_wire(cmd.paddedL1ToL2Messages); + + std::vector padded_nullifiers; + padded_nullifiers.reserve(cmd.paddedNullifiers.size()); + for (const auto& w : cmd.paddedNullifiers) { + padded_nullifiers.emplace_back(fr_from_wire(w.nullifier)); + } + + std::vector public_data_writes; + public_data_writes.reserve(cmd.publicDataWrites.size()); + for (const auto& w : cmd.publicDataWrites) { + public_data_writes.emplace_back(fr_from_wire(w.slot), fr_from_wire(w.value)); + } + + WorldStateStatusFull status = ctx.world_state.sync_block(block_state_ref, + block_header_hash, + padded_note_hashes, + padded_l1_to_l2_messages, + padded_nullifiers, + public_data_writes); + return wire::WsdbSyncBlockResponse{ + .status = msgpack_roundtrip_to_wire(status), + }; +} + +// --------------------------------------------------------------------------- +// Fork management +// --------------------------------------------------------------------------- + +wire::WsdbCreateForkResponse handle_create_fork(WsdbRequest& ctx, wire::WsdbCreateFork&& cmd) +{ + std::optional block = cmd.latest ? std::nullopt : std::optional(cmd.blockNumber); + uint64_t id = ctx.world_state.create_fork(block); + return wire::WsdbCreateForkResponse{ .forkId = id }; +} + +wire::WsdbDeleteForkResponse handle_delete_fork(WsdbRequest& ctx, wire::WsdbDeleteFork&& cmd) +{ + ctx.world_state.delete_fork(cmd.forkId); + return wire::WsdbDeleteForkResponse{}; +} + +// --------------------------------------------------------------------------- +// Block management +// --------------------------------------------------------------------------- + +wire::WsdbFinalizeBlocksResponse handle_finalize_blocks(WsdbRequest& ctx, wire::WsdbFinalizeBlocks&& cmd) +{ + WorldStateStatusSummary status = ctx.world_state.set_finalized_blocks(cmd.toBlockNumber); + return wire::WsdbFinalizeBlocksResponse{ + .status = msgpack_roundtrip_to_wire(status), + }; +} + +wire::WsdbUnwindBlocksResponse handle_unwind_blocks(WsdbRequest& ctx, wire::WsdbUnwindBlocks&& cmd) +{ + WorldStateStatusFull status = ctx.world_state.unwind_blocks(cmd.toBlockNumber); + return wire::WsdbUnwindBlocksResponse{ + .status = msgpack_roundtrip_to_wire(status), + }; +} + +wire::WsdbRemoveHistoricalBlocksResponse handle_remove_historical_blocks(WsdbRequest& ctx, + wire::WsdbRemoveHistoricalBlocks&& cmd) +{ + WorldStateStatusFull status = ctx.world_state.remove_historical_blocks(cmd.toBlockNumber); + return wire::WsdbRemoveHistoricalBlocksResponse{ + .status = msgpack_roundtrip_to_wire(status), + }; +} + +// --------------------------------------------------------------------------- +// Status +// --------------------------------------------------------------------------- + +wire::WsdbGetStatusResponse handle_get_status(WsdbRequest& ctx, wire::WsdbGetStatus&&) +{ + WorldStateStatusSummary status; + ctx.world_state.get_status_summary(status); + return wire::WsdbGetStatusResponse{ + .status = msgpack_roundtrip_to_wire(status), + }; +} + +// --------------------------------------------------------------------------- +// Checkpoint operations +// --------------------------------------------------------------------------- + +wire::WsdbCreateCheckpointResponse handle_create_checkpoint(WsdbRequest& ctx, wire::WsdbCreateCheckpoint&& cmd) +{ + ctx.world_state.checkpoint(cmd.forkId); + return wire::WsdbCreateCheckpointResponse{}; +} + +wire::WsdbCommitCheckpointResponse handle_commit_checkpoint(WsdbRequest& ctx, wire::WsdbCommitCheckpoint&& cmd) +{ + ctx.world_state.commit_checkpoint(cmd.forkId); + return wire::WsdbCommitCheckpointResponse{}; +} + +wire::WsdbRevertCheckpointResponse handle_revert_checkpoint(WsdbRequest& ctx, wire::WsdbRevertCheckpoint&& cmd) +{ + ctx.world_state.revert_checkpoint(cmd.forkId); + return wire::WsdbRevertCheckpointResponse{}; +} + +wire::WsdbCommitAllCheckpointsResponse handle_commit_all_checkpoints(WsdbRequest& ctx, + wire::WsdbCommitAllCheckpoints&& cmd) +{ + ctx.world_state.commit_all_checkpoints_to(cmd.forkId, 0); + return wire::WsdbCommitAllCheckpointsResponse{}; +} + +wire::WsdbRevertAllCheckpointsResponse handle_revert_all_checkpoints(WsdbRequest& ctx, + wire::WsdbRevertAllCheckpoints&& cmd) +{ + ctx.world_state.revert_all_checkpoints_to(cmd.forkId, 0); + return wire::WsdbRevertAllCheckpointsResponse{}; +} + +// --------------------------------------------------------------------------- +// Database operations +// --------------------------------------------------------------------------- + +wire::WsdbCopyStoresResponse handle_copy_stores(WsdbRequest& ctx, wire::WsdbCopyStores&& cmd) +{ + ctx.world_state.copy_stores(cmd.dstPath, cmd.compact.value_or(false)); + return wire::WsdbCopyStoresResponse{}; +} + +} // namespace bb::wsdb diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.hpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.hpp new file mode 100644 index 000000000000..f92ccf4d8e01 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_handlers.hpp @@ -0,0 +1,55 @@ +#pragma once +/** + * @file wsdb_handlers.hpp + * @brief Non-template handler declarations for the wsdb service. + * + * The codegen-emitted server (generated/wsdb_ipc_server.hpp) declares + * template handle_(Ctx&, wire::Cmd&&). The free-function + * overloads below provide concrete definitions for `Ctx = WsdbRequest` + * so that overload resolution prefers them at the template's instantiation + * point inside make_wsdb_handler(...). + * + * Definitions live in wsdb_handlers.cpp. This header keeps the + * instantiation-time lookup honest. + */ +#include "barretenberg/wsdb/generated/wsdb_types.hpp" +#include "barretenberg/wsdb/wsdb_request.hpp" + +namespace bb::wsdb { + +wire::WsdbGetTreeInfoResponse handle_get_tree_info(WsdbRequest& ctx, wire::WsdbGetTreeInfo&& cmd); +wire::WsdbGetStateReferenceResponse handle_get_state_reference(WsdbRequest& ctx, wire::WsdbGetStateReference&& cmd); +wire::WsdbGetInitialStateReferenceResponse handle_get_initial_state_reference(WsdbRequest& ctx, + wire::WsdbGetInitialStateReference&& cmd); +wire::WsdbGetLeafValueResponse handle_get_leaf_value(WsdbRequest& ctx, wire::WsdbGetLeafValue&& cmd); +wire::WsdbGetLeafPreimageResponse handle_get_leaf_preimage(WsdbRequest& ctx, wire::WsdbGetLeafPreimage&& cmd); +wire::WsdbGetSiblingPathResponse handle_get_sibling_path(WsdbRequest& ctx, wire::WsdbGetSiblingPath&& cmd); +wire::WsdbGetBlockNumbersForLeafIndicesResponse handle_get_block_numbers_for_leaf_indices( + WsdbRequest& ctx, wire::WsdbGetBlockNumbersForLeafIndices&& cmd); +wire::WsdbFindLeafIndicesResponse handle_find_leaf_indices(WsdbRequest& ctx, wire::WsdbFindLeafIndices&& cmd); +wire::WsdbFindLowLeafResponse handle_find_low_leaf(WsdbRequest& ctx, wire::WsdbFindLowLeaf&& cmd); +wire::WsdbFindSiblingPathsResponse handle_find_sibling_paths(WsdbRequest& ctx, wire::WsdbFindSiblingPaths&& cmd); +wire::WsdbAppendLeavesResponse handle_append_leaves(WsdbRequest& ctx, wire::WsdbAppendLeaves&& cmd); +wire::WsdbBatchInsertResponse handle_batch_insert(WsdbRequest& ctx, wire::WsdbBatchInsert&& cmd); +wire::WsdbSequentialInsertResponse handle_sequential_insert(WsdbRequest& ctx, wire::WsdbSequentialInsert&& cmd); +wire::WsdbUpdateArchiveResponse handle_update_archive(WsdbRequest& ctx, wire::WsdbUpdateArchive&& cmd); +wire::WsdbCommitResponse handle_commit(WsdbRequest& ctx, wire::WsdbCommit&& cmd); +wire::WsdbRollbackResponse handle_rollback(WsdbRequest& ctx, wire::WsdbRollback&& cmd); +wire::WsdbSyncBlockResponse handle_sync_block(WsdbRequest& ctx, wire::WsdbSyncBlock&& cmd); +wire::WsdbCreateForkResponse handle_create_fork(WsdbRequest& ctx, wire::WsdbCreateFork&& cmd); +wire::WsdbDeleteForkResponse handle_delete_fork(WsdbRequest& ctx, wire::WsdbDeleteFork&& cmd); +wire::WsdbFinalizeBlocksResponse handle_finalize_blocks(WsdbRequest& ctx, wire::WsdbFinalizeBlocks&& cmd); +wire::WsdbUnwindBlocksResponse handle_unwind_blocks(WsdbRequest& ctx, wire::WsdbUnwindBlocks&& cmd); +wire::WsdbRemoveHistoricalBlocksResponse handle_remove_historical_blocks(WsdbRequest& ctx, + wire::WsdbRemoveHistoricalBlocks&& cmd); +wire::WsdbGetStatusResponse handle_get_status(WsdbRequest& ctx, wire::WsdbGetStatus&& cmd); +wire::WsdbCreateCheckpointResponse handle_create_checkpoint(WsdbRequest& ctx, wire::WsdbCreateCheckpoint&& cmd); +wire::WsdbCommitCheckpointResponse handle_commit_checkpoint(WsdbRequest& ctx, wire::WsdbCommitCheckpoint&& cmd); +wire::WsdbRevertCheckpointResponse handle_revert_checkpoint(WsdbRequest& ctx, wire::WsdbRevertCheckpoint&& cmd); +wire::WsdbCommitAllCheckpointsResponse handle_commit_all_checkpoints(WsdbRequest& ctx, + wire::WsdbCommitAllCheckpoints&& cmd); +wire::WsdbRevertAllCheckpointsResponse handle_revert_all_checkpoints(WsdbRequest& ctx, + wire::WsdbRevertAllCheckpoints&& cmd); +wire::WsdbCopyStoresResponse handle_copy_stores(WsdbRequest& ctx, wire::WsdbCopyStores&& cmd); + +} // namespace bb::wsdb diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_ipc_server.cpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_ipc_server.cpp index b7469770f881..4506f9b47d42 100644 --- a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_ipc_server.cpp +++ b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_ipc_server.cpp @@ -3,7 +3,9 @@ #include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" #include "barretenberg/serialize/msgpack.hpp" #include "barretenberg/world_state/world_state.hpp" -#include "barretenberg/wsdb/wsdb_execute.hpp" +#include "barretenberg/wsdb/generated/wsdb_ipc_server.hpp" +#include "barretenberg/wsdb/wsdb_handlers.hpp" +#include "barretenberg/wsdb/wsdb_request.hpp" #include "ipc_runtime/ipc_server.hpp" #include "ipc_runtime/serve_helper.hpp" #include "ipc_runtime/signal_handlers.hpp" @@ -202,72 +204,14 @@ int execute_wsdb_server(const std::string& input_path, std::cerr << "aztec-wsdb IPC server ready" << '\n'; - // Run server with wsdb command handler - server->run([&request](int client_id, std::span raw_request) -> std::vector { - try { - // Deserialize msgpack command - // Format: [["CommandName", {payload}]] - a 1-element tuple containing the NamedUnion - auto unpacked = msgpack::unpack(reinterpret_cast(raw_request.data()), raw_request.size()); - auto obj = unpacked.get(); - - // Expect array of size 1 (tuple wrapping) - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) - if (obj.type != msgpack::type::ARRAY || obj.via.array.size != 1) { - std::cerr << "Error: Expected array of size 1 from client " << client_id << '\n'; - return {}; - } - - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) - auto& command_obj = obj.via.array.ptr[0]; - - // Check for shutdown before converting - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) - if (command_obj.type == msgpack::type::ARRAY && command_obj.via.array.size == 2 && - command_obj.via.array.ptr[0].type == msgpack::type::STR) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) - std::string_view command_name(command_obj.via.array.ptr[0].via.str.ptr, - command_obj.via.array.ptr[0].via.str.size); - bool is_shutdown = (command_name == "WsdbShutdown"); - - // Convert and execute - WsdbCommand command; - command_obj.convert(command); - auto response = wsdb(request, std::move(command)); - - // Serialize response - msgpack::sbuffer response_buffer; - msgpack::pack(response_buffer, response); - std::vector result(response_buffer.data(), response_buffer.data() + response_buffer.size()); - - if (is_shutdown) { - throw ipc::ShutdownRequested(std::move(result)); - } - - return result; - } - - // Fallback: try converting directly - WsdbCommand command; - command_obj.convert(command); - auto response = wsdb(request, std::move(command)); - - msgpack::sbuffer response_buffer; - msgpack::pack(response_buffer, response); - return std::vector(response_buffer.data(), response_buffer.data() + response_buffer.size()); - - } catch (const ipc::ShutdownRequested&) { - throw; - } catch (const std::exception& e) { - std::cerr << "Error processing request from client " << client_id << ": " << e.what() << '\n'; - std::cerr.flush(); - - WsdbErrorResponse error_response{ .message = std::string(e.what()) }; - WsdbCommandResponse response = error_response; - - msgpack::sbuffer response_buffer; - msgpack::pack(response_buffer, response); - return std::vector(response_buffer.data(), response_buffer.data() + response_buffer.size()); - } + // The codegen-emitted make_wsdb_handler instantiates a + // dispatch table keyed by command name; each entry deserialises the + // wire-typed payload and calls our handle_(WsdbRequest&, wire::X&&) + // overload (see wsdb_handlers.hpp). It throws ipc::ShutdownRequested on + // WsdbShutdown; the runtime's run() catches that and exits cleanly. + auto handler = make_wsdb_handler(request); + server->run([&handler](int /*client_id*/, std::span raw) { + return handler(std::vector(raw.begin(), raw.end())); }); server->close(); diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_request.hpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_request.hpp new file mode 100644 index 000000000000..a0a4bb847e93 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_request.hpp @@ -0,0 +1,18 @@ +#pragma once +/** + * @file wsdb_request.hpp + * @brief Service-level context passed to every wsdb handler. + * + * Each codegen-emitted handler in wsdb_handlers.hpp takes a WsdbRequest& + * as its `Ctx`. The struct owns no state of its own — it just bundles the + * WorldState reference handlers need to do their work. + */ +#include "barretenberg/world_state/world_state.hpp" + +namespace bb::wsdb { + +struct WsdbRequest { + world_state::WorldState& world_state; +}; + +} // namespace bb::wsdb diff --git a/barretenberg/cpp/src/barretenberg/wsdb/wsdb_wire_convert.hpp b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_wire_convert.hpp new file mode 100644 index 000000000000..59d2b5569e90 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/wsdb/wsdb_wire_convert.hpp @@ -0,0 +1,140 @@ +#pragma once +/** + * @file wsdb_wire_convert.hpp + * @brief Wire <-> domain conversion helpers for the aztec-wsdb service. + * + * The codegen-emitted wire types in generated/wsdb_types.hpp are POD-shaped + * (uint32_t for tree IDs, std::array for field elements, etc). + * Domain types come from world_state/, crypto/merkle_tree/, ecc/. This file + * is the single place that translates between them — used by handlers (server + * side) and by wsdb_ipc_merkle_db.cpp (AVM client side). + */ +#include "barretenberg/crypto/merkle_tree/response.hpp" +#include "barretenberg/crypto/merkle_tree/types.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/world_state/types.hpp" +#include "barretenberg/wsdb/generated/wsdb_types.hpp" + +#include + +namespace bb::wsdb { + +inline ::Fr fr_to_wire(const bb::fr& d) +{ + ::Fr r{}; + bb::fr::serialize_to_buffer(d, r.data()); + return r; +} + +inline bb::fr fr_from_wire(const ::Fr& w) +{ + return bb::fr::serialize_from_buffer(w.data()); +} + +inline std::vector<::Fr> fr_vec_to_wire(const std::vector& d) +{ + std::vector<::Fr> r; + r.reserve(d.size()); + for (const auto& x : d) { + r.push_back(fr_to_wire(x)); + } + return r; +} + +inline std::vector fr_vec_from_wire(const std::vector<::Fr>& w) +{ + std::vector r; + r.reserve(w.size()); + for (const auto& x : w) { + r.push_back(fr_from_wire(x)); + } + return r; +} + +inline wire::WorldStateRevision revision_to_wire(const world_state::WorldStateRevision& d) +{ + return wire::WorldStateRevision{ + .forkId = d.forkId, + .blockNumber = d.blockNumber, + .includeUncommitted = d.includeUncommitted, + }; +} + +inline world_state::WorldStateRevision revision_from_wire(const wire::WorldStateRevision& w) +{ + return world_state::WorldStateRevision{ + .forkId = w.forkId, + .blockNumber = w.blockNumber, + .includeUncommitted = w.includeUncommitted, + }; +} + +inline uint32_t tree_id_to_wire(world_state::MerkleTreeId d) +{ + return static_cast(d); +} + +inline world_state::MerkleTreeId tree_id_from_wire(uint32_t w) +{ + return static_cast(w); +} + +// StateReference: domain unordered_map>. +// Wire: unordered_map, uint64_t>>, where the +// inner vector holds the msgpack-encoded `fr` (preserving the +// canonical 34-byte bin8-prefixed encoding for AVM <-> wsdb roundtrip). +inline std::unordered_map, uint64_t>> state_reference_to_wire( + const world_state::StateReference& d) +{ + std::unordered_map, uint64_t>> r; + r.reserve(d.size()); + for (const auto& [tree_id, tree_ref] : d) { + msgpack::sbuffer buf; + msgpack::pack(buf, tree_ref.first); + std::vector root_bytes(buf.data(), buf.data() + buf.size()); + r.emplace(static_cast(tree_id), std::make_pair(std::move(root_bytes), tree_ref.second)); + } + return r; +} + +inline world_state::StateReference state_reference_from_wire( + const std::unordered_map, uint64_t>>& w) +{ + world_state::StateReference r; + r.reserve(w.size()); + for (const auto& [tree_id, p] : w) { + const auto& root_bytes = p.first; + bb::fr root_fr; + auto unpacked = msgpack::unpack(reinterpret_cast(root_bytes.data()), root_bytes.size()); + unpacked.get().convert(root_fr); + r.emplace(static_cast(tree_id), + world_state::TreeStateReference{ root_fr, static_cast(p.second) }); + } + return r; +} + +// Generic msgpack roundtrip — for status/meta types whose wire and domain +// representations have isomorphic SERIALIZATION_FIELDS shapes (same field +// names + msgpack-compatible field types). Cheaper to roundtrip the bytes +// than to write field-by-field accessors for ~20 fields. +template inline Wire msgpack_roundtrip_to_wire(const Domain& d) +{ + msgpack::sbuffer buf; + msgpack::pack(buf, d); + auto unpacked = msgpack::unpack(buf.data(), buf.size()); + Wire w; + unpacked.get().convert(w); + return w; +} + +template inline Domain msgpack_roundtrip_from_wire(const Wire& w) +{ + msgpack::sbuffer buf; + msgpack::pack(buf, w); + auto unpacked = msgpack::unpack(buf.data(), buf.size()); + Domain d; + unpacked.get().convert(d); + return d; +} + +} // namespace bb::wsdb diff --git a/ipc-codegen/src/cpp_codegen.ts b/ipc-codegen/src/cpp_codegen.ts index 481c53691db5..725a385015f5 100644 --- a/ipc-codegen/src/cpp_codegen.ts +++ b/ipc-codegen/src/cpp_codegen.ts @@ -426,11 +426,22 @@ ${methods} #include #include +#include #include #include #include #include +// THROW/RETHROW mirror barretenberg's try_catch_shim macros so the same +// generated header works in both standalone builds (where exceptions are +// available) and in WASM builds (where the includer can predefine these to +// abort-with-message variants before including this header). +#ifndef THROW +#define THROW throw +#define RETHROW throw +#endif +#include + // --------------------------------------------------------------------------- // Self-contained serialization macro. // Defines a msgpack() method that enumerates field name/value pairs. @@ -468,8 +479,69 @@ ${methods} template void msgpack(_PackFn pack_fn) { pack_fn(_SF_NVP(__VA_ARGS__)); } #endif -/// 32-byte field element (Fr/Fq). Fixed-size, stack-allocated. -using Fr = std::array; +// --------------------------------------------------------------------------- +// 32-byte field element (Fr/Fq). +// +// Wire format: msgpack \`bin\` (2-byte header + raw 32 bytes), matching the +// schema's ["fr", "bin32"] alias and barretenberg's own bb::fr msgpack adapter. +// +// The default std::array msgpack adapter packs as \`array\` which +// is the wrong wire encoding (and incompatible with bb::fr / Rust / +// msgpackr-bin clients), so we wrap the array in a struct and provide +// explicit msgpack::adaptor specializations below. +// --------------------------------------------------------------------------- +struct Fr { + std::array bytes{}; + + uint8_t* data() { return bytes.data(); } + const uint8_t* data() const { return bytes.data(); } + constexpr std::size_t size() const { return bytes.size(); } + uint8_t& operator[](std::size_t i) { return bytes[i]; } + const uint8_t& operator[](std::size_t i) const { return bytes[i]; } + + bool operator==(const Fr&) const = default; +}; + +namespace msgpack { +MSGPACK_API_VERSION_NAMESPACE(v1) { +namespace adaptor { + +template <> struct pack<::Fr> { + template packer& operator()(packer& o, ::Fr const& v) const + { + o.pack_bin(static_cast(v.bytes.size())); + o.pack_bin_body(reinterpret_cast(v.bytes.data()), static_cast(v.bytes.size())); + return o; + } +}; + +template <> struct convert<::Fr> { + msgpack::object const& operator()(msgpack::object const& o, ::Fr& v) const + { + // Preferred: bin (matches schema + bb::fr). + if (o.type == msgpack::type::BIN) { + if (o.via.bin.size != v.bytes.size()) + throw msgpack::type_error(); + std::memcpy(v.bytes.data(), o.via.bin.ptr, v.bytes.size()); + return o; + } + // Fallback: array — kept so this type can decode payloads + // emitted by msgpack libraries that don't distinguish. + if (o.type == msgpack::type::ARRAY) { + if (o.via.array.size != v.bytes.size()) + throw msgpack::type_error(); + for (std::size_t i = 0; i < v.bytes.size(); ++i) { + o.via.array.ptr[i].convert(v.bytes[i]); + } + return o; + } + throw msgpack::type_error(); + } +}; + +} // namespace adaptor +} // MSGPACK_API_VERSION_NAMESPACE(v1) +} // namespace msgpack namespace ${ns}${this.opts.wireNamespace ? "::" + this.opts.wireNamespace : ""} { diff --git a/ipc-codegen/templates/cpp/msgpack_struct_map_impl.hpp b/ipc-codegen/templates/cpp/msgpack_struct_map_impl.hpp index c770b835248c..b829011f3cef 100644 --- a/ipc-codegen/templates/cpp/msgpack_struct_map_impl.hpp +++ b/ipc-codegen/templates/cpp/msgpack_struct_map_impl.hpp @@ -6,9 +6,19 @@ // msgpack headers. // // Self-contained struct-map msgpack adaptor — only depends on msgpack-c. +// +// In barretenberg context the framework ships its own equivalent under +// barretenberg/serialize/msgpack_impl/struct_map_impl.hpp. Both define +// `template struct convert / pack` in +// `msgpack::adaptor`, with overlapping constraints, so including both in a +// single TU triggers "ambiguous partial specialization" errors. Consumers +// in that context predefine IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS so this +// self-contained adaptor opts out and yields to the framework's. -#include #include + +#ifndef IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS +#include #include #include @@ -92,3 +102,4 @@ template struct pack { }; } // namespace msgpack::adaptor +#endif // IPC_CODEGEN_USE_BB_MSGPACK_ADAPTORS