From e2d98796366a51166e2fb3368ad0b5465a5ba7c6 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 22 Jul 2026 13:38:17 +0300 Subject: [PATCH] refactor: remove direct nodes table writes from chat_core/conn_mgr, use topo_node_sqlite API - chat_core_init: replace INSERT INTO nodes with topo_node_sqlite_node_update_verified, remove redundant topo_node_sqlite_init call - chat_core_update_my_name: replace UPDATE nodes with topo_node_sqlite_node_update_verified - chat_conn_mgr_connect_from_invite: simplify invite node insert (x25519 only, no ed25519) - topo_node_sqlite: add detailed column comments to peers table DDL (both server and chatgui) - chat_core: add detailed column comments to peers table CREATE TABLE --- src/routing_layer/topo_node_sqlite.c | 33 ++++++++------- tools/chatgui/transport/chat_conn_mgr.c | 14 ++++--- tools/chatgui/transport/chat_core.c | 56 ++++++++++--------------- 3 files changed, 49 insertions(+), 54 deletions(-) diff --git a/src/routing_layer/topo_node_sqlite.c b/src/routing_layer/topo_node_sqlite.c index 32766311..f430dbdd 100644 --- a/src/routing_layer/topo_node_sqlite.c +++ b/src/routing_layer/topo_node_sqlite.c @@ -254,20 +254,25 @@ int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id, const char* ddl_tmpl = "CREATE TABLE IF NOT EXISTS \"%s\" (" - " id INTEGER PRIMARY KEY AUTOINCREMENT," - " node_id INTEGER NOT NULL UNIQUE," - " x25519_pubkey BLOB NOT NULL," - " ed25519_pubkey BLOB NOT NULL," - " join_sig BLOB NOT NULL," - " join_ts INTEGER NOT NULL," - " update_sig BLOB," - " update_ts INTEGER DEFAULT 0," - " userinfo TEXT NOT NULL DEFAULT ''," - " creator_sig BLOB," - " adm_tags TEXT," - " adm_tags_sig BLOB," - " node_type INTEGER NOT NULL DEFAULT 0," - " node_RTT INTEGER" + " id INTEGER PRIMARY KEY AUTOINCREMENT," /* суррогатный ключ */ + " node_id INTEGER NOT NULL UNIQUE," /* уникальный ID узла (64-bit) */ + " x25519_pubkey BLOB NOT NULL," /* X25519 публичный ключ (32 байта) */ + " ed25519_pubkey BLOB NOT NULL," /* Ed25519 публичный ключ (32 байта) — верификация join_sig/update_sig */ + " join_sig BLOB NOT NULL," /* Ed25519 подпись присоединения (PEERS_JOIN_SIG_SIZE=64). + signed: ch_x25519(32)||ch_ed25519(32)||node_id(8 LE)||x25519(32)||join_ts(8 LE) */ + " join_ts INTEGER NOT NULL," /* NTP timestamp подписи join_sig — защита от replay */ + " update_sig BLOB," /* Ed25519 подпись обновления userinfo (PEERS_UPDATE_SIG_SIZE=64). + signed: join_sig(64)||update_ts(8 LE)||userinfo(NUL-terminated) */ + " update_ts INTEGER DEFAULT 0," /* NTP timestamp подписи update_sig */ + " userinfo TEXT NOT NULL DEFAULT ''," /* JSON с информацией о пользователе: {"name":""} */ + " creator_sig BLOB," /* Ed25519 подпись создателя (PEERS_JOIN_SIG_SIZE=64), пока заглушка */ + " adm_tags TEXT," /* теги администратора, key=value через пробел/запятую. + сейчас: "supernode=yes" → node_type=4 */ + " adm_tags_sig BLOB," /* Ed25519 подпись над adm_tags (64 байта) — верификация пока не реализована */ + " node_type INTEGER NOT NULL DEFAULT 0," /* вычисляемый тип узла (topo_node_sqlite_nodeinfo_updated): + 0=неизвестно 1=прямой(addr_type NETIF/DIRECT/NAT_STRICT) + 2=EIM NAT 3=(не исп.) 4=суперузел(DIRECT+"supernode=yes") */ + " node_RTT INTEGER" /* RTT до узла в мс, часть индекса (node_type, node_RTT) */ ")"; int ddl_sz = snprintf(NULL, 0, ddl_tmpl, peers_tbl); diff --git a/tools/chatgui/transport/chat_conn_mgr.c b/tools/chatgui/transport/chat_conn_mgr.c index 0cbc3533..a4e189f9 100644 --- a/tools/chatgui/transport/chat_conn_mgr.c +++ b/tools/chatgui/transport/chat_conn_mgr.c @@ -596,12 +596,14 @@ void chat_conn_mgr_connect_from_invite(struct chat_conn_mgr* mgr, struct chat_in if (!mgr || !inv) return; uint64_t node_id = inv->node_id; - /* save pubkey */ - sqlite3_stmt* st = NULL; - if (sqlite3_prepare_v2(mgr->db, "INSERT INTO nodes(node_id,x25519_pubkey,created_at) VALUES(?,?,?)" - " ON CONFLICT(node_id) DO UPDATE SET x25519_pubkey=excluded.x25519_pubkey," - " created_at=COALESCE(nodes.created_at, excluded.created_at)", - -1, &st, NULL) == SQLITE_OK) { + /* save pubkey — minimal node record, ed25519/name придут позже через протокол */ + { + sqlite3_stmt* st = NULL; + sqlite3_prepare_v2(mgr->db, + "INSERT INTO nodes(node_id,x25519_pubkey,created_at) VALUES(?,?,?)" + " ON CONFLICT(node_id) DO UPDATE SET x25519_pubkey=excluded.x25519_pubkey," + " created_at=COALESCE(nodes.created_at, excluded.created_at)", + -1, &st, NULL); sqlite3_bind_int64(st, 1, (sqlite3_int64)node_id); sqlite3_bind_blob(st, 2, inv->pubkey, 32, SQLITE_STATIC); sqlite3_bind_int64(st, 3, (sqlite3_int64)ntp_time_get_seconds(mgr->inst)); diff --git a/tools/chatgui/transport/chat_core.c b/tools/chatgui/transport/chat_core.c index efd52a5d..5efd5d13 100644 --- a/tools/chatgui/transport/chat_core.c +++ b/tools/chatgui/transport/chat_core.c @@ -114,24 +114,13 @@ int chat_core_init(struct UTUN_INSTANCE* inst, const char* db_path) { g_cc.my_node_id = inst->node_id; sqlite3_int64 now_sec = (sqlite3_int64)ntp_time_get_seconds(inst); - topo_node_sqlite_init(g_cc.db); - - /* записать себя в nodes + local_identity с реальным node_id и именем */ + /* записать себя в nodes + local_identity */ { const char* my_name = inst->name[0] ? inst->name : "Me"; + topo_node_sqlite_node_update_verified(g_cc.db, g_cc.my_node_id, + my_name, inst->my_keys.public_key, inst->my_ed25519_pubkey, + (uint64_t)now_sec, (time_t)now_sec); sqlite3_stmt* st = NULL; - sqlite3_prepare_v2(g_cc.db, - "INSERT OR REPLACE INTO nodes(node_id, name, x25519_pubkey, ed25519_pubkey, created_at, online)" - " VALUES(?,?,?,?,?,1)", -1, &st, NULL); - if (st) { - sqlite3_bind_int64(st, 1, (sqlite3_int64)g_cc.my_node_id); - sqlite3_bind_text(st, 2, my_name, -1, SQLITE_STATIC); - sqlite3_bind_blob(st, 3, inst->my_keys.public_key, 32, SQLITE_STATIC); - sqlite3_bind_blob(st, 4, inst->my_ed25519_pubkey, 32, SQLITE_STATIC); - sqlite3_bind_int64(st, 5, now_sec); - sqlite3_step(st); sqlite3_finalize(st); - } - st = NULL; sqlite3_prepare_v2(g_cc.db, "INSERT OR REPLACE INTO local_identity(id,node_id,name,x25519_pubkey,ed25519_pubkey,created_at,updated_at)" " VALUES(1,?,?,?,?,?,?)", -1, &st, NULL); @@ -268,14 +257,9 @@ void chat_core_set_my_node_id(uint64_t node_id) { void chat_core_update_my_name(const char* name) { if (!g_cc.initialized || !name) return; - sqlite3_stmt* st = NULL; - sqlite3_prepare_v2(g_cc.db, "UPDATE nodes SET name=? WHERE node_id=?", -1, &st, NULL); - if (st) { - sqlite3_bind_text(st, 1, name, -1, SQLITE_STATIC); - sqlite3_bind_int64(st, 2, (sqlite3_int64)g_cc.my_node_id); - sqlite3_step(st); sqlite3_finalize(st); - } - /* update instance name for NODEINFO */ + topo_node_sqlite_node_update_verified(g_cc.db, g_cc.my_node_id, + name, g_cc.inst->my_keys.public_key, g_cc.inst->my_ed25519_pubkey, + (uint64_t)ntp_time_get_seconds(g_cc.inst), 0); snprintf(g_cc.inst->name, sizeof(g_cc.inst->name), "%s", name); /* recompute join_sigs for all channels where I'm a member */ @@ -660,17 +644,21 @@ void chat_core_ensure_channel_ready(const char* ch_id) { char sql[512]; snprintf(sql, sizeof(sql), "CREATE TABLE IF NOT EXISTS \"%s\" (" - " node_id INTEGER PRIMARY KEY," - " x25519_pubkey BLOB NOT NULL," - " ed25519_pubkey BLOB," - " join_sig BLOB," - " join_ts INTEGER DEFAULT 0," - " update_sig BLOB," - " update_ts INTEGER DEFAULT 0," - " userinfo TEXT NOT NULL DEFAULT ''," - " creator_sig BLOB," - " comment TEXT," - " joined_at INTEGER DEFAULT (unixepoch())" + " node_id INTEGER PRIMARY KEY," /* уникальный ID узла (64-bit) */ + " x25519_pubkey BLOB NOT NULL," /* X25519 публичный ключ (32 байта) */ + " ed25519_pubkey BLOB," /* Ed25519 публичный ключ (32 байта) — верификация join_sig/update_sig */ + " join_sig BLOB," /* Ed25519 подпись присоединения (PEERS_JOIN_SIG_SIZE=64). + signed: ch_x25519(32)||ch_ed25519(32)||node_id(8 LE)||x25519(32)||join_ts(8 LE) */ + " join_ts INTEGER DEFAULT 0," /* NTP timestamp подписи join_sig — защита от replay */ + " update_sig BLOB," /* Ed25519 подпись обновления userinfo (PEERS_UPDATE_SIG_SIZE=64). + signed: join_sig(64)||update_ts(8 LE)||userinfo(NUL-terminated) */ + " update_ts INTEGER DEFAULT 0," /* NTP timestamp подписи update_sig */ + " userinfo TEXT NOT NULL DEFAULT ''," /* JSON с информацией о пользователе: {"name":""}. + извлекается через json_flat_get(userinfo, "name", ...) */ + " creator_sig BLOB," /* Ed25519 подпись создателя (PEERS_JOIN_SIG_SIZE=64). + в CHANNEL_INFO_RESP ставится join_sig инвайтера, иначе NULL (заглушка) */ + " comment TEXT," /* произвольная заметка (пока не используется в логике) */ + " joined_at INTEGER DEFAULT (unixepoch())" /* NTP timestamp добавления записи в таблицу */ ")", tbl_peers); db_exec(sql);