Skip to content

Commit

Permalink
wallet: save last known address.
Browse files Browse the repository at this point in the history
If we connected out, remember that address.  We always remember the last
address, but that may be an incoming address.  This is explicitly the last
outgoing address which worked.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Nov 25, 2024
1 parent 64af5db commit 68feb55
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 8 deletions.
12 changes: 12 additions & 0 deletions db/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,18 @@ struct secret *db_col_secret_arr(const tal_t *ctx,
return db_col_arr(ctx, stmt, colname, struct secret);
}

struct wireaddr *db_col_wireaddr(const tal_t *ctx,
struct db_stmt *stmt,
const char *colname)
{
struct wireaddr *waddr = tal(ctx, struct wireaddr);
const u8 *wire = db_col_arr(tmpctx, stmt, colname, u8);
size_t len = tal_bytelen(wire);
if (!fromwire_wireaddr(&wire, &len, waddr))
return tal_free(waddr);
return waddr;
}

void db_col_txid(struct db_stmt *stmt, const char *colname, struct bitcoin_txid *t)
{
db_col_sha256d(stmt, colname, &t->shad);
Expand Down
3 changes: 3 additions & 0 deletions db/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ struct bitcoin_tx *db_col_psbt_to_tx(const tal_t *ctx, struct db_stmt *stmt, con

struct onionreply *db_col_onionreply(const tal_t *ctx,
struct db_stmt *stmt, const char *colname);
struct wireaddr *db_col_wireaddr(const tal_t *ctx,
struct db_stmt *stmt,
const char *colname);

#define db_col_arr(ctx, stmt, colname, type) \
((type *)db_col_arr_((ctx), (stmt), (colname), \
Expand Down
1 change: 1 addition & 0 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,7 @@ static struct channel *stub_chan(struct command *cmd,
&nodeid,
&wint,
NULL,
NULL,
false);
}

Expand Down
23 changes: 21 additions & 2 deletions lightningd/peer_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ void peer_set_dbid(struct peer *peer, u64 dbid)
struct peer *new_peer(struct lightningd *ld, u64 dbid,
const struct node_id *id,
const struct wireaddr_internal *addr,
const struct wireaddr *last_known_addr,
const u8 *their_features,
bool connected_incoming)
{
Expand All @@ -102,6 +103,7 @@ struct peer *new_peer(struct lightningd *ld, u64 dbid,
peer->id = *id;
peer->uncommitted_channel = NULL;
peer->addr = *addr;
peer->last_known_addr = tal_dup_or_null(peer, struct wireaddr, last_known_addr);
peer->connected_incoming = connected_incoming;
peer->remote_addr = NULL;
list_head_init(&peer->channels);
Expand Down Expand Up @@ -1673,6 +1675,7 @@ void peer_connected(struct lightningd *ld, const u8 *msg)
struct peer_connected_hook_payload *hook_payload;
u64 connectd_counter;
const char *cmd_id;
struct wireaddr *last_known_addr;

hook_payload = tal(NULL, struct peer_connected_hook_payload);
hook_payload->ld = ld;
Expand All @@ -1691,15 +1694,31 @@ void peer_connected(struct lightningd *ld, const u8 *msg)
* now it's reconnected, we've gotta force them out. */
peer_channels_cleanup(ld, &id);

/* If we connected, and it's a normal address */
if (!hook_payload->incoming
&& hook_payload->addr.itype == ADDR_INTERNAL_WIREADDR
&& !hook_payload->addr.u.wireaddr.is_websocket) {
last_known_addr = &hook_payload->addr.u.wireaddr.wireaddr;
} else {
last_known_addr = NULL;
}

/* If we're already dealing with this peer, hand off to correct
* subdaemon. Otherwise, we'll hand to openingd to wait there. */
peer = peer_by_id(ld, &id);
if (!peer)
if (!peer) {
/* If we connected to them, we know this is a good address. */
peer = new_peer(ld, 0, &id, &hook_payload->addr,
last_known_addr,
take(their_features), hook_payload->incoming);
else {
} else {
tal_free(peer->their_features);
peer->their_features = tal_steal(peer, their_features);

/* Update known address. */
tal_free(peer->last_known_addr);
peer->last_known_addr = tal_dup_or_null(peer, struct wireaddr,
last_known_addr);
}

/* We track this, because messages can race between connectd and us.
Expand Down
4 changes: 4 additions & 0 deletions lightningd/peer_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ struct peer {
struct wireaddr_internal addr;
bool connected_incoming;

/* If we ever successfully connected out to an address, this is non-NULL */
struct wireaddr *last_known_addr;

/* They send what they see as our address as remote_addr */
struct wireaddr *remote_addr;

Expand All @@ -71,6 +74,7 @@ struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid);
struct peer *new_peer(struct lightningd *ld, u64 dbid,
const struct node_id *id,
const struct wireaddr_internal *addr,
const struct wireaddr *last_known_addr,
const u8 *their_features TAKES,
bool connected_incoming);

Expand Down
3 changes: 3 additions & 0 deletions plugins/bkpr/test/run-bkpr_db.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for fromwire_wireaddr */
bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED)
{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); }
/* Generated stub for fromwire_wirestring */
char *fromwire_wirestring(const tal_t *ctx UNNEEDED, const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_wirestring called!\n"); abort(); }
Expand Down
3 changes: 3 additions & 0 deletions plugins/bkpr/test/run-recorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for fromwire_wireaddr */
bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED)
{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); }
/* Generated stub for fromwire_wirestring */
char *fromwire_wirestring(const tal_t *ctx UNNEEDED, const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_wirestring called!\n"); abort(); }
Expand Down
1 change: 1 addition & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,7 @@ static struct migration dbmigrations[] = {
" addrtype INTEGER)"), NULL},
{NULL, insert_addrtype_to_addresses},
{SQL("ALTER TABLE channel_funding_inflights ADD remote_funding BLOB DEFAULT NULL;"), NULL},
{SQL("ALTER TABLE peers ADD last_known_address BLOB DEFAULT NULL;"), NULL},
};

/**
Expand Down
1 change: 1 addition & 0 deletions wallet/test/run-db.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ struct logger *new_logger(const tal_t *ctx UNNEEDED, struct log_book *record UNN
struct peer *new_peer(struct lightningd *ld UNNEEDED, u64 dbid UNNEEDED,
const struct node_id *id UNNEEDED,
const struct wireaddr_internal *addr UNNEEDED,
const struct wireaddr *last_known_addr UNNEEDED,
const u8 *their_features TAKES UNNEEDED,
bool connected_incoming UNNEEDED)
{ fprintf(stderr, "new_peer called!\n"); abort(); }
Expand Down
6 changes: 3 additions & 3 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx)

/* Add another utxo that's CSV-locked for 5 blocks */
assert(parse_wireaddr_internal(tmpctx, "localhost:1234", 0, false, &addr) == NULL);
channel.peer = new_peer(ld, 0, &id, &addr, NULL, false);
channel.peer = new_peer(ld, 0, &id, &addr, NULL, NULL, false);
channel.dbid = 1;
channel.type = channel_type_anchors_zero_fee_htlc(tmpctx);
memset(&u.outpoint, 3, sizeof(u.outpoint));
Expand Down Expand Up @@ -1767,7 +1767,7 @@ static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx)
c1.first_blocknum = 1;
assert(parse_wireaddr_internal(tmpctx, "localhost:1234", 0, false, &addr) == NULL);
c1.final_key_idx = 1337;
p = new_peer(ld, 0, &id, &addr, NULL, false);
p = new_peer(ld, 0, &id, &addr, NULL, NULL, false);
c1.peer = p;
c1.dbid = wallet_get_channel_dbid(w);
c1.state = CHANNELD_NORMAL;
Expand Down Expand Up @@ -1935,7 +1935,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx)
assert(parse_wireaddr_internal(tmpctx, "localhost:1234", 0, false, &addr) == NULL);

/* new channel! */
p = new_peer(ld, 0, &id, &addr, NULL, false);
p = new_peer(ld, 0, &id, &addr, NULL, NULL, false);

funding_sats = AMOUNT_SAT(4444444);
our_sats = AMOUNT_SAT(3333333);
Expand Down
28 changes: 25 additions & 3 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1011,10 +1011,11 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
struct peer *peer = NULL;
struct node_id id;
struct wireaddr_internal addr;
struct wireaddr *last_known_addr;
struct db_stmt *stmt;

stmt = db_prepare_v2(
w->db, SQL("SELECT id, node_id, address, feature_bits FROM peers WHERE id=?;"));
w->db, SQL("SELECT id, node_id, address, feature_bits, last_known_address FROM peers WHERE id=?;"));
db_bind_u64(stmt, dbid);
db_query_prepared(stmt);

Expand All @@ -1025,6 +1026,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
db_col_ignore(stmt, "address");
db_col_ignore(stmt, "id");
db_col_ignore(stmt, "feature_bits");
db_col_ignore(stmt, "last_known_address");
goto done;
}

Expand All @@ -1041,8 +1043,18 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
assert(!err);
}

/* FIXME: save incoming in db! */
peer = new_peer(w->ld, db_col_u64(stmt, "id"), &id, &addr, db_col_arr(stmt, stmt, "feature_bits", u8), false);
if (db_col_is_null(stmt, "last_known_address")) {
last_known_addr = NULL;
} else {
last_known_addr = db_col_wireaddr(tmpctx, stmt, "last_known_address");
if (!last_known_addr) {
log_broken(w->log, "Unparsable lastknown address %s: ignoring",
tal_hex(tmpctx, db_col_arr(tmpctx, stmt, "last_known_address", u8)));
}
}

peer = new_peer(w->ld, db_col_u64(stmt, "id"), &id, &addr, last_known_addr,
db_col_arr(stmt, stmt, "feature_bits", u8), false);

done:
tal_free(stmt);
Expand Down Expand Up @@ -2583,6 +2595,16 @@ static void wallet_peer_save(struct wallet *w, struct peer *peer)
db_exec_prepared_v2(stmt);
peer_set_dbid(peer, db_last_insert_id_v2(take(stmt)));
}

if (peer->last_known_addr) {
u8 *wire = tal_arr(tmpctx, u8, 0);
towire_wireaddr(&wire, peer->last_known_addr);
stmt = db_prepare_v2(w->db,
SQL("UPDATE peers SET last_known_address = ? WHERE id = ?;"));
db_bind_talarr(stmt, wire);
db_bind_u64(stmt, peer->dbid);
db_exec_prepared_v2(take(stmt));
}
}

bool channel_exists_by_id(struct wallet *w, u64 dbid) {
Expand Down

0 comments on commit 68feb55

Please sign in to comment.