mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-07 08:04:23 +01:00
lightningd: fail htlcs we fulfill if peer unresponsive after deadline.
Closes: #241 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -289,9 +289,6 @@ static void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage)
|
||||
if (peer_state_on_chain(hin->key.peer->state)) {
|
||||
msg = towire_onchain_known_preimage(hin, preimage);
|
||||
} else {
|
||||
/* FIXME: fail the peer if it doesn't tell us that htlc
|
||||
* fulfill is committed before deadline.
|
||||
*/
|
||||
msg = towire_channel_fulfill_htlc(hin, hin->key.id, preimage);
|
||||
}
|
||||
subd_send_msg(hin->key.peer->owner, take(msg));
|
||||
@@ -1437,6 +1434,21 @@ static u32 htlc_out_deadline(const struct htlc_out *hout)
|
||||
return hout->cltv_expiry + 1;
|
||||
}
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* For HTLCs we accept and have a preimage: the fulfillment deadline when we
|
||||
* have to fail the channel and fulfill the HTLC onchain before its
|
||||
* `cltv_expiry`. This is steps 4-7 above, which means a deadline of `2R+G+S`
|
||||
* blocks before `cltv_expiry`; 7 blocks is reasonable.
|
||||
*/
|
||||
/* We approximate this, by using half the cltv_expiry_delta (3R+2G+2S),
|
||||
* rounded up. */
|
||||
static u32 htlc_in_deadline(const struct lightningd *ld,
|
||||
const struct htlc_in *hin)
|
||||
{
|
||||
return hin->cltv_expiry - (ld->config.cltv_expiry_delta + 1)/2;
|
||||
}
|
||||
|
||||
void notify_new_block(struct lightningd *ld, u32 height)
|
||||
{
|
||||
bool removed;
|
||||
@@ -1480,4 +1492,49 @@ void notify_new_block(struct lightningd *ld, u32 height)
|
||||
}
|
||||
/* Iteration while removing is safe, but can skip entries! */
|
||||
} while (removed);
|
||||
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST estimate a fulfillment deadline for each HTLC it is
|
||||
* attempting to fulfill. A node ... MUST fail the connection if a
|
||||
* HTLC it has fulfilled is in either node's current commitment
|
||||
* transaction past this fulfillment deadline.
|
||||
*/
|
||||
do {
|
||||
struct htlc_in *hin;
|
||||
struct htlc_in_map_iter ini;
|
||||
|
||||
removed = false;
|
||||
|
||||
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
|
||||
hin;
|
||||
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
|
||||
/* Not fulfilled? If overdue, that's their problem... */
|
||||
if (!hin->preimage)
|
||||
continue;
|
||||
|
||||
/* Not timed out yet? */
|
||||
if (height < htlc_in_deadline(ld, hin))
|
||||
continue;
|
||||
|
||||
/* Peer on chain already? */
|
||||
if (peer_on_chain(hin->key.peer))
|
||||
continue;
|
||||
|
||||
/* Peer already failed, or we hit it? */
|
||||
if (hin->key.peer->error)
|
||||
continue;
|
||||
|
||||
peer_fail_permanent_str(hin->key.peer,
|
||||
take(tal_fmt(hin,
|
||||
"Fulfilled HTLC %"PRIu64
|
||||
" %s cltv %u hit deadline",
|
||||
hin->key.id,
|
||||
htlc_state_name(hin->hstate),
|
||||
hin->cltv_expiry)));
|
||||
removed = true;
|
||||
}
|
||||
/* Iteration while removing is safe, but can skip entries! */
|
||||
} while (removed);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user