fix: copilot comments, add isHex helper

This commit is contained in:
erhant 2026-07-02 15:07:28 +03:00
parent 4a710acdd0
commit 57766ef2a8
4 changed files with 40 additions and 16 deletions

View File

@ -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.

View File

@ -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.

View File

@ -5,6 +5,7 @@
#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <string>
@ -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;
}

View File

@ -42,11 +42,13 @@ public:
int64_t stop_indexer();
/// Stop the indexer (if running) and delete the RocksDB store for the config's
/// channel — `<instancePersistencePath>/rocksdb-<channel_id>`, 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 — `<storage>/rocksdb-<channel_id>`, where `<storage>` 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