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
24 changes: 24 additions & 0 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -7048,3 +7048,27 @@ def test_htlc_tlv_crash(node_factory):

l1.rpc.waitsendpay(inv1['payment_hash'], TIMEOUT)
l1.rpc.waitsendpay(inv2['payment_hash'], TIMEOUT)


@pytest.mark.openchannel('v1')
@pytest.mark.openchannel('v2')
def test_bolt11_annotation_after_restart(node_factory):
"""Test bolt11 field persists in listpays after restart. Fixes #6978"""
l1, l2 = node_factory.line_graph(2)

inv = l2.rpc.invoice(100000, 'test_bolt11_persist', 'Test BOLT11 persistence')['bolt11']
l1.rpc.pay(inv)

pays_before = l1.rpc.listpays()['pays']
payment_before = [p for p in pays_before if 'bolt11' in p and p['bolt11'] == inv][0]
assert payment_before['status'] == 'complete'
assert payment_before['bolt11'] == inv
payment_hash = payment_before['payment_hash']

l1.restart()

pays_after = l1.rpc.listpays()['pays']
payment_after = [p for p in pays_after if 'bolt11' in p and p['bolt11'] == inv][0]
assert payment_after['payment_hash'] == payment_hash
assert payment_after['status'] == 'complete'
assert payment_after['bolt11'] == inv
29 changes: 29 additions & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ static void migrate_our_funding(struct lightningd *ld, struct db *db);

static void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db);

static void migrate_add_payment_id_to_htlcs(struct lightningd *ld, struct db *db);

static void
migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db);

Expand Down Expand Up @@ -1092,6 +1094,8 @@ static struct migration dbmigrations[] = {
")"), NULL},
/* We do a lookup before each append, to avoid duplicates */
{SQL("CREATE INDEX chain_moves_utxo_idx ON chain_moves (utxo)"), NULL},
/* Add payment_id column to channel_htlcs */
{NULL, migrate_add_payment_id_to_htlcs},
{NULL, migrate_from_account_db},
};

Expand Down Expand Up @@ -2080,6 +2084,31 @@ static void migrate_initialize_alias_local(struct lightningd *ld,
}
}

/* Add payment_id column to channel_htlcs */
static void migrate_add_payment_id_to_htlcs(struct lightningd *ld, struct db *db)
{
struct db_stmt *stmt;

stmt = db_prepare_v2(db, SQL("ALTER TABLE channel_htlcs ADD COLUMN payment_id BIGINT"));
db_exec_prepared_v2(stmt);
tal_free(stmt);

stmt = db_prepare_v2(db, SQL("UPDATE channel_htlcs "
"SET payment_id = ("
" SELECT p.id FROM payments p "
" WHERE p.payment_hash = channel_htlcs.payment_hash "
" AND p.partid = channel_htlcs.partid "
" AND p.groupid = channel_htlcs.groupid "
" LIMIT 1"
")"));
db_exec_prepared_v2(stmt);
tal_free(stmt);

stmt = db_prepare_v2(db, SQL("CREATE INDEX channel_htlcs_payment_id_idx ON channel_htlcs (payment_id)"));
db_exec_prepared_v2(stmt);
tal_free(stmt);
}

/* Insert address type as `ADDR_ALL` for issued addresses */
static void insert_addrtype_to_addresses(struct lightningd *ld,
struct db *db)
Expand Down
28 changes: 26 additions & 2 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -3316,11 +3316,29 @@ void wallet_htlc_save_out(struct wallet *wallet,
struct htlc_out *out)
{
struct db_stmt *stmt;
u64 payment_id = 0;

/* We absolutely need the incoming HTLC to be persisted before
* we can persist it's dependent */
assert(out->in == NULL || out->in->dbid != 0);

/* Get payment_id if this is an outgoing payment */
if (out->am_origin) {
struct db_stmt *payment_stmt = db_prepare_v2(wallet->db,
SQL("SELECT id FROM payments "
"WHERE payment_hash = ? AND partid = ? AND groupid = ? "
"LIMIT 1"));
db_bind_sha256(payment_stmt, &out->payment_hash);
db_bind_u64(payment_stmt, out->partid);
db_bind_u64(payment_stmt, out->groupid);
db_query_prepared(payment_stmt);

if (db_step(payment_stmt)) {
payment_id = db_col_u64(payment_stmt, "id");
}
tal_free(payment_stmt);
}

stmt = db_prepare_v2(
wallet->db,
SQL("INSERT INTO channel_htlcs ("
Expand All @@ -3339,8 +3357,9 @@ void wallet_htlc_save_out(struct wallet *wallet,
" partid,"
" groupid,"
" fees_msat,"
" min_commit_num"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?);"));
" min_commit_num,"
" payment_id"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?);"));

out->dbid = htlcs_index_created(wallet->ld,
out->key.id,
Expand Down Expand Up @@ -3384,6 +3403,11 @@ void wallet_htlc_save_out(struct wallet *wallet,
db_bind_u64(stmt, min_u64(chan->next_index[LOCAL]-1,
chan->next_index[REMOTE]-1));

if (payment_id > 0)
db_bind_u64(stmt, payment_id);
else
db_bind_null(stmt);

db_exec_prepared_v2(take(stmt));
}

Expand Down