From 8ffdeea522847a21a35e19b2995cfe0243aa2f49 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 18 Aug 2017 14:13:53 +0930 Subject: [PATCH] daemon/chaintopology: hand full txs to watch_tx() This is required for onchaind: we want to watch all descendents by default, as to do otherwise would be racy, which means we need to traverse the outputs when a tx appears. Signed-off-by: Rusty Russell --- daemon/chaintopology.c | 60 ++++++++++++++++----------- daemon/chaintopology.h | 7 ++-- daemon/peer.c | 28 +++++++------ daemon/watch.c | 86 ++++++++++++++++++++------------------- daemon/watch.h | 20 +++++---- lightningd/lightningd.c | 6 --- lightningd/peer_control.c | 24 ++++++++--- 7 files changed, 131 insertions(+), 100 deletions(-) diff --git a/daemon/chaintopology.c b/daemon/chaintopology.c index e02be4567..8c649839f 100644 --- a/daemon/chaintopology.c +++ b/daemon/chaintopology.c @@ -54,13 +54,14 @@ static u32 get_mediantime(const struct chain_topology *topo, const struct block } /* FIXME: Remove tx from block when peer done. */ -static void add_tx_to_block(struct block *b, const struct sha256_double *txid, const u32 txnum) +static void add_tx_to_block(struct block *b, + const struct bitcoin_tx *tx, const u32 txnum) { - size_t n = tal_count(b->txids); + size_t n = tal_count(b->txs); - tal_resize(&b->txids, n+1); + tal_resize(&b->txs, n+1); tal_resize(&b->txnums, n+1); - b->txids[n] = *txid; + b->txs[n] = tal_steal(b->txs, tx); b->txnums[n] = txnum; } @@ -96,7 +97,7 @@ static void connect_block(struct chain_topology *topo, /* Now we see if any of those txs are interesting. */ for (i = 0; i < tal_count(b->full_txs); i++) { - struct bitcoin_tx *tx = b->full_txs[i]; + const struct bitcoin_tx *tx = b->full_txs[i]; struct sha256_double txid; size_t j; @@ -115,7 +116,7 @@ static void connect_block(struct chain_topology *topo, /* We did spends first, in case that tells us to watch tx. */ bitcoin_txid(tx, &txid); if (watching_txid(topo, &txid) || we_broadcast(topo, &txid)) - add_tx_to_block(b, &txid, i); + add_tx_to_block(b, tx, i); } b->full_txs = tal_free(b->full_txs); @@ -123,37 +124,46 @@ static void connect_block(struct chain_topology *topo, notify_new_block(topo, b->height); } -static bool tx_in_block(const struct block *b, - const struct sha256_double *txid) +static const struct bitcoin_tx *tx_in_block(const struct block *b, + const struct sha256_double *txid) { - size_t i, n = tal_count(b->txids); + size_t i, n = tal_count(b->txs); for (i = 0; i < n; i++) { - if (structeq(&b->txids[i], txid)) - return true; + struct sha256_double this_txid; + bitcoin_txid(b->txs[i], &this_txid); + if (structeq(&this_txid, txid)) + return b->txs[i]; } - return false; + return NULL; } /* FIXME: Use hash table. */ static struct block *block_for_tx(const struct chain_topology *topo, - const struct sha256_double *txid) + const struct sha256_double *txid, + const struct bitcoin_tx **tx) { struct block *b; + const struct bitcoin_tx *dummy_tx; + + if (!tx) + tx = &dummy_tx; for (b = topo->tip; b; b = b->prev) { - if (tx_in_block(b, txid)) + *tx = tx_in_block(b, txid); + if (*tx) return b; } return NULL; } size_t get_tx_depth(const struct chain_topology *topo, - const struct sha256_double *txid) + const struct sha256_double *txid, + const struct bitcoin_tx **tx) { const struct block *b; - b = block_for_tx(topo, txid); + b = block_for_tx(topo, txid, tx); if (!b) return 0; return topo->tip->height - b->height + 1; @@ -215,7 +225,7 @@ static void rebroadcast_txs(struct chain_topology *topo, struct command *cmd) /* Put any txs we want to broadcast in ->txs. */ txs->txs = tal_arr(txs, const char *, 0); list_for_each(&topo->outgoing_txs, otx, list) { - if (block_for_tx(topo, &otx->txid)) + if (block_for_tx(topo, &otx->txid, NULL)) continue; tal_resize(&txs->txs, num_txs+1); @@ -293,11 +303,11 @@ static void free_blocks(struct chain_topology *topo, struct block *b) struct block *next; while (b) { - size_t i, n = tal_count(b->txids); + size_t i, n = tal_count(b->txs); /* Notify that txs are kicked out. */ for (i = 0; i < n; i++) - txwatch_fire(topo, &b->txids[i], 0); + txwatch_fire(topo, b->txs[i], 0); next = b->next; tal_free(b); @@ -359,7 +369,7 @@ static struct block *new_block(struct chain_topology *topo, b->hdr = blk->hdr; - b->txids = tal_arr(b, struct sha256_double, 0); + b->txs = tal_arr(b, const struct bitcoin_tx *, 0); b->txnums = tal_arr(b, u32, 0); b->full_txs = tal_steal(b, blk->tx); @@ -468,7 +478,7 @@ u32 get_tx_mediantime(const struct chain_topology *topo, { struct block *b; - b = block_for_tx(topo, txid); + b = block_for_tx(topo, txid, NULL); if (b) return b->mediantime; @@ -502,16 +512,18 @@ u64 get_feerate(const struct chain_topology *topo) struct txlocator *locate_tx(const void *ctx, const struct chain_topology *topo, const struct sha256_double *txid) { - struct block *block = block_for_tx(topo, txid); + struct block *block = block_for_tx(topo, txid, NULL); if (block == NULL) { return NULL; } struct txlocator *loc = talz(ctx, struct txlocator); loc->blkheight = block->height; - size_t i, n = tal_count(block->txids); + size_t i, n = tal_count(block->txs); for (i = 0; i < n; i++) { - if (structeq(&block->txids[i], txid)){ + struct sha256_double this_txid; + bitcoin_txid(block->txs[i], &this_txid); + if (structeq(&this_txid, txid)){ loc->index = block->txnums[i]; return loc; } diff --git a/daemon/chaintopology.h b/daemon/chaintopology.h index 110f50c40..2eb690e0e 100644 --- a/daemon/chaintopology.h +++ b/daemon/chaintopology.h @@ -49,7 +49,7 @@ struct block { u32 mediantime; /* Transactions in this block we care about */ - struct sha256_double *txids; + const struct bitcoin_tx **txs; /* And their associated index in the block */ u32 *txnums; @@ -131,9 +131,10 @@ struct txlocator { }; /* This is the number of blocks which would have to be mined to invalidate - * the tx. */ + * the tx (optional tx is filled in if return is non-zero). */ size_t get_tx_depth(const struct chain_topology *topo, - const struct sha256_double *txid); + const struct sha256_double *txid, + const struct bitcoin_tx **tx); /* Get the mediantime of the block including this tx (must be one!) */ u32 get_tx_mediantime(const struct chain_topology *topo, diff --git a/daemon/peer.c b/daemon/peer.c index 7901825fb..8041b0e49 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -3360,8 +3360,8 @@ static void peer_depth_ok(struct peer *peer) } static enum watch_result anchor_depthchange(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, void *unused) { log_debug(peer->log, "Anchor at depth %u", depth); @@ -3620,8 +3620,8 @@ static void fail_own_htlc(struct peer *peer, struct htlc *htlc) * than the HTLC timeout difference. */ static enum watch_result our_htlc_timeout_depth(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, struct htlc *htlc) { if (depth == 0) @@ -3683,24 +3683,28 @@ static enum watch_result our_htlc_depth(struct peer *peer, } static enum watch_result our_htlc_depth_theircommit(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, ptrint_t *out_num) { - return our_htlc_depth(peer, depth, txid, REMOTE, ptr2int(out_num)); + struct sha256_double txid; + bitcoin_txid(tx, &txid); + return our_htlc_depth(peer, depth, &txid, REMOTE, ptr2int(out_num)); } static enum watch_result our_htlc_depth_ourcommit(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, ptrint_t *out_num) { - return our_htlc_depth(peer, depth, txid, LOCAL, ptr2int(out_num)); + struct sha256_double txid; + bitcoin_txid(tx, &txid); + return our_htlc_depth(peer, depth, &txid, LOCAL, ptr2int(out_num)); } static enum watch_result their_htlc_depth(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, ptrint_t *out_num) { u32 height; @@ -3725,8 +3729,8 @@ static enum watch_result their_htlc_depth(struct peer *peer, } static enum watch_result our_main_output_depth(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, void *unused) { /* Not past CSV timeout? */ @@ -3755,8 +3759,8 @@ static enum watch_result our_main_output_depth(struct peer *peer, /* Any of our HTLCs we didn't have in our commitment tx, but they did, * we can't fail until we're sure our commitment tx will win. */ static enum watch_result our_unilateral_depth(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, void *unused) { struct htlc_map_iter it; @@ -3837,8 +3841,8 @@ static enum watch_result our_htlc_spent(struct peer *peer, static void resolve_our_htlc(struct peer *peer, unsigned int out_num, enum watch_result (*cb)(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double*, ptrint_t *out_num)) { /* FIXME-OLD #onchain: @@ -3998,8 +4002,8 @@ static void resolve_mutual_close(struct peer *peer) /* Called every time the tx spending the funding tx changes depth. */ static enum watch_result check_for_resolution(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, void *unused) { size_t i, n = tal_count(peer->onchain.resolved); @@ -4028,7 +4032,7 @@ static enum watch_result check_for_resolution(struct peer *peer, struct sha256_double txid; bitcoin_txid(peer->onchain.resolved[i], &txid); - if (get_tx_depth(peer->dstate->topology, &txid) < forever) + if (get_tx_depth(peer->dstate->topology, &txid, NULL) < forever) return KEEP_WATCHING; } diff --git a/daemon/watch.c b/daemon/watch.c index 838689957..8853c65bf 100644 --- a/daemon/watch.c +++ b/daemon/watch.c @@ -90,8 +90,8 @@ struct txwatch *watch_txid_(const tal_t *ctx, struct peer *peer, const struct sha256_double *txid, enum watch_result (*cb)(struct peer *peer, + const struct bitcoin_tx *, unsigned int depth, - const struct sha256_double *, void *arg), void *cb_arg) { @@ -122,8 +122,8 @@ struct txwatch *watch_tx_(const tal_t *ctx, struct peer *peer, const struct bitcoin_tx *tx, enum watch_result (*cb)(struct peer *peer, + const struct bitcoin_tx *, unsigned int depth, - const struct sha256_double *, void *arg), void *cb_arg) { @@ -159,31 +159,46 @@ struct txowatch *watch_txo_(const tal_t *ctx, return w; } +/* Returns true if we fired a callback */ +static bool txw_fire(struct chain_topology *topo, + struct txwatch *txw, + const struct bitcoin_tx *tx, + unsigned int depth) +{ + enum watch_result r; + + if (depth == txw->depth) + return false; + peer_debug(txw->peer, + "Got depth change %u->%u for %02x%02x%02x...\n", + txw->depth, depth, + txw->txid.sha.u.u8[0], + txw->txid.sha.u.u8[1], + txw->txid.sha.u.u8[2]); + txw->depth = depth; + r = txw->cb(txw->peer, tx, txw->depth, txw->cbdata); + switch (r) { + case DELETE_WATCH: + tal_free(txw); + return true; + case KEEP_WATCHING: + return true; + } + fatal("txwatch callback %p returned %i\n", txw->cb, r); +} + void txwatch_fire(struct chain_topology *topo, - const struct sha256_double *txid, + const struct bitcoin_tx *tx, unsigned int depth) { - struct txwatch *txw = txwatch_hash_get(&topo->txwatches, txid); - - if (txw && depth != txw->depth) { - enum watch_result r; - peer_debug(txw->peer, - "Got depth change %u for %02x%02x%02x...\n", - txw->depth, - txw->txid.sha.u.u8[0], - txw->txid.sha.u.u8[1], - txw->txid.sha.u.u8[2]); - txw->depth = depth; - r = txw->cb(txw->peer, txw->depth, &txw->txid, txw->cbdata); - switch (r) { - case DELETE_WATCH: - tal_free(txw); - return; - case KEEP_WATCHING: - return; - } - fatal("txwatch callback %p returned %i\n", txw->cb, r); - } + struct sha256_double txid; + struct txwatch *txw; + + bitcoin_txid(tx, &txid); + txw = txwatch_hash_get(&topo->txwatches, &txid); + + if (txw) + txw_fire(topo, txw, tx, depth); } void txowatch_fire(struct chain_topology *topo, @@ -228,23 +243,12 @@ again: for (w = txwatch_hash_first(&topo->txwatches, &i); w; w = txwatch_hash_next(&topo->txwatches, &i)) { - size_t depth; - - depth = get_tx_depth(topo, &w->txid); - if (depth != w->depth) { - enum watch_result r; - w->depth = depth; - needs_rerun = true; - r = w->cb(w->peer, w->depth, &w->txid, w->cbdata); - switch (r) { - case DELETE_WATCH: - tal_free(w); - continue; - case KEEP_WATCHING: - continue; - } - fatal("txwatch callback %p returned %i\n", w->cb, r); - } + u32 depth; + const struct bitcoin_tx *tx; + + depth = get_tx_depth(topo, &w->txid, &tx); + if (depth) + needs_rerun |= txw_fire(topo, w, tx, depth); } if (needs_rerun) goto again; diff --git a/daemon/watch.h b/daemon/watch.h index 0b2ff7db5..d783e6389 100644 --- a/daemon/watch.h +++ b/daemon/watch.h @@ -58,9 +58,11 @@ struct txwatch { unsigned int depth; /* A new depth (0 if kicked out, otherwise 1 = tip, etc.) */ - enum watch_result (*cb)(struct peer *peer, unsigned int depth, - const struct sha256_double *txid, + enum watch_result (*cb)(struct peer *peer, + const struct bitcoin_tx *tx, + unsigned int depth, void *cbdata); + void *cbdata; }; @@ -76,8 +78,8 @@ struct txwatch *watch_txid_(const tal_t *ctx, struct peer *peer, const struct sha256_double *txid, enum watch_result (*cb)(struct peer *peer, + const struct bitcoin_tx *, unsigned int depth, - const struct sha256_double*, void *), void *cbdata); @@ -86,8 +88,8 @@ struct txwatch *watch_txid_(const tal_t *ctx, typesafe_cb_preargs(enum watch_result, void *, \ (cb), (cbdata), \ struct peer *, \ - unsigned int depth, \ - const struct sha256_double *), \ + const struct bitcoin_tx *, \ + unsigned int depth), \ (cbdata)) struct txwatch *watch_tx_(const tal_t *ctx, @@ -95,8 +97,8 @@ struct txwatch *watch_tx_(const tal_t *ctx, struct peer *peer, const struct bitcoin_tx *tx, enum watch_result (*cb)(struct peer *peer, + const struct bitcoin_tx *, unsigned int depth, - const struct sha256_double *, void *), void *cbdata); @@ -105,8 +107,8 @@ struct txwatch *watch_tx_(const tal_t *ctx, typesafe_cb_preargs(enum watch_result, void *, \ (cb), (cbdata), \ struct peer *, \ - unsigned int depth, \ - const struct sha256_double *), \ + const struct bitcoin_tx *, \ + unsigned int depth), \ (cbdata)) struct txowatch *watch_txo_(const tal_t *ctx, @@ -130,7 +132,7 @@ struct txowatch *watch_txo_(const tal_t *ctx, (cbdata)) void txwatch_fire(struct chain_topology *topo, - const struct sha256_double *txid, + const struct bitcoin_tx *tx, unsigned int depth); void txowatch_fire(struct chain_topology *topo, diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index bba5bbf59..11662e650 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -46,12 +46,6 @@ struct peer *find_peer_by_unique_id(struct lightningd *ld, u64 unique_id) return NULL; } -void peer_debug(struct peer *peer, const char *fmt, ...); -void peer_debug(struct peer *peer, const char *fmt, ...) -{ - FIXME_IMPLEMENT(); -} - void debug_dump_peers(struct lightningd_state *dstate); void debug_dump_peers(struct lightningd_state *dstate) { diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index bd0970f4c..503f8b018 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -49,6 +49,17 @@ static void destroy_peer(struct peer *peer) list_del_from(&peer->ld->peers, &peer->list); } +/* FIXME: Remove this with legacy daemon! */ +void peer_debug(struct peer *peer, const char *fmt, ...); +void peer_debug(struct peer *peer, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + logv(peer->log, LOG_DBG, fmt, ap); + va_end(ap); +} + /* Mutual recursion, sets timer. */ static void peer_reconnect(struct peer *peer); @@ -918,8 +929,8 @@ static void funding_broadcast_failed(struct peer *peer, } static enum watch_result funding_announce_cb(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, void *unused) { if (depth < ANNOUNCE_MIN_DEPTH) { @@ -938,14 +949,17 @@ static enum watch_result funding_announce_cb(struct peer *peer, } static enum watch_result funding_lockin_cb(struct peer *peer, + const struct bitcoin_tx *tx, unsigned int depth, - const struct sha256_double *txid, void *unused) { - const char *txidstr = type_to_string(peer, struct sha256_double, txid); + struct sha256_double txid; + const char *txidstr; struct txlocator *loc; bool peer_ready; + bitcoin_txid(tx, &txid); + txidstr = type_to_string(peer, struct sha256_double, &txid); log_debug(peer->log, "Funding tx %s depth %u of %u", txidstr, depth, peer->minimum_depth); tal_free(txidstr); @@ -953,7 +967,7 @@ static enum watch_result funding_lockin_cb(struct peer *peer, if (depth < peer->minimum_depth) return KEEP_WATCHING; - loc = locate_tx(peer, peer->ld->topology, txid); + loc = locate_tx(peer, peer->ld->topology, &txid); peer->scid = tal(peer, struct short_channel_id); peer->scid->blocknum = loc->blkheight; @@ -995,7 +1009,7 @@ static enum watch_result funding_lockin_cb(struct peer *peer, take(towire_channel_funding_announce_depth(peer))); } else { /* Worst case, we'll send next block. */ - watch_txid(peer, peer->ld->topology, peer, txid, + watch_txid(peer, peer->ld->topology, peer, &txid, funding_announce_cb, NULL); } return DELETE_WATCH;