Skip to content

Commit 1d6a8c9

Browse files
committed
onchaind: explicit ack for onchaind_spent method.
This means it always tells us explicitly whether to keep watching or not, and we know it's processed it. Signed-off-by: Rusty Russell <[email protected]>
1 parent ecff6f1 commit 1d6a8c9

File tree

7 files changed

+89
-71
lines changed

7 files changed

+89
-71
lines changed

Diff for: lightningd/onchain_control.c

+45-36
Original file line numberDiff line numberDiff line change
@@ -218,21 +218,64 @@ static enum watch_result onchain_tx_watched(struct lightningd *ld,
218218
static void watch_tx_and_outputs(struct channel *channel,
219219
const struct bitcoin_tx *tx);
220220

221+
static void replay_unwatch_txid(struct channel *channel,
222+
const struct bitcoin_txid *txid)
223+
{
224+
replay_tx_hash_delkey(channel->onchaind_replay_watches, txid);
225+
}
226+
227+
static void onchaind_spent_reply(struct subd *onchaind, const u8 *msg,
228+
const int *fds,
229+
struct bitcoin_txid *txid)
230+
{
231+
bool interested;
232+
struct txwatch *txw;
233+
struct channel *channel = onchaind->channel;
234+
235+
if (!fromwire_onchaind_spent_reply(msg, &interested))
236+
channel_internal_error(channel, "Invalid onchaind_spent_reply %s",
237+
tal_hex(tmpctx, msg));
238+
239+
/* Only delete watch if it says it doesn't care */
240+
if (interested)
241+
return;
242+
243+
/* If we're doing replay: */
244+
if (channel->onchaind_replay_watches) {
245+
replay_unwatch_txid(channel, txid);
246+
return;
247+
}
248+
249+
/* Frees the txo watches, too: see watch_tx_and_outputs() */
250+
txw = find_txwatch(channel->peer->ld->topology, txid,
251+
onchain_tx_watched, channel);
252+
if (!txw)
253+
log_unusual(channel->log, "Can't unwatch txid %s",
254+
fmt_bitcoin_txid(tmpctx, txid));
255+
tal_free(txw);
256+
}
257+
221258
/**
222259
* Notify onchaind that an output was spent and register new watches.
223260
*/
224261
static void onchain_txo_spent(struct channel *channel, const struct bitcoin_tx *tx, size_t input_num, u32 blockheight)
225262
{
226263
u8 *msg;
264+
struct bitcoin_txid *txid;
227265
/* Onchaind needs all inputs, since it uses those to compare
228266
* with existing spends (which can vary, with feerate changes). */
229267
struct tx_parts *parts = tx_parts_from_wally_tx(tmpctx, tx->wtx,
230268
-1, -1);
231269

232270
watch_tx_and_outputs(channel, tx);
233271

272+
/* Reply will need this if we want to unwatch */
273+
txid = tal(NULL, struct bitcoin_txid);
274+
bitcoin_txid(tx, txid);
275+
234276
msg = towire_onchaind_spent(channel, parts, input_num, blockheight);
235-
subd_send_msg(channel->owner, take(msg));
277+
subd_req(channel->owner, channel->owner, take(msg), -1, 0,
278+
onchaind_spent_reply, take(txid));
236279

237280
}
238281

@@ -304,12 +347,6 @@ static void replay_watch_tx(struct channel *channel,
304347
replay_tx_hash_add(channel->onchaind_replay_watches, rtx);
305348
}
306349

307-
static void replay_unwatch_txid(struct channel *channel,
308-
const struct bitcoin_txid *txid)
309-
{
310-
replay_tx_hash_delkey(channel->onchaind_replay_watches, txid);
311-
}
312-
313350
/* We've finished replaying, turn any txs left into live watches */
314351
static void convert_replay_txs(struct channel *channel)
315352
{
@@ -372,31 +409,6 @@ static void replay_block(struct bitcoind *bitcoind,
372409
bitcoind_getrawblockbyheight(channel, bitcoind, height + 1, replay_block, channel);
373410
}
374411

375-
static void handle_onchain_unwatch_tx(struct channel *channel, const u8 *msg)
376-
{
377-
struct bitcoin_txid txid;
378-
struct txwatch *txw;
379-
380-
if (!fromwire_onchaind_unwatch_tx(msg, &txid)) {
381-
channel_internal_error(channel, "Invalid onchain_unwatch_tx");
382-
return;
383-
}
384-
385-
/* If we're doing replay: */
386-
if (channel->onchaind_replay_watches) {
387-
replay_unwatch_txid(channel, &txid);
388-
return;
389-
}
390-
391-
/* Frees the txo watches, too: see watch_tx_and_outputs() */
392-
txw = find_txwatch(channel->peer->ld->topology, &txid,
393-
onchain_tx_watched, channel);
394-
if (!txw)
395-
log_unusual(channel->log, "Can't unwatch txid %s",
396-
fmt_bitcoin_txid(tmpctx, &txid));
397-
tal_free(txw);
398-
}
399-
400412
static void handle_extracted_preimage(struct channel *channel, const u8 *msg)
401413
{
402414
struct preimage preimage;
@@ -1545,10 +1557,6 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U
15451557
handle_onchain_init_reply(sd->channel, msg);
15461558
break;
15471559

1548-
case WIRE_ONCHAIND_UNWATCH_TX:
1549-
handle_onchain_unwatch_tx(sd->channel, msg);
1550-
break;
1551-
15521560
case WIRE_ONCHAIND_EXTRACTED_PREIMAGE:
15531561
handle_extracted_preimage(sd->channel, msg);
15541562
break;
@@ -1614,6 +1622,7 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U
16141622
case WIRE_ONCHAIND_SPEND_CREATED:
16151623
case WIRE_ONCHAIND_DEV_MEMLEAK:
16161624
case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY:
1625+
case WIRE_ONCHAIND_SPENT_REPLY:
16171626
break;
16181627
}
16191628

Diff for: lightningd/test/run-invoice-select-inchan.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ struct subd_req *subd_req_(const tal_t *ctx UNNEEDED,
939939
const u8 *msg_out UNNEEDED,
940940
int fd_out UNNEEDED, size_t num_fds_in UNNEEDED,
941941
void (*replycb)(struct subd * UNNEEDED, const u8 * UNNEEDED, const int * UNNEEDED, void *) UNNEEDED,
942-
void *replycb_data UNNEEDED)
942+
void *replycb_data TAKES UNNEEDED)
943943
{ fprintf(stderr, "subd_req_ called!\n"); abort(); }
944944
/* Generated stub for subd_send_fd */
945945
void subd_send_fd(struct subd *sd UNNEEDED, int fd UNNEEDED)

Diff for: onchaind/onchaind.c

+28-24
Original file line numberDiff line numberDiff line change
@@ -978,14 +978,6 @@ static void billboard_update(struct tracked_output **outs)
978978
output_type_name(best->output_type), best->depth);
979979
}
980980

981-
static void unwatch_txid(const struct bitcoin_txid *txid)
982-
{
983-
u8 *msg;
984-
985-
msg = towire_onchaind_unwatch_tx(NULL, txid);
986-
wire_sync_write(REQ_FD, take(msg));
987-
}
988-
989981
static void handle_htlc_onchain_fulfill(struct tracked_output *out,
990982
const struct tx_parts *tx_parts,
991983
const struct bitcoin_outpoint *htlc_outpoint)
@@ -1194,23 +1186,30 @@ static void onchain_annotate_txin(const struct bitcoin_txid *txid, u32 innum,
11941186
tmpctx, txid, innum, type)));
11951187
}
11961188

1197-
/* An output has been spent: see if it resolves something we care about. */
1198-
static void output_spent(struct tracked_output ***outs,
1189+
/* An output has been spent: see if it resolves something we care about.
1190+
* Return true if it's useful to know about, false to suppress this and any
1191+
* child transactions.
1192+
*/
1193+
static bool output_spent(struct tracked_output ***outs,
11991194
const struct tx_parts *tx_parts,
12001195
u32 input_num,
12011196
u32 tx_blockheight)
12021197
{
1198+
bool interesting;
1199+
12031200
for (size_t i = 0; i < tal_count(*outs); i++) {
12041201
struct tracked_output *out = (*outs)[i];
12051202
struct bitcoin_outpoint htlc_outpoint;
12061203

1207-
if (out->resolved)
1208-
continue;
1209-
12101204
if (!wally_tx_input_spends(tx_parts->inputs[input_num],
12111205
&out->outpoint))
12121206
continue;
12131207

1208+
interesting = true;
1209+
1210+
if (out->resolved)
1211+
continue;
1212+
12141213
/* Was this our resolution? */
12151214
if (resolved_by_proposal(out, tx_parts)) {
12161215
/* If it's our htlc tx, we need to resolve that, too. */
@@ -1221,7 +1220,7 @@ static void output_spent(struct tracked_output ***outs,
12211220

12221221
record_coin_movements(out, tx_blockheight,
12231222
&tx_parts->txid);
1224-
return;
1223+
return interesting;
12251224
}
12261225

12271226
htlc_outpoint.txid = tx_parts->txid;
@@ -1342,17 +1341,18 @@ static void output_spent(struct tracked_output ***outs,
13421341
tx_type_name(out->tx_type),
13431342
output_type_name(out->output_type));
13441343
}
1345-
return;
13461344
}
13471345

1348-
struct bitcoin_txid txid;
1349-
wally_tx_input_get_txid(tx_parts->inputs[input_num], &txid);
1350-
/* Not interesting to us, so unwatch the tx and all its outputs */
1351-
status_debug("Notified about tx %s output %u spend, but we don't care",
1352-
fmt_bitcoin_txid(tmpctx, &txid),
1353-
tx_parts->inputs[input_num]->index);
1346+
if (!interesting) {
1347+
struct bitcoin_txid txid;
1348+
wally_tx_input_get_txid(tx_parts->inputs[input_num], &txid);
13541349

1355-
unwatch_txid(&tx_parts->txid);
1350+
status_debug("Notified about tx %s output %u spend, but we don't care",
1351+
fmt_bitcoin_txid(tmpctx, &txid),
1352+
tx_parts->inputs[input_num]->index);
1353+
}
1354+
1355+
return interesting;
13561356
}
13571357

13581358
static void update_resolution_depth(struct tracked_output *out, u32 depth)
@@ -1610,12 +1610,16 @@ static void handle_onchaind_spent(struct tracked_output ***outs, const u8 *msg)
16101610
{
16111611
struct tx_parts *tx_parts;
16121612
u32 input_num, tx_blockheight;
1613+
bool interesting;
16131614

16141615
if (!fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num,
16151616
&tx_blockheight))
16161617
master_badmsg(WIRE_ONCHAIND_SPENT, msg);
16171618

1618-
output_spent(outs, tx_parts, input_num, tx_blockheight);
1619+
interesting = output_spent(outs, tx_parts, input_num, tx_blockheight);
1620+
1621+
/* Tell lightningd if it was interesting */
1622+
wire_sync_write(REQ_FD, take(towire_onchaind_spent_reply(NULL, interesting)));
16191623
}
16201624

16211625
static void handle_onchaind_known_preimage(struct tracked_output ***outs,
@@ -1675,7 +1679,7 @@ static void wait_for_resolved(struct tracked_output **outs)
16751679

16761680
/* We send these, not receive! */
16771681
case WIRE_ONCHAIND_INIT_REPLY:
1678-
case WIRE_ONCHAIND_UNWATCH_TX:
1682+
case WIRE_ONCHAIND_SPENT_REPLY:
16791683
case WIRE_ONCHAIND_EXTRACTED_PREIMAGE:
16801684
case WIRE_ONCHAIND_MISSING_HTLC_OUTPUT:
16811685
case WIRE_ONCHAIND_HTLC_TIMEOUT:

Diff for: onchaind/onchaind_wire.csv

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,15 @@ msgdata,onchaind_spent,tx,tx_parts,
6767
msgdata,onchaind_spent,input_num,u32,
6868
msgdata,onchaind_spent,blockheight,u32,
6969

70+
# onchaind->master: do we want to continue watching this?
71+
msgtype,onchaind_spent_reply,5104
72+
msgdata,onchaind_spent_reply,interested,bool,
73+
7074
# master->onchaind: We will receive more than one of these, as depth changes.
7175
msgtype,onchaind_depth,5005
7276
msgdata,onchaind_depth,txid,bitcoin_txid,
7377
msgdata,onchaind_depth,depth,u32,
7478

75-
# onchaind->master: We don't want to watch this tx, or its outputs
76-
msgtype,onchaind_unwatch_tx,5006
77-
msgdata,onchaind_unwatch_tx,txid,bitcoin_txid,
78-
7979
# master->onchaind: We know HTLC preimage
8080
msgtype,onchaind_known_preimage,5007
8181
msgdata,onchaind_known_preimage,preimage,preimage,

Diff for: onchaind/test/run-grind_feerate.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,9 @@ u8 *towire_onchaind_spend_penalty(const tal_t *ctx UNNEEDED, const struct bitcoi
334334
/* Generated stub for towire_onchaind_spend_to_us */
335335
u8 *towire_onchaind_spend_to_us(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u32 minblock UNNEEDED, u64 commit_num UNNEEDED, const u8 *wscript UNNEEDED)
336336
{ fprintf(stderr, "towire_onchaind_spend_to_us called!\n"); abort(); }
337-
/* Generated stub for towire_onchaind_unwatch_tx */
338-
u8 *towire_onchaind_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
339-
{ fprintf(stderr, "towire_onchaind_unwatch_tx called!\n"); abort(); }
337+
/* Generated stub for towire_onchaind_spent_reply */
338+
u8 *towire_onchaind_spent_reply(const tal_t *ctx UNNEEDED, bool interested UNNEEDED)
339+
{ fprintf(stderr, "towire_onchaind_spent_reply called!\n"); abort(); }
340340
/* Generated stub for towire_secp256k1_ecdsa_signature */
341341
void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
342342
const secp256k1_ecdsa_signature *signature UNNEEDED)

Diff for: tests/test_closing.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1751,7 +1751,7 @@ def test_onchain_first_commit(node_factory, bitcoind):
17511751
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
17521752

17531753

1754-
def test_onchain_unwatch(node_factory, bitcoind):
1754+
def test_onchain_unwatch(node_factory, bitcoind, chainparams):
17551755
"""Onchaind should not watch random spends"""
17561756
# We track channel balances, to verify that accounting is ok.
17571757
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
@@ -1784,7 +1784,12 @@ def test_onchain_unwatch(node_factory, bitcoind):
17841784
# Daemon gets told about wallet; says it doesn't care.
17851785
l1.rpc.withdraw(l1.rpc.newaddr()['bech32'], 'all')
17861786
bitcoind.generate_block(1)
1787-
l1.daemon.wait_for_log("but we don't care")
1787+
1788+
# We see *two* of these: one for anchor spend as well!
1789+
if chainparams['elements']:
1790+
l1.daemon.wait_for_log("but we don't care")
1791+
else:
1792+
l1.daemon.wait_for_logs(["but we don't care"] * 2)
17881793

17891794
# And lightningd should respect that!
17901795
assert not l1.daemon.is_in_log("Can't unwatch txid")

Diff for: wallet/test/run-wallet.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ struct subd_req *subd_req_(const tal_t *ctx UNNEEDED,
985985
const u8 *msg_out UNNEEDED,
986986
int fd_out UNNEEDED, size_t num_fds_in UNNEEDED,
987987
void (*replycb)(struct subd * UNNEEDED, const u8 * UNNEEDED, const int * UNNEEDED, void *) UNNEEDED,
988-
void *replycb_data UNNEEDED)
988+
void *replycb_data TAKES UNNEEDED)
989989
{ fprintf(stderr, "subd_req_ called!\n"); abort(); }
990990
/* Generated stub for subd_send_fd */
991991
void subd_send_fd(struct subd *sd UNNEEDED, int fd UNNEEDED)

0 commit comments

Comments
 (0)