Propagate all member block binding and finalization failures before index publication

This commit is contained in:
evgeny committed 2026-10-27 04:36:09 +01:00
1 parent 1ce58cbeac
commit 60942e542b
2 files changed
+38 -19

No files matched your search

+37 -19
View File
@@ -726,7 +726,9 @@ int topo_node_sqlite_member_block_put(sqlite3* db, const char* channel_id, uint6
const uint8_t* x25519_pubkey, const uint8_t* ed25519_pubkey,
const char* userinfo, const uint8_t* creator_sig,
uint64_t signed_by, const uint8_t* signature) {
if (!db || !channel_id || !x25519_pubkey || !ed25519_pubkey) return -1;
if (!db || !channel_id || !x25519_pubkey || !ed25519_pubkey) {
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "member block: invalid database/channel/key arguments"); return -1;
}
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl));
char sql[768];
snprintf(sql, sizeof(sql),
@@ -746,24 +748,40 @@ int topo_node_sqlite_member_block_put(sqlite3* db, const char* channel_id, uint6
" signature=excluded.signature,"
" source=0", peers_tbl);
sqlite3_stmt* stmt = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) return -1;
sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id);
sqlite3_bind_blob(stmt, 2, x25519_pubkey, 32, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 3, ed25519_pubkey, 32, SQLITE_STATIC);
if (join_sig) sqlite3_bind_blob(stmt, 4, join_sig, PEERS_JOIN_SIG_SIZE, SQLITE_STATIC);
else { static const unsigned char zsig[PEERS_JOIN_SIG_SIZE] = {0}; sqlite3_bind_blob(stmt, 4, zsig, PEERS_JOIN_SIG_SIZE, SQLITE_STATIC); }
sqlite3_bind_int64(stmt, 5, (sqlite3_int64)join_ts);
if (update_sig) sqlite3_bind_blob(stmt, 6, update_sig, PEERS_UPDATE_SIG_SIZE, SQLITE_STATIC);
else sqlite3_bind_null(stmt, 6);
sqlite3_bind_int64(stmt, 7, (sqlite3_int64)update_ts);
sqlite3_bind_text(stmt, 8, userinfo ? userinfo : "", -1, SQLITE_STATIC);
if (creator_sig) sqlite3_bind_blob(stmt, 9, creator_sig, PEERS_JOIN_SIG_SIZE, SQLITE_STATIC);
else sqlite3_bind_null(stmt, 9);
sqlite3_bind_int64(stmt, 10, (sqlite3_int64)signed_by);
if (signature) sqlite3_bind_blob(stmt, 11, signature, 64, SQLITE_STATIC);
else sqlite3_bind_null(stmt, 11);
int rc = sqlite3_step(stmt); sqlite3_finalize(stmt);
return rc == SQLITE_DONE ? 0 : -1;
const char* stage = "prepare";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc == SQLITE_OK) { stage = "bind node"; rc = sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); }
if (rc == SQLITE_OK) { stage = "bind X25519"; rc = sqlite3_bind_blob(stmt, 2, x25519_pubkey, 32, SQLITE_STATIC); }
if (rc == SQLITE_OK) { stage = "bind Ed25519"; rc = sqlite3_bind_blob(stmt, 3, ed25519_pubkey, 32, SQLITE_STATIC); }
if (rc == SQLITE_OK) {
static const uint8_t zero_signature[PEERS_JOIN_SIG_SIZE] = {0}; stage = "bind JOIN signature";
rc = sqlite3_bind_blob(stmt, 4, join_sig ? join_sig : zero_signature, PEERS_JOIN_SIG_SIZE, SQLITE_STATIC);
}
if (rc == SQLITE_OK) { stage = "bind JOIN timestamp"; rc = sqlite3_bind_int64(stmt, 5, (sqlite3_int64)join_ts); }
if (rc == SQLITE_OK) {
stage = "bind profile signature";
rc = update_sig ? sqlite3_bind_blob(stmt, 6, update_sig, PEERS_UPDATE_SIG_SIZE, SQLITE_STATIC) : sqlite3_bind_null(stmt, 6);
}
if (rc == SQLITE_OK) { stage = "bind profile timestamp"; rc = sqlite3_bind_int64(stmt, 7, (sqlite3_int64)update_ts); }
if (rc == SQLITE_OK) { stage = "bind profile"; rc = sqlite3_bind_text(stmt, 8, userinfo ? userinfo : "", -1, SQLITE_STATIC); }
if (rc == SQLITE_OK) {
stage = "bind creator signature";
rc = creator_sig ? sqlite3_bind_blob(stmt, 9, creator_sig, PEERS_JOIN_SIG_SIZE, SQLITE_STATIC) : sqlite3_bind_null(stmt, 9);
}
if (rc == SQLITE_OK) { stage = "bind inviter"; rc = sqlite3_bind_int64(stmt, 10, (sqlite3_int64)signed_by); }
if (rc == SQLITE_OK) {
stage = "bind invitation signature";
rc = signature ? sqlite3_bind_blob(stmt, 11, signature, 64, SQLITE_STATIC) : sqlite3_bind_null(stmt, 11);
}
if (rc == SQLITE_OK) { stage = "write"; rc = sqlite3_step(stmt); }
int changed = rc == SQLITE_DONE ? sqlite3_changes(db) : 0;
if (rc != SQLITE_DONE || changed != 1) DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC,
"member block: channel=%s node=%016llx stage=%s rc=%d (%s) changed=%d db=%s",
channel_id, (unsigned long long)node_id, stage, rc, sqlite3_errstr(rc), changed, sqlite3_errmsg(db));
int final = sqlite3_finalize(stmt);
if (final != SQLITE_OK) DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "member block: finalize channel=%s node=%016llx rc=%d",
channel_id, (unsigned long long)node_id, final);
return rc == SQLITE_DONE && changed == 1 && final == SQLITE_OK ? 0 : -1;
}
/* Обновляет только блок владельца (adm_tags/adm_tags_sig/storage),
+1
View File
@@ -79,6 +79,7 @@ int topo_node_sqlite_member_placeholder_put(sqlite3* db, const char* channel_id,
* signed_by/signature — дерево приглашений: кто подписал pubkey узла (0 = корень, ключом группы).
* 0/-1; подписи по 64, ключи по 32 байта. NULL join_sig даёт нулевую подпись, userinfo=NULL даёт ''.
* Сбрасывает source=0; свежесть/подписи проверяет вызывающий, owner/local-поля сохраняются. */
/* Проверяет все bind,step,changes1 и finalize;при отказе caller откатывает свою транзакцию записи/индекса. */
int topo_node_sqlite_member_block_put(sqlite3* db, const char* channel_id, uint64_t node_id,
const uint8_t* join_sig, uint64_t join_ts,
const uint8_t* update_sig, uint64_t update_ts,