Skip to content

Commit a37a4c2

Browse files
committed
Persist feature bits across restarts
1 parent 1e457bd commit a37a4c2

File tree

7 files changed

+54
-22
lines changed

7 files changed

+54
-22
lines changed

lightningd/opening_control.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,7 @@ static struct channel *stub_chan(struct command *cmd,
13511351
0,
13521352
&nodeid,
13531353
&wint,
1354+
NULL,
13541355
false);
13551356
}
13561357

lightningd/peer_control.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,7 @@ static void destroy_peer(struct peer *peer)
7474
peer_node_id_map_del(peer->ld->peers, peer);
7575
if (peer->dbid)
7676
peer_dbid_map_del(peer->ld->peers_by_dbid, peer);
77-
}
78-
79-
static void peer_update_features(struct peer *peer,
80-
const u8 *their_features TAKES)
81-
{
8277
tal_free(peer->their_features);
83-
peer->their_features = tal_dup_talarr(peer, u8, their_features);
8478
}
8579

8680
void peer_set_dbid(struct peer *peer, u64 dbid)
@@ -94,6 +88,7 @@ void peer_set_dbid(struct peer *peer, u64 dbid)
9488
struct peer *new_peer(struct lightningd *ld, u64 dbid,
9589
const struct node_id *id,
9690
const struct wireaddr_internal *addr,
91+
const u8 *their_features,
9792
bool connected_incoming)
9893
{
9994
/* We are owned by our channels, and freed manually by destroy_channel */
@@ -106,12 +101,16 @@ struct peer *new_peer(struct lightningd *ld, u64 dbid,
106101
peer->addr = *addr;
107102
peer->connected_incoming = connected_incoming;
108103
peer->remote_addr = NULL;
109-
peer->their_features = NULL;
110104
list_head_init(&peer->channels);
111105
peer->direction = node_id_idx(&peer->ld->id, &peer->id);
112106
peer->connected = PEER_DISCONNECTED;
113107
peer->last_connect_attempt.ts.tv_sec
114108
= peer->last_connect_attempt.ts.tv_nsec = 0;
109+
if (their_features)
110+
peer->their_features = tal_dup_talarr(peer, u8, their_features);
111+
else
112+
peer->their_features = NULL;
113+
115114
#if DEVELOPER
116115
peer->ignore_htlcs = false;
117116
#endif
@@ -1403,7 +1402,11 @@ void peer_connected(struct lightningd *ld, const u8 *msg)
14031402
peer = peer_by_id(ld, &id);
14041403
if (!peer)
14051404
peer = new_peer(ld, 0, &id, &hook_payload->addr,
1406-
hook_payload->incoming);
1405+
their_features, hook_payload->incoming);
1406+
else {
1407+
tal_free(peer->their_features);
1408+
peer->their_features = tal_dup_talarr(peer, u8, their_features);
1409+
}
14071410

14081411
/* We track this, because messages can race between connectd and us.
14091412
* For example, we could tell it to attach a subd, but it's actually
@@ -1423,7 +1426,6 @@ void peer_connected(struct lightningd *ld, const u8 *msg)
14231426
if (peer->remote_addr)
14241427
tal_free(peer->remote_addr);
14251428
peer->remote_addr = NULL;
1426-
peer_update_features(peer, their_features);
14271429
hook_payload->peer_id = id;
14281430

14291431
/* If there's a connect command, use its id as basis for hook id */
@@ -1942,9 +1944,6 @@ static void json_add_peer(struct lightningd *ld,
19421944
num_channels++;
19431945
json_add_num(response, "num_channels", num_channels);
19441946

1945-
/* If it's not connected, features are unreliable: we don't
1946-
* store them in the database, and they would only reflect
1947-
* their features *last* time they connected. */
19481947
if (p->connected == PEER_CONNECTED) {
19491948
json_array_start(response, "netaddr");
19501949
json_add_string(response, NULL,
@@ -1956,8 +1955,11 @@ static void json_add_peer(struct lightningd *ld,
19561955
if (p->remote_addr)
19571956
json_add_string(response, "remote_addr",
19581957
fmt_wireaddr(response, p->remote_addr));
1959-
json_add_hex_talarr(response, "features", p->their_features);
19601958
}
1959+
1960+
/* Note: If !PEER_CONNECTED, peer may use different features on reconnect */
1961+
json_add_hex_talarr(response, "features", p->their_features);
1962+
19611963
if (deprecated_apis) {
19621964
json_array_start(response, "channels");
19631965
json_add_uncommitted_channel(response, p->uncommitted_channel, NULL);

lightningd/peer_control.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid);
7373
struct peer *new_peer(struct lightningd *ld, u64 dbid,
7474
const struct node_id *id,
7575
const struct wireaddr_internal *addr,
76+
const u8 *their_features,
7677
bool connected_incoming);
7778

7879
/* Last one out deletes peer. Also removes from db. */

tests/test_connection.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4393,6 +4393,30 @@ def test_peer_disconnected_reflected_in_channel_state(node_factory):
43934393
wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['peer_connected'] is False)
43944394

43954395

4396+
def test_peer_disconnected_has_featurebits(node_factory):
4397+
"""
4398+
Make sure that if a node is restarted, it still remembers feature
4399+
bits from a peer it has a channel with but isn't connected to
4400+
"""
4401+
l1, l2 = node_factory.line_graph(2)
4402+
4403+
expected_features = expected_peer_features()
4404+
4405+
l1_features = only_one(l2.rpc.listpeers()['peers'])['features']
4406+
l2_features = only_one(l1.rpc.listpeers()['peers'])['features']
4407+
assert l1_features == expected_features
4408+
assert l2_features == expected_features
4409+
4410+
l1.stop()
4411+
l2.stop()
4412+
4413+
# Ensure we persisted feature bits and return them even when disconnected
4414+
l1.start()
4415+
4416+
wait_for(lambda: only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected'] is False)
4417+
wait_for(lambda: only_one(l1.rpc.listpeers()['peers'])['features'] == expected_features)
4418+
4419+
43964420
@pytest.mark.developer("needs dev-no-reconnect")
43974421
def test_reconnect_no_additional_transient_failure(node_factory, bitcoind):
43984422
l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True},

wallet/db.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,7 @@ static struct migration dbmigrations[] = {
949949
{NULL, migrate_invalid_last_tx_psbts},
950950
{SQL("ALTER TABLE channels ADD channel_type BLOB DEFAULT NULL;"), NULL},
951951
{NULL, migrate_fill_in_channel_type},
952+
{SQL("ALTER TABLE peers ADD feature_bits BLOB DEFAULT NULL;"), NULL},
952953
};
953954

954955
/**

wallet/test/run-wallet.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx)
11721172

11731173
/* Add another utxo that's CSV-locked for 5 blocks */
11741174
assert(parse_wireaddr_internal(tmpctx, "localhost:1234", 0, false, &addr) == NULL);
1175-
channel.peer = new_peer(ld, 0, &id, &addr, false);
1175+
channel.peer = new_peer(ld, 0, &id, &addr, NULL, false);
11761176
channel.dbid = 1;
11771177
channel.type = channel_type_anchor_outputs(tmpctx);
11781178
memset(&u.outpoint, 3, sizeof(u.outpoint));
@@ -1502,7 +1502,7 @@ static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx)
15021502
c1.first_blocknum = 1;
15031503
assert(parse_wireaddr_internal(tmpctx, "localhost:1234", 0, false, &addr) == NULL);
15041504
c1.final_key_idx = 1337;
1505-
p = new_peer(ld, 0, &id, &addr, false);
1505+
p = new_peer(ld, 0, &id, &addr, NULL, false);
15061506
c1.peer = p;
15071507
c1.dbid = wallet_get_channel_dbid(w);
15081508
c1.state = CHANNELD_NORMAL;
@@ -1665,7 +1665,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx)
16651665
assert(parse_wireaddr_internal(tmpctx, "localhost:1234", 0, false, &addr) == NULL);
16661666

16671667
/* new channel! */
1668-
p = new_peer(ld, 0, &id, &addr, false);
1668+
p = new_peer(ld, 0, &id, &addr, NULL, false);
16691669

16701670
funding_sats = AMOUNT_SAT(4444444);
16711671
our_sats = AMOUNT_SAT(3333333);

wallet/wallet.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
859859
struct db_stmt *stmt;
860860

861861
stmt = db_prepare_v2(
862-
w->db, SQL("SELECT id, node_id, address FROM peers WHERE id=?;"));
862+
w->db, SQL("SELECT id, node_id, address, feature_bits FROM peers WHERE id=?;"));
863863
db_bind_u64(stmt, 0, dbid);
864864
db_query_prepared(stmt);
865865

@@ -869,6 +869,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
869869
if (db_col_is_null(stmt, "node_id")) {
870870
db_col_ignore(stmt, "address");
871871
db_col_ignore(stmt, "id");
872+
db_col_ignore(stmt, "feature_bits");
872873
goto done;
873874
}
874875

@@ -886,7 +887,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
886887
}
887888

888889
/* FIXME: save incoming in db! */
889-
peer = new_peer(w->ld, db_col_u64(stmt, "id"), &id, &addr, false);
890+
peer = new_peer(w->ld, db_col_u64(stmt, "id"), &id, &addr, db_col_arr(stmt, stmt, "feature_bits", u8), false);
890891

891892
done:
892893
tal_free(stmt);
@@ -2271,21 +2272,23 @@ static void wallet_peer_save(struct wallet *w, struct peer *peer)
22712272
peer_set_dbid(peer, db_col_u64(stmt, "id"));
22722273
tal_free(stmt);
22732274

2274-
/* Since we're at it update the wireaddr */
2275+
/* Since we're at it update the wireaddr, feature bits */
22752276
stmt = db_prepare_v2(
2276-
w->db, SQL("UPDATE peers SET address = ? WHERE id = ?"));
2277+
w->db, SQL("UPDATE peers SET address = ?, feature_bits = ? WHERE id = ?"));
22772278
db_bind_text(stmt, 0, addr);
2278-
db_bind_u64(stmt, 1, peer->dbid);
2279+
db_bind_talarr(stmt, 1, peer->their_features);
2280+
db_bind_u64(stmt, 2, peer->dbid);
22792281
db_exec_prepared_v2(take(stmt));
22802282

22812283
} else {
22822284
/* Unknown peer, create it from scratch */
22832285
tal_free(stmt);
22842286
stmt = db_prepare_v2(w->db,
2285-
SQL("INSERT INTO peers (node_id, address) VALUES (?, ?);")
2287+
SQL("INSERT INTO peers (node_id, address, feature_bits) VALUES (?, ?, ?);")
22862288
);
22872289
db_bind_node_id(stmt, 0, &peer->id);
22882290
db_bind_text(stmt, 1,addr);
2291+
db_bind_talarr(stmt, 2, peer->their_features);
22892292
db_exec_prepared_v2(stmt);
22902293
peer_set_dbid(peer, db_last_insert_id_v2(take(stmt)));
22912294
}

0 commit comments

Comments
 (0)