Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,8 @@ void payment_failed(struct lightningd *ld,
fail ? fail->erring_channel : NULL,
NULL,
failstr,
fail ? fail->channel_dir : 0);
fail ? fail->channel_dir : 0,
fail ? fail->msg : NULL);

tell_waiters_failed(ld, payment_hash, payment, pay_errcode,
failonion, fail, failstr);
Expand All @@ -675,6 +676,7 @@ static struct command_result *wait_payment(struct lightningd *ld,
struct short_channel_id *failchannel;
u8 *failupdate;
char *faildetail;
u8 *failmsg;
struct routing_failure *fail;
int faildirection;
enum jsonrpc_errcode rpcerrorcode;
Expand Down Expand Up @@ -715,7 +717,8 @@ static struct command_result *wait_payment(struct lightningd *ld,
&failchannel,
&failupdate,
&faildetail,
&faildirection);
&faildirection,
&failmsg);
/* Old DB might not save failure information */
if (!failonionreply && !failnode) {
return command_fail(cmd, PAY_UNSPECIFIED_ERROR,
Expand Down Expand Up @@ -745,8 +748,7 @@ static struct command_result *wait_payment(struct lightningd *ld,
fail->erring_channel = NULL;
}

/* FIXME: We don't store this! */
fail->msg = NULL;
fail->msg = tal_dup_talarr(fail, u8, failmsg);

/* Peers which fail directly can hit this! */
if (failcode & BADONION)
Expand Down Expand Up @@ -1530,7 +1532,7 @@ static struct command_result *self_payment(struct lightningd *ld,
fail->failcode, fail->erring_node,
NULL, NULL,
err,
0);
0, NULL);
/* We do this even though there really can't be any waiters,
* since we didn't block. */
tell_waiters_failed(ld, rhash, payment, PAY_DESTINATION_PERM_FAIL,
Expand Down
9 changes: 9 additions & 0 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -2861,6 +2861,15 @@ def test_error_returns_blockheight(node_factory, bitcoind):
assert (err.value.error['data']['raw_message']
== '400f{:016x}{:08x}'.format(100, bitcoind.rpc.getblockcount()))

# A second waitsendpay replays the failure from the database (the
# path a waitsendpay racing the failure takes): raw_message must
# survive that round trip too.
with pytest.raises(RpcError, match=r"INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS.*'erring_index': 1") as err:
l1.rpc.waitsendpay('00' * 32, TIMEOUT)

assert (err.value.error['data']['raw_message']
== '400f{:016x}{:08x}'.format(100, bitcoind.rpc.getblockcount()))


@unittest.skipIf(TEST_NETWORK != 'regtest', "Invoice is network specific")
def test_pay_no_secret(node_factory, bitcoind):
Expand Down
4 changes: 4 additions & 0 deletions wallet/migrations.c
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,10 @@ static const struct db_migration dbmigrations[] = {
* writes stop in the release that removes chaintopology, freezing all
* the legacy tables at the same height. */
{NULL, migrate_backfill_bwatch_tables, NULL, NULL},
/* Raw BOLT4 failure message, so waitsendpay can report it even
* after the failure was recorded (issue #9341). */
{SQL("ALTER TABLE payments ADD failmsg BLOB;"), NULL,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! ALTER TABLE - ADD failmsg BLOB is valid on a STRICT table (BLOB is an allowed strict type), so this won't break test_sqlite_strict_mode!

SQL("ALTER TABLE payments DROP COLUMN failmsg"), NULL},
};

const struct db_migration *get_db_migrations(size_t *num)
Expand Down
14 changes: 12 additions & 2 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -4322,7 +4322,8 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
struct short_channel_id **failchannel,
u8 **failupdate,
char **faildetail,
int *faildirection)
int *faildirection,
u8 **failmsg)
{
struct db_stmt *stmt;
bool resb;
Expand All @@ -4332,6 +4333,7 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
", failindex, failcode"
", failnode, failscid"
", failupdate, faildetail, faildirection"
", failmsg"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention failmsg in the doc comments for wallet_payment_get_failinfo/wallet_payment_set_failinfo in wallet/wallet.h?

" FROM payments"
" WHERE payment_hash=? AND partid=? AND groupid=?;"));
db_bind_sha256(stmt, payment_hash);
Expand Down Expand Up @@ -4366,6 +4368,10 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
*faildetail = db_col_strdup(ctx, stmt, "faildetail");
else
*faildetail = NULL;
if (db_col_is_null(stmt, "failmsg"))
*failmsg = NULL;
else
*failmsg = db_col_arr(ctx, stmt, "failmsg", u8);

tal_free(stmt);
}
Expand All @@ -4381,7 +4387,8 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
const struct short_channel_id *failchannel,
const u8 *failupdate /*tal_arr*/,
const char *faildetail,
int faildirection)
int faildirection,
const u8 *failmsg /*tal_arr*/)
{
struct db_stmt *stmt;

Expand All @@ -4395,6 +4402,7 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
" , faildirection=?"
" , failupdate=?"
" , faildetail=?"
" , failmsg=?"
" WHERE payment_hash=?"
" AND partid=?;"));
if (failonionreply)
Expand Down Expand Up @@ -4425,6 +4433,8 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
else
db_bind_null(stmt);

db_bind_talarr(stmt, failmsg);

db_bind_sha256(stmt, payment_hash);
db_bind_u64(stmt, partid);

Expand Down
6 changes: 4 additions & 2 deletions wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,8 @@ void wallet_payment_get_failinfo(const tal_t *ctx,
struct short_channel_id **failchannel,
u8 **failupdate,
char **faildetail,
int *faildirection);
int *faildirection,
u8 **failmsg);
/**
* wallet_payment_set_failinfo - Set failure information for a given
* `payment_hash`.
Expand All @@ -1081,7 +1082,8 @@ void wallet_payment_set_failinfo(struct wallet *wallet,
const struct short_channel_id *failchannel,
const u8 *failupdate,
const char *faildetail,
int faildirection);
int faildirection,
const u8 *failmsg);

/**
* payments_first: get first payment, optionally filtering by status
Expand Down
Loading