Store admin keys atomically and reject invalid transfer context

This commit is contained in:
evgeny committed 2026-10-26 20:44:42 +01:00
1 parent e65ceeafdc
commit 76527de44f
2 files changed
+62 -14

No files matched your search

+42 -9
View File
@@ -953,18 +953,51 @@ int topo_node_sqlite_channel_get_privs(sqlite3* db, const char* channel_id,
return 0;
}
/* Импорт пары: savepoint охватывает UPDATE и его завершение, внешний commit остаётся вызывающему. */
int topo_node_sqlite_channel_set_privs(sqlite3* db, const char* channel_id,
const uint8_t* x25519_priv, const uint8_t* ed25519_priv) {
if (!db || !channel_id || !x25519_priv || !ed25519_priv) return -1;
if (!db || !channel_id || !channel_id[0] || !x25519_priv || !ed25519_priv) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "channel private keys: invalid arguments"); return -1;
}
int own = sqlite3_get_autocommit(db);
int rc = sqlite3_exec(db, "SAVEPOINT channel_private_keys", NULL, NULL, NULL);
if (rc != SQLITE_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "channel private keys: channel=%s stage=savepoint rc=%d: %s",
channel_id, rc, sqlite3_errmsg(db)); return -1;
}
sqlite3_stmt* stmt = NULL;
if (sqlite3_prepare_v2(db,
"UPDATE channels SET x25519_privkey=?, ed25519_privkey=? WHERE channel_id=?", -1, &stmt, NULL) != SQLITE_OK) return -1;
sqlite3_bind_blob(stmt, 1, x25519_priv, 32, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 2, ed25519_priv, 32, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, channel_id, -1, SQLITE_STATIC);
int rc = sqlite3_step(stmt) == SQLITE_DONE ? 0 : -1;
sqlite3_finalize(stmt);
return rc;
const char* stage = "prepare";
rc = sqlite3_prepare_v2(db, "UPDATE channels SET x25519_privkey=?, ed25519_privkey=? WHERE channel_id=?", -1, &stmt, NULL);
if (rc != SQLITE_OK) goto fail;
stage = "bind x25519"; rc = sqlite3_bind_blob(stmt, 1, x25519_priv, 32, SQLITE_STATIC);
if (rc != SQLITE_OK) goto fail;
stage = "bind ed25519"; rc = sqlite3_bind_blob(stmt, 2, ed25519_priv, 32, SQLITE_STATIC);
if (rc != SQLITE_OK) goto fail;
stage = "bind channel"; rc = sqlite3_bind_text(stmt, 3, channel_id, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) goto fail;
stage = "update"; rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) goto fail;
int changed = sqlite3_changes(db);
stage = "finalize"; rc = sqlite3_finalize(stmt); stmt = NULL;
if (rc != SQLITE_OK) goto fail;
if (changed != 1) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "channel private keys: channel=%s changed=%d expected=1", channel_id, changed);
stage = "row count"; rc = SQLITE_NOTFOUND; goto fail;
}
stage = "release"; rc = sqlite3_exec(db, "RELEASE channel_private_keys", NULL, NULL, NULL);
if (rc != SQLITE_OK) goto fail;
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "channel private keys stored: channel=%s committed=%d", channel_id, own);
return 0;
fail:
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "channel private keys: channel=%s stage=%s rc=%d: %s",
channel_id, stage, rc, sqlite3_errmsg(db));
int final_rc = sqlite3_finalize(stmt);
if (final_rc != SQLITE_OK) DEBUG_ERROR(DEBUG_CATEGORY_BGP,
"channel private keys: cleanup finalize channel=%s rc=%d: %s", channel_id, final_rc, sqlite3_errmsg(db));
if (!sqlite3_get_autocommit(db) &&
sqlite3_exec(db, "ROLLBACK TO channel_private_keys; RELEASE channel_private_keys", NULL, NULL, NULL) != SQLITE_OK)
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "channel private keys: rollback failed channel=%s: %s", channel_id, sqlite3_errmsg(db));
return -1;
}
int topo_node_sqlite_node_set_online(sqlite3* db, uint64_t node_id, int online) {