Skip to content

Commit caa18e6

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 a49c639 commit caa18e6

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,
@@ -1781,51 +1781,56 @@ enum watch_result onchaind_funding_spent(struct channel *channel,
17811781
feerate_min(ld, NULL));
17821782
subd_send_msg(channel->owner, take(msg));
17831783

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

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

17901795
void onchaind_replay_channels(struct lightningd *ld)
17911796
{
1792-
u32 *onchaind_ids;
1793-
struct channeltx *txs;
1794-
struct channel *chan;
1797+
struct peer *peer;
1798+
struct peer_node_id_map_iter it;
17951799

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

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)