Browse Source

wallet, payalgo: Save detail of payment failures for later reporting. (#1345)

Pointless for remote failures as those are never sent by
the erring node, but for local failures we can give more
detail.
ppa-0.6.1
ZmnSCPxj, ZmnSCPxj jxPCSmnZ 7 years ago
committed by Christian Decker
parent
commit
11ca729d85
  1. 11
      lightningd/pay.c
  2. 8
      lightningd/payalgo.c
  3. 6
      wallet/db.c
  4. 17
      wallet/wallet.c
  5. 6
      wallet/wallet.h

11
lightningd/pay.c

@ -515,7 +515,8 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
fail ? fail->failcode : 0,
fail ? &fail->erring_node : NULL,
fail ? &fail->erring_channel : NULL,
fail ? fail->channel_update : NULL);
fail ? fail->channel_update : NULL,
failmsg);
/* Report to gossipd if we decided we should. */
if (report_to_gossipd)
@ -549,6 +550,7 @@ bool wait_payment(const tal_t *cxt,
struct pubkey *failnode;
struct short_channel_id *failchannel;
u8 *failupdate;
char *faildetail;
struct routing_failure *fail;
payment = wallet_payment_by_hash(tmpctx, ld->wallet, payment_hash);
@ -588,7 +590,8 @@ bool wait_payment(const tal_t *cxt,
&failcode,
&failnode,
&failchannel,
&failupdate);
&failupdate,
&faildetail);
/* Old DB might not save failure information */
if (!failonionreply && !failnode)
result = sendpay_result_simple_fail(tmpctx,
@ -596,7 +599,7 @@ bool wait_payment(const tal_t *cxt,
"Payment failure reason unknown");
else if (failonionreply) {
/* failed to parse returned onion error */
result = sendpay_result_route_failure(tmpctx, true, NULL, failonionreply, "reply from remote");
result = sendpay_result_route_failure(tmpctx, true, NULL, failonionreply, faildetail);
} else {
/* Parsed onion error, get its details */
assert(failnode);
@ -607,7 +610,7 @@ bool wait_payment(const tal_t *cxt,
fail->erring_node = *failnode;
fail->erring_channel = *failchannel;
fail->channel_update = failupdate;
result = sendpay_result_route_failure(tmpctx, !faildestperm, fail, NULL, "route failure");
result = sendpay_result_route_failure(tmpctx, !faildestperm, fail, NULL, faildetail);
}
cb(result, cbarg);

8
lightningd/payalgo.c

@ -39,6 +39,9 @@ struct pay_failure {
/* The routing failure, if TYPE_PAYMENT_REPLY, a tal
* object whose parent is this struct */
struct routing_failure *routing_failure;
/* The detail of the routing failure. A tal_arr
* string whose parent is this struct. */
char *details;
};
/* Output a pay failure */
@ -48,12 +51,12 @@ json_add_failure(struct json_result *r, char const *n,
{
struct routing_failure *rf;
json_object_start(r, n);
json_add_string(r, "message", f->details);
switch (f->type) {
case FAIL_UNPARSEABLE_ONION:
json_add_string(r, "type", "FAIL_UNPARSEABLE_ONION");
json_add_hex(r, "onionreply", f->onionreply,
tal_len(f->onionreply));
json_add_route(r, "route", f->route, tal_count(f->route));
break;
case FAIL_PAYMENT_REPLY:
@ -68,9 +71,9 @@ json_add_failure(struct json_result *r, char const *n,
json_add_hex(r, "channel_update",
rf->channel_update,
tal_len(rf->channel_update));
json_add_route(r, "route", f->route, tal_count(f->route));
break;
}
json_add_route(r, "route", f->route, tal_count(f->route));
json_object_end(r);
}
@ -173,6 +176,7 @@ add_pay_failure(struct pay *pay,
default:
abort();
}
f->details = tal_strdup(f, r->details);
/* Grab the route */
f->route = tal_steal(f, pay->route);
pay->route = NULL;

6
wallet/db.c

@ -300,6 +300,12 @@ char *dbmigrations[] = {
", rawtx BLOB"
", PRIMARY KEY (id)"
");",
/* -- Detailed payment failure -- */
"ALTER TABLE payments ADD faildetail TEXT;",
"UPDATE payments"
" SET faildetail = 'unspecified payment failure reason'"
" WHERE status = 2;", /* PAYMENT_FAILED */
/* -- Detailed payment faiure ends -- */
NULL,
};

17
wallet/wallet.c

@ -11,6 +11,7 @@
#include <lightningd/log.h>
#include <lightningd/peer_control.h>
#include <lightningd/peer_htlcs.h>
#include <string.h>
#define SQLITE_MAX_UINT 0x7FFFFFFFFFFFFFFF
#define DIRECTION_INCOMING 0
@ -1770,7 +1771,8 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
enum onion_type *failcode,
struct pubkey **failnode,
struct short_channel_id **failchannel,
u8 **failupdate)
u8 **failupdate,
char **faildetail)
{
sqlite3_stmt *stmt;
int res;
@ -1781,7 +1783,7 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
"SELECT failonionreply, faildestperm"
" , failindex, failcode"
" , failnode, failchannel"
" , failupdate"
" , failupdate, faildetail"
" FROM payments"
" WHERE payment_hash=?;");
sqlite3_bind_sha256(stmt, 1, payment_hash);
@ -1818,6 +1820,8 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
*failupdate = tal_arr(ctx, u8, len);
memcpy(*failupdate, sqlite3_column_blob(stmt, 6), len);
}
*faildetail = tal_strndup(ctx, sqlite3_column_blob(stmt, 7),
sqlite3_column_bytes(stmt, 7));
sqlite3_finalize(stmt);
}
@ -1830,7 +1834,8 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
enum onion_type failcode,
const struct pubkey *failnode,
const struct short_channel_id *failchannel,
const u8 *failupdate /*tal_arr*/)
const u8 *failupdate /*tal_arr*/,
const char *faildetail)
{
sqlite3_stmt *stmt;
@ -1843,6 +1848,7 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
" , failnode=?"
" , failchannel=?"
" , failupdate=?"
" , faildetail=?"
" WHERE payment_hash=?;");
if (failonionreply)
sqlite3_bind_blob(stmt, 1,
@ -1871,8 +1877,11 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
SQLITE_TRANSIENT);
else
sqlite3_bind_null(stmt, 7);
sqlite3_bind_blob(stmt, 8,
faildetail, strlen(faildetail),
SQLITE_TRANSIENT);
sqlite3_bind_sha256(stmt, 8, payment_hash);
sqlite3_bind_sha256(stmt, 9, payment_hash);
db_exec_prepared(wallet->db, stmt);
}

6
wallet/wallet.h

@ -735,7 +735,8 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
enum onion_type *failcode,
struct pubkey **failnode,
struct short_channel_id **failchannel,
u8 **failupdate);
u8 **failupdate,
char **faildetail);
/**
* wallet_payment_set_failinfo - Set failure information for a given
* `payment_hash`.
@ -748,7 +749,8 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
enum onion_type failcode,
const struct pubkey *failnode,
const struct short_channel_id *failchannel,
const u8 *failupdate);
const u8 *failupdate,
const char *faildetail);
/**
* wallet_payment_list - Retrieve a list of payments

Loading…
Cancel
Save