From 69dbf45a57f94345d46ceca3c9bc563ce5fab0ae Mon Sep 17 00:00:00 2001 From: erhant Date: Thu, 2 Jul 2026 12:02:37 +0300 Subject: [PATCH 1/6] refactor: bump flake, update configs, better logging & remove `init_logger` --- README.md | 10 +++--- config/indexer_config.json | 44 +------------------------- flake.lock | 12 +++---- flake.nix | 6 +--- metadata.json | 1 + src/lez_indexer_module_impl.cpp | 55 +++++++++++++++++++++------------ src/lez_indexer_module_impl.h | 5 --- 7 files changed, 49 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 420f92f..4910e6a 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,11 @@ On success it returns `0`; a non-zero return is the FFI `OperationStatus` (e.g. > [!TIP] > -> By default the indexer is silent. Call `init_logger(level)` once (e.g. -> `init_logger("info")`; accepts `off`/`error`/`warn`/`info`/`debug`/`trace`) to -> surface the indexer's own `log` output — useful since a failed call otherwise -> only reports a numeric `OperationStatus`. Logging is scoped to the indexer -> crates, and the first call wins. +> The module logs its lifecycle (start/stop, the resolved config + storage paths, +> and failures with their `OperationStatus`) to stderr, which the `logos_host` +> captures and surfaces through its own logger. For ongoing indexer health — sync +> state, and a parked/stalled tip with its reason — poll `getStatus()`; that runs +> inside the indexer and reports what the C++ lifecycle logs can't see. ### Query methods (the Logos-protocol API) diff --git a/config/indexer_config.json b/config/indexer_config.json index 72ec53f..af991bb 100644 --- a/config/indexer_config.json +++ b/config/indexer_config.json @@ -7,47 +7,5 @@ "max_retries": 5 } }, - "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", - "initial_accounts": [ - { - "account_id": "CbgR6tj5kWx5oziiFptM7jMvrQeYY3Mzaao6ciuhSr2r", - "balance": 10000 - }, - { - "account_id": "2RHZhw9h534Zr3eq2RGhQete2Hh667foECzXPmSkGni2", - "balance": 20000 - } - ], - "initial_commitments": [ - { - "npk": [ - 139, 19, 158, 11, 155, 231, 85, 206, 132, 228, 220, 114, 145, 89, 113, - 156, 238, 142, 242, 74, 182, 91, 43, 100, 6, 190, 31, 15, 31, 88, 96, - 204 - ], - "account": { - "program_owner": [0, 0, 0, 0, 0, 0, 0, 0], - "balance": 10000, - "data": [], - "nonce": 0 - } - }, - { - "npk": [ - 173, 134, 33, 223, 54, 226, 10, 71, 215, 254, 143, 172, 24, 244, 243, - 208, 65, 112, 118, 70, 217, 240, 69, 100, 129, 3, 121, 25, 213, 132, 42, - 45 - ], - "account": { - "program_owner": [0, 0, 0, 0, 0, 0, 0, 0], - "balance": 20000, - "data": [], - "nonce": 0 - } - } - ], - "signing_key": [ - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37 - ] + "channel_id": "0101010101010101010101010101010101010101010101010101010101010101" } diff --git a/flake.lock b/flake.lock index fb76b21..7ff4e6d 100644 --- a/flake.lock +++ b/flake.lock @@ -1574,16 +1574,16 @@ "rust-rapidsnark": "rust-rapidsnark" }, "locked": { - "lastModified": 1782820738, - "narHash": "sha256-OnXBx3nD/r7vCzZwh/RXmoqbtNF9rG+ZZsWXPsXoOzk=", - "ref": "refs/tags/v0.2.0", - "rev": "a58fbce2ff48c58b7bb5001b1a27e64b9596ee3a", - "revCount": 2828, + "lastModified": 1782941647, + "narHash": "sha256-H7T0mBWY75tZjCf9zcQUAFteurZhqnZ+2srtdPeQTRQ=", + "ref": "main", + "rev": "d1637b65e2479e80bb617b900ec5d4024216457d", + "revCount": 2830, "type": "git", "url": "https://github.com/logos-blockchain/logos-execution-zone" }, "original": { - "ref": "refs/tags/v0.2.0", + "ref": "main", "type": "git", "url": "https://github.com/logos-blockchain/logos-execution-zone" } diff --git a/flake.nix b/flake.nix index bf4a513..170edbd 100644 --- a/flake.nix +++ b/flake.nix @@ -3,11 +3,7 @@ inputs = { logos-module-builder.url = "github:logos-co/logos-module-builder"; - - # The LEZ indexer Rust FFI lib + header come from this flake's `indexer` - # package output (/lib/libindexer_ffi.* + /include/indexer_ffi.h). It is a - # prebuilt Nix derivation, so mkExternalLib consumes it directly (no build). - logos-execution-zone.url = "git+https://github.com/logos-blockchain/logos-execution-zone?ref=refs/tags/v0.2.0"; + logos-execution-zone.url = "git+https://github.com/logos-blockchain/logos-execution-zone?ref=main"; }; outputs = diff --git a/metadata.json b/metadata.json index 3a54678..d70cf2d 100644 --- a/metadata.json +++ b/metadata.json @@ -1,5 +1,6 @@ { "name": "lez_indexer_module", + "display_name": "LEZ Indexer", "version": "1.0.0", "type": "core", "interface": "universal", diff --git a/src/lez_indexer_module_impl.cpp b/src/lez_indexer_module_impl.cpp index f600b92..8de2f86 100644 --- a/src/lez_indexer_module_impl.cpp +++ b/src/lez_indexer_module_impl.cpp @@ -5,6 +5,7 @@ #include #include +#include using namespace marshalling; @@ -15,34 +16,50 @@ namespace { return static_cast(p); } - void warn(const char* method, const char* msg) { - std::fprintf(stderr, "lez_indexer_module: %s: %s\n", method, msg); + // Module diagnostics go to stderr; logos_host captures it and routes each line + // through its own logger, keying on a leading "Error:"/"Warning:" token to pick + // the level (plain lines are treated as info). Prefix accordingly. + void info(const char* method, const std::string& msg) { + std::fprintf(stderr, "lez_indexer_module: %s: %s\n", method, msg.c_str()); + } + void warn(const char* method, const std::string& msg) { + std::fprintf(stderr, "lez_indexer_module: Warning: %s: %s\n", method, msg.c_str()); + } + void error(const char* method, const std::string& msg) { + std::fprintf(stderr, "lez_indexer_module: Error: %s: %s\n", method, msg.c_str()); } } // namespace LezIndexerModuleImpl::~LezIndexerModuleImpl() { if (stop_indexer() != 0) { - warn("destructor", "indexer FFI error on stop"); + error("destructor", "indexer FFI error on stop"); } } // === Indexer Lifecycle === int64_t LezIndexerModuleImpl::start_indexer(const std::string& config_path) { - if (!indexer_service_ffi) { - // Null runtime: the FFI creates and owns its own tokio runtime. Storage - // goes under this module's instance persistence path (host-owned, stable - // per Basecamp --user-dir) so RocksDB never lands in the process CWD. - InitializedIndexerServiceFFIResult res = - ::start_indexer(nullptr, config_path.c_str(), instancePersistencePath().c_str()); - if (is_error(&res.error)) { - warn("start_indexer", "indexer FFI error"); - return static_cast(res.error); - } - - indexer_service_ffi = res.value; + if (indexer_service_ffi) { + info("start_indexer", "indexer already running; ignoring start request"); + return 0; } + // Null runtime: the FFI creates and owns its own tokio runtime. Storage goes + // under this module's instance persistence path (host-owned, stable per + // Basecamp --user-dir) so RocksDB never lands in the process CWD. + const std::string& storage = instancePersistencePath(); + info("start_indexer", "starting indexer (config=" + config_path + ", storage=" + storage + ")"); + + InitializedIndexerServiceFFIResult res = + ::start_indexer(nullptr, config_path.c_str(), storage.c_str()); + if (is_error(&res.error)) { + error("start_indexer", "FFI failed to start indexer (OperationStatus " + + std::to_string(static_cast(res.error)) + ")"); + return static_cast(res.error); + } + + indexer_service_ffi = res.value; + info("start_indexer", "indexer started"); return 0; } @@ -55,16 +72,14 @@ int64_t LezIndexerModuleImpl::stop_indexer() { OperationStatus operation_result = ::stop_indexer(handle(indexer_service_ffi)); indexer_service_ffi = nullptr; if (is_error(&operation_result)) { - warn("stop_indexer", "indexer FFI error on stop"); + error("stop_indexer", "FFI error on stop (OperationStatus " + + std::to_string(static_cast(operation_result)) + ")"); return static_cast(operation_result); } + info("stop_indexer", "indexer stopped"); return 0; } -void LezIndexerModuleImpl::init_logger(const std::string& level) { - ::init_logger(level.c_str()); -} - // === Indexer Queries === // // Each method calls the matching query_* FFI function on the handle we hold, diff --git a/src/lez_indexer_module_impl.h b/src/lez_indexer_module_impl.h index 55d2340..e2e2206 100644 --- a/src/lez_indexer_module_impl.h +++ b/src/lez_indexer_module_impl.h @@ -71,11 +71,6 @@ public: std::string getTransactionsByAccount(const std::string& account_id, const std::string& offset, const std::string& limit); // clang-format on - /// Enable the indexer's logging at `level` (off/error/warn/info/debug/trace; - /// null or unparseable falls back to info). Scoped to the indexer crates - /// only; the first call wins (subsequent calls are no-ops). - void init_logger(const std::string& level); - private: // IndexerServiceFFI* — opaque here (see class comment); cast in the .cpp. void* indexer_service_ffi = nullptr; From e17bc549f4fd1450bea0b48fe4b00262a7ee4c77 Mon Sep 17 00:00:00 2001 From: erhant Date: Thu, 2 Jul 2026 12:19:00 +0300 Subject: [PATCH 2/6] chore: prettify --- src/lez_indexer_module_impl.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/lez_indexer_module_impl.cpp b/src/lez_indexer_module_impl.cpp index 8de2f86..919ed52 100644 --- a/src/lez_indexer_module_impl.cpp +++ b/src/lez_indexer_module_impl.cpp @@ -50,11 +50,12 @@ int64_t LezIndexerModuleImpl::start_indexer(const std::string& config_path) { const std::string& storage = instancePersistencePath(); info("start_indexer", "starting indexer (config=" + config_path + ", storage=" + storage + ")"); - InitializedIndexerServiceFFIResult res = - ::start_indexer(nullptr, config_path.c_str(), storage.c_str()); + InitializedIndexerServiceFFIResult res = ::start_indexer(nullptr, config_path.c_str(), storage.c_str()); if (is_error(&res.error)) { - error("start_indexer", "FFI failed to start indexer (OperationStatus " - + std::to_string(static_cast(res.error)) + ")"); + error( + "start_indexer", + "FFI failed to start indexer (OperationStatus " + std::to_string(static_cast(res.error)) + ")" + ); return static_cast(res.error); } @@ -72,8 +73,10 @@ int64_t LezIndexerModuleImpl::stop_indexer() { OperationStatus operation_result = ::stop_indexer(handle(indexer_service_ffi)); indexer_service_ffi = nullptr; if (is_error(&operation_result)) { - error("stop_indexer", "FFI error on stop (OperationStatus " - + std::to_string(static_cast(operation_result)) + ")"); + error( + "stop_indexer", + "FFI error on stop (OperationStatus " + std::to_string(static_cast(operation_result)) + ")" + ); return static_cast(operation_result); } info("stop_indexer", "indexer stopped"); From 731bcc4a413ba7ea50ef8c5654333967e9afd1b2 Mon Sep 17 00:00:00 2001 From: erhant Date: Thu, 2 Jul 2026 14:09:35 +0300 Subject: [PATCH 3/6] feat: add `reset_storage` function --- src/lez_indexer_module_impl.cpp | 49 +++++++++++++++++++++++++++++++++ src/lez_indexer_module_impl.h | 8 ++++++ 2 files changed, 57 insertions(+) diff --git a/src/lez_indexer_module_impl.cpp b/src/lez_indexer_module_impl.cpp index 919ed52..67539c5 100644 --- a/src/lez_indexer_module_impl.cpp +++ b/src/lez_indexer_module_impl.cpp @@ -5,6 +5,7 @@ #include #include +#include #include using namespace marshalling; @@ -83,6 +84,54 @@ int64_t LezIndexerModuleImpl::stop_indexer() { return 0; } +int64_t LezIndexerModuleImpl::reset_storage(const std::string& config_path) { + // Stop first so RocksDB is closed before its files are deleted + const int64_t stop_code = stop_indexer(); + if (stop_code != 0) { + error("reset_storage", "could not stop indexer before wiping storage"); + return stop_code; + } + + const std::string& storage = instancePersistencePath(); + if (storage.empty()) { + error("reset_storage", "no instance persistence path; refusing to wipe (nothing to target)"); + return -1; + } + + // FFI stores RocksDB at /rocksdb-{channel_id} + std::string channel_id; + try { + std::ifstream in(config_path); + if (!in) { + error("reset_storage", "could not open config " + config_path); + return -1; + } + channel_id = nlohmann::json::parse(in).at("channel_id").get(); + } catch (const std::exception& e) { + error("reset_storage", std::string("could not read channel_id from config: ") + e.what()); + return -1; + } + if (channel_id.empty()) { + error("reset_storage", "config has an empty channel_id"); + return -1; + } + + const std::filesystem::path store = std::filesystem::path(storage) / ("rocksdb-" + channel_id); + std::error_code ec; + if (!std::filesystem::exists(store, ec)) { + info("reset_storage", "no store at " + store.string() + "; nothing to wipe"); + return 0; + } + std::filesystem::remove_all(store, ec); + if (ec) { + error("reset_storage", "failed to remove " + store.string() + ": " + ec.message()); + return -1; + } + + info("reset_storage", "wiped rocksdb store " + store.string()); + return 0; +} + // === Indexer Queries === // // Each method calls the matching query_* FFI function on the handle we hold, diff --git a/src/lez_indexer_module_impl.h b/src/lez_indexer_module_impl.h index e2e2206..d0d2fa6 100644 --- a/src/lez_indexer_module_impl.h +++ b/src/lez_indexer_module_impl.h @@ -41,6 +41,14 @@ public: /// own). Returns 0 on success, else the FFI OperationStatus code. int64_t stop_indexer(); + /// Stop the indexer (if running) and delete the RocksDB store for the config's + /// channel — `/rocksdb-`, the exact path the + /// FFI uses — so the next start_indexer re-indexes from scratch. The recovery + /// path when the store is stale against a different/reset chain. Pass the same + /// `config_path` given to start_indexer; does NOT restart. Returns 0 on success, + /// else non-zero. int64_t for the same codegen reason as start_indexer. + int64_t reset_storage(const std::string& config_path); + /// Account by id, accepting Base58 (canonical) or 32-byte hex. The returned /// JSON omits the id; callers inject the queried id themselves. std::string getAccount(const std::string& account_id); From b2fde3c000d00c04da374b2c31719e29a237b2a4 Mon Sep 17 00:00:00 2001 From: erhant Date: Thu, 2 Jul 2026 14:29:16 +0300 Subject: [PATCH 4/6] fix: fallback to CWD --- src/lez_indexer_module_impl.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lez_indexer_module_impl.cpp b/src/lez_indexer_module_impl.cpp index 67539c5..ffb1804 100644 --- a/src/lez_indexer_module_impl.cpp +++ b/src/lez_indexer_module_impl.cpp @@ -92,10 +92,12 @@ int64_t LezIndexerModuleImpl::reset_storage(const std::string& config_path) { return stop_code; } - const std::string& storage = instancePersistencePath(); + // if running from Basecamp, the instance persistence path is stable and owned by the host; + // otherwise it falls back to the process CWD (the same path start_indexer uses). + std::filesystem::path storage = instancePersistencePath(); if (storage.empty()) { - error("reset_storage", "no instance persistence path; refusing to wipe (nothing to target)"); - return -1; + warn("reset_storage", "no instance persistence path; using the working directory (matches start_indexer)"); + storage = "."; } // FFI stores RocksDB at /rocksdb-{channel_id} @@ -116,7 +118,7 @@ int64_t LezIndexerModuleImpl::reset_storage(const std::string& config_path) { return -1; } - const std::filesystem::path store = std::filesystem::path(storage) / ("rocksdb-" + channel_id); + const std::filesystem::path store = storage / ("rocksdb-" + channel_id); std::error_code ec; if (!std::filesystem::exists(store, ec)) { info("reset_storage", "no store at " + store.string() + "; nothing to wipe"); From 4a710acdd0ae0513a62e5a76ac4c9eea3158661c Mon Sep 17 00:00:00 2001 From: erhant Date: Thu, 2 Jul 2026 14:40:06 +0300 Subject: [PATCH 5/6] chore: use the same path resolution as a shared method --- src/lez_indexer_module_impl.cpp | 28 ++++++++++++++++------------ src/lez_indexer_module_impl.h | 5 +++++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/lez_indexer_module_impl.cpp b/src/lez_indexer_module_impl.cpp index ffb1804..53091e7 100644 --- a/src/lez_indexer_module_impl.cpp +++ b/src/lez_indexer_module_impl.cpp @@ -39,16 +39,27 @@ LezIndexerModuleImpl::~LezIndexerModuleImpl() { // === Indexer Lifecycle === +std::string LezIndexerModuleImpl::resolveStorageDir(const char* method) const { + // The host owns where state lives (its instance persistence path). When that + // isn't provisioned (e.g. running outside Basecamp), fall back to the process + // working directory — the same "." the FFI's start_indexer uses — so start and + // reset always agree on the store location. + const std::string& path = instancePersistencePath(); + if (!path.empty()) { + return path; + } + warn(method, "no instance persistence path; using the working directory"); + return "."; +} + int64_t LezIndexerModuleImpl::start_indexer(const std::string& config_path) { if (indexer_service_ffi) { info("start_indexer", "indexer already running; ignoring start request"); return 0; } - // Null runtime: the FFI creates and owns its own tokio runtime. Storage goes - // under this module's instance persistence path (host-owned, stable per - // Basecamp --user-dir) so RocksDB never lands in the process CWD. - const std::string& storage = instancePersistencePath(); + // Null runtime: the FFI creates and owns its own tokio runtime. + const std::string storage = resolveStorageDir("start_indexer"); info("start_indexer", "starting indexer (config=" + config_path + ", storage=" + storage + ")"); InitializedIndexerServiceFFIResult res = ::start_indexer(nullptr, config_path.c_str(), storage.c_str()); @@ -92,15 +103,8 @@ int64_t LezIndexerModuleImpl::reset_storage(const std::string& config_path) { return stop_code; } - // if running from Basecamp, the instance persistence path is stable and owned by the host; - // otherwise it falls back to the process CWD (the same path start_indexer uses). - std::filesystem::path storage = instancePersistencePath(); - if (storage.empty()) { - warn("reset_storage", "no instance persistence path; using the working directory (matches start_indexer)"); - storage = "."; - } - // FFI stores RocksDB at /rocksdb-{channel_id} + const std::filesystem::path storage = resolveStorageDir("reset_storage"); std::string channel_id; try { std::ifstream in(config_path); diff --git a/src/lez_indexer_module_impl.h b/src/lez_indexer_module_impl.h index d0d2fa6..b496c23 100644 --- a/src/lez_indexer_module_impl.h +++ b/src/lez_indexer_module_impl.h @@ -80,6 +80,11 @@ public: // clang-format on private: + // Storage dir handed to the FFI, either: + // - the host's instance persistence path + // - the process working directory (".") when the host didn't provision one + std::string resolveStorageDir(const char* method) const; + // IndexerServiceFFI* — opaque here (see class comment); cast in the .cpp. void* indexer_service_ffi = nullptr; }; From 57766ef2a8c34b6d11de506afd6ee323a04804c7 Mon Sep 17 00:00:00 2001 From: erhant Date: Thu, 2 Jul 2026 15:07:28 +0300 Subject: [PATCH 6/6] fix: copilot comments, add `isHex` helper --- src/lez_ffi_marshalling.cpp | 13 +++++++++++++ src/lez_ffi_marshalling.h | 5 +++++ src/lez_indexer_module_impl.cpp | 26 +++++++++++++++----------- src/lez_indexer_module_impl.h | 12 +++++++----- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/lez_ffi_marshalling.cpp b/src/lez_ffi_marshalling.cpp index 6f8f3b2..9d63143 100644 --- a/src/lez_ffi_marshalling.cpp +++ b/src/lez_ffi_marshalling.cpp @@ -152,6 +152,19 @@ namespace marshalling { return true; } + // True iff `s` is exactly `num_chars` hex digits (no prefix/whitespace). + bool isHex(const std::string& s, const size_t num_chars) { + if (s.size() != num_chars) { + return false; + } + for (const char c : s) { + if (hexNibble(c) < 0) { + return false; + } + } + return true; + } + // Base58-encode `length` raw bytes (plain Bitcoin alphabet). Big-integer // base 256 -> 58, leading zero bytes map to leading '1's. Mirrors // Base58.js::encode so account ids match the wallet UI and canonical LEZ. diff --git a/src/lez_ffi_marshalling.h b/src/lez_ffi_marshalling.h index 0eae49b..86b102b 100644 --- a/src/lez_ffi_marshalling.h +++ b/src/lez_ffi_marshalling.h @@ -40,6 +40,11 @@ namespace marshalling { // Returns false unless it decodes to exactly 32 bytes. bool hexToBytes32(const std::string& hex, FfiBytes32* out); + // True iff `s` is exactly `num_chars` hex digits (no 0x prefix, no whitespace). + // For validating fixed-width hex identifiers (e.g. a 64-char channel id) before + // trusting them as-is, such as when composing a filesystem path. + bool isHex(const std::string& s, size_t num_chars); + // Base58 (plain Bitcoin alphabet, no checksum) of `length` raw bytes. This is // the canonical string form of an LEZ *account id* — it matches lee::AccountId // Display, wallet_ffi's account_id_to_base58, and the wallet UI's Base58.js. diff --git a/src/lez_indexer_module_impl.cpp b/src/lez_indexer_module_impl.cpp index 53091e7..1314837 100644 --- a/src/lez_indexer_module_impl.cpp +++ b/src/lez_indexer_module_impl.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -18,8 +19,8 @@ namespace { } // Module diagnostics go to stderr; logos_host captures it and routes each line - // through its own logger, keying on a leading "Error:"/"Warning:" token to pick - // the level (plain lines are treated as info). Prefix accordingly. + // through its own logger, classifying by an "Error:"/"Warning:" token found + // anywhere in the line (plain lines are treated as info). Prefix accordingly. void info(const char* method, const std::string& msg) { std::fprintf(stderr, "lez_indexer_module: %s: %s\n", method, msg.c_str()); } @@ -117,24 +118,27 @@ int64_t LezIndexerModuleImpl::reset_storage(const std::string& config_path) { error("reset_storage", std::string("could not read channel_id from config: ") + e.what()); return -1; } - if (channel_id.empty()) { - error("reset_storage", "config has an empty channel_id"); + // A channel id is a 32-byte hex string. Validate before building a path so a + // malformed/edited config can't inject separators ("../", absolute paths) and + // make remove_all escape the storage dir. + if (!isHex(channel_id, 64)) { + error("reset_storage", "config channel_id is not a 64-char hex string; refusing to build a wipe path"); return -1; } const std::filesystem::path store = storage / ("rocksdb-" + channel_id); std::error_code ec; - if (!std::filesystem::exists(store, ec)) { - info("reset_storage", "no store at " + store.string() + "; nothing to wipe"); - return 0; - } - std::filesystem::remove_all(store, ec); + // remove_all returns the number of entries removed and only sets `ec` on a real + // error; a missing store removes 0 with no error. No exists() pre-check — that + // would mask an IO/permission error as a successful "nothing to wipe". + const std::uintmax_t removed = std::filesystem::remove_all(store, ec); if (ec) { error("reset_storage", "failed to remove " + store.string() + ": " + ec.message()); return -1; } - - info("reset_storage", "wiped rocksdb store " + store.string()); + info("reset_storage", + removed == 0 ? "no store at " + store.string() + "; nothing to wipe" + : "wiped rocksdb store " + store.string()); return 0; } diff --git a/src/lez_indexer_module_impl.h b/src/lez_indexer_module_impl.h index b496c23..b7e17d3 100644 --- a/src/lez_indexer_module_impl.h +++ b/src/lez_indexer_module_impl.h @@ -42,11 +42,13 @@ public: int64_t stop_indexer(); /// Stop the indexer (if running) and delete the RocksDB store for the config's - /// channel — `/rocksdb-`, the exact path the - /// FFI uses — so the next start_indexer re-indexes from scratch. The recovery - /// path when the store is stale against a different/reset chain. Pass the same - /// `config_path` given to start_indexer; does NOT restart. Returns 0 on success, - /// else non-zero. int64_t for the same codegen reason as start_indexer. + /// channel — `/rocksdb-`, where `` is resolved the + /// same way start_indexer resolves it (the host's instance persistence path, or + /// the process working directory when unset) — so the next start_indexer + /// re-indexes from scratch. The recovery path when the store is stale against a + /// different/reset chain. Pass the same `config_path` given to start_indexer; + /// does NOT restart. Returns 0 on success, else non-zero. int64_t for the same + /// codegen reason as start_indexer. int64_t reset_storage(const std::string& config_path); /// Account by id, accepting Base58 (canonical) or 32-byte hex. The returned