wallet: replace forwarded_payments table with forwards table.

This one directly contains the scids of the channels involved, not
references, so can outlive the channels.  As a side-effect, however,
it now never lists `payment_hash`.  Having it listed (via join) is not
possible as it is a *string* in the channels table, and difficult
anyway because of channel aliases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2022-09-19 10:19:53 +09:30 committed by Christian Decker
parent 2022e4a7a9
commit 63457229cb
5 changed files with 66 additions and 39 deletions

View file

@ -2413,12 +2413,7 @@ def test_listforwards(node_factory, bitcoind):
l1.rpc.waitsendpay(failed_inv['payment_hash'])
all_forwards = l2.rpc.listforwards()['forwards']
print(json.dumps(all_forwards, indent=True))
assert len(all_forwards) == 3
assert i31['payment_hash'] in map(lambda x: x['payment_hash'], all_forwards)
assert i41['payment_hash'] in map(lambda x: x['payment_hash'], all_forwards)
assert failed_inv['payment_hash'] in map(lambda x: x['payment_hash'], all_forwards)
# status=settled
settled_forwards = l2.rpc.listforwards(status='settled')['forwards']

View file

@ -1389,7 +1389,7 @@ def test_forward_stats(node_factory, bitcoind):
# Select all forwardings, ordered by htlc_id to ensure the order
# matches below
forwardings = l2.db_query("SELECT *, in_msatoshi - out_msatoshi as fee "
"FROM forwarded_payments "
"FROM forwards "
"ORDER BY in_htlc_id;")
assert(len(forwardings) == 3)
states = [f['state'] for f in forwardings]

View file

@ -1345,6 +1345,10 @@ def test_forward_event_notification(node_factory, bitcoind, executor):
plugin_stats = l2.rpc.call('listforwards_plugin')['forwards']
assert len(plugin_stats) == 6
# We don't have payment_hash in listforwards any more.
for p in plugin_stats:
del p['payment_hash']
# use stats to build what we expect went to plugin.
expect = stats[0].copy()
# First event won't have conclusion.

View file

@ -887,6 +887,39 @@ static struct migration dbmigrations[] = {
{SQL("ALTER TABLE payments ADD completed_at INTEGER DEFAULT NULL;"), NULL},
{SQL("UPDATE payments SET completed_at = timestamp WHERE status != 0;"), NULL},
{SQL("CREATE INDEX payments_idx ON payments (payment_hash)"), NULL},
/* forwards table outlives the channels, so we move there from old forwarded_payments table;
* but here the ids are the HTLC numbers, not the internal db ids. */
{SQL("CREATE TABLE forwards ("
"in_channel_scid BIGINT"
", in_htlc_id BIGINT"
", out_channel_scid BIGINT"
", out_htlc_id BIGINT"
", in_msatoshi BIGINT"
", out_msatoshi BIGINT"
", state INTEGER"
", received_time BIGINT"
", resolved_time BIGINT"
", failcode INTEGER"
", forward_style INTEGER"
", PRIMARY KEY(in_channel_scid, in_htlc_id))"), NULL},
{SQL("INSERT INTO forwards SELECT"
" in_channel_scid"
", (SELECT channel_htlc_id FROM channel_htlcs WHERE id = forwarded_payments.in_htlc_id)"
", out_channel_scid"
", (SELECT channel_htlc_id FROM channel_htlcs WHERE id = forwarded_payments.out_htlc_id)"
", in_msatoshi"
", out_msatoshi"
", state"
", received_time"
", resolved_time"
", failcode"
", forward_style"
" FROM forwarded_payments"
" WHERE"
" in_htlc_id IS NOT NULL"), NULL},
{SQL("DROP INDEX forwarded_payments_state;"), NULL},
{SQL("DROP INDEX forwarded_payments_out_htlc_id;"), NULL},
{SQL("DROP TABLE forwarded_payments;"), NULL},
};
/* Released versions are of form v{num}[.{num}]* */

View file

@ -4356,14 +4356,14 @@ static bool wallet_forwarded_payment_update(struct wallet *w,
* having to have two versions of the update statement (one with and
* one without the htlc_out restriction).*/
stmt = db_prepare_v2(w->db,
SQL("UPDATE forwarded_payments SET"
SQL("UPDATE forwards SET"
" in_msatoshi=?"
", out_msatoshi=?"
", state=?"
", resolved_time=?"
", failcode=?"
", forward_style=?"
" WHERE in_htlc_id=?"));
" WHERE in_htlc_id=? AND in_channel_scid=?"));
db_bind_amount_msat(stmt, 0, &in->msat);
if (out) {
@ -4392,7 +4392,9 @@ static bool wallet_forwarded_payment_update(struct wallet *w,
db_bind_null(stmt, 5);
else
db_bind_int(stmt, 5, forward_style_in_db(forward_style));
db_bind_u64(stmt, 6, in->dbid);
db_bind_u64(stmt, 6, in->key.id);
db_bind_u64(stmt, 7,
channel_scid_or_local_alias(in->key.channel)->u64);
db_exec_prepared_v2(stmt);
changed = db_count_changes(stmt) != 0;
tal_free(stmt);
@ -4421,7 +4423,7 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in,
goto notify;
stmt = db_prepare_v2(w->db,
SQL("INSERT INTO forwarded_payments ("
SQL("INSERT INTO forwards ("
" in_htlc_id"
", out_htlc_id"
", in_channel_scid"
@ -4434,7 +4436,7 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in,
", failcode"
", forward_style"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
db_bind_u64(stmt, 0, in->dbid);
db_bind_u64(stmt, 0, in->key.id);
/* FORWARD_LOCAL_FAILED may occur before we get htlc_out */
if (!out || !scid_out) {
@ -4443,7 +4445,7 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in,
}
if (out)
db_bind_u64(stmt, 1, out->dbid);
db_bind_u64(stmt, 1, out->key.id);
else
db_bind_null(stmt, 1);
@ -4499,7 +4501,7 @@ struct amount_msat wallet_total_forward_fees(struct wallet *w)
stmt = db_prepare_v2(w->db, SQL("SELECT"
" CAST(COALESCE(SUM(in_msatoshi - out_msatoshi), 0) AS BIGINT)"
" FROM forwarded_payments "
" FROM forwards "
"WHERE state = ?;"));
db_bind_int(stmt, 0, wallet_forward_status_in_db(FORWARD_SETTLED));
db_query_prepared(stmt);
@ -4549,21 +4551,19 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
stmt = db_prepare_v2(
w->db,
SQL("SELECT"
" f.state"
" state"
", in_msatoshi"
", out_msatoshi"
", hin.payment_hash as payment_hash"
", in_channel_scid"
", out_channel_scid"
", f.received_time"
", f.resolved_time"
", f.failcode "
", f.forward_style "
"FROM forwarded_payments f "
"LEFT JOIN channel_htlcs hin ON (f.in_htlc_id = hin.id) "
"WHERE (1 = ? OR f.state = ?) AND "
"(1 = ? OR f.in_channel_scid = ?) AND "
"(1 = ? OR f.out_channel_scid = ?)"));
", received_time"
", resolved_time"
", failcode "
", forward_style "
"FROM forwards "
"WHERE (1 = ? OR state = ?) AND "
"(1 = ? OR in_channel_scid = ?) AND "
"(1 = ? OR out_channel_scid = ?)"));
if (status == FORWARD_ANY) {
// any status
@ -4600,7 +4600,7 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
for (count=0; db_step(stmt); count++) {
tal_resize(&results, count+1);
struct forwarding *cur = &results[count];
cur->status = db_col_int(stmt, "f.state");
cur->status = db_col_int(stmt, "state");
db_col_amount_msat(stmt, "in_msatoshi", &cur->msat_in);
if (!db_col_is_null(stmt, "out_msatoshi")) {
@ -4622,13 +4622,8 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
cur->fee = AMOUNT_MSAT(0);
}
if (!db_col_is_null(stmt, "payment_hash")) {
cur->payment_hash = tal(ctx, struct sha256);
db_col_sha256(stmt, "payment_hash", cur->payment_hash);
} else {
cur->payment_hash = NULL;
}
/* FIXME: This now requires complex join to determine! */
cur->payment_hash = NULL;
cur->channel_in.u64 = db_col_u64(stmt, "in_channel_scid");
if (!db_col_is_null(stmt, "out_channel_scid")) {
@ -4639,28 +4634,28 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
cur->channel_out.u64 = 0;
}
cur->received_time = db_col_timeabs(stmt, "f.received_time");
cur->received_time = db_col_timeabs(stmt, "received_time");
if (!db_col_is_null(stmt, "f.resolved_time")) {
if (!db_col_is_null(stmt, "resolved_time")) {
cur->resolved_time = tal(ctx, struct timeabs);
*cur->resolved_time
= db_col_timeabs(stmt, "f.resolved_time");
= db_col_timeabs(stmt, "resolved_time");
} else {
cur->resolved_time = NULL;
}
if (!db_col_is_null(stmt, "f.failcode")) {
if (!db_col_is_null(stmt, "failcode")) {
assert(cur->status == FORWARD_FAILED ||
cur->status == FORWARD_LOCAL_FAILED);
cur->failcode = db_col_int(stmt, "f.failcode");
cur->failcode = db_col_int(stmt, "failcode");
} else {
cur->failcode = 0;
}
if (db_col_is_null(stmt, "f.forward_style")) {
if (db_col_is_null(stmt, "forward_style")) {
cur->forward_style = FORWARD_STYLE_UNKNOWN;
} else {
cur->forward_style
= forward_style_in_db(db_col_int(stmt, "f.forward_style"));
= forward_style_in_db(db_col_int(stmt, "forward_style"));
}
}
tal_free(stmt);