diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 373f8434e..e6df3b411 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -48,6 +48,7 @@ msgdata,channel_init,fulfilled_sides,enum side,num_fulfilled msgdata,channel_init,num_failed,u16, msgdata,channel_init,failed,failed_htlc,num_failed msgdata,channel_init,failed_sides,enum side,num_failed +msgdata,channel_init,failheight,u32, msgdata,channel_init,local_funding_locked,bool, msgdata,channel_init,remote_funding_locked,bool, msgdata,channel_init,funding_short_id,short_channel_id, @@ -97,6 +98,7 @@ msgdata,channel_fulfill_htlc,fulfilled_htlc,fulfilled_htlc, # Main daemon says HTLC failed msgtype,channel_fail_htlc,1006 msgdata,channel_fail_htlc,failed_htlc,failed_htlc, +msgdata,channel_fail_htlc,failheight,u32, # When we receive funding_locked. msgtype,channel_got_funding_locked,1019 diff --git a/channeld/channeld.c b/channeld/channeld.c index bb02ce37a..b47d0c240 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -883,7 +883,8 @@ static u8 *make_failmsg(const tal_t *ctx, const struct htlc *htlc, enum onion_type failcode, const struct short_channel_id *scid, - const struct sha256 *sha256) + const struct sha256 *sha256, + u32 failheight) { u8 *msg, *channel_update = NULL; u32 cltv_expiry = abs_locktime_to_blocks(&htlc->expiry); @@ -940,10 +941,12 @@ static u8 *make_failmsg(const tal_t *ctx, msg = towire_expiry_too_far(ctx); goto done; case WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS: + assert(failheight); msg = towire_incorrect_or_unknown_payment_details( ctx, htlc->amount); goto done; case WIRE_FINAL_EXPIRY_TOO_SOON: + assert(failheight); msg = towire_final_expiry_too_soon(ctx); goto done; case WIRE_FINAL_INCORRECT_CLTV_EXPIRY: @@ -1915,7 +1918,8 @@ static void send_fail_or_fulfill(struct peer *peer, const struct htlc *h) /* Local failure, make a message. */ u8 *failmsg = make_failmsg(tmpctx, peer, h, h->failcode, h->failed_scid, - &h->next_onion_sha); + &h->next_onion_sha, + h->failblock); onion = create_onionreply(tmpctx, h->shared_secret, failmsg); } else /* Remote failure, just forward. */ @@ -2695,8 +2699,9 @@ static void handle_fail(struct peer *peer, const u8 *inmsg) struct failed_htlc *failed_htlc; enum channel_remove_err e; struct htlc *h; + u32 failheight; - if (!fromwire_channel_fail_htlc(inmsg, inmsg, &failed_htlc)) + if (!fromwire_channel_fail_htlc(inmsg, inmsg, &failed_htlc, &failheight)) master_badmsg(WIRE_CHANNEL_FAIL_HTLC, inmsg); e = channel_fail_htlc(peer->channel, REMOTE, failed_htlc->id, &h); @@ -2705,6 +2710,7 @@ static void handle_fail(struct peer *peer, const u8 *inmsg) h->failcode = failed_htlc->failcode; h->fail = tal_steal(h, failed_htlc->failreason); h->failed_scid = tal_steal(h, failed_htlc->scid); + h->failblock = failheight; send_fail_or_fulfill(peer, h); start_commit_timer(peer); return; @@ -2855,7 +2861,7 @@ static void init_channel(struct peer *peer) u8 *funding_signed; const u8 *msg; u32 feerate_per_kw[NUM_SIDES]; - u32 minimum_depth; + u32 minimum_depth, failheight; struct secret last_remote_per_commit_secret; secp256k1_ecdsa_signature *remote_ann_node_sig; secp256k1_ecdsa_signature *remote_ann_bitcoin_sig; @@ -2901,6 +2907,7 @@ static void init_channel(struct peer *peer) &fulfilled_sides, &failed, &failed_sides, + &failheight, &peer->funding_locked[LOCAL], &peer->funding_locked[REMOTE], &peer->short_channel_ids[LOCAL], @@ -2978,7 +2985,7 @@ static void init_channel(struct peer *peer) fulfilled, fulfilled_sides, cast_const2(const struct failed_htlc **, failed), - failed_sides)) + failed_sides, failheight)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could not restore HTLCs"); diff --git a/channeld/channeld_htlc.h b/channeld/channeld_htlc.h index 37b06ffad..6a5a30351 100644 --- a/channeld/channeld_htlc.h +++ b/channeld/channeld_htlc.h @@ -40,6 +40,8 @@ struct htlc { enum onion_type failcode; /* If failcode & UPDATE, this is channel which failed. Otherwise NULL. */ const struct short_channel_id *failed_scid; + /* Block height it failed at */ + u32 failblock; }; static inline bool htlc_has(const struct htlc *h, int flag) diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 190dd8448..838efc75e 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -1133,7 +1133,8 @@ bool channel_force_htlcs(struct channel *channel, const struct fulfilled_htlc *fulfilled, const enum side *fulfilled_sides, const struct failed_htlc **failed, - const enum side *failed_sides) + const enum side *failed_sides, + u32 failheight) { size_t i; struct htlc *htlc; @@ -1259,6 +1260,10 @@ bool channel_force_htlcs(struct channel *channel, return false; } htlc->failcode = failed[i]->failcode; + /* We assume they all failed at the same height, which is + * not necessarily true in case of restart. But it's only + * a hint. */ + htlc->failblock = failheight; if (failed[i]->failreason) htlc->fail = tal_dup_arr(htlc, u8, failed[i]->failreason, diff --git a/channeld/full_channel.h b/channeld/full_channel.h index e55daf3be..551764521 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -236,6 +236,7 @@ size_t num_channel_htlcs(const struct channel *channel); * @fulfilled_sides: sides for ids in @fulfilled * @failed: htlcs of those which are failed * @failed_sides: sides for ids in @failed + * @failheight: block number which htlcs failed at. * * This is used for restoring a channel state. */ @@ -245,7 +246,8 @@ bool channel_force_htlcs(struct channel *channel, const struct fulfilled_htlc *fulfilled, const enum side *fulfilled_sides, const struct failed_htlc **failed, - const enum side *failed_sides); + const enum side *failed_sides, + u32 failheight); /** * dump_htlcs: debugging dump of all HTLCs diff --git a/devtools/mkcommit.c b/devtools/mkcommit.c index 8d2b27790..d671725f8 100644 --- a/devtools/mkcommit.c +++ b/devtools/mkcommit.c @@ -357,7 +357,8 @@ int main(int argc, char *argv[]) &funding_localkey, &funding_remotekey, fee_payer); - if (!channel_force_htlcs(channel, htlcs, hstates, NULL, NULL, NULL, NULL)) + if (!channel_force_htlcs(channel, htlcs, hstates, NULL, NULL, NULL, NULL, + 0)) errx(1, "Cannot add HTLCs"); u8 *funding_wscript = bitcoin_redeem_2of2(NULL, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index f5ac55013..b05bdc955 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -410,6 +410,9 @@ void peer_start_channeld(struct channel *channel, htlcs, htlc_states, fulfilled_htlcs, fulfilled_sides, failed_htlcs, failed_sides, + /* This is an approximation, but failing + * on restart is a corner case */ + get_block_height(ld->topology), channel->scid != NULL, channel->remote_funding_locked, &scid, diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 9dc5d6bd0..3bf82759f 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -124,7 +124,8 @@ static void fail_in_htlc(struct htlc_in *hin, else failed_htlc.scid = NULL; subd_send_msg(hin->key.channel->owner, - take(towire_channel_fail_htlc(NULL, &failed_htlc))); + take(towire_channel_fail_htlc(NULL, &failed_htlc, + get_block_height(hin->key.channel->owner->ld->topology)))); } /* This is used for cases where we can immediately fail the HTLC. */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 0cbc89f9e..be8dc36e6 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -541,7 +541,7 @@ u8 *towire_channel_dev_memleak(const tal_t *ctx UNNEEDED) u8 *towire_channel_dev_reenable_commit(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channel_dev_reenable_commit called!\n"); abort(); } /* Generated stub for towire_channel_fail_htlc */ -u8 *towire_channel_fail_htlc(const tal_t *ctx UNNEEDED, const struct failed_htlc *failed_htlc UNNEEDED) +u8 *towire_channel_fail_htlc(const tal_t *ctx UNNEEDED, const struct failed_htlc *failed_htlc UNNEEDED, u32 failheight UNUSED) { fprintf(stderr, "towire_channel_fail_htlc called!\n"); abort(); } /* Generated stub for towire_channel_fulfill_htlc */ u8 *towire_channel_fulfill_htlc(const tal_t *ctx UNNEEDED, const struct fulfilled_htlc *fulfilled_htlc UNNEEDED)