|
|
@ -12,6 +12,7 @@ |
|
|
|
#include <common/type_to_string.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <plugins/libplugin-pay.h> |
|
|
|
#include <wire/peer_wire.h> |
|
|
|
|
|
|
|
static struct gossmap *global_gossmap; |
|
|
|
|
|
|
@ -1340,13 +1341,106 @@ static bool assign_blame(const struct payment *p, |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/* Fix up the channel_update to include the type if it doesn't currently have
|
|
|
|
* one. See ElementsProject/lightning#1730 and lightningnetwork/lnd#1599 for the |
|
|
|
* in-depth discussion on why we break message parsing here... */ |
|
|
|
static u8 *patch_channel_update(const tal_t *ctx, u8 *channel_update TAKES) |
|
|
|
{ |
|
|
|
u8 *fixed; |
|
|
|
if (channel_update != NULL && |
|
|
|
fromwire_peektype(channel_update) != WIRE_CHANNEL_UPDATE) { |
|
|
|
/* This should be a channel_update, prefix with the
|
|
|
|
* WIRE_CHANNEL_UPDATE type, but isn't. Let's prefix it. */ |
|
|
|
fixed = tal_arr(ctx, u8, 0); |
|
|
|
towire_u16(&fixed, WIRE_CHANNEL_UPDATE); |
|
|
|
towire(&fixed, channel_update, tal_bytelen(channel_update)); |
|
|
|
if (taken(channel_update)) |
|
|
|
tal_free(channel_update); |
|
|
|
return fixed; |
|
|
|
} else { |
|
|
|
return tal_dup_talarr(ctx, u8, channel_update); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Return NULL if the wrapped onion error message has no channel_update field,
|
|
|
|
* or return the embedded channel_update message otherwise. */ |
|
|
|
static u8 *channel_update_from_onion_error(const tal_t *ctx, |
|
|
|
const u8 *onion_message) |
|
|
|
{ |
|
|
|
u8 *channel_update = NULL; |
|
|
|
struct amount_msat unused_msat; |
|
|
|
u32 unused32; |
|
|
|
|
|
|
|
/* Identify failcodes that have some channel_update.
|
|
|
|
* |
|
|
|
* TODO > BOLT 1.0: Add new failcodes when updating to a |
|
|
|
* new BOLT version. */ |
|
|
|
if (!fromwire_temporary_channel_failure(ctx, |
|
|
|
onion_message, |
|
|
|
&channel_update) && |
|
|
|
!fromwire_amount_below_minimum(ctx, |
|
|
|
onion_message, &unused_msat, |
|
|
|
&channel_update) && |
|
|
|
!fromwire_fee_insufficient(ctx, |
|
|
|
onion_message, &unused_msat, |
|
|
|
&channel_update) && |
|
|
|
!fromwire_incorrect_cltv_expiry(ctx, |
|
|
|
onion_message, &unused32, |
|
|
|
&channel_update) && |
|
|
|
!fromwire_expiry_too_soon(ctx, |
|
|
|
onion_message, |
|
|
|
&channel_update)) |
|
|
|
/* No channel update. */ |
|
|
|
return NULL; |
|
|
|
|
|
|
|
return patch_channel_update(ctx, take(channel_update)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static struct command_result * |
|
|
|
payment_waitsendpay_finished(struct command *cmd, const char *buffer, |
|
|
|
const jsmntok_t *toks, struct payment *p) |
|
|
|
payment_addgossip_success(struct command *cmd, const char *buffer, |
|
|
|
const jsmntok_t *toks, struct payment *p) |
|
|
|
{ |
|
|
|
const struct node_id *errnode; |
|
|
|
const struct route_hop *errchan; |
|
|
|
|
|
|
|
if (!assign_blame(p, &errnode, &errchan)) { |
|
|
|
paymod_log(p, LOG_UNUSUAL, |
|
|
|
"No erring_index set in `waitsendpay` result: %.*s", |
|
|
|
json_tok_full_len(toks), |
|
|
|
json_tok_full(buffer, toks)); |
|
|
|
/* FIXME: Pick a random channel to fail? */ |
|
|
|
payment_set_step(p, PAYMENT_STEP_FAILED); |
|
|
|
payment_continue(p); |
|
|
|
return command_still_pending(cmd); |
|
|
|
} |
|
|
|
|
|
|
|
if (!errchan) |
|
|
|
return handle_final_failure(cmd, p, errnode, |
|
|
|
p->result->failcode); |
|
|
|
|
|
|
|
return handle_intermediate_failure(cmd, p, errnode, errchan, |
|
|
|
p->result->failcode); |
|
|
|
} |
|
|
|
|
|
|
|
/* If someone gives us an invalid update, all we can do is log it */ |
|
|
|
static struct command_result * |
|
|
|
payment_addgossip_failure(struct command *cmd, const char *buffer, |
|
|
|
const jsmntok_t *toks, struct payment *p) |
|
|
|
{ |
|
|
|
paymod_log(p, LOG_DBG, "Invalid channel_update: %.*s", |
|
|
|
json_tok_full_len(toks), |
|
|
|
json_tok_full(buffer, toks)); |
|
|
|
|
|
|
|
return payment_addgossip_success(cmd, NULL, NULL, p); |
|
|
|
} |
|
|
|
|
|
|
|
static struct command_result * |
|
|
|
payment_waitsendpay_finished(struct command *cmd, const char *buffer, |
|
|
|
const jsmntok_t *toks, struct payment *p) |
|
|
|
{ |
|
|
|
u8 *update; |
|
|
|
|
|
|
|
assert(p->route != NULL); |
|
|
|
|
|
|
|
p->end_time = time_now(); |
|
|
@ -1372,23 +1466,19 @@ payment_waitsendpay_finished(struct command *cmd, const char *buffer, |
|
|
|
|
|
|
|
payment_chanhints_apply_route(p, true); |
|
|
|
|
|
|
|
if (!assign_blame(p, &errnode, &errchan)) { |
|
|
|
paymod_log(p, LOG_UNUSUAL, |
|
|
|
"No erring_index set in `waitsendpay` result: %.*s", |
|
|
|
json_tok_full_len(toks), |
|
|
|
json_tok_full(buffer, toks)); |
|
|
|
/* FIXME: Pick a random channel to fail? */ |
|
|
|
payment_set_step(p, PAYMENT_STEP_FAILED); |
|
|
|
payment_continue(p); |
|
|
|
/* Tell gossipd, if we received an update */ |
|
|
|
update = channel_update_from_onion_error(tmpctx, p->result->raw_message); |
|
|
|
if (update) { |
|
|
|
struct out_req *req; |
|
|
|
req = jsonrpc_request_start(p->plugin, NULL, "addgossip", |
|
|
|
payment_addgossip_success, |
|
|
|
payment_addgossip_failure, p); |
|
|
|
json_add_hex_talarr(req->js, "message", update); |
|
|
|
send_outreq(p->plugin, req); |
|
|
|
return command_still_pending(cmd); |
|
|
|
} |
|
|
|
|
|
|
|
if (!errchan) |
|
|
|
return handle_final_failure(cmd, p, errnode, |
|
|
|
p->result->failcode); |
|
|
|
|
|
|
|
return handle_intermediate_failure(cmd, p, errnode, errchan, |
|
|
|
p->result->failcode); |
|
|
|
return payment_addgossip_success(cmd, NULL, NULL, p); |
|
|
|
} |
|
|
|
|
|
|
|
static struct command_result *payment_sendonion_success(struct command *cmd, |
|
|
|