Browse Source

merkle_sync: fix level 0 SQL range, rebuild trees at startup

- _get_level_hashes: use separate SQL without prefix64<=? for level 0.
  UINT64_MAX cast to sqlite3_int64 becomes -1, making prefix64<=-1 always
  false for positive prefixes → bitmap always 0 → sync never exchanges data.
- member_sync_init: add _rebuild_all_trees to scan all peers_* tables and
  call merkle_sync_recompute_path for each member. Ensures merkle_tree_hash
  has entries for members added before merkle sync existed.
topo_upd
Evgeny 2 months ago
parent
commit
cd3c3ad07d
  1. 25
      tools/chatgui/transport/member_sync.c
  2. 21
      tools/chatgui/transport/merkle_sync.c

25
tools/chatgui/transport/member_sync.c

@ -306,11 +306,36 @@ static const struct merkle_sync_data_ops g_member_ops = {
/* ── Public API ── */
static void _rebuild_all_trees(struct UTUN_INSTANCE* inst) {
sqlite3* db = _db(inst); if (!db) return;
sqlite3_stmt* st = NULL;
if (sqlite3_prepare_v2(db,
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'peers_%'",
-1, &st, NULL) != SQLITE_OK) return;
while (sqlite3_step(st) == SQLITE_ROW) {
const char* tbl = (const char*)sqlite3_column_text(st, 0);
if (!tbl || strncmp(tbl, "peers_", 6) != 0) continue;
const char* ch_id = tbl + 6;
sqlite3_stmt* ns = NULL;
char sql[256]; snprintf(sql, sizeof(sql), "SELECT node_id FROM \"%s\"", tbl);
if (sqlite3_prepare_v2(db, sql, -1, &ns, NULL) == SQLITE_OK) {
while (sqlite3_step(ns) == SQLITE_ROW) {
uint64_t nid = (uint64_t)sqlite3_column_int64(ns, 0);
merkle_sync_recompute_path(inst, ch_id, nid);
DEBUG_DEBUG(DEBUG_CATEGORY_DB_SYNC, "%s: rebuild tree ns=%s nid=%016llx", MS_ID, ch_id, (unsigned long long)nid);
}
sqlite3_finalize(ns);
}
}
sqlite3_finalize(st);
}
int member_sync_init(struct UTUN_INSTANCE* inst) {
if (!inst) return -1;
DEBUG_TRACE(DEBUG_CATEGORY_DB_SYNC, "%s: init", MS_ID);
int rc = merkle_sync_init(inst, 0x31, &g_member_ops, inst);
if (rc != 0) return rc;
_rebuild_all_trees(inst);
DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: initialized, merkle_rc=%d", MS_ID, rc);
return 0;
}

21
tools/chatgui/transport/merkle_sync.c

@ -173,22 +173,25 @@ static int _get_level_hashes(struct merkle_sync* ms, const char* ns,
next_shift = 63 - ((int)level + 1) * 5; if (next_shift < 0) next_shift = 0;
}
uint64_t range_end = (level == 0) ? UINT64_MAX
: prefix | (0x1FULL << (next_shift > 0 ? next_shift : 0));
sqlite3_stmt* stmt = NULL;
int query_level = (int)(level + 1);
if (sqlite3_prepare_v2(db,
"SELECT prefix64, hash FROM merkle_tree_hash"
" WHERE namespace=? AND level=? AND prefix64>=? AND prefix64<=?"
" ORDER BY prefix64", -1, &stmt, NULL) != SQLITE_OK || !stmt) {
const char* sql = (level == 0)
? "SELECT prefix64, hash FROM merkle_tree_hash"
" WHERE namespace=? AND level=? ORDER BY prefix64"
: "SELECT prefix64, hash FROM merkle_tree_hash"
" WHERE namespace=? AND level=? AND prefix64>=? AND prefix64<=?"
" ORDER BY prefix64";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK || !stmt) {
DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: _get_level_hashes SQL error ns=%s L%d — %s", MS_ID, ns, level, sqlite3_errmsg(db));
return -1;
}
sqlite3_bind_text(stmt, 1, ns, -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, query_level);
sqlite3_bind_int64(stmt, 3, (sqlite3_int64)prefix);
sqlite3_bind_int64(stmt, 4, (sqlite3_int64)range_end);
if (level > 0) {
uint64_t range_end = prefix | (0x1FULL << (next_shift > 0 ? next_shift : 0));
sqlite3_bind_int64(stmt, 3, (sqlite3_int64)prefix);
sqlite3_bind_int64(stmt, 4, (sqlite3_int64)range_end);
}
while (sqlite3_step(stmt) == SQLITE_ROW) {
sqlite3_int64 row_pfx = sqlite3_column_int64(stmt, 0);
const void* h = sqlite3_column_blob(stmt, 1);

Loading…
Cancel
Save