From f1da7d7ee85fd7a3fb5a3f27ec0a578fac16c6cd Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 21:42:40 +0100 Subject: [PATCH] Align desktop history reads with Merkle schema and fix PM test setup --- tools/chatgui/db/db_manager.cpp | 51 ++++-------------------- tools/chatgui/db/db_manager.h | 5 --- tools/chatgui/tests/test_dm_deletion.cpp | 11 ++++- 3 files changed, 17 insertions(+), 50 deletions(-) diff --git a/tools/chatgui/db/db_manager.cpp b/tools/chatgui/db/db_manager.cpp index f41d503a..85833165 100644 --- a/tools/chatgui/db/db_manager.cpp +++ b/tools/chatgui/db/db_manager.cpp @@ -41,30 +41,6 @@ uint64_t DbManager::computeDatahash(const QByteArray& data) { uint64_t dh; memcpy(&dh, hash, 8); return dh; } -QByteArray DbManager::computeChainHash(const QByteArray& prevChain, - qint64 timestamp, uint64_t datahash) { - uint8_t buf[32 + 8 + 8]; - memcpy(buf, prevChain.constData(), 32); - memcpy(buf + 32, ×tamp, 8); - memcpy(buf + 40, &datahash, 8); - uint8_t hash[32]; - SHA256(buf, 48, hash); - return QByteArray((const char*)hash, 32); -} - -QByteArray DbManager::getLastChainHash(const QString& chId) const { - QString tbl = msgTableName(chId); - QByteArray sql = QStringLiteral( - "SELECT chain_hash FROM \"%1\" ORDER BY timestamp, author_signature DESC LIMIT 1") - .arg(tbl).toUtf8(); - sqlite3_stmt* stmt = prepareOrNull(sql.constData()); - if (!stmt) return QByteArray(32, '\0'); - QByteArray r = (sqlite3_step(stmt) == SQLITE_ROW) ? colBlob(stmt, 0) - : QByteArray(32, '\0'); - sqlite3_finalize(stmt); - return r.size() == 32 ? r : QByteArray(32, '\0'); -} - /* ── lifecycle ── */ DbManager::DbManager(QObject* parent) @@ -247,9 +223,9 @@ static MessageRow readMessage(sqlite3_stmt* stmt, quint64 myId) { GUI_WARN("reply: malformed reference message_row=%lld", (long long)m.id); m.replyTo.clear(); } } - m.timestamp = sqlite3_column_int64(stmt, 3); m.chainHash = DbManager::colBlob(stmt, 4); - m.signature = DbManager::colBlob(stmt, 5); m.localAttrs = DbManager::colBlob(stmt, 6); - m.messageId = DbManager::colBlob(stmt, 7); m.isOutgoing = m.authorNodeId == myId; m.isRead = true; + m.timestamp = sqlite3_column_int64(stmt, 3); m.signature = DbManager::colBlob(stmt, 4); + m.localAttrs = DbManager::colBlob(stmt, 5); m.messageId = DbManager::colBlob(stmt, 6); + m.isOutgoing = m.authorNodeId == myId; m.isRead = true; return m; } @@ -260,7 +236,7 @@ QList DbManager::getMessages(const QString& chId, int limit, const Q GUI_ERROR("history: invalid anchor/window bytes=%d limit=%d", int(around.size()), limit); return list; } QString sql = QStringLiteral( - "SELECT id, node_id, data, timestamp, chain_hash, author_signature, local_attrs, message_id" + "SELECT id, node_id, data, timestamp, author_signature, local_attrs, message_id" " FROM \"%1\" ORDER BY timestamp DESC, author_signature DESC LIMIT ?1").arg(msgTableName(chId)); if (!around.isEmpty()) sql += QStringLiteral( " OFFSET min(max(0,(SELECT count(*) FROM \"%1\" n JOIN \"%1\" a ON a.message_id=?2 " @@ -287,7 +263,7 @@ QList DbManager::getMessages(const QString& chId, int limit, const Q QList DbManager::getMessagesSince(const QString& chId, qint64 sinceId) const { QList list; QString sql = QStringLiteral( - "SELECT id, node_id, data, timestamp, chain_hash, author_signature, local_attrs, message_id" + "SELECT id, node_id, data, timestamp, author_signature, local_attrs, message_id" " FROM \"%1\" WHERE id > ? ORDER BY id ASC").arg(msgTableName(chId)); sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData()); if (!stmt) return list; @@ -303,7 +279,7 @@ QList DbManager::getMessagesSince(const QString& chId, qint64 sinceI MessageRow DbManager::getMessageById(const QString& chId, qint64 msgId) const { MessageRow m; QString sql = QStringLiteral( - "SELECT id, node_id, data, timestamp, chain_hash, author_signature, local_attrs, message_id" + "SELECT id, node_id, data, timestamp, author_signature, local_attrs, message_id" " FROM \"%1\" WHERE id = ?").arg(msgTableName(chId)); sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData()); if (!stmt) return m; @@ -321,7 +297,7 @@ MessageRow DbManager::getMessageById(const QString& chId, qint64 msgId) const { MessageRow DbManager::getMessageByKey(const QString& chId, const QByteArray& key) const { MessageRow message; if (key.size() != 32) { GUI_ERROR("reply: invalid lookup key bytes=%d", int(key.size())); return message; } - const auto sql = QStringLiteral("SELECT id,node_id,data,timestamp,chain_hash,author_signature,local_attrs,message_id " + const auto sql = QStringLiteral("SELECT id,node_id,data,timestamp,author_signature,local_attrs,message_id " "FROM \"%1\" WHERE message_id=?").arg(msgTableName(chId)).toUtf8(); sqlite3_stmt* stmt = prepareOrNull(sql.constData()); if (!stmt) return message; @@ -625,19 +601,6 @@ QByteArray DbManager::syncCount(const QString& chId) const { QByteArray out; out.append((const char*)&cnt, 4); return out; } -QByteArray DbManager::syncChainHashAt(const QString& chId, uint32_t pos) const { - QString sql = QStringLiteral( - "SELECT chain_hash FROM \"%1\" ORDER BY timestamp, author_signature ASC LIMIT 1 OFFSET ?") - .arg(msgTableName(chId)); - sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData()); - if (!stmt) return QByteArray(32, '\0'); - sqlite3_bind_int64(stmt, 1, pos); - QByteArray r; - if (sqlite3_step(stmt) == SQLITE_ROW) r = colBlob(stmt, 0); - sqlite3_finalize(stmt); - return r.size() == 32 ? r : QByteArray(32, '\0'); -} - QByteArray DbManager::syncCursorOpen(const QString& chId) { QString sql = QStringLiteral( "SELECT timestamp, node_id, data, author_signature" diff --git a/tools/chatgui/db/db_manager.h b/tools/chatgui/db/db_manager.h index b4667920..e2e4824a 100644 --- a/tools/chatgui/db/db_manager.h +++ b/tools/chatgui/db/db_manager.h @@ -40,7 +40,6 @@ struct MessageRow { QByteArray data; qint64 timestamp = 0; uint64_t datahash = 0; - QByteArray chainHash; QByteArray signature; QByteArray messageId; // общий ID подписанного сообщения, 32 байта QByteArray replyTo; // общий ID оригинала в этом канале, либо пусто @@ -140,7 +139,6 @@ public: /* ── Sync-операции (read-only, для gui_bridge/inline) ── */ QByteArray syncListChannels() const; QByteArray syncCount(const QString& chId) const; - QByteArray syncChainHashAt(const QString& chId, uint32_t pos) const; QByteArray syncCursorOpen(const QString& chId); QByteArray syncCursorNext(uint32_t cursorId); void syncCursorClose(uint32_t cursorId); @@ -155,9 +153,6 @@ public: QString peersTableName(const QString& chId) const; static QString sanitizeTableName(const QString& chId); static uint64_t computeDatahash(const QByteArray& data); - static QByteArray computeChainHash(const QByteArray& prevChain, - qint64 timestamp, uint64_t datahash); - QByteArray getLastChainHash(const QString& chId) const; IntegrityResult integrityCheckQuick() const; IntegrityResult integrityCheckFull() const; diff --git a/tools/chatgui/tests/test_dm_deletion.cpp b/tools/chatgui/tests/test_dm_deletion.cpp index 7a3fab14..29d3bb28 100644 --- a/tools/chatgui/tests/test_dm_deletion.cpp +++ b/tools/chatgui/tests/test_dm_deletion.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include extern "C" { @@ -63,9 +64,17 @@ private slots: void deleteThroughWindowAndCore() { QTemporaryDir directory; QVERIFY(directory.isValid()); + directory.setAutoRemove(false); + auto diagnostics = qScopeGuard([&directory] { + directory.setAutoRemove(!QTest::currentTestFailed()); + if (QTest::currentTestFailed()) DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "DM test diagnostics retained: %s", qPrintable(directory.path())); + }); const QString configPath = directory.filePath("node.cfg"); QFile config(configPath); QVERIFY(config.open(QIODevice::WriteOnly)); - const QByteArray text = "[global]\ntun_enabled=no\n[server:local]\naddr=127.0.0.1:0\ntype=private\n" + const QByteArray text = "[global]\n" + "my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\n" + "my_public_key=b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01\n" + "tun_enabled=no\n[server:local]\naddr=127.0.0.1:0\ntype=private\n" "[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\nlocal_invites_enabled=0\nlocal_broadcasts_enabled=0\n" "[ntp]\nenabled=no\n"; QCOMPARE(config.write(text), text.size()); config.close();