mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
lightningd: instead of malformed code, keep generic error code.
This is in preparation for generating the actual error messages inside channeld. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
70cebb8653
commit
be35895847
@@ -80,8 +80,10 @@ struct htlc_in *htlc_in_check(const struct htlc_in *hin, const char *abortstr)
|
|||||||
return corrupt(hin, abortstr, "invalid state %s",
|
return corrupt(hin, abortstr, "invalid state %s",
|
||||||
htlc_state_name(hin->hstate));
|
htlc_state_name(hin->hstate));
|
||||||
else if (hin->failuremsg && hin->preimage)
|
else if (hin->failuremsg && hin->preimage)
|
||||||
return corrupt(hin, abortstr, "Both failed and succeeded");
|
return corrupt(hin, abortstr, "Both failuremsg and succeeded");
|
||||||
else if (hin->failuremsg && hin->malformed)
|
else if (hin->failcode != 0 && hin->preimage)
|
||||||
|
return corrupt(hin, abortstr, "Both failcode and succeeded");
|
||||||
|
else if (hin->failuremsg && (hin->failcode & BADONION))
|
||||||
return corrupt(hin, abortstr, "Both failed and malformed");
|
return corrupt(hin, abortstr, "Both failed and malformed");
|
||||||
|
|
||||||
return cast_const(struct htlc_in *, hin);
|
return cast_const(struct htlc_in *, hin);
|
||||||
@@ -107,8 +109,8 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
|
|||||||
sizeof(hin->onion_routing_packet));
|
sizeof(hin->onion_routing_packet));
|
||||||
|
|
||||||
hin->hstate = RCVD_ADD_COMMIT;
|
hin->hstate = RCVD_ADD_COMMIT;
|
||||||
|
hin->failcode = 0;
|
||||||
hin->failuremsg = NULL;
|
hin->failuremsg = NULL;
|
||||||
hin->malformed = 0;
|
|
||||||
hin->preimage = NULL;
|
hin->preimage = NULL;
|
||||||
|
|
||||||
return htlc_in_check(hin, "new_htlc_in");
|
return htlc_in_check(hin, "new_htlc_in");
|
||||||
@@ -155,8 +157,8 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
|
|||||||
sizeof(hout->onion_routing_packet));
|
sizeof(hout->onion_routing_packet));
|
||||||
|
|
||||||
hout->hstate = SENT_ADD_HTLC;
|
hout->hstate = SENT_ADD_HTLC;
|
||||||
|
hout->failcode = 0;
|
||||||
hout->failuremsg = NULL;
|
hout->failuremsg = NULL;
|
||||||
hout->malformed = 0;
|
|
||||||
hout->preimage = NULL;
|
hout->preimage = NULL;
|
||||||
|
|
||||||
hout->in = in;
|
hout->in = in;
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ struct htlc_in {
|
|||||||
/* Shared secret for us to send any failure message. */
|
/* Shared secret for us to send any failure message. */
|
||||||
struct secret shared_secret;
|
struct secret shared_secret;
|
||||||
|
|
||||||
/* If we failed HTLC, here's the message. */
|
/* If a local error, this is non-zero. */
|
||||||
const u8 *failuremsg;
|
enum onion_type failcode;
|
||||||
|
|
||||||
/* If it was malformed, here's the error. */
|
/* Either a remote error, or local error if !(failure & BADONION). */
|
||||||
enum onion_type malformed;
|
const u8 *failuremsg;
|
||||||
|
|
||||||
/* If they fulfilled, here's the preimage. */
|
/* If they fulfilled, here's the preimage. */
|
||||||
struct preimage *preimage;
|
struct preimage *preimage;
|
||||||
@@ -58,11 +58,11 @@ struct htlc_out {
|
|||||||
/* Onion information */
|
/* Onion information */
|
||||||
u8 onion_routing_packet[TOTAL_PACKET_SIZE];
|
u8 onion_routing_packet[TOTAL_PACKET_SIZE];
|
||||||
|
|
||||||
/* If we failed HTLC, here's the message. */
|
/* If a local error, this is non-zero. */
|
||||||
const u8 *failuremsg;
|
enum onion_type failcode;
|
||||||
|
|
||||||
/* If it was malformed, here's the error. */
|
/* Either a remote error, or local error if !(failure & BADONION). */
|
||||||
enum onion_type malformed;
|
const u8 *failuremsg;
|
||||||
|
|
||||||
/* If we fulfilled, here's the preimage. */
|
/* If we fulfilled, here's the preimage. */
|
||||||
struct preimage *preimage;
|
struct preimage *preimage;
|
||||||
|
|||||||
@@ -79,41 +79,35 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
|
|||||||
const char *localfail)
|
const char *localfail)
|
||||||
{
|
{
|
||||||
struct pay_command *pc = hout->pay_command;
|
struct pay_command *pc = hout->pay_command;
|
||||||
enum onion_type failcode;
|
|
||||||
struct onionreply *reply;
|
struct onionreply *reply;
|
||||||
|
enum onion_type failcode;
|
||||||
|
|
||||||
wallet_payment_set_status(ld->wallet, &hout->payment_hash, PAYMENT_FAILED);
|
wallet_payment_set_status(ld->wallet, &hout->payment_hash, PAYMENT_FAILED);
|
||||||
|
|
||||||
/* This gives more details than a generic failure message,
|
/* This gives more details than a generic failure message */
|
||||||
* and also the failuremsg here is unencrypted */
|
|
||||||
if (localfail) {
|
if (localfail) {
|
||||||
size_t max = tal_len(hout->failuremsg);
|
json_pay_failed(pc, NULL, hout->failcode, localfail);
|
||||||
const u8 *p = hout->failuremsg;
|
|
||||||
failcode = fromwire_u16(&p, &max);
|
|
||||||
json_pay_failed(pc, NULL, failcode, localfail);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hout->malformed)
|
/* Must be remote fail. */
|
||||||
failcode = hout->malformed;
|
assert(!hout->failcode);
|
||||||
else {
|
reply = unwrap_onionreply(pc, pc->path_secrets,
|
||||||
reply = unwrap_onionreply(pc, pc->path_secrets,
|
tal_count(pc->path_secrets),
|
||||||
tal_count(pc->path_secrets),
|
hout->failuremsg);
|
||||||
hout->failuremsg);
|
if (!reply) {
|
||||||
if (!reply) {
|
log_info(hout->key.peer->log,
|
||||||
log_info(hout->key.peer->log,
|
"htlc %"PRIu64" failed with bad reply (%s)",
|
||||||
"htlc %"PRIu64" failed with bad reply (%s)",
|
hout->key.id,
|
||||||
hout->key.id,
|
tal_hex(pc, hout->failuremsg));
|
||||||
tal_hex(pc, hout->failuremsg));
|
failcode = WIRE_PERMANENT_NODE_FAILURE;
|
||||||
failcode = WIRE_PERMANENT_NODE_FAILURE;
|
} else {
|
||||||
} else {
|
failcode = fromwire_peektype(reply->msg);
|
||||||
failcode = fromwire_peektype(reply->msg);
|
log_info(hout->key.peer->log,
|
||||||
log_info(hout->key.peer->log,
|
"htlc %"PRIu64" failed from %ith node with code 0x%04x (%s)",
|
||||||
"htlc %"PRIu64" failed from %ith node with code 0x%04x (%s)",
|
hout->key.id,
|
||||||
hout->key.id,
|
reply->origin_index,
|
||||||
reply->origin_index,
|
failcode, onion_type_name(failcode));
|
||||||
failcode, onion_type_name(failcode));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: save ids we can turn reply->origin_index into sender. */
|
/* FIXME: save ids we can turn reply->origin_index into sender. */
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
u8 *msg;
|
||||||
|
|
||||||
log_info(hin->key.peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)",
|
log_info(hin->key.peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)",
|
||||||
hin->key.id, failcode, onion_type_name(failcode));
|
hin->key.id, failcode, onion_type_name(failcode));
|
||||||
|
|
||||||
if (failcode & BADONION)
|
/* FIXME: Get update! */
|
||||||
fail_in_htlc(hin, failcode, NULL);
|
msg = make_failmsg(hin, hin->key.peer->log,
|
||||||
else {
|
hin->msatoshi, failcode, NULL);
|
||||||
u8 *msg;
|
|
||||||
|
|
||||||
if (failcode & UPDATE) {
|
fail_in_htlc(hin, failcode, msg);
|
||||||
/* FIXME: Ask gossip daemon for channel_update. */
|
tal_free(msg);
|
||||||
}
|
|
||||||
|
|
||||||
msg = make_failmsg(hin, hin->key.peer->log,
|
|
||||||
hin->msatoshi, failcode, NULL);
|
|
||||||
fail_in_htlc(hin, 0, take(create_onionreply(hin, &hin->shared_secret, 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) {
|
||||||
|
|||||||
@@ -901,8 +901,9 @@ static bool wallet_stmt2htlc_in(const struct wallet_channel *channel,
|
|||||||
memcpy(&in->onion_routing_packet, sqlite3_column_blob(stmt, 8),
|
memcpy(&in->onion_routing_packet, sqlite3_column_blob(stmt, 8),
|
||||||
sizeof(in->onion_routing_packet));
|
sizeof(in->onion_routing_packet));
|
||||||
|
|
||||||
|
/* FIXME: These need to be saved in db! */
|
||||||
in->failuremsg = NULL;
|
in->failuremsg = NULL;
|
||||||
in->malformed = 0;
|
in->failcode = 0;
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -936,7 +937,7 @@ static bool wallet_stmt2htlc_out(const struct wallet_channel *channel,
|
|||||||
sizeof(out->onion_routing_packet));
|
sizeof(out->onion_routing_packet));
|
||||||
|
|
||||||
out->failuremsg = NULL;
|
out->failuremsg = NULL;
|
||||||
out->malformed = 0;
|
out->failcode = 0;
|
||||||
|
|
||||||
/* Need to defer wiring until we can look up all incoming
|
/* Need to defer wiring until we can look up all incoming
|
||||||
* htlcs, will wire using origin_htlc_id */
|
* htlcs, will wire using origin_htlc_id */
|
||||||
|
|||||||
Reference in New Issue
Block a user