mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
channeld: don't commit until we've seen recent incoming msg, ping if required.
Now sending a ping makes sense: it should force the other end to send a reply, unblocking the commitment process. Note that rather than waiting for a reply, we're actually spinning on a 100ms loop in this case. But it's simple and it works. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
93e445daf5
commit
63e4ea17af
@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||||||
- JSON API: `listnodes` has new field `global_features`.
|
- JSON API: `listnodes` has new field `global_features`.
|
||||||
- JSON API: `ping` command to send a ping to a connected peer.
|
- JSON API: `ping` command to send a ping to a connected peer.
|
||||||
- Protocol: gossipd now deliberately delays spamming with `channel_update`.
|
- Protocol: gossipd now deliberately delays spamming with `channel_update`.
|
||||||
|
- Protocol: liveness ping when we commit changes but peer is idle: speeds up
|
||||||
|
failures and reduces forced closures.
|
||||||
- Config: `--conf` option to set config file.
|
- Config: `--conf` option to set config file.
|
||||||
- JSON API: Added description to invoices and payments (#1740).
|
- JSON API: Added description to invoices and payments (#1740).
|
||||||
- pylightning: RpcError now has `method` and `payload` fields.
|
- pylightning: RpcError now has `method` and `payload` fields.
|
||||||
|
@ -155,6 +155,9 @@ struct peer {
|
|||||||
|
|
||||||
/* Make sure timestamps move forward. */
|
/* Make sure timestamps move forward. */
|
||||||
u32 last_update_timestamp;
|
u32 last_update_timestamp;
|
||||||
|
|
||||||
|
/* Make sure peer is live. */
|
||||||
|
struct timeabs last_recv;
|
||||||
};
|
};
|
||||||
|
|
||||||
static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer);
|
static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer);
|
||||||
@ -928,12 +931,23 @@ static struct commit_sigs *calc_commitsigs(const tal_t *ctx,
|
|||||||
return commit_sigs;
|
return commit_sigs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Have we received something from peer recently? */
|
||||||
|
static bool peer_recently_active(struct peer *peer)
|
||||||
|
{
|
||||||
|
return time_less(time_between(time_now(), peer->last_recv),
|
||||||
|
time_from_sec(30));
|
||||||
|
}
|
||||||
|
|
||||||
static void maybe_send_ping(struct peer *peer)
|
static void maybe_send_ping(struct peer *peer)
|
||||||
{
|
{
|
||||||
/* Already have a ping in flight? */
|
/* Already have a ping in flight? */
|
||||||
if (peer->expecting_pong)
|
if (peer->expecting_pong)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (peer_recently_active(peer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Send a ping to try to elicit a receive. */
|
||||||
sync_crypto_write_no_delay(&peer->cs, PEER_FD,
|
sync_crypto_write_no_delay(&peer->cs, PEER_FD,
|
||||||
take(make_ping(NULL, 1, 0)));
|
take(make_ping(NULL, 1, 0)));
|
||||||
peer->expecting_pong = true;
|
peer->expecting_pong = true;
|
||||||
@ -982,6 +996,14 @@ static void send_commit(struct peer *peer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we haven't received a packet for > 30 seconds, delay. */
|
||||||
|
if (!peer_recently_active(peer)) {
|
||||||
|
/* Mark this as done and try again. */
|
||||||
|
peer->commit_timer = NULL;
|
||||||
|
start_commit_timer(peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we wanted to update fees, do it now. */
|
/* If we wanted to update fees, do it now. */
|
||||||
if (peer->channel->funder == LOCAL
|
if (peer->channel->funder == LOCAL
|
||||||
&& peer->desired_feerate != channel_feerate(peer->channel, REMOTE)) {
|
&& peer->desired_feerate != channel_feerate(peer->channel, REMOTE)) {
|
||||||
@ -1587,6 +1609,8 @@ static void peer_in(struct peer *peer, const u8 *msg)
|
|||||||
{
|
{
|
||||||
enum wire_type type = fromwire_peektype(msg);
|
enum wire_type type = fromwire_peektype(msg);
|
||||||
|
|
||||||
|
peer->last_recv = time_now();
|
||||||
|
|
||||||
/* Catch our own ping replies. */
|
/* Catch our own ping replies. */
|
||||||
if (type == WIRE_PONG && peer->expecting_pong) {
|
if (type == WIRE_PONG && peer->expecting_pong) {
|
||||||
peer->expecting_pong = false;
|
peer->expecting_pong = false;
|
||||||
@ -2455,6 +2479,8 @@ int main(int argc, char *argv[])
|
|||||||
peer->next_commit_sigs = NULL;
|
peer->next_commit_sigs = NULL;
|
||||||
peer->shutdown_sent[LOCAL] = false;
|
peer->shutdown_sent[LOCAL] = false;
|
||||||
peer->last_update_timestamp = 0;
|
peer->last_update_timestamp = 0;
|
||||||
|
/* We actually received it in the previous daemon, but near enough */
|
||||||
|
peer->last_recv = time_now();
|
||||||
|
|
||||||
/* We send these to HSM to get real signatures; don't have valgrind
|
/* We send these to HSM to get real signatures; don't have valgrind
|
||||||
* complain. */
|
* complain. */
|
||||||
|
@ -778,7 +778,6 @@ def test_reserve_enforcement(node_factory, executor):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(strict=True)
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs dev_disconnect")
|
@unittest.skipIf(not DEVELOPER, "needs dev_disconnect")
|
||||||
def test_htlc_send_timeout(node_factory, bitcoind):
|
def test_htlc_send_timeout(node_factory, bitcoind):
|
||||||
"""Test that we don't commit an HTLC to an unreachable node."""
|
"""Test that we don't commit an HTLC to an unreachable node."""
|
||||||
|
Loading…
Reference in New Issue
Block a user