mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-15 11:59:16 +01:00
wallet: Annotate migrations using the SQL macro
Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
5270c149e3
commit
66a47d2761
1 changed files with 427 additions and 363 deletions
790
wallet/db.c
790
wallet/db.c
|
@ -29,369 +29,433 @@ void migrate_pr2342_feerate_per_channel(struct lightningd *ld, struct db *db);
|
||||||
* migrate existing databases from a previous state, based on the
|
* migrate existing databases from a previous state, based on the
|
||||||
* string indices */
|
* string indices */
|
||||||
static struct migration dbmigrations[] = {
|
static struct migration dbmigrations[] = {
|
||||||
{ "CREATE TABLE version (version INTEGER)", NULL },
|
{SQL("CREATE TABLE version (version INTEGER)"), NULL},
|
||||||
{ "INSERT INTO version VALUES (1)", NULL },
|
{SQL("INSERT INTO version VALUES (1)"), NULL},
|
||||||
{ "CREATE TABLE outputs ( \
|
{SQL("CREATE TABLE outputs ("
|
||||||
prev_out_tx CHAR(64), \
|
" prev_out_tx CHAR(64)"
|
||||||
prev_out_index INTEGER, \
|
", prev_out_index INTEGER"
|
||||||
value INTEGER, \
|
", value INTEGER"
|
||||||
type INTEGER, \
|
", type INTEGER"
|
||||||
status INTEGER, \
|
", status INTEGER"
|
||||||
keyindex INTEGER, \
|
", keyindex INTEGER"
|
||||||
PRIMARY KEY (prev_out_tx, prev_out_index) \
|
", PRIMARY KEY (prev_out_tx, prev_out_index));"),
|
||||||
);", NULL },
|
NULL},
|
||||||
{ "CREATE TABLE vars (name VARCHAR(32), val VARCHAR(255), PRIMARY KEY (name));", NULL },
|
{SQL("CREATE TABLE vars ("
|
||||||
{ "CREATE TABLE shachains ( \
|
" name VARCHAR(32)"
|
||||||
id INTEGER, \
|
", val VARCHAR(255)"
|
||||||
min_index INTEGER, \
|
", PRIMARY KEY (name)"
|
||||||
num_valid INTEGER, \
|
");"),
|
||||||
PRIMARY KEY (id));", NULL },
|
NULL},
|
||||||
{ "CREATE TABLE shachain_known ( \
|
{SQL("CREATE TABLE shachains ("
|
||||||
shachain_id INTEGER REFERENCES shachains(id) ON DELETE CASCADE, \
|
" id INTEGER"
|
||||||
pos INTEGER, \
|
", min_index INTEGER"
|
||||||
idx INTEGER, \
|
", num_valid INTEGER"
|
||||||
hash BLOB, \
|
", PRIMARY KEY (id)"
|
||||||
PRIMARY KEY (shachain_id, pos));", NULL },
|
");"),
|
||||||
{ "CREATE TABLE channels ("
|
NULL},
|
||||||
" id INTEGER," /* chan->id */
|
{SQL("CREATE TABLE shachain_known ("
|
||||||
" peer_id INTEGER REFERENCES peers(id) ON DELETE CASCADE,"
|
" shachain_id INTEGER REFERENCES shachains(id) ON DELETE CASCADE"
|
||||||
" short_channel_id BLOB,"
|
", pos INTEGER"
|
||||||
" channel_config_local INTEGER,"
|
", idx INTEGER"
|
||||||
" channel_config_remote INTEGER,"
|
", hash BLOB"
|
||||||
" state INTEGER,"
|
", PRIMARY KEY (shachain_id, pos)"
|
||||||
" funder INTEGER,"
|
");"),
|
||||||
" channel_flags INTEGER,"
|
NULL},
|
||||||
" minimum_depth INTEGER,"
|
{SQL("CREATE TABLE channels ("
|
||||||
" next_index_local INTEGER,"
|
" id INTEGER," /* chan->id */
|
||||||
" next_index_remote INTEGER,"
|
" peer_id INTEGER REFERENCES peers(id) ON DELETE CASCADE,"
|
||||||
" next_htlc_id INTEGER, "
|
" short_channel_id BLOB,"
|
||||||
" funding_tx_id BLOB,"
|
" channel_config_local INTEGER,"
|
||||||
" funding_tx_outnum INTEGER,"
|
" channel_config_remote INTEGER,"
|
||||||
" funding_satoshi INTEGER,"
|
" state INTEGER,"
|
||||||
" funding_locked_remote INTEGER,"
|
" funder INTEGER,"
|
||||||
" push_msatoshi INTEGER,"
|
" channel_flags INTEGER,"
|
||||||
" msatoshi_local INTEGER," /* our_msatoshi */
|
" minimum_depth INTEGER,"
|
||||||
/* START channel_info */
|
" next_index_local INTEGER,"
|
||||||
" fundingkey_remote BLOB,"
|
" next_index_remote INTEGER,"
|
||||||
" revocation_basepoint_remote BLOB,"
|
" next_htlc_id INTEGER, "
|
||||||
" payment_basepoint_remote BLOB,"
|
" funding_tx_id BLOB,"
|
||||||
" htlc_basepoint_remote BLOB,"
|
" funding_tx_outnum INTEGER,"
|
||||||
" delayed_payment_basepoint_remote BLOB,"
|
" funding_satoshi INTEGER,"
|
||||||
" per_commit_remote BLOB,"
|
" funding_locked_remote INTEGER,"
|
||||||
" old_per_commit_remote BLOB,"
|
" push_msatoshi INTEGER,"
|
||||||
" local_feerate_per_kw INTEGER,"
|
" msatoshi_local INTEGER," /* our_msatoshi */
|
||||||
" remote_feerate_per_kw INTEGER,"
|
/* START channel_info */
|
||||||
/* END channel_info */
|
" fundingkey_remote BLOB,"
|
||||||
" shachain_remote_id INTEGER,"
|
" revocation_basepoint_remote BLOB,"
|
||||||
" shutdown_scriptpubkey_remote BLOB,"
|
" payment_basepoint_remote BLOB,"
|
||||||
" shutdown_keyidx_local INTEGER,"
|
" htlc_basepoint_remote BLOB,"
|
||||||
" last_sent_commit_state INTEGER,"
|
" delayed_payment_basepoint_remote BLOB,"
|
||||||
" last_sent_commit_id INTEGER,"
|
" per_commit_remote BLOB,"
|
||||||
" last_tx BLOB,"
|
" old_per_commit_remote BLOB,"
|
||||||
" last_sig BLOB,"
|
" local_feerate_per_kw INTEGER,"
|
||||||
" closing_fee_received INTEGER,"
|
" remote_feerate_per_kw INTEGER,"
|
||||||
" closing_sig_received BLOB,"
|
/* END channel_info */
|
||||||
" PRIMARY KEY (id)"
|
" shachain_remote_id INTEGER,"
|
||||||
");", NULL },
|
" shutdown_scriptpubkey_remote BLOB,"
|
||||||
{ "CREATE TABLE peers ("
|
" shutdown_keyidx_local INTEGER,"
|
||||||
" id INTEGER,"
|
" last_sent_commit_state INTEGER,"
|
||||||
" node_id BLOB UNIQUE," /* pubkey */
|
" last_sent_commit_id INTEGER,"
|
||||||
" address TEXT,"
|
" last_tx BLOB,"
|
||||||
" PRIMARY KEY (id)"
|
" last_sig BLOB,"
|
||||||
");", NULL },
|
" closing_fee_received INTEGER,"
|
||||||
{ "CREATE TABLE channel_configs ("
|
" closing_sig_received BLOB,"
|
||||||
" id INTEGER,"
|
" PRIMARY KEY (id)"
|
||||||
" dust_limit_satoshis INTEGER,"
|
");"),
|
||||||
" max_htlc_value_in_flight_msat INTEGER,"
|
NULL},
|
||||||
" channel_reserve_satoshis INTEGER,"
|
{SQL("CREATE TABLE peers ("
|
||||||
" htlc_minimum_msat INTEGER,"
|
" id INTEGER"
|
||||||
" to_self_delay INTEGER,"
|
", node_id BLOB UNIQUE" /* pubkey */
|
||||||
" max_accepted_htlcs INTEGER,"
|
", address TEXT"
|
||||||
" PRIMARY KEY (id)"
|
", PRIMARY KEY (id)"
|
||||||
");", NULL },
|
");"),
|
||||||
{ "CREATE TABLE channel_htlcs ("
|
NULL},
|
||||||
" id INTEGER,"
|
{SQL("CREATE TABLE channel_configs ("
|
||||||
" channel_id INTEGER REFERENCES channels(id) ON DELETE CASCADE,"
|
" id INTEGER,"
|
||||||
" channel_htlc_id INTEGER,"
|
" dust_limit_satoshis INTEGER,"
|
||||||
" direction INTEGER,"
|
" max_htlc_value_in_flight_msat INTEGER,"
|
||||||
" origin_htlc INTEGER,"
|
" channel_reserve_satoshis INTEGER,"
|
||||||
" msatoshi INTEGER,"
|
" htlc_minimum_msat INTEGER,"
|
||||||
" cltv_expiry INTEGER,"
|
" to_self_delay INTEGER,"
|
||||||
" payment_hash BLOB,"
|
" max_accepted_htlcs INTEGER,"
|
||||||
" payment_key BLOB,"
|
" PRIMARY KEY (id)"
|
||||||
" routing_onion BLOB,"
|
");"),
|
||||||
" failuremsg BLOB,"
|
NULL},
|
||||||
" malformed_onion INTEGER,"
|
{SQL("CREATE TABLE channel_htlcs ("
|
||||||
" hstate INTEGER,"
|
" id INTEGER,"
|
||||||
" shared_secret BLOB,"
|
" channel_id INTEGER REFERENCES channels(id) ON DELETE CASCADE,"
|
||||||
" PRIMARY KEY (id),"
|
" channel_htlc_id INTEGER,"
|
||||||
" UNIQUE (channel_id, channel_htlc_id, direction)"
|
" direction INTEGER,"
|
||||||
");", NULL },
|
" origin_htlc INTEGER,"
|
||||||
{ "CREATE TABLE invoices ("
|
" msatoshi INTEGER,"
|
||||||
" id INTEGER,"
|
" cltv_expiry INTEGER,"
|
||||||
" state INTEGER,"
|
" payment_hash BLOB,"
|
||||||
" msatoshi INTEGER,"
|
" payment_key BLOB,"
|
||||||
" payment_hash BLOB,"
|
" routing_onion BLOB,"
|
||||||
" payment_key BLOB,"
|
" failuremsg BLOB,"
|
||||||
" label TEXT,"
|
" malformed_onion INTEGER,"
|
||||||
" PRIMARY KEY (id),"
|
" hstate INTEGER,"
|
||||||
" UNIQUE (label),"
|
" shared_secret BLOB,"
|
||||||
" UNIQUE (payment_hash)"
|
" PRIMARY KEY (id),"
|
||||||
");", NULL },
|
" UNIQUE (channel_id, channel_htlc_id, direction)"
|
||||||
{ "CREATE TABLE payments ("
|
");"),
|
||||||
" id INTEGER,"
|
NULL},
|
||||||
" timestamp INTEGER,"
|
{SQL("CREATE TABLE invoices ("
|
||||||
" status INTEGER,"
|
" id INTEGER,"
|
||||||
" payment_hash BLOB,"
|
" state INTEGER,"
|
||||||
" direction INTEGER,"
|
" msatoshi INTEGER,"
|
||||||
" destination BLOB,"
|
" payment_hash BLOB,"
|
||||||
" msatoshi INTEGER,"
|
" payment_key BLOB,"
|
||||||
" PRIMARY KEY (id),"
|
" label TEXT,"
|
||||||
" UNIQUE (payment_hash)"
|
" PRIMARY KEY (id),"
|
||||||
");", NULL },
|
" UNIQUE (label),"
|
||||||
/* Add expiry field to invoices (effectively infinite). */
|
" UNIQUE (payment_hash)"
|
||||||
{ "ALTER TABLE invoices ADD expiry_time INTEGER;", NULL },
|
");"),
|
||||||
{ "UPDATE invoices SET expiry_time=9223372036854775807;", NULL },
|
NULL},
|
||||||
/* Add pay_index field to paid invoices (initially, same order as id). */
|
{SQL("CREATE TABLE payments ("
|
||||||
{ "ALTER TABLE invoices ADD pay_index INTEGER;", NULL },
|
" id INTEGER,"
|
||||||
{ "CREATE UNIQUE INDEX invoices_pay_index"
|
" timestamp INTEGER,"
|
||||||
" ON invoices(pay_index);", NULL },
|
" status INTEGER,"
|
||||||
{ "UPDATE invoices SET pay_index=id WHERE state=1;", NULL }, /* only paid invoice */
|
" payment_hash BLOB,"
|
||||||
/* Create next_pay_index variable (highest pay_index). */
|
" direction INTEGER,"
|
||||||
{ "INSERT OR REPLACE INTO vars(name, val)"
|
" destination BLOB,"
|
||||||
" VALUES('next_pay_index', "
|
" msatoshi INTEGER,"
|
||||||
" COALESCE((SELECT MAX(pay_index) FROM invoices WHERE state=1), 0) + 1"
|
" PRIMARY KEY (id),"
|
||||||
" );", NULL },
|
" UNIQUE (payment_hash)"
|
||||||
/* Create first_block field; initialize from channel id if any.
|
");"),
|
||||||
* This fails for channels still awaiting lockin, but that only applies to
|
NULL},
|
||||||
* pre-release software, so it's forgivable. */
|
/* Add expiry field to invoices (effectively infinite). */
|
||||||
{ "ALTER TABLE channels ADD first_blocknum INTEGER;", NULL },
|
{SQL("ALTER TABLE invoices ADD expiry_time INTEGER;"), NULL},
|
||||||
{ "UPDATE channels SET first_blocknum=CAST(short_channel_id AS INTEGER) WHERE short_channel_id IS NOT NULL;", NULL },
|
{SQL("UPDATE invoices SET expiry_time=9223372036854775807;"), NULL},
|
||||||
{ "ALTER TABLE outputs ADD COLUMN channel_id INTEGER;", NULL },
|
/* Add pay_index field to paid invoices (initially, same order as id). */
|
||||||
{ "ALTER TABLE outputs ADD COLUMN peer_id BLOB;", NULL },
|
{SQL("ALTER TABLE invoices ADD pay_index INTEGER;"), NULL},
|
||||||
{ "ALTER TABLE outputs ADD COLUMN commitment_point BLOB;", NULL },
|
{SQL("CREATE UNIQUE INDEX invoices_pay_index ON invoices(pay_index);"),
|
||||||
{ "ALTER TABLE invoices ADD COLUMN msatoshi_received INTEGER;", NULL },
|
NULL},
|
||||||
/* Normally impossible, so at least we'll know if databases are ancient. */
|
{SQL("UPDATE invoices SET pay_index=id WHERE state=1;"),
|
||||||
{ "UPDATE invoices SET msatoshi_received=0 WHERE state=1;", NULL },
|
NULL}, /* only paid invoice */
|
||||||
{ "ALTER TABLE channels ADD COLUMN last_was_revoke INTEGER;", NULL },
|
/* Create next_pay_index variable (highest pay_index). */
|
||||||
/* We no longer record incoming payments: invoices cover that.
|
{SQL("INSERT OR REPLACE INTO vars(name, val)"
|
||||||
* Without ALTER_TABLE DROP COLUMN support we need to do this by
|
" VALUES('next_pay_index', "
|
||||||
* rename & copy, which works because there are no triggers etc. */
|
" COALESCE((SELECT MAX(pay_index) FROM invoices WHERE state=1), 0) "
|
||||||
{ "ALTER TABLE payments RENAME TO temp_payments;", NULL },
|
"+ 1"
|
||||||
{ "CREATE TABLE payments ("
|
" );"),
|
||||||
" id INTEGER,"
|
NULL},
|
||||||
" timestamp INTEGER,"
|
/* Create first_block field; initialize from channel id if any.
|
||||||
" status INTEGER,"
|
* This fails for channels still awaiting lockin, but that only applies to
|
||||||
" payment_hash BLOB,"
|
* pre-release software, so it's forgivable. */
|
||||||
" destination BLOB,"
|
{SQL("ALTER TABLE channels ADD first_blocknum INTEGER;"), NULL},
|
||||||
" msatoshi INTEGER,"
|
{SQL("UPDATE channels SET first_blocknum=CAST(short_channel_id AS INTEGER) "
|
||||||
" PRIMARY KEY (id),"
|
"WHERE short_channel_id IS NOT NULL;"),
|
||||||
" UNIQUE (payment_hash)"
|
NULL},
|
||||||
");", NULL },
|
{SQL("ALTER TABLE outputs ADD COLUMN channel_id INTEGER;"), NULL},
|
||||||
{ "INSERT INTO payments SELECT id, timestamp, status, payment_hash, destination, msatoshi FROM temp_payments WHERE direction=1;", NULL },
|
{SQL("ALTER TABLE outputs ADD COLUMN peer_id BLOB;"), NULL},
|
||||||
{ "DROP TABLE temp_payments;", NULL },
|
{SQL("ALTER TABLE outputs ADD COLUMN commitment_point BLOB;"), NULL},
|
||||||
/* We need to keep the preimage in case they ask to pay again. */
|
{SQL("ALTER TABLE invoices ADD COLUMN msatoshi_received INTEGER;"), NULL},
|
||||||
{ "ALTER TABLE payments ADD COLUMN payment_preimage BLOB;", NULL },
|
/* Normally impossible, so at least we'll know if databases are ancient. */
|
||||||
/* We need to keep the shared secrets to decode error returns. */
|
{SQL("UPDATE invoices SET msatoshi_received=0 WHERE state=1;"), NULL},
|
||||||
{ "ALTER TABLE payments ADD COLUMN path_secrets BLOB;", NULL },
|
{SQL("ALTER TABLE channels ADD COLUMN last_was_revoke INTEGER;"), NULL},
|
||||||
/* Create time-of-payment of invoice, default already-paid
|
/* We no longer record incoming payments: invoices cover that.
|
||||||
* invoices to current time. */
|
* Without ALTER_TABLE DROP COLUMN support we need to do this by
|
||||||
{ "ALTER TABLE invoices ADD paid_timestamp INTEGER;", NULL },
|
* rename & copy, which works because there are no triggers etc. */
|
||||||
{ "UPDATE invoices"
|
{SQL("ALTER TABLE payments RENAME TO temp_payments;"), NULL},
|
||||||
" SET paid_timestamp = strftime('%s', 'now')"
|
{SQL("CREATE TABLE payments ("
|
||||||
" WHERE state = 1;", NULL },
|
" id INTEGER,"
|
||||||
/* We need to keep the route node pubkeys and short channel ids to
|
" timestamp INTEGER,"
|
||||||
* correctly mark routing failures. We separate short channel ids
|
" status INTEGER,"
|
||||||
* because we cannot safely save them as blobs due to byteorder
|
" payment_hash BLOB,"
|
||||||
* concerns. */
|
" destination BLOB,"
|
||||||
{ "ALTER TABLE payments ADD COLUMN route_nodes BLOB;", NULL },
|
" msatoshi INTEGER,"
|
||||||
{ "ALTER TABLE payments ADD COLUMN route_channels TEXT;", NULL },
|
" PRIMARY KEY (id),"
|
||||||
{ "CREATE TABLE htlc_sigs (channelid INTEGER REFERENCES channels(id) ON DELETE CASCADE, signature BLOB);", NULL },
|
" UNIQUE (payment_hash)"
|
||||||
{ "CREATE INDEX channel_idx ON htlc_sigs (channelid)", NULL },
|
");"),
|
||||||
/* Get rid of OPENINGD entries; we don't put them in db any more */
|
NULL},
|
||||||
{ "DELETE FROM channels WHERE state=1", NULL },
|
{SQL("INSERT INTO payments SELECT id, timestamp, status, payment_hash, "
|
||||||
/* Keep track of db upgrades, for debugging */
|
"destination, msatoshi FROM temp_payments WHERE direction=1;"),
|
||||||
{ "CREATE TABLE db_upgrades (upgrade_from INTEGER, lightning_version TEXT);", NULL },
|
NULL},
|
||||||
/* We used not to clean up peers when their channels were gone. */
|
{SQL("DROP TABLE temp_payments;"), NULL},
|
||||||
{ "DELETE FROM peers WHERE id NOT IN (SELECT peer_id FROM channels);", NULL },
|
/* We need to keep the preimage in case they ask to pay again. */
|
||||||
/* The ONCHAIND_CHEATED/THEIR_UNILATERAL/OUR_UNILATERAL/MUTUAL are now one */
|
{SQL("ALTER TABLE payments ADD COLUMN payment_preimage BLOB;"), NULL},
|
||||||
{ "UPDATE channels SET STATE = 8 WHERE state > 8;", NULL },
|
/* We need to keep the shared secrets to decode error returns. */
|
||||||
/* Add bolt11 to invoices table*/
|
{SQL("ALTER TABLE payments ADD COLUMN path_secrets BLOB;"), NULL},
|
||||||
{ "ALTER TABLE invoices ADD bolt11 TEXT;", NULL },
|
/* Create time-of-payment of invoice, default already-paid
|
||||||
/* What do we think the head of the blockchain looks like? Used
|
* invoices to current time. */
|
||||||
* primarily to track confirmations across restarts and making
|
{SQL("ALTER TABLE invoices ADD paid_timestamp INTEGER;"), NULL},
|
||||||
* sure we handle reorgs correctly. */
|
{SQL("UPDATE invoices"
|
||||||
{ "CREATE TABLE blocks (height INT, hash BLOB, prev_hash BLOB, UNIQUE(height));", NULL },
|
" SET paid_timestamp = strftime('%s', 'now')"
|
||||||
/* ON DELETE CASCADE would have been nice for confirmation_height,
|
" WHERE state = 1;"),
|
||||||
* so that we automatically delete outputs that fall off the
|
NULL},
|
||||||
* blockchain and then we rediscover them if they are included
|
/* We need to keep the route node pubkeys and short channel ids to
|
||||||
* again. However, we have the their_unilateral/to_us which we
|
* correctly mark routing failures. We separate short channel ids
|
||||||
* can't simply recognize from the chain without additional
|
* because we cannot safely save them as blobs due to byteorder
|
||||||
* hints. So we just mark them as unconfirmed should the block
|
* concerns. */
|
||||||
* die. */
|
{SQL("ALTER TABLE payments ADD COLUMN route_nodes BLOB;"), NULL},
|
||||||
{ "ALTER TABLE outputs ADD COLUMN confirmation_height INTEGER REFERENCES blocks(height) ON DELETE SET NULL;", NULL },
|
{SQL("ALTER TABLE payments ADD COLUMN route_channels TEXT;"), NULL},
|
||||||
{ "ALTER TABLE outputs ADD COLUMN spend_height INTEGER REFERENCES blocks(height) ON DELETE SET NULL;", NULL },
|
{SQL("CREATE TABLE htlc_sigs (channelid INTEGER REFERENCES channels(id) ON "
|
||||||
/* Create a covering index that covers both fields */
|
"DELETE CASCADE, signature BLOB);"),
|
||||||
{ "CREATE INDEX output_height_idx ON outputs (confirmation_height, spend_height);", NULL },
|
NULL},
|
||||||
{ "CREATE TABLE utxoset ("
|
{SQL("CREATE INDEX channel_idx ON htlc_sigs (channelid)"), NULL},
|
||||||
" txid BLOB,"
|
/* Get rid of OPENINGD entries; we don't put them in db any more */
|
||||||
" outnum INT,"
|
{SQL("DELETE FROM channels WHERE state=1"), NULL},
|
||||||
" blockheight INT REFERENCES blocks(height) ON DELETE CASCADE,"
|
/* Keep track of db upgrades, for debugging */
|
||||||
" spendheight INT REFERENCES blocks(height) ON DELETE SET NULL,"
|
{SQL("CREATE TABLE db_upgrades (upgrade_from INTEGER, lightning_version "
|
||||||
" txindex INT,"
|
"TEXT);"),
|
||||||
" scriptpubkey BLOB,"
|
NULL},
|
||||||
" satoshis BIGINT,"
|
/* We used not to clean up peers when their channels were gone. */
|
||||||
" PRIMARY KEY(txid, outnum));", NULL },
|
{SQL("DELETE FROM peers WHERE id NOT IN (SELECT peer_id FROM channels);"),
|
||||||
{ "CREATE INDEX short_channel_id ON utxoset (blockheight, txindex, outnum)", NULL },
|
NULL},
|
||||||
/* Necessary index for long rollbacks of the blockchain, otherwise we're
|
/* The ONCHAIND_CHEATED/THEIR_UNILATERAL/OUR_UNILATERAL/MUTUAL are now one
|
||||||
* doing table scans for every block removed. */
|
*/
|
||||||
{ "CREATE INDEX utxoset_spend ON utxoset (spendheight)", NULL },
|
{SQL("UPDATE channels SET STATE = 8 WHERE state > 8;"), NULL},
|
||||||
/* Assign key 0 to unassigned shutdown_keyidx_local. */
|
/* Add bolt11 to invoices table*/
|
||||||
{ "UPDATE channels SET shutdown_keyidx_local=0 WHERE shutdown_keyidx_local = -1;", NULL },
|
{SQL("ALTER TABLE invoices ADD bolt11 TEXT;"), NULL},
|
||||||
/* FIXME: We should rename shutdown_keyidx_local to final_key_index */
|
/* What do we think the head of the blockchain looks like? Used
|
||||||
/* -- Payment routing failure information -- */
|
* primarily to track confirmations across restarts and making
|
||||||
/* BLOB if failure was due to unparseable onion, NULL otherwise */
|
* sure we handle reorgs correctly. */
|
||||||
{ "ALTER TABLE payments ADD failonionreply BLOB;", NULL },
|
{SQL("CREATE TABLE blocks (height INT, hash BLOB, prev_hash BLOB, "
|
||||||
/* 0 if we could theoretically retry, 1 if PERM fail at payee */
|
"UNIQUE(height));"),
|
||||||
{ "ALTER TABLE payments ADD faildestperm INTEGER;", NULL },
|
NULL},
|
||||||
/* Contents of routing_failure (only if not unparseable onion) */
|
/* ON DELETE CASCADE would have been nice for confirmation_height,
|
||||||
{ "ALTER TABLE payments ADD failindex INTEGER;", NULL }, /* erring_index */
|
* so that we automatically delete outputs that fall off the
|
||||||
{ "ALTER TABLE payments ADD failcode INTEGER;", NULL }, /* failcode */
|
* blockchain and then we rediscover them if they are included
|
||||||
{ "ALTER TABLE payments ADD failnode BLOB;", NULL }, /* erring_node */
|
* again. However, we have the their_unilateral/to_us which we
|
||||||
{ "ALTER TABLE payments ADD failchannel BLOB;", NULL }, /* erring_channel */
|
* can't simply recognize from the chain without additional
|
||||||
{ "ALTER TABLE payments ADD failupdate BLOB;", NULL }, /* channel_update - can be NULL*/
|
* hints. So we just mark them as unconfirmed should the block
|
||||||
/* -- Payment routing failure information ends -- */
|
* die. */
|
||||||
/* Delete route data for already succeeded or failed payments */
|
{SQL("ALTER TABLE outputs ADD COLUMN confirmation_height INTEGER "
|
||||||
{ "UPDATE payments"
|
"REFERENCES blocks(height) ON DELETE SET NULL;"),
|
||||||
" SET path_secrets = NULL"
|
NULL},
|
||||||
" , route_nodes = NULL"
|
{SQL("ALTER TABLE outputs ADD COLUMN spend_height INTEGER REFERENCES "
|
||||||
" , route_channels = NULL"
|
"blocks(height) ON DELETE SET NULL;"),
|
||||||
" WHERE status <> 0;", NULL }, /* PAYMENT_PENDING */
|
NULL},
|
||||||
/* -- Routing statistics -- */
|
/* Create a covering index that covers both fields */
|
||||||
{ "ALTER TABLE channels ADD in_payments_offered INTEGER;", NULL },
|
{SQL("CREATE INDEX output_height_idx ON outputs (confirmation_height, "
|
||||||
{ "ALTER TABLE channels ADD in_payments_fulfilled INTEGER;", NULL },
|
"spend_height);"),
|
||||||
{ "ALTER TABLE channels ADD in_msatoshi_offered INTEGER;", NULL },
|
NULL},
|
||||||
{ "ALTER TABLE channels ADD in_msatoshi_fulfilled INTEGER;", NULL },
|
{SQL("CREATE TABLE utxoset ("
|
||||||
{ "ALTER TABLE channels ADD out_payments_offered INTEGER;", NULL },
|
" txid BLOB,"
|
||||||
{ "ALTER TABLE channels ADD out_payments_fulfilled INTEGER;", NULL },
|
" outnum INT,"
|
||||||
{ "ALTER TABLE channels ADD out_msatoshi_offered INTEGER;", NULL },
|
" blockheight INT REFERENCES blocks(height) ON DELETE CASCADE,"
|
||||||
{ "ALTER TABLE channels ADD out_msatoshi_fulfilled INTEGER;", NULL },
|
" spendheight INT REFERENCES blocks(height) ON DELETE SET NULL,"
|
||||||
{ "UPDATE channels"
|
" txindex INT,"
|
||||||
" SET in_payments_offered = 0, in_payments_fulfilled = 0"
|
" scriptpubkey BLOB,"
|
||||||
" , in_msatoshi_offered = 0, in_msatoshi_fulfilled = 0"
|
" satoshis BIGINT,"
|
||||||
" , out_payments_offered = 0, out_payments_fulfilled = 0"
|
" PRIMARY KEY(txid, outnum));"),
|
||||||
" , out_msatoshi_offered = 0, out_msatoshi_fulfilled = 0"
|
NULL},
|
||||||
" ;", NULL },
|
{SQL("CREATE INDEX short_channel_id ON utxoset (blockheight, txindex, "
|
||||||
/* -- Routing statistics ends --*/
|
"outnum)"),
|
||||||
/* Record the msatoshi actually sent in a payment. */
|
NULL},
|
||||||
{ "ALTER TABLE payments ADD msatoshi_sent INTEGER;", NULL },
|
/* Necessary index for long rollbacks of the blockchain, otherwise we're
|
||||||
{ "UPDATE payments SET msatoshi_sent = msatoshi;", NULL },
|
* doing table scans for every block removed. */
|
||||||
/* Delete dangling utxoset entries due to Issue #1280 */
|
{SQL("CREATE INDEX utxoset_spend ON utxoset (spendheight)"), NULL},
|
||||||
{ "DELETE FROM utxoset WHERE blockheight IN ("
|
/* Assign key 0 to unassigned shutdown_keyidx_local. */
|
||||||
" SELECT DISTINCT(blockheight)"
|
{SQL("UPDATE channels SET shutdown_keyidx_local=0 WHERE "
|
||||||
" FROM utxoset LEFT OUTER JOIN blocks on (blockheight == blocks.height) "
|
"shutdown_keyidx_local = -1;"),
|
||||||
" WHERE blocks.hash IS NULL"
|
NULL},
|
||||||
");", NULL },
|
/* FIXME: We should rename shutdown_keyidx_local to final_key_index */
|
||||||
/* Record feerate range, to optimize onchaind grinding actual fees. */
|
/* -- Payment routing failure information -- */
|
||||||
{ "ALTER TABLE channels ADD min_possible_feerate INTEGER;", NULL },
|
/* BLOB if failure was due to unparseable onion, NULL otherwise */
|
||||||
{ "ALTER TABLE channels ADD max_possible_feerate INTEGER;", NULL },
|
{SQL("ALTER TABLE payments ADD failonionreply BLOB;"), NULL},
|
||||||
/* https://bitcoinfees.github.io/#1d says Dec 17 peak was ~1M sat/kb
|
/* 0 if we could theoretically retry, 1 if PERM fail at payee */
|
||||||
* which is 250,000 sat/Sipa */
|
{SQL("ALTER TABLE payments ADD faildestperm INTEGER;"), NULL},
|
||||||
{ "UPDATE channels SET min_possible_feerate=0, max_possible_feerate=250000;", NULL },
|
/* Contents of routing_failure (only if not unparseable onion) */
|
||||||
/* -- Min and max msatoshi_to_us -- */
|
{SQL("ALTER TABLE payments ADD failindex INTEGER;"),
|
||||||
{ "ALTER TABLE channels ADD msatoshi_to_us_min INTEGER;", NULL },
|
NULL}, /* erring_index */
|
||||||
{ "ALTER TABLE channels ADD msatoshi_to_us_max INTEGER;", NULL },
|
{SQL("ALTER TABLE payments ADD failcode INTEGER;"), NULL}, /* failcode */
|
||||||
{ "UPDATE channels"
|
{SQL("ALTER TABLE payments ADD failnode BLOB;"), NULL}, /* erring_node */
|
||||||
" SET msatoshi_to_us_min = msatoshi_local"
|
{SQL("ALTER TABLE payments ADD failchannel BLOB;"),
|
||||||
" , msatoshi_to_us_max = msatoshi_local"
|
NULL}, /* erring_channel */
|
||||||
" ;", NULL },
|
{SQL("ALTER TABLE payments ADD failupdate BLOB;"),
|
||||||
/* -- Min and max msatoshi_to_us ends -- */
|
NULL}, /* channel_update - can be NULL*/
|
||||||
/* Transactions we are interested in. Either we sent them ourselves or we
|
/* -- Payment routing failure information ends -- */
|
||||||
* are watching them. We don't cascade block height deletes so we don't
|
/* Delete route data for already succeeded or failed payments */
|
||||||
* forget any of them by accident.*/
|
{SQL("UPDATE payments"
|
||||||
{ "CREATE TABLE transactions ("
|
" SET path_secrets = NULL"
|
||||||
" id BLOB"
|
" , route_nodes = NULL"
|
||||||
", blockheight INTEGER REFERENCES blocks(height) ON DELETE SET NULL"
|
" , route_channels = NULL"
|
||||||
", txindex INTEGER"
|
" WHERE status <> 0;"),
|
||||||
", rawtx BLOB"
|
NULL}, /* PAYMENT_PENDING */
|
||||||
", PRIMARY KEY (id)"
|
/* -- Routing statistics -- */
|
||||||
");", NULL },
|
{SQL("ALTER TABLE channels ADD in_payments_offered INTEGER;"), NULL},
|
||||||
/* -- Detailed payment failure -- */
|
{SQL("ALTER TABLE channels ADD in_payments_fulfilled INTEGER;"), NULL},
|
||||||
{ "ALTER TABLE payments ADD faildetail TEXT;", NULL },
|
{SQL("ALTER TABLE channels ADD in_msatoshi_offered INTEGER;"), NULL},
|
||||||
{ "UPDATE payments"
|
{SQL("ALTER TABLE channels ADD in_msatoshi_fulfilled INTEGER;"), NULL},
|
||||||
" SET faildetail = 'unspecified payment failure reason'"
|
{SQL("ALTER TABLE channels ADD out_payments_offered INTEGER;"), NULL},
|
||||||
" WHERE status = 2;", NULL }, /* PAYMENT_FAILED */
|
{SQL("ALTER TABLE channels ADD out_payments_fulfilled INTEGER;"), NULL},
|
||||||
/* -- Detailed payment faiure ends -- */
|
{SQL("ALTER TABLE channels ADD out_msatoshi_offered INTEGER;"), NULL},
|
||||||
{ "CREATE TABLE channeltxs ("
|
{SQL("ALTER TABLE channels ADD out_msatoshi_fulfilled INTEGER;"), NULL},
|
||||||
/* The id serves as insertion order and short ID */
|
{SQL("UPDATE channels"
|
||||||
" id INTEGER"
|
" SET in_payments_offered = 0, in_payments_fulfilled = 0"
|
||||||
", channel_id INTEGER REFERENCES channels(id) ON DELETE CASCADE"
|
" , in_msatoshi_offered = 0, in_msatoshi_fulfilled = 0"
|
||||||
", type INTEGER"
|
" , out_payments_offered = 0, out_payments_fulfilled = 0"
|
||||||
", transaction_id BLOB REFERENCES transactions(id) ON DELETE CASCADE"
|
" , out_msatoshi_offered = 0, out_msatoshi_fulfilled = 0"
|
||||||
/* The input_num is only used by the txo_watch, 0 if txwatch */
|
" ;"),
|
||||||
", input_num INTEGER"
|
NULL},
|
||||||
/* The height at which we sent the depth notice */
|
/* -- Routing statistics ends --*/
|
||||||
", blockheight INTEGER REFERENCES blocks(height) ON DELETE CASCADE"
|
/* Record the msatoshi actually sent in a payment. */
|
||||||
", PRIMARY KEY(id)"
|
{SQL("ALTER TABLE payments ADD msatoshi_sent INTEGER;"), NULL},
|
||||||
");", NULL },
|
{SQL("UPDATE payments SET msatoshi_sent = msatoshi;"), NULL},
|
||||||
/* -- Set the correct rescan height for PR #1398 -- */
|
/* Delete dangling utxoset entries due to Issue #1280 */
|
||||||
/* Delete blocks that are higher than our initial scan point, this is a
|
{SQL("DELETE FROM utxoset WHERE blockheight IN ("
|
||||||
* no-op if we don't have a channel. */
|
" SELECT DISTINCT(blockheight)"
|
||||||
{ "DELETE FROM blocks WHERE height > (SELECT MIN(first_blocknum) FROM channels);", NULL },
|
" FROM utxoset LEFT OUTER JOIN blocks on (blockheight == "
|
||||||
/* Now make sure we have the lower bound block with the first_blocknum
|
"blocks.height) "
|
||||||
* height. This may introduce a block with NULL height if we didn't have any
|
" WHERE blocks.hash IS NULL"
|
||||||
* blocks, remove that in the next. */
|
");"),
|
||||||
{ "INSERT OR IGNORE INTO blocks (height) VALUES ((SELECT MIN(first_blocknum) FROM channels));", NULL },
|
NULL},
|
||||||
{ "DELETE FROM blocks WHERE height IS NULL;", NULL },
|
/* Record feerate range, to optimize onchaind grinding actual fees. */
|
||||||
/* -- End of PR #1398 -- */
|
{SQL("ALTER TABLE channels ADD min_possible_feerate INTEGER;"), NULL},
|
||||||
{ "ALTER TABLE invoices ADD description TEXT;", NULL },
|
{SQL("ALTER TABLE channels ADD max_possible_feerate INTEGER;"), NULL},
|
||||||
/* FIXME: payments table 'description' is really a 'label' */
|
/* https://bitcoinfees.github.io/#1d says Dec 17 peak was ~1M sat/kb
|
||||||
{ "ALTER TABLE payments ADD description TEXT;", NULL },
|
* which is 250,000 sat/Sipa */
|
||||||
/* future_per_commitment_point if other side proves we're out of date -- */
|
{SQL("UPDATE channels SET min_possible_feerate=0, "
|
||||||
{ "ALTER TABLE channels ADD future_per_commitment_point BLOB;", NULL },
|
"max_possible_feerate=250000;"),
|
||||||
/* last_sent_commit array fix */
|
NULL},
|
||||||
{ "ALTER TABLE channels ADD last_sent_commit BLOB;", NULL },
|
/* -- Min and max msatoshi_to_us -- */
|
||||||
/* Stats table to track forwarded HTLCs. The values in the HTLCs
|
{SQL("ALTER TABLE channels ADD msatoshi_to_us_min INTEGER;"), NULL},
|
||||||
* and their states are replicated here and the entries are not
|
{SQL("ALTER TABLE channels ADD msatoshi_to_us_max INTEGER;"), NULL},
|
||||||
* deleted when the HTLC entries or the channel entries are
|
{SQL("UPDATE channels"
|
||||||
* deleted to avoid unexpected drops in statistics. */
|
" SET msatoshi_to_us_min = msatoshi_local"
|
||||||
{ "CREATE TABLE forwarded_payments ("
|
" , msatoshi_to_us_max = msatoshi_local"
|
||||||
" in_htlc_id INTEGER REFERENCES channel_htlcs(id) ON DELETE SET NULL"
|
" ;"),
|
||||||
", out_htlc_id INTEGER REFERENCES channel_htlcs(id) ON DELETE SET NULL"
|
NULL},
|
||||||
", in_channel_scid INTEGER"
|
/* -- Min and max msatoshi_to_us ends -- */
|
||||||
", out_channel_scid INTEGER"
|
/* Transactions we are interested in. Either we sent them ourselves or we
|
||||||
", in_msatoshi INTEGER"
|
* are watching them. We don't cascade block height deletes so we don't
|
||||||
", out_msatoshi INTEGER"
|
* forget any of them by accident.*/
|
||||||
", state INTEGER"
|
{SQL("CREATE TABLE transactions ("
|
||||||
", UNIQUE(in_htlc_id, out_htlc_id)"
|
" id BLOB"
|
||||||
");", NULL },
|
", blockheight INTEGER REFERENCES blocks(height) ON DELETE SET NULL"
|
||||||
/* Add a direction for failed payments. */
|
", txindex INTEGER"
|
||||||
{ "ALTER TABLE payments ADD faildirection INTEGER;", NULL }, /* erring_direction */
|
", rawtx BLOB"
|
||||||
/* Fix dangling peers with no channels. */
|
", PRIMARY KEY (id)"
|
||||||
{ "DELETE FROM peers WHERE id NOT IN (SELECT peer_id FROM channels);", NULL },
|
");"),
|
||||||
{ "ALTER TABLE outputs ADD scriptpubkey BLOB;", NULL },
|
NULL},
|
||||||
/* Keep bolt11 string for payments. */
|
/* -- Detailed payment failure -- */
|
||||||
{ "ALTER TABLE payments ADD bolt11 TEXT;", NULL },
|
{SQL("ALTER TABLE payments ADD faildetail TEXT;"), NULL},
|
||||||
/* PR #2342 feerate per channel */
|
{SQL("UPDATE payments"
|
||||||
{ "ALTER TABLE channels ADD feerate_base INTEGER;", NULL },
|
" SET faildetail = 'unspecified payment failure reason'"
|
||||||
{ "ALTER TABLE channels ADD feerate_ppm INTEGER;", NULL },
|
" WHERE status = 2;"),
|
||||||
{ NULL, migrate_pr2342_feerate_per_channel },
|
NULL}, /* PAYMENT_FAILED */
|
||||||
{ "ALTER TABLE channel_htlcs ADD received_time INTEGER", NULL },
|
/* -- Detailed payment faiure ends -- */
|
||||||
{ "ALTER TABLE forwarded_payments ADD received_time INTEGER", NULL },
|
{SQL("CREATE TABLE channeltxs ("
|
||||||
{ "ALTER TABLE forwarded_payments ADD resolved_time INTEGER", NULL },
|
/* The id serves as insertion order and short ID */
|
||||||
{ "ALTER TABLE channels ADD remote_upfront_shutdown_script BLOB;", NULL },
|
" id INTEGER"
|
||||||
/* PR #2524: Add failcode into forward_payment */
|
", channel_id INTEGER REFERENCES channels(id) ON DELETE CASCADE"
|
||||||
{ "ALTER TABLE forwarded_payments ADD failcode INTEGER;", NULL },
|
", type INTEGER"
|
||||||
/* remote signatures for channel announcement */
|
", transaction_id BLOB REFERENCES transactions(id) ON DELETE CASCADE"
|
||||||
{ "ALTER TABLE channels ADD remote_ann_node_sig BLOB;", NULL },
|
/* The input_num is only used by the txo_watch, 0 if txwatch */
|
||||||
{ "ALTER TABLE channels ADD remote_ann_bitcoin_sig BLOB;", NULL },
|
", input_num INTEGER"
|
||||||
/* Additional information for transaction tracking and listing */
|
/* The height at which we sent the depth notice */
|
||||||
{ "ALTER TABLE transactions ADD type INTEGER;", NULL },
|
", blockheight INTEGER REFERENCES blocks(height) ON DELETE CASCADE"
|
||||||
/* Not a foreign key on purpose since we still delete channels from
|
", PRIMARY KEY(id)"
|
||||||
* the DB which would remove this. It is mainly used to group payments
|
");"),
|
||||||
* in the list view anyway, e.g., show all close and htlc transactions
|
NULL},
|
||||||
* as a single bundle. */
|
/* -- Set the correct rescan height for PR #1398 -- */
|
||||||
{ "ALTER TABLE transactions ADD channel_id INTEGER;", NULL},
|
/* Delete blocks that are higher than our initial scan point, this is a
|
||||||
|
* no-op if we don't have a channel. */
|
||||||
|
{SQL("DELETE FROM blocks WHERE height > (SELECT MIN(first_blocknum) FROM "
|
||||||
|
"channels);"),
|
||||||
|
NULL},
|
||||||
|
/* Now make sure we have the lower bound block with the first_blocknum
|
||||||
|
* height. This may introduce a block with NULL height if we didn't have any
|
||||||
|
* blocks, remove that in the next. */
|
||||||
|
{SQL("INSERT OR IGNORE INTO blocks (height) VALUES ((SELECT "
|
||||||
|
"MIN(first_blocknum) FROM channels));"),
|
||||||
|
NULL},
|
||||||
|
{SQL("DELETE FROM blocks WHERE height IS NULL;"), NULL},
|
||||||
|
/* -- End of PR #1398 -- */
|
||||||
|
{SQL("ALTER TABLE invoices ADD description TEXT;"), NULL},
|
||||||
|
/* FIXME: payments table 'description' is really a 'label' */
|
||||||
|
{SQL("ALTER TABLE payments ADD description TEXT;"), NULL},
|
||||||
|
/* future_per_commitment_point if other side proves we're out of date -- */
|
||||||
|
{SQL("ALTER TABLE channels ADD future_per_commitment_point BLOB;"), NULL},
|
||||||
|
/* last_sent_commit array fix */
|
||||||
|
{SQL("ALTER TABLE channels ADD last_sent_commit BLOB;"), NULL},
|
||||||
|
/* Stats table to track forwarded HTLCs. The values in the HTLCs
|
||||||
|
* and their states are replicated here and the entries are not
|
||||||
|
* deleted when the HTLC entries or the channel entries are
|
||||||
|
* deleted to avoid unexpected drops in statistics. */
|
||||||
|
{SQL("CREATE TABLE forwarded_payments ("
|
||||||
|
" in_htlc_id INTEGER REFERENCES channel_htlcs(id) ON DELETE SET NULL"
|
||||||
|
", out_htlc_id INTEGER REFERENCES channel_htlcs(id) ON DELETE SET NULL"
|
||||||
|
", in_channel_scid INTEGER"
|
||||||
|
", out_channel_scid INTEGER"
|
||||||
|
", in_msatoshi INTEGER"
|
||||||
|
", out_msatoshi INTEGER"
|
||||||
|
", state INTEGER"
|
||||||
|
", UNIQUE(in_htlc_id, out_htlc_id)"
|
||||||
|
");"),
|
||||||
|
NULL},
|
||||||
|
/* Add a direction for failed payments. */
|
||||||
|
{SQL("ALTER TABLE payments ADD faildirection INTEGER;"),
|
||||||
|
NULL}, /* erring_direction */
|
||||||
|
/* Fix dangling peers with no channels. */
|
||||||
|
{SQL("DELETE FROM peers WHERE id NOT IN (SELECT peer_id FROM channels);"),
|
||||||
|
NULL},
|
||||||
|
{SQL("ALTER TABLE outputs ADD scriptpubkey BLOB;"), NULL},
|
||||||
|
/* Keep bolt11 string for payments. */
|
||||||
|
{SQL("ALTER TABLE payments ADD bolt11 TEXT;"), NULL},
|
||||||
|
/* PR #2342 feerate per channel */
|
||||||
|
{SQL("ALTER TABLE channels ADD feerate_base INTEGER;"), NULL},
|
||||||
|
{SQL("ALTER TABLE channels ADD feerate_ppm INTEGER;"), NULL},
|
||||||
|
{NULL, migrate_pr2342_feerate_per_channel},
|
||||||
|
{SQL("ALTER TABLE channel_htlcs ADD received_time INTEGER"), NULL},
|
||||||
|
{SQL("ALTER TABLE forwarded_payments ADD received_time INTEGER"), NULL},
|
||||||
|
{SQL("ALTER TABLE forwarded_payments ADD resolved_time INTEGER"), NULL},
|
||||||
|
{SQL("ALTER TABLE channels ADD remote_upfront_shutdown_script BLOB;"),
|
||||||
|
NULL},
|
||||||
|
/* PR #2524: Add failcode into forward_payment */
|
||||||
|
{SQL("ALTER TABLE forwarded_payments ADD failcode INTEGER;"), NULL},
|
||||||
|
/* remote signatures for channel announcement */
|
||||||
|
{SQL("ALTER TABLE channels ADD remote_ann_node_sig BLOB;"), NULL},
|
||||||
|
{SQL("ALTER TABLE channels ADD remote_ann_bitcoin_sig BLOB;"), NULL},
|
||||||
|
/* Additional information for transaction tracking and listing */
|
||||||
|
{SQL("ALTER TABLE transactions ADD type INTEGER;"), NULL},
|
||||||
|
/* Not a foreign key on purpose since we still delete channels from
|
||||||
|
* the DB which would remove this. It is mainly used to group payments
|
||||||
|
* in the list view anyway, e.g., show all close and htlc transactions
|
||||||
|
* as a single bundle. */
|
||||||
|
{SQL("ALTER TABLE transactions ADD channel_id INTEGER;"), NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Leak tracking. */
|
/* Leak tracking. */
|
||||||
|
|
Loading…
Add table
Reference in a new issue