Browse Source

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>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
be35895847
  1. 10
      lightningd/htlc_end.c
  2. 16
      lightningd/htlc_end.h
  3. 16
      lightningd/pay.c
  4. 66
      lightningd/peer_htlcs.c
  5. 5
      wallet/wallet.c

10
lightningd/htlc_end.c

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

16
lightningd/htlc_end.h

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

16
lightningd/pay.c

@ -79,24 +79,19 @@ 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);
@ -114,7 +109,6 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
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. */

66
lightningd/peer_htlcs.c

@ -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) {

5
wallet/wallet.c

@ -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 */

Loading…
Cancel
Save