From 522457a12bdf82ca44c5131cbf428614bad996fe Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 13 Nov 2025 15:42:31 +1030 Subject: [PATCH] connectd, gossipd, pay, bcli: use timemono when solely measuring duration for timeouts. This is immune to things like clock changes, and has the convenient side-effect that it will *not* be overridden when we override time for developer purposes. Signed-off-by: Rusty Russell --- connectd/connectd.c | 2 +- connectd/connectd.h | 2 +- connectd/multiplex.c | 6 +++--- gossipd/gossip_store.c | 4 ++-- lightningd/channel.h | 2 +- lightningd/pay.c | 2 +- lightningd/peer_control.c | 2 +- lightningd/peer_htlcs.c | 4 ++-- plugins/bcli.c | 6 +++--- plugins/keysend.c | 2 +- plugins/libplugin-pay.c | 4 ++-- plugins/libplugin-pay.h | 2 +- plugins/pay.c | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) diff --git a/connectd/connectd.c b/connectd/connectd.c index 1b19b3930..ffe938212 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -131,7 +131,7 @@ static struct peer *new_peer(struct daemon *daemon, peer->draining_state = NOT_DRAINING; peer->peer_in_lastmsg = -1; peer->peer_outq = msg_queue_new(peer, false); - peer->last_recv_time = time_now(); + peer->last_recv_time = time_mono(); peer->is_websocket = is_websocket; peer->dev_writes_enabled = NULL; peer->dev_read_enabled = true; diff --git a/connectd/connectd.h b/connectd/connectd.h index fd7509631..cae8b149e 100644 --- a/connectd/connectd.h +++ b/connectd/connectd.h @@ -105,7 +105,7 @@ struct peer { struct oneshot *ping_timer; /* Last time we received traffic */ - struct timeabs last_recv_time; + struct timemono last_recv_time; /* How long have we been ignoring peer input? */ struct timemono peer_in_lasttime; diff --git a/connectd/multiplex.c b/connectd/multiplex.c index a06a21079..5c6fc4fe5 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -634,8 +634,8 @@ static void send_ping(struct peer *peer) /* If it's still sending us traffic, maybe ping reply is backed up? * That's OK, ping is just to make sure it's still alive, and clearly * it is. */ - if (time_before(peer->last_recv_time, - timeabs_sub(time_now(), time_from_sec(60)))) { + if (timemono_before(peer->last_recv_time, + timemono_sub(time_mono(), time_from_sec(60)))) { /* Already have a ping in flight? */ if (peer->expecting_pong != PONG_UNEXPECTED) { status_peer_debug(&peer->id, "Last ping unreturned: hanging up"); @@ -1258,7 +1258,7 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, } /* We got something! */ - peer->last_recv_time = time_now(); + peer->last_recv_time = time_mono(); /* Don't process packets while we're closing */ if (peer->draining_state != NOT_DRAINING) diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 214362514..c68e24545 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -194,7 +194,7 @@ static int gossip_store_compact(struct daemon *daemon, struct gossip_hdr hdr; u8 oldversion, version = GOSSIP_STORE_VER; struct stat st; - struct timeabs start = time_now(); + struct timemono start = time_mono(); const char *bad; *populated = false; @@ -360,7 +360,7 @@ rename_new: } status_debug("Store compact time: %"PRIu64" msec", - time_to_msec(time_between(time_now(), start))); + time_to_msec(timemono_between(time_mono(), start))); status_debug("gossip_store: Read %zu/%zu/%zu/%zu cannounce/cupdate/nannounce/delete from store in %"PRIu64" bytes, now %"PRIu64" bytes (populated=%s)", cannounces, cupdates, nannounces, deleted, old_len, *total_len, diff --git a/lightningd/channel.h b/lightningd/channel.h index 3606d0f98..1281c61e9 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -295,7 +295,7 @@ struct channel { u32 feerate_base, feerate_ppm; /* But allow these feerates/htlcs up until this time. */ - struct timeabs old_feerate_timeout; + struct timemono old_feerate_timeout; u32 old_feerate_base, old_feerate_ppm; struct amount_msat old_htlc_minimum_msat, old_htlc_maximum_msat; diff --git a/lightningd/pay.c b/lightningd/pay.c index b38b8e1e9..068e142e2 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -2018,7 +2018,7 @@ static struct command_result *json_injectpaymentonion(struct command *cmd, if (amount_msat_greater(*msat, next->htlc_maximum_msat) || amount_msat_less(*msat, next->htlc_minimum_msat)) { /* Are we in old-range grace-period? */ - if (!time_before(time_now(), next->old_feerate_timeout) + if (!timemono_before(time_mono(), next->old_feerate_timeout) || amount_msat_less(*msat, next->old_htlc_minimum_msat) || amount_msat_greater(*msat, next->old_htlc_maximum_msat)) { return command_fail(cmd, JSONRPC2_INVALID_PARAMS, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index f5b064ca8..4b44384d9 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -3207,7 +3207,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel, || (htlc_max && amount_msat_less(*htlc_max, channel->htlc_maximum_msat))) { channel->old_feerate_timeout - = timeabs_add(time_now(), time_from_sec(delaysecs)); + = timemono_add(time_mono(), time_from_sec(delaysecs)); channel->old_feerate_base = channel->feerate_base; channel->old_feerate_ppm = channel->feerate_ppm; channel->old_htlc_minimum_msat = channel->htlc_minimum_msat; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 7c818782b..548a15c82 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -848,7 +848,7 @@ static void forward_htlc(struct htlc_in *hin, * - If it creates a new `channel_update` with updated channel parameters: * - SHOULD keep accepting the previous channel parameters for 10 minutes */ - if (!time_before(time_now(), next->old_feerate_timeout) + if (!timemono_before(time_mono(), next->old_feerate_timeout) || !check_fwd_amount(hin, amt_to_forward, hin->msat, next->old_feerate_base, next->old_feerate_ppm)) { @@ -864,7 +864,7 @@ static void forward_htlc(struct htlc_in *hin, if (amount_msat_greater(amt_to_forward, next->htlc_maximum_msat) || amount_msat_less(amt_to_forward, next->htlc_minimum_msat)) { /* Are we in old-range grace-period? */ - if (!time_before(time_now(), next->old_feerate_timeout) + if (!timemono_before(time_mono(), next->old_feerate_timeout) || amount_msat_less(amt_to_forward, next->old_htlc_minimum_msat) || amount_msat_greater(amt_to_forward, next->old_htlc_maximum_msat)) { failmsg = towire_temporary_channel_failure(tmpctx, diff --git a/plugins/bcli.c b/plugins/bcli.c index 7646b3480..faa155c78 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -77,7 +77,7 @@ struct bitcoin_cli { pid_t pid; const char **args; const char **stdinargs; - struct timeabs start; + struct timemono start; enum bitcoind_prio prio; char *output; size_t output_bytes; @@ -260,7 +260,7 @@ static void bcli_finished(struct io_conn *conn UNUSED, struct bitcoin_cli *bcli) int ret, status; struct command_result *res; enum bitcoind_prio prio = bcli->prio; - u64 msec = time_to_msec(time_between(time_now(), bcli->start)); + u64 msec = time_to_msec(timemono_between(time_mono(), bcli->start)); /* If it took over 10 seconds, that's rather strange. */ if (msec > 10000) @@ -336,7 +336,7 @@ static void next_bcli(enum bitcoind_prio prio) } close(in); - bcli->start = time_now(); + bcli->start = time_mono(); bitcoind->num_requests[prio]++; diff --git a/plugins/keysend.c b/plugins/keysend.c index 2e1ba2974..30de252e4 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -239,7 +239,7 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf, p->invstring_used = true; p->why = "Initial attempt"; p->constraints.cltv_budget = *maxdelay; - p->deadline = timeabs_add(time_now(), time_from_sec(*retryfor)); + p->deadline = timemono_add(time_mono(), time_from_sec(*retryfor)); p->getroute->riskfactorppm = 10000000; if (node_id_eq(&my_id, p->route_destination)) { diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 919ca7de3..40814352e 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -2526,12 +2526,12 @@ static struct command_result *retry_step_cb(struct retry_mod_data *rd, { struct payment *subpayment, *root = payment_root(p); struct retry_mod_data *rdata = payment_mod_retry_get_data(p); - struct timeabs now = time_now(); + struct timemono now = time_mono(); if (p->step != PAYMENT_STEP_FAILED) return payment_continue(p); - if (time_after(now, p->deadline)) { + if (timemono_after(now, p->deadline)) { paymod_log( p, LOG_INFORM, "Payment deadline expired, not retrying (partial-)payment " diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index 1498f0fb4..50bd00008 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -200,7 +200,7 @@ struct payment { u32 start_block; struct timeabs start_time, end_time; - struct timeabs deadline; + struct timemono deadline; /* Constraints the state machine and modifiers needs to maintain. */ struct payment_constraints constraints; diff --git a/plugins/pay.c b/plugins/pay.c index acb532c3a..4f44b5e32 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1471,7 +1471,7 @@ static struct command_result *json_pay(struct command *cmd, p->why = "Initial attempt"; p->constraints.cltv_budget = *maxdelay; tal_free(maxdelay); - p->deadline = timeabs_add(time_now(), time_from_sec(*retryfor)); + p->deadline = timemono_add(time_mono(), time_from_sec(*retryfor)); tal_free(retryfor); p->getroute->riskfactorppm = *riskfactor_millionths; tal_free(riskfactor_millionths);