From 4dcd4ca1556b13b6964a10040ba1d5ef82de4788 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 3 Mar 2021 13:46:57 +1030 Subject: [PATCH] listpeers: add latest feerate and actual last fee amount. Users have no idea what they would pay for unilateral closes. At least this gives them a clue! Reported-by: @az0re on IRC. Changelog-Added: JSON-RPC: `listpeers` now shows latest feerate and unilaral close fee. Signed-off-by: Rusty Russell --- doc/lightning-listpeers.7 | 9 ++++++++- doc/lightning-listpeers.7.md | 4 ++++ lightningd/peer_control.c | 11 +++++++++++ lightningd/test/run-invoice-select-inchan.c | 6 ++++++ tests/test_connection.py | 9 ++++++++- wallet/db_postgres_sqlgen.c | 2 +- wallet/db_sqlite3_sqlgen.c | 2 +- wallet/statements_gettextgen.po | 6 +++--- wallet/test/run-wallet.c | 6 ++++++ 9 files changed, 48 insertions(+), 7 deletions(-) diff --git a/doc/lightning-listpeers.7 b/doc/lightning-listpeers.7 index 88085537c..1e3120240 100644 --- a/doc/lightning-listpeers.7 +++ b/doc/lightning-listpeers.7 @@ -272,6 +272,13 @@ successfully claimed\fR over this channel\. outgoing HTLCs offered \fIand successfully claimed\fR over this channel; a number followed by a string unit\. .IP \[bu] +\fIscratch_txid\fR: The txid of the latest transaction (what we would sign and +send to chain if the channel were to fail now)\. +.IP \[bu] +\fIlast_tx_fee\fR: The fee on that latest transaction\. +.IP \[bu] +\fIfeerate\fR: An object containing the latest feerate as both \fIperkw\fR and \fIperkb\fR\. +.IP \[bu] \fIhtlcs\fR: An array of objects describing the HTLCs currently in-flight in the channel\. @@ -334,4 +341,4 @@ Main web site: \fIhttps://github.com/ElementsProject/lightning\fR Lightning RFC site (BOLT #9): \fIhttps://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md\fR -\" SHA256STAMP:9e2ed8ce1612c02a6251db7da1d62e2d12f8e0648a54888687f177f0784ef2e6 +\" SHA256STAMP:1163bde5a9f836ba7bd142559cd3bab893ab3159a99041a88ac8b31556b67905 diff --git a/doc/lightning-listpeers.7.md b/doc/lightning-listpeers.7.md index e30c7c788..e97f534a1 100644 --- a/doc/lightning-listpeers.7.md +++ b/doc/lightning-listpeers.7.md @@ -202,6 +202,10 @@ state, or in various circumstances: * *out\_fulfilled\_msat*: A string describing the total amount of all outgoing HTLCs offered *and successfully claimed* over this channel; a number followed by a string unit. +* *scratch_txid*: The txid of the latest transaction (what we would sign and + send to chain if the channel were to fail now). +* *last_tx_fee*: The fee on that latest transaction. +* *feerate*: An object containing the latest feerate as both *perkw* and *perkb*. * *htlcs*: An array of objects describing the HTLCs currently in-flight in the channel. diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index e209f45f8..a086178d4 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -698,6 +698,7 @@ static void json_add_channel(struct lightningd *ld, struct amount_sat peer_funded_sats; struct peer *p = channel->peer; struct state_change_entry *state_changes; + u32 feerate; json_object_start(response, key); json_add_string(response, "state", channel_state_name(channel)); @@ -706,7 +707,17 @@ static void json_add_channel(struct lightningd *ld, bitcoin_txid(channel->last_tx, &txid); json_add_txid(response, "scratch_txid", &txid); + json_add_amount_sat_only(response, "last_tx_fee", + bitcoin_tx_compute_fee(channel->last_tx)); } + + json_object_start(response, "feerate"); + feerate = get_feerate(channel->fee_states, channel->opener, LOCAL); + json_add_u32(response, feerate_style_name(FEERATE_PER_KSIPA), feerate); + json_add_u32(response, feerate_style_name(FEERATE_PER_KBYTE), + feerate_to_style(feerate, FEERATE_PER_KBYTE)); + json_object_end(response); + if (channel->owner) json_add_string(response, "owner", channel->owner->name); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index fb26c2199..7a1e33134 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -267,6 +267,12 @@ void json_add_amount_sat_compat(struct json_stream *result UNNEEDED, const char *msatfieldname) { fprintf(stderr, "json_add_amount_sat_compat called!\n"); abort(); } +/* Generated stub for json_add_amount_sat_only */ +void json_add_amount_sat_only(struct json_stream *result UNNEEDED, + const char *msatfieldname UNNEEDED, + struct amount_sat sat) + +{ fprintf(stderr, "json_add_amount_sat_only called!\n"); abort(); } /* Generated stub for json_add_bolt11 */ void json_add_bolt11(struct json_stream *response UNNEEDED, const struct bolt11 *b11 UNNEEDED) diff --git a/tests/test_connection.py b/tests/test_connection.py index c04a54a3c..88b58da9b 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1606,7 +1606,8 @@ def test_multifunding_feerates(node_factory, bitcoind): Test feerate parameters for multifundchannel ''' funding_tx_feerate = '10000perkw' - commitment_tx_feerate = '2000perkw' + commitment_tx_feerate_int = 2000 + commitment_tx_feerate = str(commitment_tx_feerate_int) + 'perkw' l1, l2, l3 = node_factory.get_nodes(3, opts={'log-level': 'debug'}) @@ -1626,6 +1627,11 @@ def test_multifunding_feerates(node_factory, bitcoind): expected_fee = int(funding_tx_feerate[:-5]) * weight // 1000 assert expected_fee == entry['fees']['base'] * 10 ** 8 + assert only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])['feerate']['perkw'] == commitment_tx_feerate_int + assert only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])['feerate']['perkb'] == commitment_tx_feerate_int * 4 + + txfee = only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])['last_tx_fee'] + # We get the expected close txid, force close the channel, then fish # the details about the transaction out of the mempoool entry close_txid = only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])['scratch_txid'] @@ -1652,6 +1658,7 @@ def test_multifunding_feerates(node_factory, bitcoind): expected_fee += 330 assert expected_fee == entry['fees']['base'] * 10 ** 8 + assert Millisatoshi(str(expected_fee) + 'sat') == Millisatoshi(txfee) def test_multifunding_param_failures(node_factory): diff --git a/wallet/db_postgres_sqlgen.c b/wallet/db_postgres_sqlgen.c index 0ba1589c8..cef31fab4 100644 --- a/wallet/db_postgres_sqlgen.c +++ b/wallet/db_postgres_sqlgen.c @@ -1834,4 +1834,4 @@ struct db_query db_postgres_queries[] = { #endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */ -// SHA256STAMP:6b28c95645d860341a96102fc5f9240eaae6d10c30feb69459f42e78026de2b6 +// SHA256STAMP:9556cf46f2cbd29da75f53004ff8910b55604d5f9888d1a953c12cfa508e6f7f diff --git a/wallet/db_sqlite3_sqlgen.c b/wallet/db_sqlite3_sqlgen.c index 11ce587bb..a88afdede 100644 --- a/wallet/db_sqlite3_sqlgen.c +++ b/wallet/db_sqlite3_sqlgen.c @@ -1834,4 +1834,4 @@ struct db_query db_sqlite3_queries[] = { #endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */ -// SHA256STAMP:6b28c95645d860341a96102fc5f9240eaae6d10c30feb69459f42e78026de2b6 +// SHA256STAMP:9556cf46f2cbd29da75f53004ff8910b55604d5f9888d1a953c12cfa508e6f7f diff --git a/wallet/statements_gettextgen.po b/wallet/statements_gettextgen.po index eeae6a4b7..64f27e716 100644 --- a/wallet/statements_gettextgen.po +++ b/wallet/statements_gettextgen.po @@ -1202,11 +1202,11 @@ msgstr "" msgid "not a valid SQL statement" msgstr "" -#: wallet/test/run-wallet.c:1404 +#: wallet/test/run-wallet.c:1410 msgid "SELECT COUNT(1) FROM channel_funding_inflights WHERE channel_id = ?;" msgstr "" -#: wallet/test/run-wallet.c:1602 +#: wallet/test/run-wallet.c:1608 msgid "INSERT INTO channels (id) VALUES (1);" msgstr "" -# SHA256STAMP:b9f3498738d18d7ed02f83699d902e480e8d75289b18deb5c2d5fe9d1f66c149 +# SHA256STAMP:033aa14057e8777fff79f9dfb1b469f72c9665f58e011b4cd907a976ce0f4ea4 diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index c1eaafd3b..6ecbffe25 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -268,6 +268,12 @@ void json_add_amount_sat_compat(struct json_stream *result UNNEEDED, const char *msatfieldname) { fprintf(stderr, "json_add_amount_sat_compat called!\n"); abort(); } +/* Generated stub for json_add_amount_sat_only */ +void json_add_amount_sat_only(struct json_stream *result UNNEEDED, + const char *msatfieldname UNNEEDED, + struct amount_sat sat) + +{ fprintf(stderr, "json_add_amount_sat_only called!\n"); abort(); } /* Generated stub for json_add_bool */ void json_add_bool(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, bool value UNNEEDED)