Skip to content

Commit 6c60375

Browse files
committed
lightningd: scan back to seek missing UTXOs.
We only do this once, and not on new nodes. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 1e66414 commit 6c60375

File tree

4 files changed

+84
-10
lines changed

4 files changed

+84
-10
lines changed

lightningd/chaintopology.c

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -888,8 +888,8 @@ static void updates_complete(struct chain_topology *topo)
888888
}
889889

890890
static void record_wallet_spend(struct lightningd *ld,
891-
struct bitcoin_outpoint *outpoint,
892-
struct bitcoin_txid *txid,
891+
const struct bitcoin_outpoint *outpoint,
892+
const struct bitcoin_txid *txid,
893893
u32 tx_blockheight)
894894
{
895895
struct utxo *utxo;
@@ -911,31 +911,34 @@ static void record_wallet_spend(struct lightningd *ld,
911911
/**
912912
* topo_update_spends -- Tell the wallet about all spent outpoints
913913
*/
914-
static void topo_update_spends(struct chain_topology *topo, struct block *b)
914+
static void topo_update_spends(struct chain_topology *topo,
915+
struct bitcoin_tx **txs,
916+
const struct bitcoin_txid *txids,
917+
u32 blockheight)
915918
{
916919
const struct short_channel_id *spent_scids;
917-
const size_t num_txs = tal_count(b->full_txs);
920+
const size_t num_txs = tal_count(txs);
918921
for (size_t i = 0; i < num_txs; i++) {
919-
const struct bitcoin_tx *tx = b->full_txs[i];
922+
const struct bitcoin_tx *tx = txs[i];
920923

921924
for (size_t j = 0; j < tx->wtx->num_inputs; j++) {
922925
struct bitcoin_outpoint outpoint;
923926

924927
bitcoin_tx_input_get_outpoint(tx, j, &outpoint);
925928

926929
if (wallet_outpoint_spend(tmpctx, topo->ld->wallet,
927-
b->height, &outpoint))
930+
blockheight, &outpoint))
928931
record_wallet_spend(topo->ld, &outpoint,
929-
&b->txids[i], b->height);
932+
&txids[i], blockheight);
930933

931934
}
932935
}
933936

934937
/* Retrieve all potential channel closes from the UTXO set and
935938
* tell gossipd about them. */
936939
spent_scids =
937-
wallet_utxoset_get_spent(tmpctx, topo->ld->wallet, b->height);
938-
gossipd_notify_spends(topo->bitcoind->ld, b->height, spent_scids);
940+
wallet_utxoset_get_spent(tmpctx, topo->ld->wallet, blockheight);
941+
gossipd_notify_spends(topo->bitcoind->ld, blockheight, spent_scids);
939942
}
940943

941944
static void topo_add_utxos(struct chain_topology *topo, struct block *b)
@@ -982,7 +985,7 @@ static void add_tip(struct chain_topology *topo, struct block *b)
982985
trace_span_end(b);
983986

984987
trace_span_start("topo_update_spends", b);
985-
topo_update_spends(topo, b);
988+
topo_update_spends(topo, b->full_txs, b->txids, b->height);
986989
trace_span_end(b);
987990

988991
/* Only keep the transactions we care about. */
@@ -1388,6 +1391,7 @@ void setup_topology(struct chain_topology *topo)
13881391
struct bitcoin_block *blk;
13891392
bool blockscan_start_set;
13901393
u32 blockscan_start;
1394+
s64 fixup;
13911395

13921396
/* This waits for bitcoind. */
13931397
bitcoind_check_commands(topo->bitcoind);
@@ -1413,6 +1417,15 @@ void setup_topology(struct chain_topology *topo)
14131417
blockscan_start = blocknum_reduce(blockscan_start, topo->ld->config.rescan);
14141418
}
14151419

1420+
fixup = db_get_intvar(topo->ld->wallet->db, "fixup_block_scan", -1);
1421+
if (fixup == -1) {
1422+
/* Never done fixup: this is set to non-zero if we have blocks. */
1423+
topo->old_block_scan = wallet_blocks_minheight(topo->ld->wallet);
1424+
db_set_intvar(topo->ld->wallet->db, "fixup_block_scan",
1425+
topo->old_block_scan);
1426+
} else {
1427+
topo->old_block_scan = fixup;
1428+
}
14161429
db_commit_transaction(topo->ld->wallet->db);
14171430

14181431
/* Sanity checks, then topology initialization. */
@@ -1509,6 +1522,36 @@ void setup_topology(struct chain_topology *topo)
15091522
tal_add_destructor(topo, destroy_chain_topology);
15101523
}
15111524

1525+
static void fixup_scan_block(struct bitcoind *bitcoind,
1526+
u32 height,
1527+
struct bitcoin_blkid *blkid,
1528+
struct bitcoin_block *blk,
1529+
struct chain_topology *topo)
1530+
{
1531+
log_debug(topo->ld->log, "fixup_scan: block %u with %zu txs", height, tal_count(blk->tx));
1532+
topo_update_spends(topo, blk->tx, blk->txids, height);
1533+
1534+
/* Caught up. */
1535+
if (height == get_block_height(topo)) {
1536+
log_info(topo->ld->log, "Scanning for missed UTXOs finished");
1537+
db_set_intvar(topo->ld->wallet->db, "fixup_block_scan", 0);
1538+
return;
1539+
}
1540+
1541+
db_set_intvar(topo->ld->wallet->db, "fixup_block_scan", ++topo->old_block_scan);
1542+
bitcoind_getrawblockbyheight(topo, topo->bitcoind,
1543+
topo->old_block_scan,
1544+
fixup_scan_block, topo);
1545+
}
1546+
1547+
static void fixup_scan(struct chain_topology *topo)
1548+
{
1549+
log_info(topo->ld->log, "Scanning for missed UTXOs from block %u", topo->old_block_scan);
1550+
bitcoind_getrawblockbyheight(topo, topo->bitcoind,
1551+
topo->old_block_scan,
1552+
fixup_scan_block, topo);
1553+
}
1554+
15121555
void begin_topology(struct chain_topology *topo)
15131556
{
15141557
/* If we were not synced, start looping to check */
@@ -1518,6 +1561,9 @@ void begin_topology(struct chain_topology *topo)
15181561
start_fee_estimate(topo);
15191562
/* Regular block updates */
15201563
try_extend_tip(topo);
1564+
1565+
if (topo->old_block_scan)
1566+
fixup_scan(topo);
15211567
}
15221568

15231569
void stop_topology(struct chain_topology *topo)

lightningd/chaintopology.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ struct chain_topology {
143143
/* The number of headers known to the bitcoin backend at startup. Not
144144
* updated after the initial check. */
145145
u32 headercount;
146+
147+
/* Progress on routine to look for old missed transactions. 0 = not interested. */
148+
u32 old_block_scan;
146149
};
147150

148151
/* Information relevant to locating a TX in a blockchain. */

wallet/wallet.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,6 +2554,22 @@ u32 wallet_blocks_maxheight(struct wallet *w)
25542554
return max;
25552555
}
25562556

2557+
u32 wallet_blocks_minheight(struct wallet *w)
2558+
{
2559+
u32 min = 0;
2560+
struct db_stmt *stmt = db_prepare_v2(w->db, SQL("SELECT MIN(height) FROM blocks;"));
2561+
db_query_prepared(stmt);
2562+
2563+
/* If we ever processed a block we'll get the latest block in the chain */
2564+
if (db_step(stmt)) {
2565+
if (!db_col_is_null(stmt, "MIN(height)")) {
2566+
min = db_col_int(stmt, "MIN(height)");
2567+
}
2568+
}
2569+
tal_free(stmt);
2570+
return min;
2571+
}
2572+
25572573
static void wallet_channel_config_insert(struct wallet *w,
25582574
struct channel_config *cc)
25592575
{

wallet/wallet.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,15 @@ void wallet_channel_stats_incr_out_fulfilled(struct wallet *w, u64 cdbid, struct
789789
*/
790790
u32 wallet_blocks_maxheight(struct wallet *w);
791791

792+
/**
793+
* Retrieve the blockheight of the first block processed by lightningd.
794+
*
795+
* Will return the 0 if the wallet was never used before.
796+
*
797+
* @w: wallet to load from.
798+
*/
799+
u32 wallet_blocks_minheight(struct wallet *w);
800+
792801
/**
793802
* wallet_extract_owned_outputs - given a tx, extract all of our outputs
794803
*/

0 commit comments

Comments
 (0)