|
|
@ -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); |
|
|
|
} |
|
|
|