Skip to content
2 changes: 2 additions & 0 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,8 @@ static void handle_channeld_my_alt_addr(struct lightningd *ld, struct channel *c
return;
}

wallet_add_alt_addr(ld->wallet->db, &channel->peer->id,
(char *)my_alt_addr, true);
tal_free(my_alt_addr);
}

Expand Down
1 change: 1 addition & 0 deletions lightningd/connect_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ static void handle_peer_alt_addr(struct lightningd *ld, const u8 *msg)
return;
}

wallet_add_alt_addr(ld->wallet->db, &p_id, (char *)p_alt_addr, false);
tal_free(p_alt_addr);
}

Expand Down
2 changes: 2 additions & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,8 @@ static struct migration dbmigrations[] = {
{SQL("ALTER TABLE channels ADD remote_htlc_minimum_msat BIGINT DEFAULT NULL;"), NULL},
{SQL("ALTER TABLE channels ADD last_stable_connection BIGINT DEFAULT 0;"), NULL},
{NULL, migrate_initialize_alias_local},
{SQL("ALTER TABLE peers ADD COLUMN peer_alt_addr TEXT DEFAULT '';"), NULL},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be an array of wireaddr, not a text field.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me

{SQL("ALTER TABLE peers ADD COLUMN my_alt_addr TEXT DEFAULT '';"), NULL},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this is in the db?

Copy link
Collaborator Author

@maxrantil maxrantil Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might give different alt_addrs to different peers, so you want to confirm, when they connect to you, that you have given that peer the alt_addr it is trying to connect to.

And ofcourse the db is read on node restart, that's why its there.

};

/**
Expand Down
122 changes: 122 additions & 0 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,128 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
return peer;
}

void wallet_add_alt_addr(struct db *db,
const struct node_id *node_id,
const char *alt_addr,
bool is_my_alt_addr)
{
struct db_stmt *stmt;

if (is_my_alt_addr)
stmt = db_prepare_v2(db, SQL("UPDATE peers"
" SET my_alt_addr=?"
" WHERE node_id = ?;"));
else
stmt = db_prepare_v2(db, SQL("UPDATE peers"
" SET peer_alt_addr=?"
" WHERE node_id = ?;"));

db_bind_text(stmt, alt_addr);
db_bind_node_id(stmt, node_id);
db_exec_prepared_v2(take(stmt));
}

static struct wireaddr_internal *handle_alt_addr_failure(struct wallet *w,
struct db_stmt *stmt,
bool transaction_started)
{
if (stmt)
tal_free(stmt);

if (transaction_started)
db_commit_transaction(w->db);

return NULL;
}

struct wireaddr_internal *wallet_get_alt_addr(struct wallet *w,
const struct node_id *node_id,
bool use_my_alt_addr)
{
struct db_stmt *stmt;
struct wireaddr_internal *alt_addrs;
bool transaction_started = false;
const char *addr_column = use_my_alt_addr
? "my_alt_addr"
: "peer_alt_addr";

if (!db_in_transaction(w->db)) {
db_begin_transaction(w->db);
transaction_started = true;
}

if (use_my_alt_addr)
stmt = db_prepare_v2(w->db, SQL("SELECT my_alt_addr"
" FROM peers"
" WHERE node_id = ?;"));
else
stmt = db_prepare_v2(w->db, SQL("SELECT peer_alt_addr"
" FROM peers"
" WHERE node_id = ?;"));

if (!stmt) {
log_debug(w->log, "Failed to prepare statement for node_id %s",
fmt_node_id(tmpctx, node_id));
return handle_alt_addr_failure(w, stmt, transaction_started);
}

db_bind_node_id(stmt, node_id);
db_query_prepared(stmt);

if (!db_step(stmt)) {
log_debug(w->log,
"No alternative address found for peer %s",
fmt_node_id(tmpctx, node_id));
return handle_alt_addr_failure(w, stmt, transaction_started);
}

const char *addr_str = db_col_strdup(tmpctx, stmt, addr_column);
if (!addr_str) {
log_debug(w->log,
"Invalid address string retrieved for peer %s",
fmt_node_id(tmpctx, node_id));
return handle_alt_addr_failure(w, stmt, transaction_started);
}

if (*addr_str == '\0') {
log_debug(w->log,
"Empty address string retrieved for peer %s",
fmt_node_id(tmpctx, node_id));
return handle_alt_addr_failure(w, stmt, transaction_started);
}

alt_addrs = tal_arr(tmpctx, struct wireaddr_internal, 0);
char **addr_list = tal_strsplit(tmpctx, addr_str, ",", STR_NO_EMPTY);
for (size_t i = 0; addr_list[i] != NULL; i++) {
struct wireaddr_internal *alt_addr = tal(tmpctx,
struct wireaddr_internal);
const char *err = parse_wireaddr_internal(tmpctx,
addr_list[i],
chainparams_get_ln_port(chainparams),
false,
alt_addr);
if (err) {
log_debug(w->log,
"Invalid alternative address %s for peer %s: %s",
addr_list[i],
fmt_node_id(tmpctx, node_id),
err);
tal_free(alt_addr);
continue;
}
tal_arr_expand(&alt_addrs, *alt_addr);
}

tal_free(addr_list);
tal_free(addr_str);
tal_free(stmt);

if (transaction_started)
db_commit_transaction(w->db);

return alt_addrs;
}

static struct bitcoin_signature *
wallet_htlc_sigs_load(const tal_t *ctx, struct wallet *w, u64 channelid,
bool option_anchors)
Expand Down
30 changes: 30 additions & 0 deletions wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1797,4 +1797,34 @@ void wallet_remove_local_anchors(struct wallet *w,
struct local_anchor_info *wallet_get_local_anchors(const tal_t *ctx,
struct wallet *w,
u64 channel_id);

/**
* wallet_add_alt_addr - Update the alternative address for a peer connection
* @db: the database
* @node_id: the ID of the node
* @alt_addr: the alternative address to set
* @is_our_addr: flag to update `my_alt_addr` or `peer_alt_addr`
*
* This function updates the `my_alt_addr` or `peer_alt_addr` field of a peer
* in the database based on the value of the `is_our_addr` flag. If `is_our_addr`
* is true, it updates the `my_alt_addr` field; otherwise, it updates the
* `peer_alt_addr` field. If `alt_addr` is NULL, it just returns.
*/
void wallet_add_alt_addr(struct db *db, const struct node_id *node_id,
const char *alt_addr, bool is_my_alt_addr);


/**
* wallet_get_alt_addr - Retrieve alternative connection addresses
* @w: the wallet containing the database
* @node_id: the ID of the node whose alternative addresses is to be retrieved
* @use_my_alt_addr: a boolean flag to use `my_alt_addr` or `peer_alt_addr`
*
* Returns: A pointer to the `wireaddr_internal` struct containing alternative
* addresses, or NULL if no valid alternative address is found.
*/
struct wireaddr_internal *wallet_get_alt_addr(struct wallet *w,
const struct node_id *node_id,
bool use_my_alt_addr);

#endif /* LIGHTNING_WALLET_WALLET_H */