|
@ -78,16 +78,13 @@ static bool htlc_out_update_state(struct peer *peer, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void fail_in_htlc(struct htlc_in *hin, |
|
|
static void fail_in_htlc(struct htlc_in *hin, |
|
|
enum onion_type malformed, |
|
|
enum onion_type failcode, |
|
|
const u8 *failuremsg) |
|
|
const u8 *failuremsg) |
|
|
{ |
|
|
{ |
|
|
assert(!hin->preimage); |
|
|
assert(!hin->preimage); |
|
|
if (malformed) |
|
|
|
|
|
assert(!failuremsg); |
|
|
|
|
|
else |
|
|
|
|
|
assert(failuremsg); |
|
|
|
|
|
|
|
|
|
|
|
hin->malformed = malformed; |
|
|
assert(failcode || failuremsg); |
|
|
|
|
|
hin->failcode = failcode; |
|
|
if (failuremsg) |
|
|
if (failuremsg) |
|
|
hin->failuremsg = tal_dup_arr(hin, u8, failuremsg, tal_len(failuremsg), 0); |
|
|
hin->failuremsg = tal_dup_arr(hin, u8, failuremsg, tal_len(failuremsg), 0); |
|
|
|
|
|
|
|
@ -98,11 +95,11 @@ static void fail_in_htlc(struct htlc_in *hin, |
|
|
if (!hin->key.peer->owner) |
|
|
if (!hin->key.peer->owner) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
if (hin->malformed) { |
|
|
if (!hin->failuremsg) { |
|
|
subd_send_msg(hin->key.peer->owner, |
|
|
subd_send_msg(hin->key.peer->owner, |
|
|
take(towire_channel_fail_htlc(hin, |
|
|
take(towire_channel_fail_htlc(hin, |
|
|
hin->key.id, |
|
|
hin->key.id, |
|
|
hin->malformed, |
|
|
hin->failcode, |
|
|
NULL))); |
|
|
NULL))); |
|
|
} else { |
|
|
} else { |
|
|
u8 *reply; |
|
|
u8 *reply; |
|
@ -167,7 +164,8 @@ static u8 *make_failmsg(const tal_t *ctx, |
|
|
case WIRE_INVALID_ONION_VERSION: |
|
|
case WIRE_INVALID_ONION_VERSION: |
|
|
case WIRE_INVALID_ONION_HMAC: |
|
|
case WIRE_INVALID_ONION_HMAC: |
|
|
case WIRE_INVALID_ONION_KEY: |
|
|
case WIRE_INVALID_ONION_KEY: |
|
|
fatal("Bad failmsg for %s", onion_type_name(failcode)); |
|
|
/* We don't have anything to add for these; code is enough */ |
|
|
|
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
log_broken(log, "Asked to create unknown failmsg %u:" |
|
|
log_broken(log, "Asked to create unknown failmsg %u:" |
|
@ -178,33 +176,26 @@ static u8 *make_failmsg(const tal_t *ctx, |
|
|
/* This is used for cases where we can immediately fail the HTLC. */ |
|
|
/* This is used for cases where we can immediately fail the HTLC. */ |
|
|
static void local_fail_htlc(struct htlc_in *hin, enum onion_type failcode) |
|
|
static void local_fail_htlc(struct htlc_in *hin, enum onion_type failcode) |
|
|
{ |
|
|
{ |
|
|
log_info(hin->key.peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)", |
|
|
|
|
|
hin->key.id, failcode, onion_type_name(failcode)); |
|
|
|
|
|
|
|
|
|
|
|
if (failcode & BADONION) |
|
|
|
|
|
fail_in_htlc(hin, failcode, NULL); |
|
|
|
|
|
else { |
|
|
|
|
|
u8 *msg; |
|
|
u8 *msg; |
|
|
|
|
|
|
|
|
if (failcode & UPDATE) { |
|
|
log_info(hin->key.peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)", |
|
|
/* FIXME: Ask gossip daemon for channel_update. */ |
|
|
hin->key.id, failcode, onion_type_name(failcode)); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* FIXME: Get update! */ |
|
|
msg = make_failmsg(hin, hin->key.peer->log, |
|
|
msg = make_failmsg(hin, hin->key.peer->log, |
|
|
hin->msatoshi, failcode, NULL); |
|
|
hin->msatoshi, failcode, NULL); |
|
|
fail_in_htlc(hin, 0, take(create_onionreply(hin, &hin->shared_secret, msg))); |
|
|
|
|
|
|
|
|
fail_in_htlc(hin, failcode, msg); |
|
|
tal_free(msg); |
|
|
tal_free(msg); |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* localfail are for handing to the local payer if it's local. */ |
|
|
/* localfail are for handing to the local payer if it's local. */ |
|
|
static void fail_out_htlc(struct htlc_out *hout, const char *localfail) |
|
|
static void fail_out_htlc(struct htlc_out *hout, const char *localfail) |
|
|
{ |
|
|
{ |
|
|
htlc_out_check(hout, __func__); |
|
|
htlc_out_check(hout, __func__); |
|
|
assert(hout->malformed || hout->failuremsg); |
|
|
assert(hout->failcode || hout->failuremsg); |
|
|
assert(!hout->malformed || !hout->failuremsg); |
|
|
|
|
|
if (hout->in) { |
|
|
if (hout->in) { |
|
|
fail_in_htlc(hout->in, hout->malformed, hout->failuremsg); |
|
|
fail_in_htlc(hout->in, hout->failcode, hout->failuremsg); |
|
|
} else { |
|
|
} else { |
|
|
payment_failed(hout->key.peer->ld, hout, localfail); |
|
|
payment_failed(hout->key.peer->ld, hout, localfail); |
|
|
} |
|
|
} |
|
@ -796,13 +787,16 @@ static bool peer_failed_our_htlc(struct peer *peer, |
|
|
if (!htlc_out_update_state(peer, hout, RCVD_REMOVE_COMMIT)) |
|
|
if (!htlc_out_update_state(peer, hout, RCVD_REMOVE_COMMIT)) |
|
|
return false; |
|
|
return false; |
|
|
|
|
|
|
|
|
log_debug(peer->log, "Our HTLC %"PRIu64" failed (%u)", failed->id, |
|
|
hout->failcode = failed->malformed; |
|
|
failed->malformed); |
|
|
if (!failed->malformed) |
|
|
if (failed->malformed) |
|
|
|
|
|
hout->malformed = failed->malformed; |
|
|
|
|
|
else |
|
|
|
|
|
hout->failuremsg = tal_dup_arr(hout, u8, failed->failreason, |
|
|
hout->failuremsg = tal_dup_arr(hout, u8, failed->failreason, |
|
|
tal_len(failed->failreason), 0); |
|
|
tal_len(failed->failreason), 0); |
|
|
|
|
|
|
|
|
|
|
|
else |
|
|
|
|
|
hout->failuremsg = NULL; |
|
|
|
|
|
|
|
|
|
|
|
log_debug(peer->log, "Our HTLC %"PRIu64" failed (%u)", failed->id, |
|
|
|
|
|
hout->failcode); |
|
|
htlc_out_check(hout, __func__); |
|
|
htlc_out_check(hout, __func__); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
@ -857,13 +851,13 @@ void onchain_failed_our_htlc(const struct peer *peer, |
|
|
static void remove_htlc_in(struct peer *peer, struct htlc_in *hin) |
|
|
static void remove_htlc_in(struct peer *peer, struct htlc_in *hin) |
|
|
{ |
|
|
{ |
|
|
htlc_in_check(hin, __func__); |
|
|
htlc_in_check(hin, __func__); |
|
|
assert(hin->failuremsg || hin->preimage || hin->malformed); |
|
|
assert(hin->failuremsg || hin->preimage || hin->failcode); |
|
|
|
|
|
|
|
|
log_debug(peer->log, "Removing in HTLC %"PRIu64" state %s %s", |
|
|
log_debug(peer->log, "Removing in HTLC %"PRIu64" state %s %s", |
|
|
hin->key.id, htlc_state_name(hin->hstate), |
|
|
hin->key.id, htlc_state_name(hin->hstate), |
|
|
hin->failuremsg ? "FAILED" |
|
|
hin->preimage ? "FULFILLED" |
|
|
: hin->malformed ? "MALFORMED" |
|
|
: hin->failcode ? onion_type_name(hin->failcode) |
|
|
: "FULFILLED"); |
|
|
: "REMOTEFAIL"); |
|
|
|
|
|
|
|
|
/* If we fulfilled their HTLC, credit us. */ |
|
|
/* If we fulfilled their HTLC, credit us. */ |
|
|
if (hin->preimage) { |
|
|
if (hin->preimage) { |
|
@ -879,12 +873,12 @@ static void remove_htlc_in(struct peer *peer, struct htlc_in *hin) |
|
|
static void remove_htlc_out(struct peer *peer, struct htlc_out *hout) |
|
|
static void remove_htlc_out(struct peer *peer, struct htlc_out *hout) |
|
|
{ |
|
|
{ |
|
|
htlc_out_check(hout, __func__); |
|
|
htlc_out_check(hout, __func__); |
|
|
assert(hout->failuremsg || hout->preimage || hout->malformed); |
|
|
assert(hout->failuremsg || hout->preimage || hout->failcode); |
|
|
log_debug(peer->log, "Removing out HTLC %"PRIu64" state %s %s", |
|
|
log_debug(peer->log, "Removing out HTLC %"PRIu64" state %s %s", |
|
|
hout->key.id, htlc_state_name(hout->hstate), |
|
|
hout->key.id, htlc_state_name(hout->hstate), |
|
|
hout->failuremsg ? "FAILED" |
|
|
hout->preimage ? "FULFILLED" |
|
|
: hout->malformed ? "MALFORMED" |
|
|
: hout->failcode ? onion_type_name(hout->failcode) |
|
|
: "FULFILLED"); |
|
|
: "REMOTEFAIL"); |
|
|
|
|
|
|
|
|
/* If it's failed, now we can forward since it's completely locked-in */ |
|
|
/* If it's failed, now we can forward since it's completely locked-in */ |
|
|
if (!hout->preimage) { |
|
|
if (!hout->preimage) { |
|
|