Skip to content

Commit b904a65

Browse files
committed
lightningd: separate code for onchaind watches separate if we're doing replay.
We start by telling onchaind about the funding spend, and anything which spends it, and it tells us the txids it *doesn't* want to watch any more. We're going to use a separate set of watches for the replay case: this implements that code. Once we're caught up, we convert any remaining watches to normal ones to follow future blocks. Signed-off-by: Rusty Russell <[email protected]>
1 parent efce1fa commit b904a65

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

lightningd/channel.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ struct channel *new_unsaved_channel(struct peer *peer,
310310
channel->ignore_fee_limits = ld->config.ignore_fee_limits;
311311
channel->last_stable_connection = 0;
312312
channel->stable_conn_timer = NULL;
313+
channel->onchaind_replay_watches = NULL;
313314

314315
/* No shachain yet */
315316
channel->their_shachain.id = 0;
@@ -598,6 +599,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
598599
channel->ignore_fee_limits = ignore_fee_limits;
599600
channel->last_stable_connection = last_stable_connection;
600601
channel->stable_conn_timer = NULL;
602+
channel->onchaind_replay_watches = NULL;
601603
/* Populate channel->channel_gossip */
602604
channel_gossip_init(channel, take(peer_update));
603605

lightningd/channel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ struct channel {
177177
/* Watch we have on funding output. */
178178
struct txowatch *funding_spend_watch;
179179

180+
/* If we're doing a replay for onchaind, here are the txids it's watching */
181+
struct replay_tx_hash *onchaind_replay_watches;
182+
180183
/* Our original funds, in funding amount */
181184
struct amount_sat our_funds;
182185

lightningd/onchain_control.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@
2626
#include <wally_psbt.h>
2727
#include <wire/wire_sync.h>
2828

29+
/* If we're restarting, we keep a per-channel copy of watches, and replay */
30+
struct replay_tx {
31+
u32 blockheight;
32+
struct bitcoin_txid txid;
33+
struct bitcoin_tx *tx;
34+
};
35+
36+
static const struct bitcoin_txid *replay_tx_keyof(const struct replay_tx *rtx)
37+
{
38+
return &rtx->txid;
39+
}
40+
41+
static bool replay_tx_eq_txid(const struct replay_tx *rtx,
42+
const struct bitcoin_txid *txid)
43+
{
44+
return bitcoin_txid_eq(&rtx->txid, txid);
45+
}
46+
47+
HTABLE_DEFINE_TYPE(struct replay_tx, replay_tx_keyof, txid_hash, replay_tx_eq_txid,
48+
replay_tx_hash);
49+
2950
/* We dump all the known preimages when onchaind starts up. */
3051
static void onchaind_tell_fulfill(struct channel *channel)
3152
{
@@ -280,6 +301,88 @@ static void handle_onchain_log_coin_move(struct channel *channel, const u8 *msg)
280301
tal_free(mvt);
281302
}
282303

304+
static void replay_watch_tx(struct channel *channel,
305+
u32 blockheight,
306+
const struct bitcoin_tx *tx TAKES)
307+
{
308+
struct replay_tx *rtx = tal(channel->onchaind_replay_watches, struct replay_tx);
309+
bitcoin_txid(tx, &rtx->txid);
310+
rtx->blockheight = blockheight;
311+
rtx->tx = clone_bitcoin_tx(rtx, tx);
312+
313+
replay_tx_hash_add(channel->onchaind_replay_watches, rtx);
314+
}
315+
316+
static void replay_unwatch_txid(struct channel *channel,
317+
const struct bitcoin_txid *txid)
318+
{
319+
replay_tx_hash_delkey(channel->onchaind_replay_watches, txid);
320+
}
321+
322+
/* We've finished replaying, turn any txs left into live watches */
323+
static void convert_replay_txs(struct channel *channel)
324+
{
325+
struct replay_tx *rtx;
326+
struct replay_tx_hash_iter rit;
327+
struct replay_tx_hash *watches;
328+
329+
/* Set to NULL so these are queued as real watches */
330+
watches = tal_steal(tmpctx, channel->onchaind_replay_watches);
331+
channel->onchaind_replay_watches = NULL;
332+
for (rtx = replay_tx_hash_first(watches, &rit);
333+
rtx;
334+
rtx = replay_tx_hash_next(watches, &rit)) {
335+
watch_tx_and_outputs(channel, rtx->tx);
336+
}
337+
}
338+
339+
static void replay_block(struct bitcoind *bitcoind,
340+
u32 height,
341+
struct bitcoin_blkid *blkid,
342+
struct bitcoin_block *blk,
343+
struct channel *channel)
344+
{
345+
struct replay_tx *rtx;
346+
struct replay_tx_hash_iter rit;
347+
348+
/* Tell onchaind that all existing txs have reached a new depth */
349+
for (rtx = replay_tx_hash_first(channel->onchaind_replay_watches, &rit);
350+
rtx;
351+
rtx = replay_tx_hash_next(channel->onchaind_replay_watches, &rit)) {
352+
/* This can happen with the first spend tx, where we replay block! */
353+
if (rtx->blockheight == height)
354+
continue;
355+
onchain_tx_depth(channel, &rtx->txid, height - rtx->blockheight);
356+
}
357+
358+
/* See if we add any new txs which spend a watched one */
359+
for (size_t i = 0; i < tal_count(blk->tx); i++) {
360+
for (size_t j = 0; j < blk->tx[i]->wtx->num_inputs; j++) {
361+
struct bitcoin_txid spent;
362+
bitcoin_tx_input_get_txid(blk->tx[i], j, &spent);
363+
rtx = replay_tx_hash_get(channel->onchaind_replay_watches, &spent);
364+
if (rtx) {
365+
/* Note: for efficiency, blk->tx's don't have
366+
* PSBTs, so add one now */
367+
if (!blk->tx[i]->psbt)
368+
blk->tx[i]->psbt = new_psbt(blk->tx[i], blk->tx[i]->wtx);
369+
onchain_txo_spent(channel, blk->tx[i], j, height);
370+
/* Watch this and all the children too. */
371+
replay_watch_tx(channel, height, blk->tx[i]);
372+
}
373+
}
374+
}
375+
376+
/* Replay finished? Now we'll get fed real blocks */
377+
if (height == get_block_height(bitcoind->ld->topology)) {
378+
convert_replay_txs(channel);
379+
return;
380+
}
381+
382+
/* Otherwise, loop on next block. */
383+
bitcoind_getrawblockbyheight(bitcoind, height + 1, replay_block, channel);
384+
}
385+
283386
static void handle_onchain_unwatch_tx(struct channel *channel, const u8 *msg)
284387
{
285388
struct bitcoin_txid txid;
@@ -290,6 +393,12 @@ static void handle_onchain_unwatch_tx(struct channel *channel, const u8 *msg)
290393
return;
291394
}
292395

396+
/* If we're doing replay: */
397+
if (channel->onchaind_replay_watches) {
398+
replay_unwatch_txid(channel, &txid);
399+
return;
400+
}
401+
293402
/* Frees the txo watches, too: see watch_tx_and_outputs() */
294403
txw = find_txwatch(channel->peer->ld->topology, &txid,
295404
onchain_tx_watched, channel);

0 commit comments

Comments
 (0)