From 332e3a61e52265815ea7ba8ef21140479b42f05b Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sat, 25 Jul 2026 21:53:06 +0300 Subject: [PATCH] fix merkle_sync: prefix serialization writes LSB bytes instead of MSB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _prefix_write was writing the least significant pb bytes of the 64-bit prefix, but the protocol expects the most significant pb bytes (bits 63..64-pb*8). For pb<=4 these ranges are disjoint → wire always got zeros. _prefix_read also lacked the final left-shift to align the result at bit 63. This caused all level>=2 merkle sync requests/batches to receive prefix=0 instead of the real prefix, making get_items/update_bucket_hash find zero members → handle_batch len=7 with no data → sync completed without actually exchanging member data. --- tools/chatgui/transport/member_sync.c | 2 ++ tools/chatgui/transport/merkle_sync.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/chatgui/transport/member_sync.c b/tools/chatgui/transport/member_sync.c index fe7a3414..65ef2041 100644 --- a/tools/chatgui/transport/member_sync.c +++ b/tools/chatgui/transport/member_sync.c @@ -212,6 +212,8 @@ static int _member_get_items(void* ctx, const char* ns, uint8_t level, } sqlite3_finalize(stmt); *len = off; + DEBUG_DEBUG(DEBUG_CATEGORY_DB_SYNC, "%s: get_items ns=%s L%d/P%016llx mask=%016llx count=%u off=%zu", + MS_ID, ns, level, (unsigned long long)prefix, (unsigned long long)mask, *cnt, off); return 0; } diff --git a/tools/chatgui/transport/merkle_sync.c b/tools/chatgui/transport/merkle_sync.c index 311e0171..b8e15390 100644 --- a/tools/chatgui/transport/merkle_sync.c +++ b/tools/chatgui/transport/merkle_sync.c @@ -59,13 +59,14 @@ uint64_t merkle_sync_level_prefix(uint64_t key, uint8_t level) { uint8_t merkle_sync_prefix_bytes(uint8_t level) { int bits = level * 5; return (uint8_t)((bits + 7) / 8); } static void _prefix_write(uint8_t* out, uint64_t prefix, uint8_t pb) { - for (int i = (int)pb - 1; i >= 0; i--) out[pb - 1 - i] = (uint8_t)(prefix >> (i * 8)); + for (int i = 0; i < (int)pb; i++) + out[i] = (uint8_t)(prefix >> (8 * (7 - i))); } static uint64_t _prefix_read(const uint8_t* in, uint8_t pb) { uint64_t v = 0; for (uint8_t i = 0; i < pb && i < 8; i++) v = (v << 8) | in[i]; - return v; + return v << (8 * (8 - (int)pb)); } static int _popcount_u32(uint32_t v) { return __builtin_popcount(v); }