Skip to content

Commit f1bea55

Browse files
committed
lightningd: fix occasional missing txid detection.
I was working on rewriting our (somewhat chaotic) tx watching code for 0.7.2, when I found this bug: we don't always notice the funding tx in corner cases where more than one block is detected at once. This is just the one commit needed to fix the problem: it has some unnecessary changes, but I'd prefer not to diverge too far from my cleanup-txwatch branch. Fixes: #2352 Signed-off-by: Rusty Russell <[email protected]>
1 parent 707ce4c commit f1bea55

File tree

8 files changed

+108
-6
lines changed

8 files changed

+108
-6
lines changed

lightningd/chaintopology.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "bitcoin/tx.h"
55
#include "bitcoind.h"
66
#include "chaintopology.h"
7+
#include "channel.h"
78
#include "jsonrpc.h"
89
#include "lightningd.h"
910
#include "log.h"
@@ -100,6 +101,8 @@ static void filter_block_txs(struct chain_topology *topo, struct block *b)
100101
wallet_transaction_add(topo->ld->wallet,
101102
tx, b->height, i);
102103
}
104+
105+
txwatch_inform(topo, &txid, tx);
103106
}
104107
b->full_txs = tal_free(b->full_txs);
105108
}
@@ -240,8 +243,26 @@ void broadcast_tx(struct chain_topology *topo,
240243
static enum watch_result closeinfo_txid_confirmed(struct lightningd *ld,
241244
struct channel *channel,
242245
const struct bitcoin_txid *txid,
246+
const struct bitcoin_tx *tx,
243247
unsigned int depth)
244248
{
249+
/* Sanity check. */
250+
if (tx != NULL) {
251+
struct bitcoin_txid txid2;
252+
253+
bitcoin_txid(tx, &txid2);
254+
if (!bitcoin_txid_eq(txid, &txid2)) {
255+
channel_internal_error(channel, "Txid for %s is not %s",
256+
type_to_string(tmpctx,
257+
struct bitcoin_tx,
258+
tx),
259+
type_to_string(tmpctx,
260+
struct bitcoin_txid,
261+
txid));
262+
return DELETE_WATCH;
263+
}
264+
}
265+
245266
/* We delete ourselves first time, so should not be reorged out!! */
246267
assert(depth > 0);
247268
/* Subtle: depth 1 == current block. */

lightningd/onchain_control.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,31 @@ static void onchain_tx_depth(struct channel *channel,
7979
static enum watch_result onchain_tx_watched(struct lightningd *ld,
8080
struct channel *channel,
8181
const struct bitcoin_txid *txid,
82+
const struct bitcoin_tx *tx,
8283
unsigned int depth)
8384
{
8485
u32 blockheight = get_block_height(ld->topology);
86+
87+
if (tx != NULL) {
88+
struct bitcoin_txid txid2;
89+
90+
bitcoin_txid(tx, &txid2);
91+
if (!bitcoin_txid_eq(txid, &txid2)) {
92+
channel_internal_error(channel, "Txid for %s is not %s",
93+
type_to_string(tmpctx,
94+
struct bitcoin_tx,
95+
tx),
96+
type_to_string(tmpctx,
97+
struct bitcoin_txid,
98+
txid));
99+
return DELETE_WATCH;
100+
}
101+
}
102+
85103
if (depth == 0) {
86104
log_unusual(channel->log, "Chain reorganization!");
87105
channel_set_owner(channel, NULL, false);
88106

89-
/* FIXME!
90-
topology_rescan(peer->ld->topology, peer->funding_txid);
91-
*/
92-
93107
/* We will most likely be freed, so this is a noop */
94108
return KEEP_WATCHING;
95109
}

lightningd/peer_control.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,14 +945,48 @@ void peer_connected(struct lightningd *ld, const u8 *msg,
945945
plugin_hook_call_peer_connected(ld, hook_payload, hook_payload);
946946
}
947947

948+
/* FIXME: Unify our watch code so we get notified by txout, instead, like
949+
* the wallet code does. */
950+
static bool check_funding_tx(const struct bitcoin_tx *tx,
951+
const struct channel *channel)
952+
{
953+
u8 *wscript;
954+
955+
if (channel->funding_outnum >= tx->wtx->num_outputs)
956+
return false;
957+
958+
if (!amount_sat_eq(bitcoin_tx_output_get_amount(tx,
959+
channel->funding_outnum),
960+
channel->funding))
961+
return false;
962+
963+
wscript = bitcoin_redeem_2of2(tmpctx,
964+
&channel->local_funding_pubkey,
965+
&channel->channel_info.remote_fundingkey);
966+
return scripteq(scriptpubkey_p2wsh(tmpctx, wscript),
967+
bitcoin_tx_output_get_script(tmpctx, tx,
968+
channel->funding_outnum));
969+
}
970+
948971
static enum watch_result funding_depth_cb(struct lightningd *ld,
949972
struct channel *channel,
950973
const struct bitcoin_txid *txid,
974+
const struct bitcoin_tx *tx,
951975
unsigned int depth)
952976
{
953977
const char *txidstr;
954978
struct short_channel_id scid;
955979

980+
/* Sanity check */
981+
if (tx && !check_funding_tx(tx, channel)) {
982+
channel_internal_error(channel, "Bad tx %s: %s",
983+
type_to_string(tmpctx,
984+
struct bitcoin_txid, txid),
985+
type_to_string(tmpctx,
986+
struct bitcoin_tx, tx));
987+
return DELETE_WATCH;
988+
}
989+
956990
txidstr = type_to_string(tmpctx, struct bitcoin_txid, txid);
957991
log_debug(channel->log, "Funding tx %s depth %u of %u",
958992
txidstr, depth, channel->minimum_depth);

lightningd/peer_htlcs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
struct channel;
1111
struct htlc_in;
12+
struct htlc_in_map;
1213
struct htlc_out;
14+
struct htlc_out_map;
1315
struct htlc_stub;
1416
struct lightningd;
1517

lightningd/test/run-invoice-select-inchan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED,
578578
enum watch_result (*cb)(struct lightningd *ld UNNEEDED,
579579
struct channel *channel UNNEEDED,
580580
const struct bitcoin_txid * UNNEEDED,
581+
const struct bitcoin_tx * UNNEEDED,
581582
unsigned int depth))
582583
{ fprintf(stderr, "watch_txid called!\n"); abort(); }
583584
/* Generated stub for watch_txo */

lightningd/watch.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,17 @@ struct txwatch {
6363

6464
/* Transaction to watch. */
6565
struct bitcoin_txid txid;
66+
67+
/* May be NULL if we haven't seen it yet. */
68+
const struct bitcoin_tx *tx;
69+
6670
unsigned int depth;
6771

6872
/* A new depth (0 if kicked out, otherwise 1 = tip, etc.) */
6973
enum watch_result (*cb)(struct lightningd *ld,
7074
struct channel *channel,
7175
const struct bitcoin_txid *txid,
76+
const struct bitcoin_tx *tx,
7277
unsigned int depth);
7378
};
7479

@@ -124,7 +129,8 @@ struct txwatch *watch_txid(const tal_t *ctx,
124129
const struct bitcoin_txid *txid,
125130
enum watch_result (*cb)(struct lightningd *ld,
126131
struct channel *channel,
127-
const struct bitcoin_txid *,
132+
const struct bitcoin_txid *txid,
133+
const struct bitcoin_tx *tx,
128134
unsigned int depth))
129135
{
130136
struct txwatch *w;
@@ -133,6 +139,7 @@ struct txwatch *watch_txid(const tal_t *ctx,
133139
w->topo = topo;
134140
w->depth = 0;
135141
w->txid = *txid;
142+
w->tx = NULL;
136143
w->channel = channel;
137144
w->cb = cb;
138145

@@ -173,11 +180,13 @@ struct txwatch *watch_tx(const tal_t *ctx,
173180
enum watch_result (*cb)(struct lightningd *ld,
174181
struct channel *channel,
175182
const struct bitcoin_txid *,
183+
const struct bitcoin_tx *,
176184
unsigned int depth))
177185
{
178186
struct bitcoin_txid txid;
179187

180188
bitcoin_txid(tx, &txid);
189+
/* FIXME: Save populate txwatch->tx here, too! */
181190
return watch_txid(ctx, topo, channel, &txid, cb);
182191
}
183192

@@ -227,7 +236,8 @@ static bool txw_fire(struct txwatch *txw,
227236
type_to_string(tmpctx, struct bitcoin_txid, &txw->txid),
228237
depth ? "" : " REORG");
229238
txw->depth = depth;
230-
r = txw->cb(txw->topo->bitcoind->ld, txw->channel, txid, txw->depth);
239+
r = txw->cb(txw->topo->bitcoind->ld, txw->channel, txid, txw->tx,
240+
txw->depth);
231241
switch (r) {
232242
case DELETE_WATCH:
233243
tal_free(txw);
@@ -295,3 +305,15 @@ void watch_topology_changed(struct chain_topology *topo)
295305
}
296306
} while (needs_rerun);
297307
}
308+
309+
void txwatch_inform(const struct chain_topology *topo,
310+
const struct bitcoin_txid *txid,
311+
const struct bitcoin_tx *tx_may_steal)
312+
{
313+
struct txwatch *txw;
314+
315+
txw = txwatch_hash_get(&topo->txwatches, txid);
316+
317+
if (txw && !txw->tx)
318+
txw->tx = tal_steal(txw, tx_may_steal);
319+
}

lightningd/watch.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct txwatch *watch_txid(const tal_t *ctx,
4747
enum watch_result (*cb)(struct lightningd *ld,
4848
struct channel *channel,
4949
const struct bitcoin_txid *,
50+
const struct bitcoin_tx *,
5051
unsigned int depth));
5152

5253
struct txwatch *watch_tx(const tal_t *ctx,
@@ -56,6 +57,7 @@ struct txwatch *watch_tx(const tal_t *ctx,
5657
enum watch_result (*cb)(struct lightningd *ld,
5758
struct channel *channel,
5859
const struct bitcoin_txid *,
60+
const struct bitcoin_tx *,
5961
unsigned int depth));
6062

6163
struct txowatch *watch_txo(const tal_t *ctx,
@@ -83,5 +85,10 @@ void txowatch_fire(const struct txowatch *txow,
8385
bool watching_txid(const struct chain_topology *topo,
8486
const struct bitcoin_txid *txid);
8587

88+
/* FIXME: Implement bitcoin_tx_dup() so we tx arg can be TAKEN */
89+
void txwatch_inform(const struct chain_topology *topo,
90+
const struct bitcoin_txid *txid,
91+
const struct bitcoin_tx *tx_may_steal);
92+
8693
void watch_topology_changed(struct chain_topology *topo);
8794
#endif /* LIGHTNING_LIGHTNINGD_WATCH_H */

wallet/test/run-wallet.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED,
569569
enum watch_result (*cb)(struct lightningd *ld UNNEEDED,
570570
struct channel *channel UNNEEDED,
571571
const struct bitcoin_txid * UNNEEDED,
572+
const struct bitcoin_tx * UNNEEDED,
572573
unsigned int depth))
573574
{ fprintf(stderr, "watch_txid called!\n"); abort(); }
574575
/* Generated stub for watch_txo */

0 commit comments

Comments
 (0)