Browse Source

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
topo_upd
Evgeny 2 months ago
parent
commit
e2d9879636
  1. 33
      src/routing_layer/topo_node_sqlite.c
  2. 14
      tools/chatgui/transport/chat_conn_mgr.c
  3. 56
      tools/chatgui/transport/chat_core.c

33
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":"<display_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);

14
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));

56
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":"<display_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);

Loading…
Cancel
Save