Skip to content

Commit 001269c

Browse files
committed
lightningd: use block-at-a-time replay for onchaind on restart.
And we hook in the replay watch code. Signed-off-by: Rusty Russell <[email protected]> Changelog-Fixed: `onchaind` can miss conclusion of final txs in some cases, will now replay independently.
1 parent cc68599 commit 001269c

File tree

2 files changed

+42
-37
lines changed

2 files changed

+42
-37
lines changed

lightningd/onchain_control.c

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static void convert_replay_txs(struct channel *channel)
336336
}
337337
}
338338

339-
static UNNEEDED void replay_block(struct bitcoind *bitcoind,
339+
static void replay_block(struct bitcoind *bitcoind,
340340
u32 height,
341341
struct bitcoin_blkid *blkid,
342342
struct bitcoin_block *blk,
@@ -1783,51 +1783,56 @@ enum watch_result onchaind_funding_spent(struct channel *channel,
17831783
feerate_min(ld, NULL));
17841784
subd_send_msg(channel->owner, take(msg));
17851785

1786-
watch_tx_and_outputs(channel, tx);
1786+
/* If we're replaying, we just watch this */
1787+
if (channel->onchaind_replay_watches) {
1788+
replay_watch_tx(channel, blockheight, tx);
1789+
} else {
1790+
watch_tx_and_outputs(channel, tx);
1791+
}
17871792

17881793
/* We keep watching until peer finally deleted, for reorgs. */
17891794
return KEEP_WATCHING;
17901795
}
17911796

17921797
void onchaind_replay_channels(struct lightningd *ld)
17931798
{
1794-
u32 *onchaind_ids;
1795-
struct channeltx *txs;
1796-
struct channel *chan;
1799+
struct peer *peer;
1800+
struct peer_node_id_map_iter it;
17971801

1802+
/* We don't hold a db tx for all of init */
17981803
db_begin_transaction(ld->wallet->db);
1799-
onchaind_ids = wallet_onchaind_channels(tmpctx, ld->wallet);
1800-
1801-
for (size_t i = 0; i < tal_count(onchaind_ids); i++) {
1802-
log_info(ld->log, "Restarting onchaind for channel %d",
1803-
onchaind_ids[i]);
1804-
1805-
txs = wallet_channeltxs_get(onchaind_ids, ld->wallet,
1806-
onchaind_ids[i]);
1807-
chan = channel_by_dbid(ld, onchaind_ids[i]);
1808-
1809-
for (size_t j = 0; j < tal_count(txs); j++) {
1810-
if (txs[j].type == WIRE_ONCHAIND_INIT) {
1811-
onchaind_funding_spent(chan, txs[j].tx,
1812-
txs[j].blockheight);
1813-
1814-
} else if (txs[j].type == WIRE_ONCHAIND_SPENT) {
1815-
onchain_txo_spent(chan, txs[j].tx,
1816-
txs[j].input_num,
1817-
txs[j].blockheight);
1818-
1819-
} else if (txs[j].type == WIRE_ONCHAIND_DEPTH) {
1820-
onchain_tx_depth(chan, &txs[j].txid,
1821-
txs[j].depth);
1822-
1823-
} else {
1824-
fatal("unknown message of type %d during "
1825-
"onchaind replay",
1826-
txs[j].type);
1827-
}
1804+
1805+
/* For each channel, if we've recorded a spend, it's onchaind time! */
1806+
for (peer = peer_node_id_map_first(ld->peers, &it);
1807+
peer;
1808+
peer = peer_node_id_map_next(ld->peers, &it)) {
1809+
struct channel *channel;
1810+
1811+
list_for_each(&peer->channels, channel, list) {
1812+
struct bitcoin_tx *tx;
1813+
u32 blockheight;
1814+
1815+
if (channel_state_uncommitted(channel->state))
1816+
continue;
1817+
1818+
tx = wallet_get_funding_spend(tmpctx, ld->wallet, channel->dbid,
1819+
&blockheight);
1820+
if (!tx)
1821+
continue;
1822+
1823+
log_info(channel->log,
1824+
"Restarting onchaind (%s): closed in block %u",
1825+
channel_state_name(channel), blockheight);
1826+
1827+
/* We're in replay mode */
1828+
channel->onchaind_replay_watches = tal(channel, struct replay_tx_hash);
1829+
replay_tx_hash_init(channel->onchaind_replay_watches);
1830+
1831+
onchaind_funding_spent(channel, tx, blockheight);
1832+
/* Ask bitcoind to start grabbing those blocks for replay */
1833+
bitcoind_getrawblockbyheight(channel, ld->topology->bitcoind, blockheight,
1834+
replay_block, channel);
18281835
}
1829-
tal_free(txs);
18301836
}
1831-
18321837
db_commit_transaction(ld->wallet->db);
18331838
}

tests/test_closing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1848,7 +1848,7 @@ def test_onchaind_replay(node_factory, bitcoind):
18481848
l1.restart()
18491849

18501850
# Can't wait for it, it's after the "Server started" wait in restart()
1851-
assert l1.daemon.is_in_log(r'Restarting onchaind for channel')
1851+
assert l1.daemon.is_in_log(r'Restarting onchaind \(ONCHAIN\): closed in block 109')
18521852

18531853
# l1 should still notice that the funding was spent and that we should react to it
18541854
_, txid, blocks = l1.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',

0 commit comments

Comments
 (0)