mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 18:57:06 +01:00
parent
452925c05a
commit
a6c6b8d9d3
2 changed files with 94 additions and 25 deletions
|
@ -10,4 +10,13 @@
|
||||||
#define JSONRPC2_METHOD_NOT_FOUND -32601
|
#define JSONRPC2_METHOD_NOT_FOUND -32601
|
||||||
#define JSONRPC2_INVALID_PARAMS -32602
|
#define JSONRPC2_INVALID_PARAMS -32602
|
||||||
|
|
||||||
|
/* Errors from `pay` and `sendpay` commands */
|
||||||
|
#define PAY_IN_PROGRESS 200
|
||||||
|
#define PAY_RHASH_ALREADY_USED 201
|
||||||
|
#define PAY_UNPARSEABLE_ONION 202
|
||||||
|
#define PAY_DESTINATION_PERM_FAIL 203
|
||||||
|
#define PAY_TRY_OTHER_ROUTE 204
|
||||||
|
#define PAY_ROUTE_NOT_FOUND 205
|
||||||
|
#define PAY_ROUTE_TOO_EXPENSIVE 206
|
||||||
|
|
||||||
#endif /* !defined (LIGHTNING_LIGHTNINGD_JSONRPC_ERRORS_H) */
|
#endif /* !defined (LIGHTNING_LIGHTNINGD_JSONRPC_ERRORS_H) */
|
||||||
|
|
104
lightningd/pay.c
104
lightningd/pay.c
|
@ -10,6 +10,7 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <lightningd/chaintopology.h>
|
#include <lightningd/chaintopology.h>
|
||||||
#include <lightningd/jsonrpc.h>
|
#include <lightningd/jsonrpc.h>
|
||||||
|
#include <lightningd/jsonrpc_errors.h>
|
||||||
#include <lightningd/lightningd.h>
|
#include <lightningd/lightningd.h>
|
||||||
#include <lightningd/log.h>
|
#include <lightningd/log.h>
|
||||||
#include <lightningd/options.h>
|
#include <lightningd/options.h>
|
||||||
|
@ -73,9 +74,61 @@ static void json_pay_success(struct lightningd *ld,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct routing_failure {
|
||||||
|
int origin_index;
|
||||||
|
enum onion_type failcode;
|
||||||
|
struct pubkey erring_node;
|
||||||
|
struct short_channel_id erring_channel;
|
||||||
|
u8 *channel_update;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
json_pay_command_routing_failed(struct command *cmd,
|
||||||
|
bool retry_plausible,
|
||||||
|
const struct routing_failure *fail,
|
||||||
|
const u8 *onionreply,
|
||||||
|
const char *details)
|
||||||
|
{
|
||||||
|
int code =
|
||||||
|
(!fail) ? PAY_UNPARSEABLE_ONION :
|
||||||
|
(!retry_plausible) ? PAY_DESTINATION_PERM_FAIL :
|
||||||
|
/*otherwise*/ PAY_TRY_OTHER_ROUTE ;
|
||||||
|
struct json_result *data = new_json_result(cmd);
|
||||||
|
enum onion_type failure_code;
|
||||||
|
|
||||||
|
/* Prepare data. */
|
||||||
|
json_object_start(data, NULL);
|
||||||
|
if (fail) {
|
||||||
|
failure_code = fail->failcode;
|
||||||
|
json_add_snum(data, "origin_index", fail->origin_index);
|
||||||
|
json_add_num(data, "failcode", (unsigned) fail->failcode);
|
||||||
|
json_add_hex(data, "erring_node",
|
||||||
|
&fail->erring_node, sizeof(fail->erring_node));
|
||||||
|
json_add_short_channel_id(data, "erring_channel",
|
||||||
|
&fail->erring_channel);
|
||||||
|
if (fail->channel_update)
|
||||||
|
json_add_hex(data, "channel_update",
|
||||||
|
fail->channel_update,
|
||||||
|
tal_len(fail->channel_update));
|
||||||
|
} else {
|
||||||
|
assert(onionreply);
|
||||||
|
failure_code = WIRE_PERMANENT_NODE_FAILURE;
|
||||||
|
json_add_hex(data, "onionreply",
|
||||||
|
onionreply, tal_len(onionreply));
|
||||||
|
}
|
||||||
|
json_object_end(data);
|
||||||
|
|
||||||
|
/* Deletes cmd. */
|
||||||
|
command_fail_detailed(cmd, code, data, "failed: %s (%s)",
|
||||||
|
onion_type_name(failure_code),
|
||||||
|
details);
|
||||||
|
}
|
||||||
|
|
||||||
static void json_pay_failed(struct lightningd *ld,
|
static void json_pay_failed(struct lightningd *ld,
|
||||||
const struct sha256 *payment_hash,
|
const struct sha256 *payment_hash,
|
||||||
enum onion_type failure_code,
|
bool retry_plausible,
|
||||||
|
const struct routing_failure *fail,
|
||||||
|
const u8 *onionreply,
|
||||||
const char *details)
|
const char *details)
|
||||||
{
|
{
|
||||||
struct pay_command *pc, *next;
|
struct pay_command *pc, *next;
|
||||||
|
@ -84,9 +137,12 @@ static void json_pay_failed(struct lightningd *ld,
|
||||||
if (!structeq(payment_hash, &pc->payment_hash))
|
if (!structeq(payment_hash, &pc->payment_hash))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Deletes itself. */
|
/* Deletes cmd. */
|
||||||
command_fail(pc->cmd, "failed: %s (%s)",
|
json_pay_command_routing_failed(pc->cmd,
|
||||||
onion_type_name(failure_code), details);
|
retry_plausible,
|
||||||
|
fail,
|
||||||
|
onionreply,
|
||||||
|
details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,14 +189,6 @@ static u8 *channel_update_from_onion_error(const tal_t *ctx,
|
||||||
return channel_update;
|
return channel_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct routing_failure {
|
|
||||||
int origin_index;
|
|
||||||
enum onion_type failcode;
|
|
||||||
struct pubkey erring_node;
|
|
||||||
struct short_channel_id erring_channel;
|
|
||||||
u8 *channel_update;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Return a struct routing_failure for an immediate failure
|
/* Return a struct routing_failure for an immediate failure
|
||||||
* (returned directly from send_htlc_out). The returned
|
* (returned directly from send_htlc_out). The returned
|
||||||
* failure is allocated from the given context. */
|
* failure is allocated from the given context. */
|
||||||
|
@ -361,7 +409,10 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
|
||||||
* and payment again. */
|
* and payment again. */
|
||||||
(void) retry_plausible;
|
(void) retry_plausible;
|
||||||
|
|
||||||
json_pay_failed(ld, &hout->payment_hash, failcode, failmsg);
|
/* Report to RPC. */
|
||||||
|
json_pay_failed(ld, &hout->payment_hash,
|
||||||
|
retry_plausible, fail, hout->failuremsg,
|
||||||
|
failmsg);
|
||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,20 +467,26 @@ static bool send_payment(struct command *cmd,
|
||||||
log_debug(cmd->ld->log, "json_sendpay: found previous");
|
log_debug(cmd->ld->log, "json_sendpay: found previous");
|
||||||
if (payment->status == PAYMENT_PENDING) {
|
if (payment->status == PAYMENT_PENDING) {
|
||||||
log_add(cmd->ld->log, "Payment is still in progress");
|
log_add(cmd->ld->log, "Payment is still in progress");
|
||||||
command_fail(cmd, "Payment is still in progress");
|
command_fail_detailed(cmd, PAY_IN_PROGRESS, NULL,
|
||||||
|
"Payment is still in progress");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (payment->status == PAYMENT_COMPLETE) {
|
if (payment->status == PAYMENT_COMPLETE) {
|
||||||
log_add(cmd->ld->log, "... succeeded");
|
log_add(cmd->ld->log, "... succeeded");
|
||||||
/* Must match successful payment parameters. */
|
/* Must match successful payment parameters. */
|
||||||
if (payment->msatoshi != hop_data[n_hops-1].amt_forward) {
|
if (payment->msatoshi != hop_data[n_hops-1].amt_forward) {
|
||||||
command_fail(cmd,
|
command_fail_detailed(cmd,
|
||||||
"Already succeeded with amount %"
|
PAY_RHASH_ALREADY_USED,
|
||||||
PRIu64, payment->msatoshi);
|
NULL,
|
||||||
|
"Already succeeded "
|
||||||
|
"with amount %"PRIu64,
|
||||||
|
payment->msatoshi);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!structeq(&payment->destination, &ids[n_hops-1])) {
|
if (!structeq(&payment->destination, &ids[n_hops-1])) {
|
||||||
command_fail(cmd,
|
command_fail_detailed(cmd,
|
||||||
|
PAY_RHASH_ALREADY_USED,
|
||||||
|
NULL,
|
||||||
"Already succeeded to %s",
|
"Already succeeded to %s",
|
||||||
type_to_string(cmd, struct pubkey,
|
type_to_string(cmd, struct pubkey,
|
||||||
&payment->destination));
|
&payment->destination));
|
||||||
|
@ -452,7 +509,9 @@ static bool send_payment(struct command *cmd,
|
||||||
report_routing_failure(cmd->ld->log, cmd->ld->gossip, fail);
|
report_routing_failure(cmd->ld->log, cmd->ld->gossip, fail);
|
||||||
|
|
||||||
/* Report routing failure to user */
|
/* Report routing failure to user */
|
||||||
command_fail(cmd, "No connection to first peer found");
|
json_pay_command_routing_failed(cmd, true, fail, NULL,
|
||||||
|
"No connection to first "
|
||||||
|
"peer found");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,8 +536,8 @@ static bool send_payment(struct command *cmd,
|
||||||
report_routing_failure(cmd->ld->log, cmd->ld->gossip, fail);
|
report_routing_failure(cmd->ld->log, cmd->ld->gossip, fail);
|
||||||
|
|
||||||
/* Report routing failure to user */
|
/* Report routing failure to user */
|
||||||
command_fail(cmd, "First peer not ready: %s",
|
json_pay_command_routing_failed(cmd, true, fail, NULL,
|
||||||
onion_type_name(failcode));
|
"First peer not ready");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,7 +678,8 @@ static void json_pay_getroute_reply(struct subd *gossip,
|
||||||
fromwire_gossip_getroute_reply(reply, reply, NULL, &route);
|
fromwire_gossip_getroute_reply(reply, reply, NULL, &route);
|
||||||
|
|
||||||
if (tal_count(route) == 0) {
|
if (tal_count(route) == 0) {
|
||||||
command_fail(pay->cmd, "Could not find a route");
|
command_fail_detailed(pay->cmd, PAY_ROUTE_NOT_FOUND, NULL,
|
||||||
|
"Could not find a route");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue