Preserve fallback versions until receive verification instead of purging at start

This commit is contained in:
evgeny committed 2026-11-04 01:05:59 +01:00
1 parent ddf570c791
commit 778b548c9c
3 files changed
+8 -10

No files matched your search

+1 -4
View File
@@ -1778,10 +1778,7 @@ int member_sync_start(struct UTUN_INSTANCE* inst, uint64_t peer,
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "member start denied ch=%s peer=%016llx", ch_id ? ch_id : "-", (unsigned long long)peer);
return -1;
}
if (member_sync_verify_and_purge(inst, ch_id) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: start rejected after purge failure ns=%s peer=%016llx",
MS_ID, ch_id ? ch_id : "-", (unsigned long long)peer); return -1;
}
/* Прежняя запись нужна commit_pull для проверки и fallback; start её не удаляет. */
return merkle_sync_start(inst, MT_DATA_MEMBERS, peer, ch_id, done_cb, arg);
}
+3 -3
View File
@@ -149,9 +149,9 @@ int member_sync_subscribe_group(struct UTUN_INSTANCE* inst, struct TOPO_GROUP* g
/*
* Запустить синхронизацию мемберов канала ch_id с пиром peer.
* Сначала вызывает verify_and_purge, затем merkle_sync_start(MEMBERS).
* Проверяет право обмена/запроса, затем вызывает merkle_sync_start(MEMBERS).
* 0 — запрос принят; <0 — не принят, done_cb не вызывается (см. merkle_sync.h).
* Ошибка очистки отклоняет запрос до merkle_sync_start, без done callback.
* Прежние записи сохраняются для проверки и fallback после получения различий.
*/
int member_sync_start(struct UTUN_INSTANCE* inst, uint64_t peer,
const char* ch_id, merkle_sync_done_cb done_cb, void* arg);
@@ -261,7 +261,7 @@ int member_sync_verify_and_purge(struct UTUN_INSTANCE* inst, const char* ch_id)
* ранее завершённые каналы сохраняют результат. Не держит SQLite cursor через callbacks. */
int member_sync_verify_and_purge_all(struct UTUN_INSTANCE* inst);
/* COUNT(*) всех строк, включая placeholders/deleted; неверный аргумент/ошибка SQL дают 0. */
/* Число опубликованных строк, включая placeholders/deleted; неверный аргумент/ошибка SQL дают 0. */
int member_sync_count(struct UTUN_INSTANCE* inst, const char* ch_id);
/*
+4 -3
View File
@@ -287,11 +287,12 @@ static void test_purge_start(struct UASYNC* ua) {
struct conn_queue_entry* entry = (struct conn_queue_entry*)e->data; entry->peer_node_id = peer; entry->conn = &f.conn;
assert(queue_data_put_with_index(f.inst.connections, e) == 0);
int callbacks = 0;
exec_fault = "COMMIT";
f.conn.crypto_ctx.peer_public_key[0] ^= 1;
assert(member_sync_start(&f.inst, peer, "1001", purge_done, &callbacks) < 0);
reset_faults();
f.conn.crypto_ctx.peer_public_key[0] ^= 1;
assert(!f.conn.ref_count && !callbacks && member_sync_count(&f.inst, "1001") == 2);
assert(member_sync_start(&f.inst, peer, "1001", purge_done, &callbacks) == 0 && f.conn.ref_count == 1);
assert(member_sync_count(&f.inst, "1001") == 2); /* Проверка прежних версий выполняется после приёма, а не при start. */
merkle_sync_cancel_peer(&f.inst, peer);
assert(!f.conn.ref_count && !callbacks && !f.conn.send_input_q->waiter_head);
e = queue_data_get(f.inst.connections); assert(e); queue_entry_free(e);
@@ -299,7 +300,7 @@ static void test_purge_start(struct UASYNC* ua) {
queue_free(f.conn.send_input_q);
f.inst.topo_groups = NULL; queue_entry_free(queue_data_get(groups.group_list)); queue_free(groups.group_list);
purge_destroy(&f);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS purge: failed start creates no request/callback; retry attaches real session; cancel releases ownership");
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS start: wrong peer key denied; accepted start preserves old versions; cancel releases ownership");
}
/* Настоящие неверные подписи удаляются; короткий BLOB никогда не читается как полный ключ. */