From 4e102ccfcfb0bee9856657b060b22abb9d21e1c6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 4 May 2016 16:10:37 +0930 Subject: [PATCH] chaintopology: simply track txids, not watches. This is less efficient, but simpler. Signed-off-by: Rusty Russell --- daemon/chaintopology.c | 69 +++++++++++++++--------------------------- daemon/chaintopology.h | 3 +- daemon/watch.c | 21 +++++++------ daemon/watch.h | 7 +++-- 4 files changed, 44 insertions(+), 56 deletions(-) diff --git a/daemon/chaintopology.c b/daemon/chaintopology.c index 2c700ebbb..2cd2ab3e4 100644 --- a/daemon/chaintopology.c +++ b/daemon/chaintopology.c @@ -14,12 +14,6 @@ static struct timeout topology_timeout; -struct tx_in_block { - struct list_node list; - struct txwatch *w; - struct block *block; -}; - struct block { int height; @@ -39,9 +33,9 @@ struct block { u32 mediantime; /* Transactions in this block we care about */ - struct list_head txs; + struct sha256_double *txids; - /* Full copy of txs (trimmed to txs list in connect_blocks) */ + /* Full copy of txs (trimmed to txs list in connect_block) */ struct bitcoin_tx **full_txs; }; @@ -96,20 +90,13 @@ static u32 get_mediantime(const struct topology *topo, const struct block *b) return times[ARRAY_SIZE(times) / 2]; } -static void remove_tx(struct tx_in_block *t) +/* FIXME: Remove tx from block when peer done. */ +static void add_tx_to_block(struct block *b, const struct sha256_double *txid) { - list_del_from(&t->block->txs, &t->list); -} + size_t n = tal_count(b->txids); -static void add_tx_to_block(struct block *b, struct txwatch *w) -{ - /* We attach this to watch, so removed when that is */ - struct tx_in_block *t = tal(w, struct tx_in_block); - - t->block = b; - t->w = w; - list_add_tail(&b->txs, &t->list); - tal_add_destructor(t, remove_tx); + tal_resize(&b->txids, n+1); + b->txids[n] = *txid; } /* Fills in prev, height, mediantime. */ @@ -134,9 +121,7 @@ static void connect_block(struct lightningd_state *dstate, /* 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]; - struct txwatch *w; struct sha256_double txid; - struct txwatch_hash_iter iter; size_t j; /* Tell them if it spends a txo we care about. */ @@ -151,16 +136,10 @@ static void connect_block(struct lightningd_state *dstate, txowatch_fire(dstate, txo, tx, j); } - /* We do spends first, in case that tells us to watch tx. */ + /* We did spends first, in case that tells us to watch tx. */ bitcoin_txid(tx, &txid); - for (w = txwatch_hash_getfirst(&dstate->txwatches, &txid, &iter); - w; - w = txwatch_hash_getnext(&dstate->txwatches, &txid, &iter)){ - add_tx_to_block(b, w); - /* Fire if it's the first we've seen it: this might - * set up txo watches, which could fire in this block */ - txwatch_fire(dstate, w, 0); - } + if (watching_txid(dstate, &txid)) + add_tx_to_block(b, &txid); } b->full_txs = tal_free(b->full_txs); } @@ -168,19 +147,20 @@ static void connect_block(struct lightningd_state *dstate, static bool tx_in_block(const struct block *b, const struct sha256_double *txid) { - struct tx_in_block *tx; + size_t i, n = tal_count(b->txids); - list_for_each(&b->txs, tx, list) { - if (structeq(&tx->w->txid, txid)) + for (i = 0; i < n; i++) { + if (structeq(&b->txids[i], txid)) return true; } return false; } -/* FIXME: put block pointer in txwatch. */ -static struct block *block_for_tx(struct topology *topo, +/* FIXME: Use hash table. */ +static struct block *block_for_tx(struct lightningd_state *dstate, const struct sha256_double *txid) { + struct topology *topo = dstate->topology; struct block *b; for (b = topo->tip; b; b = b->prev) { @@ -190,12 +170,13 @@ static struct block *block_for_tx(struct topology *topo, return NULL; } -size_t get_tx_depth(struct lightningd_state *dstate, const struct txwatch *w) +size_t get_tx_depth(struct lightningd_state *dstate, + const struct sha256_double *txid) { struct topology *topo = dstate->topology; const struct block *b; - b = block_for_tx(topo, &w->txid); + b = block_for_tx(dstate, txid); if (!b) return 0; return topo->tip->height - b->height + 1; @@ -244,7 +225,7 @@ static void rebroadcast_txs(struct lightningd_state *dstate) list_for_each(&peer->outgoing_txs, otx, list) { u8 *rawtx; - if (block_for_tx(dstate->topology, &otx->txid)) + if (block_for_tx(dstate, &otx->txid)) continue; tal_resize(&txs, num_txs+1); @@ -291,11 +272,11 @@ static void free_blocks(struct lightningd_state *dstate, struct block *b) struct block *next; while (b) { - struct tx_in_block *tx, *n; + size_t i, n = tal_count(b->txids); /* Notify that txs are kicked out. */ - list_for_each_safe(&b->txs, tx, n, list) - txwatch_fire(dstate, tx->w, 0); + for (i = 0; i < n; i++) + txwatch_fire(dstate, &b->txids[i], 0); next = b->next; tal_free(b); @@ -349,7 +330,7 @@ static struct block *new_block(struct lightningd_state *dstate, b->hdr = blk->hdr; - list_head_init(&b->txs); + b->txids = tal_arr(b, struct sha256_double, 0); b->full_txs = tal_steal(b, blk->tx); return b; @@ -441,7 +422,7 @@ u32 get_tx_mediantime(struct lightningd_state *dstate, { struct block *b; - b = block_for_tx(dstate->topology, txid); + b = block_for_tx(dstate, txid); if (b) return b->mediantime; diff --git a/daemon/chaintopology.h b/daemon/chaintopology.h index 3bd60fc56..f621b2588 100644 --- a/daemon/chaintopology.h +++ b/daemon/chaintopology.h @@ -8,7 +8,8 @@ struct txwatch; /* This is the number of blocks which would have to be mined to invalidate * the tx. */ -size_t get_tx_depth(struct lightningd_state *dstate, const struct txwatch *w); +size_t get_tx_depth(struct lightningd_state *dstate, + const struct sha256_double *txid); /* Get the mediantime of the block including this tx (must be one!) */ u32 get_tx_mediantime(struct lightningd_state *dstate, diff --git a/daemon/watch.c b/daemon/watch.c index bcb696e12..7e0d3dce2 100644 --- a/daemon/watch.c +++ b/daemon/watch.c @@ -91,7 +91,7 @@ struct txwatch *watch_txid_(const tal_t *ctx, struct txwatch *w; w = tal(ctx, struct txwatch); - w->depth = -1; + w->depth = 0; w->txid = *txid; w->dstate = peer->dstate; w->peer = peer; @@ -104,6 +104,12 @@ struct txwatch *watch_txid_(const tal_t *ctx, return w; } +bool watching_txid(struct lightningd_state *dstate, + const struct sha256_double *txid) +{ + return txwatch_hash_get(&dstate->txwatches, txid) != NULL; +} + struct txwatch *watch_tx_(const tal_t *ctx, struct peer *peer, const struct bitcoin_tx *tx, @@ -142,12 +148,13 @@ struct txowatch *watch_txo_(const tal_t *ctx, return w; } - void txwatch_fire(struct lightningd_state *dstate, - struct txwatch *txw, + const struct sha256_double *txid, unsigned int depth) { - if (depth != txw->depth) { + struct txwatch *txw = txwatch_hash_get(&dstate->txwatches, txid); + + if (txw && depth != txw->depth) { log_debug(txw->peer->log, "Got depth change %u for %02x%02x%02x...\n", txw->depth, @@ -194,11 +201,7 @@ again: w = txwatch_hash_next(&dstate->txwatches, &i)) { size_t depth; - /* Don't fire if we haven't seen it at all. */ - if (w->depth == -1) - continue; - - depth = get_tx_depth(dstate, w); + depth = get_tx_depth(dstate, &w->txid); if (depth != w->depth) { w->depth = depth; w->cb(w->peer, w->depth, &w->txid, w->cbdata); diff --git a/daemon/watch.h b/daemon/watch.h index 41501ce65..51617f91d 100644 --- a/daemon/watch.h +++ b/daemon/watch.h @@ -45,7 +45,7 @@ struct txwatch { /* Peer who owns us. */ struct peer *peer; - + /* Transaction to watch. */ struct sha256_double txid; int depth; @@ -118,12 +118,15 @@ struct txowatch *watch_txo_(const tal_t *ctx, (cbdata)) void txwatch_fire(struct lightningd_state *dstate, - struct txwatch *txw, + const struct sha256_double *txid, unsigned int depth); void txowatch_fire(struct lightningd_state *dstate, const struct txowatch *txow, const struct bitcoin_tx *tx, size_t input_num); +bool watching_txid(struct lightningd_state *dstate, + const struct sha256_double *txid); + void watch_topology_changed(struct lightningd_state *dstate); #endif /* LIGHTNING_DAEMON_WATCH_H */