Skip to content

Commit cc68599

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 27c0ea6 commit cc68599

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
/* Nothing happened yet */
314315
memset(&channel->stats, 0, sizeof(channel->stats));
315316
channel->state_changes = tal_arr(channel, struct channel_state_change *, 0);
@@ -607,6 +608,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
607608
channel->ignore_fee_limits = ignore_fee_limits;
608609
channel->last_stable_connection = last_stable_connection;
609610
channel->stable_conn_timer = NULL;
611+
channel->onchaind_replay_watches = NULL;
610612
channel->stats = *stats;
611613
channel->state_changes = tal_steal(channel, state_changes);
612614

lightningd/channel.h

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

197+
/* If we're doing a replay for onchaind, here are the txids it's watching */
198+
struct replay_tx_hash *onchaind_replay_watches;
199+
197200
/* Our original funds, in funding amount */
198201
struct amount_sat our_funds;
199202

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 UNNEEDED 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(channel, 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)