Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

autoclean gains SUPER POWERS (and other optimizations) #5594

Merged
merged 30 commits into from
Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fef2587
libplugin: handle JSON reply after command freed.
rustyrussell Sep 19, 2022
ca4cab8
autoclean: new interface
rustyrussell Sep 19, 2022
34f5ed6
lightningd: deprecated "delexpiredinvoice", put functionality in auto…
rustyrussell Sep 19, 2022
64ad3a6
autoclean: save stats on how much we cleaned.
rustyrussell Sep 19, 2022
7161591
autoclean: allow cleaning of paid invoices too.
rustyrussell Sep 19, 2022
879b050
autoclean: handle cleaning of old payments (not just invoices).
rustyrussell Sep 19, 2022
bc5389c
lightningd: index to speed up sendpay / listsendpays
rustyrussell Sep 19, 2022
3d8c7da
wallet: simplify payments lookup so sqlite3 uses index.
rustyrussell Sep 19, 2022
3c5d656
wallet: replace forwarded_payments table with forwards table.
rustyrussell Sep 19, 2022
93ae8a9
db/bindings: rename db_bind_short_channel_id to db_bind_short_channel…
rustyrussell Sep 19, 2022
f18ba20
wallet: use db_col_scid / db_bind_scid where possible.
rustyrussell Sep 19, 2022
5cdf084
db: add `scid` field to channels table.
rustyrussell Sep 19, 2022
75fbec6
wallet: use scid not string for failchannel (now failscid) in payment…
rustyrussell Sep 19, 2022
9ba5483
lightningd: add in_htlc_id / out_htlc_id to listforwards.
rustyrussell Sep 19, 2022
da272a0
lightningd: add `listhtlcs` to list all the HTLCs we know about.
rustyrussell Sep 19, 2022
21ddd0e
lightningd: add `delforward` command.
rustyrussell Sep 19, 2022
70ef7ca
autoclean: clean up listforwards as well.
rustyrussell Sep 19, 2022
cba2a7d
autoclean: use config variables, not commands.
rustyrussell Sep 19, 2022
dbaa78a
doc: manpages and schemas for autoclean-status.
rustyrussell Sep 19, 2022
3bc0f05
autoclean: add autoclean-once command.
rustyrussell Sep 19, 2022
367b1e9
autoclean: remove per-delete debugging messages.
rustyrussell Sep 19, 2022
5d571a2
libplugin: optimize parsing lightningd rpc responses.
rustyrussell Sep 19, 2022
1eaa4f9
libplugin: avoid memmove if we have many outputs to lightningd.
rustyrussell Sep 19, 2022
85f1e50
lightningd: don't always wrap each command in a db transaction.
rustyrussell Sep 19, 2022
bf354a0
lightningd: allow a connection to specify db batching.
rustyrussell Sep 19, 2022
6684857
lightningd: listsendpays always has groupid.
rustyrussell Sep 19, 2022
45cf6f5
lightningd: allow delpay to delete a specific payment.
rustyrussell Sep 19, 2022
017acac
db/postgres: avoid memleak.
rustyrussell Sep 19, 2022
606e6d3
db: set now-unused channels.short_channel_id text column to NULL afte…
rustyrussell Sep 19, 2022
2ac334d
pytest: slow down test_autoclean.
rustyrussell Sep 22, 2022
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
Prev Previous commit
Next Next commit
db: add scid field to channels table.
Normally, we'd use the delete_columns function to remove the old
`short_channel_id` string field, *but* we can't do that for sqlite, as
there are other tables with references to it.  So add a FIXME to do
it once everyone has upgraded to an sqlite3 which has native support
for column deletion.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell authored and cdecker committed Sep 22, 2022
commit 5cdf084bf5f177ec07d413a26134bfb3b950a2bb
16 changes: 16 additions & 0 deletions contrib/pyln-testing/pyln/testing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ def write_config(filename, opts, regtest_opts=None, section_name='regtest'):
f.write("{}={}\n".format(k, v))


def scid_to_int(scid):
"""Convert a 1x2x3 scid to a raw integer"""
blocknum, txnum, outnum = scid.split("x")

# BOLT #7:
# ## Definition of `short_channel_id`
#
# The `short_channel_id` is the unique description of the funding transaction.
# It is constructed as follows:
# 1. the most significant 3 bytes: indicating the block height
# 2. the next 3 bytes: indicating the transaction index within the block
# 3. the least significant 2 bytes: indicating the output index that pays to the
# channel.
return (int(blocknum) << 40) | (int(txnum) << 16) | int(outnum)


def only_one(arr):
"""Many JSON RPC calls return an array; often we only expect a single entry
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from fixtures import * # noqa: F401,F403
from fixtures import TEST_NETWORK
from pyln.client import RpcError
from utils import wait_for, sync_blockheight, COMPAT, VALGRIND, DEVELOPER, TIMEOUT, only_one
from utils import wait_for, sync_blockheight, COMPAT, VALGRIND, DEVELOPER, TIMEOUT, only_one, scid_to_int

import base64
import os
Expand Down Expand Up @@ -161,7 +161,7 @@ def test_scid_upgrade(node_factory, bitcoind):

l1.daemon.opts['database-upgrade'] = True
l1.daemon.start()
assert l1.db_query('SELECT short_channel_id from channels;') == [{'short_channel_id': '103x1x1'}]
assert l1.db_query('SELECT scid FROM channels;') == [{'scid': scid_to_int('103x1x1')}]
assert l1.db_query('SELECT failchannel from payments;') == [{'failchannel': '103x1x1'}]


Expand Down
4 changes: 2 additions & 2 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from io import BytesIO
from pyln.client import RpcError, Millisatoshi
from pyln.proto.onion import TlvPayload
from pyln.testing.utils import EXPERIMENTAL_DUAL_FUND, FUNDAMOUNT
from pyln.testing.utils import EXPERIMENTAL_DUAL_FUND, FUNDAMOUNT, scid_to_int
from utils import (
DEVELOPER, wait_for, only_one, sync_blockheight, TIMEOUT,
EXPERIMENTAL_FEATURES, VALGRIND, mine_funding_to_announce, first_scid
Expand Down Expand Up @@ -1957,7 +1957,7 @@ def test_setchannel_usage(node_factory, bitcoind):
def channel_get_config(scid):
return l1.db.query(
'SELECT feerate_base, feerate_ppm, htlc_minimum_msat, htlc_maximum_msat FROM channels '
'WHERE short_channel_id=\'{}\';'.format(scid))
'WHERE scid={};'.format(scid_to_int(scid)))

# get short channel id
scid = l1.get_channel_scid(l2)
Expand Down
2 changes: 1 addition & 1 deletion tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pyln.testing.utils import TEST_NETWORK, TIMEOUT, VALGRIND, DEVELOPER, DEPRECATED_APIS # noqa: F401
from pyln.testing.utils import env, only_one, wait_for, write_config, TailableProc, sync_blockheight, wait_channel_quiescent, get_tx_p2wsh_outnum, mine_funding_to_announce # noqa: F401
from pyln.testing.utils import env, only_one, wait_for, write_config, TailableProc, sync_blockheight, wait_channel_quiescent, get_tx_p2wsh_outnum, mine_funding_to_announce, scid_to_int # noqa: F401
import bitstring
from pyln.client import Millisatoshi
from pyln.testing.utils import EXPERIMENTAL_DUAL_FUND
Expand Down
49 changes: 49 additions & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ static void fillin_missing_channel_blockheights(struct lightningd *ld,
struct db *db,
const struct migration_context *mc);

static void migrate_channels_scids_as_integers(struct lightningd *ld,
struct db *db,
const struct migration_context *mc);

/* Do not reorder or remove elements from this array, it is used to
* migrate existing databases from a previous state, based on the
* string indices */
Expand Down Expand Up @@ -920,6 +924,8 @@ static struct migration dbmigrations[] = {
{SQL("DROP INDEX forwarded_payments_state;"), NULL},
{SQL("DROP INDEX forwarded_payments_out_htlc_id;"), NULL},
{SQL("DROP TABLE forwarded_payments;"), NULL},
/* Adds scid column, then moves short_channel_id across to it */
{SQL("ALTER TABLE channels ADD scid BIGINT;"), migrate_channels_scids_as_integers},
};

/* Released versions are of form v{num}[.{num}]* */
Expand Down Expand Up @@ -1455,3 +1461,46 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db,

tal_free(stmt);
}

/* We used to store scids as strings... */
static void migrate_channels_scids_as_integers(struct lightningd *ld,
struct db *db,
const struct migration_context *mc)
{
struct db_stmt *stmt;
char **scids = tal_arr(tmpctx, char *, 0);

stmt = db_prepare_v2(db, SQL("SELECT short_channel_id FROM channels"));
db_query_prepared(stmt);
while (db_step(stmt)) {
if (db_col_is_null(stmt, "short_channel_id"))
continue;
tal_arr_expand(&scids,
db_col_strdup(scids, stmt, "short_channel_id"));
}
tal_free(stmt);

for (size_t i = 0; i < tal_count(scids); i++) {
struct short_channel_id scid;
if (!short_channel_id_from_str(scids[i], strlen(scids[i]), &scid))
db_fatal("Cannot convert invalid channels.short_channel_id '%s'",
scids[i]);

stmt = db_prepare_v2(db, SQL("UPDATE channels"
" SET scid = ?"
" WHERE short_channel_id = ?"));
db_bind_scid(stmt, 0, &scid);
db_bind_text(stmt, 1, scids[i]);
db_exec_prepared_v2(stmt);
if (db_count_changes(stmt) != 1)
db_fatal("Converting channels.short_channel_id '%s' gave %zu changes != 1?",
scids[i], db_count_changes(stmt));
tal_free(stmt);
}

/* FIXME: We cannot use ->delete_columns to remove
* short_channel_id, as other tables reference the channels
* (and sqlite3 has them referencing a now-deleted table!).
* When we can assume sqlite3 2021-04-19 (3.35.5), we can
* simply use DROP COLUMN (yay!) */
}
26 changes: 11 additions & 15 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1293,10 +1293,9 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm
}
}

if (!db_col_is_null(stmt, "short_channel_id")) {
if (!db_col_is_null(stmt, "scid")) {
scid = tal(tmpctx, struct short_channel_id);
if (!db_col_short_channel_id_str(stmt, "short_channel_id", scid))
return NULL;
db_col_scid(stmt, "scid", scid);
} else {
scid = NULL;
}
Expand Down Expand Up @@ -1552,7 +1551,7 @@ static bool wallet_channels_load_active(struct wallet *w)
stmt = db_prepare_v2(w->db, SQL("SELECT"
" id"
", peer_id"
", short_channel_id"
", scid"
", full_channel_id"
", channel_config_local"
", channel_config_remote"
Expand Down Expand Up @@ -1856,7 +1855,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan)

stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET"
" shachain_remote_id=?," // 0
" short_channel_id=?," // 1
" scid=?," // 1
" full_channel_id=?," // 2
" state=?," // 3
" funder=?," // 4
Expand Down Expand Up @@ -1903,7 +1902,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan)
" WHERE id=?")); // 46
db_bind_u64(stmt, 0, chan->their_shachain.id);
if (chan->scid)
db_bind_short_channel_id_str(stmt, 1, chan->scid);
db_bind_scid(stmt, 1, chan->scid);
else
db_bind_null(stmt, 1);

Expand Down Expand Up @@ -4678,11 +4677,11 @@ struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t
", t.blockheight"
", t.txindex"
", t.type as txtype"
", c2.short_channel_id as txchan"
", c2.scid as txchan"
", a.location"
", a.idx as ann_idx"
", a.type as annotation_type"
", c.short_channel_id"
", c.scid"
" FROM"
" transactions t LEFT JOIN"
" transaction_annotations a ON (a.txid = t.id) LEFT JOIN"
Expand Down Expand Up @@ -4725,8 +4724,7 @@ struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t
else
cur->annotation.type = 0;
if (!db_col_is_null(stmt, "txchan"))
db_col_short_channel_id_str(stmt, "txchan",
&cur->annotation.channel);
db_col_scid(stmt, "txchan", &cur->annotation.channel);
else
cur->annotation.channel.u64 = 0;

Expand Down Expand Up @@ -4756,16 +4754,14 @@ struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t

/* cppcheck-suppress uninitvar - false positive on fatal() above */
ann->type = db_col_int(stmt, "annotation_type");
if (!db_col_is_null(stmt, "c.short_channel_id"))
db_col_short_channel_id_str(stmt,
"c.short_channel_id",
&ann->channel);
if (!db_col_is_null(stmt, "c.scid"))
db_col_scid(stmt, "c.scid", &ann->channel);
else
ann->channel.u64 = 0;
} else {
db_col_ignore(stmt, "ann_idx");
db_col_ignore(stmt, "annotation_type");
db_col_ignore(stmt, "c.short_channel_id");
db_col_ignore(stmt, "c.scid");
}
}
tal_free(stmt);
Expand Down