Support 8 KiB member owner tags without signature or serialization truncation

This commit is contained in:
evgeny committed 2026-09-27 17:12:13 +03:00
1 parent de714f5023
commit 7374d1648c
13 files changed
+297 -169

No files matched your search

+6 -65
View File
@@ -588,7 +588,12 @@ int topo_node_sqlite_member_owner_put(sqlite3* db, const char* channel_id, uint6
sqlite3_bind_int(u, 3, storage);
sqlite3_bind_int(u, 4, adm_tags_deleted(adm_tags));
sqlite3_bind_int64(u, 5, (sqlite3_int64)node_id);
sqlite3_step(u); sqlite3_finalize(u);
int rc = sqlite3_step(u); sqlite3_finalize(u);
if (rc != SQLITE_DONE) {
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "member_owner_put: ch=%s node=%016llx rc=%d: %s",
channel_id, (unsigned long long)node_id, rc, sqlite3_errmsg(db));
return -1;
}
return 0;
}
@@ -751,70 +756,6 @@ int topo_node_sqlite_channel_set_privs(sqlite3* db, const char* channel_id,
return rc;
}
int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id,
uint8_t* buf, size_t buf_sz, size_t* out_len) {
if (!db || !channel_id || !buf || !out_len) return -1;
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl));
sqlite3_stmt* stmt = NULL;
char sql[512];
snprintf(sql, sizeof(sql),
"SELECT node_id, x25519_pubkey, ed25519_pubkey,"
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig"
" FROM \"%s\" ORDER BY node_id ASC", peers_tbl);
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) return -1;
size_t off = 0;
if (off + 2 > buf_sz) { sqlite3_finalize(stmt); return -2; }
uint16_t* cnt_ptr = (uint16_t*)(buf + off); off += 2;
*cnt_ptr = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) {
uint64_t node_id = (uint64_t)sqlite3_column_int64(stmt, 0);
const uint8_t* x25519 = (const uint8_t*)sqlite3_column_blob(stmt, 1);
const uint8_t* ed_pub = (const uint8_t*)sqlite3_column_blob(stmt, 2);
const uint8_t* join_sig = (const uint8_t*)sqlite3_column_blob(stmt, 3);
uint64_t join_ts = (uint64_t)sqlite3_column_int64(stmt, 4);
const uint8_t* update_sig = (const uint8_t*)sqlite3_column_blob(stmt, 5);
uint64_t update_ts = (uint64_t)sqlite3_column_int64(stmt, 6);
const char* puserinfo = (const char*)sqlite3_column_text(stmt, 7);
const char* adm_tags_s = (const char*)sqlite3_column_text(stmt, 8);
const uint8_t* adm_tags_sig_b = (const uint8_t*)sqlite3_column_blob(stmt, 9);
if (!x25519 || !ed_pub) continue;
uint8_t nl = puserinfo ? (uint8_t)strnlen(puserinfo, 255) : 0;
uint8_t atl = adm_tags_s ? (uint8_t)strnlen(adm_tags_s, 255) : 0;
uint8_t flags = (join_sig && join_ts) ? PEERS_FLAG_HAS_JOIN : 0;
size_t peer_needed = 8 + 32 + 32 + 1 + (flags & PEERS_FLAG_HAS_JOIN ? 64+8 : 0) + 64 + 8 + 1 + (size_t)nl + 1 + (size_t)atl + 64;
if (off + peer_needed > buf_sz) { sqlite3_finalize(stmt); return -2; }
memcpy(buf + off, &node_id, 8); off += 8;
memcpy(buf + off, x25519, 32); off += 32;
memcpy(buf + off, ed_pub, 32); off += 32;
buf[off++] = flags;
if (flags & PEERS_FLAG_HAS_JOIN) {
memcpy(buf + off, join_sig, 64); off += 64;
memcpy(buf + off, &join_ts, 8); off += 8;
}
if (update_sig && update_ts) {
memcpy(buf + off, update_sig, 64); off += 64;
memcpy(buf + off, &update_ts, 8); off += 8;
} else {
memset(buf + off, 0, 64); off += 64;
uint64_t z = 0; memcpy(buf + off, &z, 8); off += 8;
}
buf[off++] = nl;
if (nl) { memcpy(buf + off, puserinfo, nl); off += nl; }
buf[off++] = atl;
if (atl) { memcpy(buf + off, adm_tags_s, atl); off += atl; }
if (adm_tags_sig_b && sqlite3_column_bytes(stmt, 9) >= 64) { memcpy(buf + off, adm_tags_sig_b, 64); off += 64; }
else { memset(buf + off, 0, 64); off += 64; }
(*cnt_ptr)++;
}
sqlite3_finalize(stmt);
*out_len = off;
return 0;
}
int topo_node_sqlite_node_set_online(sqlite3* db, uint64_t node_id, int online) {
if (!db) return -1;
sqlite3_stmt* stmt = NULL;
-3
View File
@@ -83,9 +83,6 @@ int topo_node_sqlite_channel_get_privs(sqlite3* db, const char* channel_id,
int topo_node_sqlite_channel_set_privs(sqlite3* db, const char* channel_id,
const uint8_t* x25519_priv, const uint8_t* ed25519_priv);
int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id,
uint8_t* buf, size_t buf_sz, size_t* out_len);
int topo_node_sqlite_node_set_online(sqlite3* db, uint64_t node_id, int online);
int topo_node_sqlite_node_get_online(sqlite3* db, uint64_t node_id);
int topo_node_sqlite_get_ed25519_pubkey(sqlite3* db, uint64_t node_id, uint8_t pubkey_out[32]);
+2 -3
View File
@@ -11,11 +11,11 @@
3. Сохранять/обновлять ноды через `topo_node_sqlite_node_put()`
4. Сохранять каналы через `topo_node_sqlite_channel_put()` (автоматически создаёт таблицу `peers_<channel_id>`)
5. Добавлять участников в канал через `topo_node_sqlite_member_put()`
6. Читать участников канала через `topo_node_sqlite_channel_peers_all()` — возвращает бинарный буфер со всеми участниками (node_id, ключи, подписи, адреса)
6. Читать участников из `peers_<channel_id>`; постраничная сетевая сериализация принадлежит `member_sync`.
**Нюансы:**
- Имена таблиц `peers_<channel_id>` санитизируются: все символы кроме `[a-zA-Z0-9_]` заменяются на `_`
- `topo_node_sqlite_channel_peers_all()` формирует компактный бинарный буфер с числом записей в начале (uint16_t)
- Сетевой формат участников описан в `src/chat/member_sync_doc.md`; SQLite-слой не дублирует сериализатор.
- Ключи в BLOB-полях всегда 32 байта (x25519/ed25519), подписи — 64 байта
- Функции `online` и `get_ed25519_pubkey` — простые SELECT-запросы без JOIN
@@ -31,7 +31,6 @@
| `topo_node_sqlite_member_del(db, ch_id, node_id)` | Удаляет участника из `peers_<ch_id>` |
| `topo_node_sqlite_node_update_verified(...)` | Обновляет ключи и имя ноды по условию `update_ts < новое_значение` (защита от stale-данных) |
| `topo_node_sqlite_channel_get(...)` | Читает метаданные канала (имя, владелец, ключи, подпись) |
| `topo_node_sqlite_channel_peers_all(...)` | Сериализует всех участников канала в бинарный буфер (count + [node_id\|x25519\|ed25519\|flags\|sigs\|name\|addrs]) |
| `topo_node_sqlite_node_set_online(db, id, online)` | Устанавливает флаг `online` для ноды |
| `topo_node_sqlite_node_get_online(db, id)` | Возвращает 1 если нода online |
| `topo_node_sqlite_get_ed25519_pubkey(db, id, out)` | Извлекает ed25519-публичный ключ ноды (32 байта) |