lightningd: expose last_stable_connection in RPC.

This isuseful to find completely dead channels which are worthy of
closing.

Changelog-Added: JSON-RPC: `listpeerchannels` field `last_stable_connection` showing when we last held an established channel for a minute or more.
Changelog-Added: JSON-RPC: `listclosedchannels` field `last_stable_connection` showing when we last held an established channel for a minute or more.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-01-31 13:46:20 +10:30
parent 95bc730894
commit dd59d0617d
15 changed files with 268 additions and 194 deletions

View File

@ -939,6 +939,7 @@
"ListClosedChannels.closedchannels[].funding_txid": 12,
"ListClosedChannels.closedchannels[].last_commitment_fee_msat": 23,
"ListClosedChannels.closedchannels[].last_commitment_txid": 22,
"ListClosedChannels.closedchannels[].last_stable_connection": 25,
"ListClosedChannels.closedchannels[].leased": 14,
"ListClosedChannels.closedchannels[].max_to_us_msat": 21,
"ListClosedChannels.closedchannels[].min_to_us_msat": 20,
@ -1147,6 +1148,7 @@
"ListPeerChannels.channels[].inflight[]": 16,
"ListPeerChannels.channels[].initial_feerate": 12,
"ListPeerChannels.channels[].last_feerate": 13,
"ListPeerChannels.channels[].last_stable_connection": 56,
"ListPeerChannels.channels[].max_accepted_htlcs": 40,
"ListPeerChannels.channels[].max_to_us_msat": 25,
"ListPeerChannels.channels[].max_total_htlc_in_msat": 30,
@ -3676,6 +3678,10 @@
"added": "pre-v0.10.1",
"deprecated": false
},
"ListClosedChannels.closedchannels[].last_stable_connection": {
"added": "v24.02",
"deprecated": false
},
"ListClosedChannels.closedchannels[].leased": {
"added": "pre-v0.10.1",
"deprecated": false
@ -4408,6 +4414,10 @@
"added": "v23.02",
"deprecated": false
},
"ListPeerChannels.channels[].last_stable_connection": {
"added": "v24.02",
"deprecated": false
},
"ListPeerChannels.channels[].max_accepted_htlcs": {
"added": "v23.02",
"deprecated": false

Binary file not shown.

BIN
cln-grpc/src/convert.rs generated

Binary file not shown.

BIN
cln-rpc/src/model.rs generated

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -918,6 +918,7 @@ def listpeerchannels_channels2py(m):
"out_offered_msat": amount2msat(m.out_offered_msat), # PrimitiveField in generate_composite
"out_payments_fulfilled": m.out_payments_fulfilled, # PrimitiveField in generate_composite
"out_fulfilled_msat": amount2msat(m.out_fulfilled_msat), # PrimitiveField in generate_composite
"last_stable_connection": m.last_stable_connection, # PrimitiveField in generate_composite
"htlcs": [listpeerchannels_channels_htlcs2py(i) for i in m.htlcs], # ArrayField[composite] in generate_composite
"close_to_addr": m.close_to_addr, # PrimitiveField in generate_composite
})
@ -967,6 +968,7 @@ def listclosedchannels_closedchannels2py(m):
"last_commitment_txid": hexlify(m.last_commitment_txid), # PrimitiveField in generate_composite
"last_commitment_fee_msat": amount2msat(m.last_commitment_fee_msat), # PrimitiveField in generate_composite
"close_cause": str(m.close_cause), # EnumField in generate_composite
"last_stable_connection": m.last_stable_connection, # PrimitiveField in generate_composite
})

View File

@ -53,6 +53,7 @@ On success, an object containing **closedchannels** is returned. It is an array
- **funding\_pushed\_msat** (msat, optional): How much `opener` pushed immediate (if non-zero)
- **last\_commitment\_txid** (hash, optional): The final commitment tx's txid (or mutual close, if we accepted it). Not present for some very old, small channels pre-0.7.0.
- **last\_commitment\_fee\_msat** (msat, optional): The fee on `last_commitment_txid`
- **last\_stable\_connection** (u64, optional): Last time we reestablished the open channel and stayed connected for 1 minute *(added v24.02)*
[comment]: # (GENERATE-FROM-SCHEMA-END)
@ -76,4 +77,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning> Lightning
[comment]: # ( SHA256STAMP:1437321ab48ffcf8c5aa437db53eef72f5ed62dd1da7900483c86482e533a461)
[comment]: # ( SHA256STAMP:559d917217fe6d765d8bf019e46bf03d37dae9a437e530b1456252bcb901cbc9)

View File

@ -116,6 +116,7 @@ On success, an object containing **channels** is returned. It is an array of ob
- **out\_offered\_msat** (msat, optional): Total amount of outgoing payment attempts
- **out\_payments\_fulfilled** (u64, optional): Number of successful outgoing payment attempts
- **out\_fulfilled\_msat** (msat, optional): Total amount of successful outgoing payment attempts
- **last\_stable\_connection** (u64, optional): Last time we reestablished the open channel and stayed connected for 1 minute *(added v24.02)*
- **htlcs** (array of objects, optional): current HTLCs in this channel:
- **direction** (string): Whether it came from peer, or is going to peer (one of "in", "out")
- **id** (u64): Unique ID for this htlc on this channel in this direction
@ -219,4 +220,4 @@ Main web site: <https://github.com/ElementsProject/lightning> Lightning
RFC site (BOLT \#9):
<https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md>
[comment]: # ( SHA256STAMP:8cad14f36d38722182a8fdccc393e93d121d97999d2487decfa09d53c991a8ae)
[comment]: # ( SHA256STAMP:c2ab91a2357b83264415f923b9d5195e5294a17b7424d9e75ac9ea704bea8fc5)

View File

@ -169,6 +169,7 @@ The following tables are currently supported:
- `last_commitment_txid` (type `hash`, sqltype `BLOB`)
- `last_commitment_fee_msat` (type `msat`, sqltype `INTEGER`)
- `close_cause` (type `string`, sqltype `TEXT`)
- `last_stable_connection` (type `u64`, sqltype `INTEGER`)
- `forwards` indexed by `in_channel and in_htlc_id` (see lightning-listforwards(7))
- `created_index` (type `u64`, sqltype `INTEGER`)
@ -341,6 +342,7 @@ The following tables are currently supported:
- `out_offered_msat` (type `msat`, sqltype `INTEGER`)
- `out_payments_fulfilled` (type `u64`, sqltype `INTEGER`)
- `out_fulfilled_msat` (type `msat`, sqltype `INTEGER`)
- `last_stable_connection` (type `u64`, sqltype `INTEGER`)
- related table `peerchannels_htlcs`
- `row` (reference to `peerchannels.rowid`, sqltype `INTEGER`)
- `arrindex` (index within array, sqltype `INTEGER`)
@ -531,4 +533,4 @@ RESOURCES
---------
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:f17b33523de930b61d6397a730c40b2254929cf38930629b9be66f3d52947d0e)
[comment]: # ( SHA256STAMP:299446e88b1f847a82ae63c2087ce28a36b7c8fea2b102d4e3d87c420a9268e9)

View File

@ -180,6 +180,11 @@
"onchain"
],
"description": "What caused the channel to close"
},
"last_stable_connection": {
"type": "u64",
"added": "v24.02",
"description": "Last time we reestablished the open channel and stayed connected for 1 minute"
}
}
}

View File

@ -556,6 +556,11 @@
"type": "msat",
"description": "Total amount of successful outgoing payment attempts"
},
"last_stable_connection": {
"type": "u64",
"added": "v24.02",
"description": "Last time we reestablished the open channel and stayed connected for 1 minute"
},
"htlcs": {
"type": "array",
"description": "current HTLCs in this channel",
@ -802,6 +807,7 @@
"out_payments_fulfilled": {},
"out_fulfilled_msat": {},
"out_msatoshi_fulfilled": {},
"last_stable_connection": {},
"htlcs": {},
"initial_feerate": {},
"last_feerate": {},
@ -895,6 +901,7 @@
"out_payments_fulfilled": {},
"out_fulfilled_msat": {},
"out_msatoshi_fulfilled": {},
"last_stable_connection": {},
"htlcs": {},
"initial_feerate": {},
"last_feerate": {},
@ -987,6 +994,7 @@
"out_payments_fulfilled": {},
"out_fulfilled_msat": {},
"out_msatoshi_fulfilled": {},
"last_stable_connection": {},
"htlcs": {},
"initial_feerate": {},
"last_feerate": {},
@ -1080,6 +1088,7 @@
"out_payments_fulfilled": {},
"out_fulfilled_msat": {},
"out_msatoshi_fulfilled": {},
"last_stable_connection": {},
"htlcs": {},
"inflight": {},
"close_to_addr": {},

View File

@ -76,6 +76,10 @@ static void json_add_closed_channel(struct json_stream *response,
}
json_add_string(response, "close_cause",
channel_change_state_reason_str(channel->state_change_cause));
if (channel->last_stable_connection != 0) {
json_add_u64(response, "last_stable_connection",
channel->last_stable_connection);
}
json_object_end(response);
}

View File

@ -865,6 +865,11 @@ static void json_add_channel(struct lightningd *ld,
json_object_end(response);
}
json_object_end(response);
if (channel->last_stable_connection != 0) {
json_add_u64(response, "last_stable_connection",
channel->last_stable_connection);
}
}
json_add_string(response, "state", channel_state_name(channel));

View File

@ -4456,3 +4456,34 @@ def test_offline_fd_check(node_factory):
# if get_node starts it, it'll expect an address, so do it manually.
l1 = node_factory.get_node(options={"offline": None}, start=False)
l1.daemon.start()
def test_last_stable_connection(node_factory):
l1, l2 = node_factory.line_graph(2, opts={'may_reconnect': True})
# We wait a minute to be stable.
STABLE_TIME = 60
assert 'last_stable_connection' not in only_one(l1.rpc.listpeerchannels()['channels'])
assert 'last_stable_connection' not in only_one(l2.rpc.listpeerchannels()['channels'])
recon_time = time.time()
# This take a minute, so don't fail if TIMEOUT is set to 10.
wait_for(lambda: 'last_stable_connection' in only_one(l1.rpc.listpeerchannels()['channels']), timeout=STABLE_TIME + 15)
l1stable = only_one(l1.rpc.listpeerchannels()['channels'])['last_stable_connection']
wait_for(lambda: 'last_stable_connection' in only_one(l2.rpc.listpeerchannels()['channels']))
l2stable = only_one(l2.rpc.listpeerchannels()['channels'])['last_stable_connection']
# Disconnect, and/or restart then reconnect.
l1.rpc.disconnect(l2.info['id'], force=True)
recon_time = time.time()
l2.restart()
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
assert only_one(l1.rpc.listpeerchannels()['channels'])['last_stable_connection'] == l1stable
assert only_one(l2.rpc.listpeerchannels()['channels'])['last_stable_connection'] == l2stable
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['last_stable_connection'] != l1stable, timeout=STABLE_TIME + 15)
wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['last_stable_connection'] != l2stable)
assert only_one(l1.rpc.listpeerchannels()['channels'])['last_stable_connection'] > recon_time + STABLE_TIME
assert only_one(l2.rpc.listpeerchannels()['channels'])['last_stable_connection'] > recon_time + STABLE_TIME

View File

@ -3506,7 +3506,9 @@ def test_sql(node_factory, bitcoind):
{'name': 'last_commitment_fee_msat',
'type': 'msat'},
{'name': 'close_cause',
'type': 'string'}]},
'type': 'string'},
{'name': 'last_stable_connection',
'type': 'u64'}]},
'closedchannels_channel_type_bits': {
'columns': [{'name': 'row',
'type': 'u64'},
@ -3840,6 +3842,8 @@ def test_sql(node_factory, bitcoind):
'type': 'u64'},
{'name': 'out_fulfilled_msat',
'type': 'msat'},
{'name': 'last_stable_connection',
'type': 'u64'},
{'name': 'reestablished',
'type': 'boolean'},
{'name': 'close_to_addr',