From 923526baf33cc61bdeb6601d46b9ccb47d4d1896 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 2 Mar 2017 22:51:49 +1030 Subject: [PATCH] daemon/watch.c: move list of watched txs/txouts into struct topology. This weans daemon/watch.c off relying on struct lightningd_state. Signed-off-by: Rusty Russell --- daemon/chaintopology.c | 99 ++++++++++------------------------------- daemon/chaintopology.h | 70 ++++++++++++++++++++++++++++- daemon/lightningd.c | 5 +-- daemon/lightningd.h | 4 -- daemon/peer.c | 30 +++++++++---- daemon/watch.c | 33 ++++++++------ daemon/watch.h | 27 ++++++----- lightningd/lightningd.c | 2 - 8 files changed, 151 insertions(+), 119 deletions(-) diff --git a/daemon/chaintopology.c b/daemon/chaintopology.c index 27236f7e2..a108c0bb2 100644 --- a/daemon/chaintopology.c +++ b/daemon/chaintopology.c @@ -16,65 +16,6 @@ #include #include -struct block { - int height; - - /* Actual header. */ - struct bitcoin_block_hdr hdr; - - /* Previous block (if any). */ - struct block *prev; - - /* Next block (if any). */ - struct block *next; - - /* Key for hash table */ - struct sha256_double blkid; - - /* 0 if not enough predecessors. */ - u32 mediantime; - - /* Transactions in this block we care about */ - struct sha256_double *txids; - - /* And their associated index in the block */ - u32 *txnums; - - /* Full copy of txs (trimmed to txs list in connect_block) */ - struct bitcoin_tx **full_txs; -}; - -/* Hash blocks by sha */ -static const struct sha256_double *keyof_block_map(const struct block *b) -{ - return &b->blkid; -} - -static size_t hash_sha(const struct sha256_double *key) -{ - size_t ret; - - memcpy(&ret, key, sizeof(ret)); - return ret; -} - -static bool block_eq(const struct block *b, const struct sha256_double *key) -{ - return structeq(&b->blkid, key); -} -HTABLE_DEFINE_TYPE(struct block, keyof_block_map, hash_sha, block_eq, block_map); - -struct topology { - struct block *root; - struct block *tip; - struct block_map block_map; - u64 feerate; - bool startup; - - /* Bitcoin transctions we're broadcasting */ - struct list_head outgoing_txs; -}; - static void start_poll_chaintip(struct lightningd_state *dstate); static void next_topology_timer(struct lightningd_state *dstate) @@ -168,14 +109,14 @@ static void connect_block(struct lightningd_state *dstate, out.txid = tx->input[j].txid; out.index = tx->input[j].index; - txo = txowatch_hash_get(&dstate->txowatches, &out); + txo = txowatch_hash_get(&topo->txowatches, &out); if (txo) - txowatch_fire(dstate, txo, tx, j); + txowatch_fire(topo, txo, tx, j); } /* We did spends first, in case that tells us to watch tx. */ bitcoin_txid(tx, &txid); - if (watching_txid(dstate, &txid) || we_broadcast(dstate, &txid)) + if (watching_txid(topo, &txid) || we_broadcast(dstate, &txid)) add_tx_to_block(b, &txid, i); } b->full_txs = tal_free(b->full_txs); @@ -340,7 +281,7 @@ void broadcast_tx(struct peer *peer, const struct bitcoin_tx *tx, broadcast_done, otx); } -static void free_blocks(struct lightningd_state *dstate, struct block *b) +static void free_blocks(struct topology *topo, struct block *b) { struct block *next; @@ -349,7 +290,7 @@ static void free_blocks(struct lightningd_state *dstate, struct block *b) /* Notify that txs are kicked out. */ for (i = 0; i < n; i++) - txwatch_fire(dstate, &b->txids[i], 0); + txwatch_fire(topo, &b->txids[i], 0); next = b->next; tal_free(b); @@ -371,7 +312,7 @@ static void topology_changed(struct lightningd_state *dstate, { /* Eliminate any old chain. */ if (prev->next) - free_blocks(dstate, prev->next); + free_blocks(dstate->topology, prev->next); prev->next = b; do { @@ -381,7 +322,7 @@ static void topology_changed(struct lightningd_state *dstate, } while (b); /* Tell watch code to re-evaluate all txs. */ - watch_topology_changed(dstate); + watch_topology_changed(dstate->topology); /* Maybe need to rebroadcast. */ rebroadcast_txs(dstate, NULL); @@ -618,19 +559,27 @@ static void destroy_outgoing_txs(struct topology *topo) tal_free(otx); } -void setup_topology(struct lightningd_state *dstate) +struct topology *new_topology(const tal_t *ctx) { - dstate->topology = tal(dstate, struct topology); - block_map_init(&dstate->topology->block_map); - list_head_init(&dstate->topology->outgoing_txs); + struct topology *topo = tal(ctx, struct topology); - dstate->topology->startup = true; - dstate->topology->feerate = 0; - bitcoind_getblockcount(dstate->bitcoind, get_init_blockhash, NULL); + block_map_init(&topo->block_map); + list_head_init(&topo->outgoing_txs); + txwatch_hash_init(&topo->txwatches); + txowatch_hash_init(&topo->txowatches); - tal_add_destructor(dstate->topology, destroy_outgoing_txs); + return topo; +} + +void setup_topology(struct topology *topo, struct bitcoind *bitcoind) +{ + topo->startup = true; + topo->feerate = 0; + bitcoind_getblockcount(bitcoind, get_init_blockhash, NULL); + + tal_add_destructor(topo, destroy_outgoing_txs); /* Once it gets topology, it calls io_break() and we return. */ io_loop(NULL, NULL); - assert(!dstate->topology->startup); + assert(!topo->startup); } diff --git a/daemon/chaintopology.h b/daemon/chaintopology.h index 5b68d075f..9394d1712 100644 --- a/daemon/chaintopology.h +++ b/daemon/chaintopology.h @@ -1,12 +1,16 @@ #ifndef LIGHTNING_DAEMON_CHAINTOPOLOGY_H #define LIGHTNING_DAEMON_CHAINTOPOLOGY_H #include "config.h" +#include #include #include #include +#include +#include #include struct bitcoin_tx; +struct bitcoind; struct lightningd_state; struct peer; struct sha256_double; @@ -21,6 +25,69 @@ struct outgoing_tx { void (*failed)(struct peer *peer, int exitstatus, const char *err); }; +struct block { + int height; + + /* Actual header. */ + struct bitcoin_block_hdr hdr; + + /* Previous block (if any). */ + struct block *prev; + + /* Next block (if any). */ + struct block *next; + + /* Key for hash table */ + struct sha256_double blkid; + + /* 0 if not enough predecessors. */ + u32 mediantime; + + /* Transactions in this block we care about */ + struct sha256_double *txids; + + /* And their associated index in the block */ + u32 *txnums; + + /* Full copy of txs (trimmed to txs list in connect_block) */ + struct bitcoin_tx **full_txs; +}; + +/* Hash blocks by sha */ +static inline const struct sha256_double *keyof_block_map(const struct block *b) +{ + return &b->blkid; +} + +static inline size_t hash_sha(const struct sha256_double *key) +{ + size_t ret; + + memcpy(&ret, key, sizeof(ret)); + return ret; +} + +static inline bool block_eq(const struct block *b, const struct sha256_double *key) +{ + return structeq(&b->blkid, key); +} +HTABLE_DEFINE_TYPE(struct block, keyof_block_map, hash_sha, block_eq, block_map); + +struct topology { + struct block *root; + struct block *tip; + struct block_map block_map; + u64 feerate; + bool startup; + + /* Bitcoin transctions we're broadcasting */ + struct list_head outgoing_txs; + + /* Transactions/txos we are watching. */ + struct txwatch_hash txwatches; + struct txowatch_hash txowatches; +}; + /* Information relevant to locating a TX in a blockchain. */ struct txlocator { @@ -56,7 +123,8 @@ void broadcast_tx(struct peer *peer, const struct bitcoin_tx *tx, int exitstatus, const char *err)); -void setup_topology(struct lightningd_state *dstate); +struct topology *new_topology(const tal_t *ctx); +void setup_topology(struct topology *topology, struct bitcoind *bitcoind); struct txlocator *locate_tx(const void *ctx, struct lightningd_state *dstate, const struct sha256_double *txid); diff --git a/daemon/lightningd.c b/daemon/lightningd.c index 523641ac9..597e80138 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -41,8 +41,6 @@ static struct lightningd_state *lightningd_state(void) dstate->portnum = 0; dstate->testnet = true; timers_init(&dstate->timers, time_mono()); - txwatch_hash_init(&dstate->txwatches); - txowatch_hash_init(&dstate->txowatches); list_head_init(&dstate->wallet); list_head_init(&dstate->addresses); dstate->dev_never_routefail = false; @@ -69,6 +67,7 @@ int main(int argc, char *argv[]) | SECP256K1_CONTEXT_SIGN); dstate->bitcoind = new_bitcoind(dstate, dstate->base_log); + dstate->topology = new_topology(dstate); /* Handle options and config; move to .lightningd */ register_opts(dstate); @@ -88,7 +87,7 @@ int main(int argc, char *argv[]) db_init(dstate); /* Initialize block topology. */ - setup_topology(dstate); + setup_topology(dstate->topology, dstate->bitcoind); /* Create RPC socket (if any) */ setup_jsonrpc(dstate, dstate->rpc_filename); diff --git a/daemon/lightningd.h b/daemon/lightningd.h index aa4ab5549..881478315 100644 --- a/daemon/lightningd.h +++ b/daemon/lightningd.h @@ -110,10 +110,6 @@ struct lightningd_state { /* This is us. */ struct pubkey id; - /* Transactions/txos we are watching. */ - struct txwatch_hash txwatches; - struct txowatch_hash txowatches; - /* Our tame bitcoind. */ struct bitcoind *bitcoind; diff --git a/daemon/peer.c b/daemon/peer.c index 68e4277c4..e2c5e10f2 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -3659,6 +3659,7 @@ static enum watch_result our_htlc_depth(struct peer *peer, if (!peer->onchain.resolved[out_num]) { peer->onchain.resolved[out_num] = htlc_timeout_tx(peer, out_num); watch_tx(peer->onchain.resolved[out_num], + peer->dstate->topology, peer, peer->onchain.resolved[out_num], our_htlc_timeout_depth, h); @@ -3832,10 +3833,13 @@ static void resolve_our_htlc(struct peer *peer, * (the node pays back to itself) or redemption transaction (the other * node provides the redemption preimage). */ - watch_txo(peer->onchain.tx, peer, &peer->onchain.txid, out_num, + watch_txo(peer->onchain.tx, + peer->dstate->topology, + peer, &peer->onchain.txid, out_num, our_htlc_spent, peer->onchain.htlcs[out_num]); - watch_txid(peer->onchain.tx, peer, - &peer->onchain.txid, cb, int2ptr(out_num)); + watch_txid(peer->onchain.tx, + peer->dstate->topology, + peer, &peer->onchain.txid, cb, int2ptr(out_num)); } static void resolve_their_htlc(struct peer *peer, unsigned int out_num) @@ -3855,7 +3859,9 @@ static void resolve_their_htlc(struct peer *peer, unsigned int out_num) * Otherwise, if the output HTLC has expired, it is considered * *irrevocably resolved*. */ - watch_tx(peer->onchain.tx, peer, peer->onchain.tx, + watch_tx(peer->onchain.tx, + peer->dstate->topology, + peer, peer->onchain.tx, their_htlc_depth, int2ptr(out_num)); } } @@ -3867,12 +3873,13 @@ static void resolve_their_htlc(struct peer *peer, unsigned int out_num) static void resolve_our_unilateral(struct peer *peer) { unsigned int i; + struct topology *topo = peer->dstate->topology; const struct bitcoin_tx *tx = peer->onchain.tx; /* This only works because we always watch for a long time before * freeing peer, by which time this has resolved. We could create * resolved[] entries for these uncommitted HTLCs, too. */ - watch_tx(tx, peer, tx, our_unilateral_depth, NULL); + watch_tx(tx, topo, peer, tx, our_unilateral_depth, NULL); for (i = 0; i < tal_count(tx->output); i++) { /* FIXME-OLD #onchain: @@ -3884,7 +3891,8 @@ static void resolve_our_unilateral(struct peer *peer) * spending the output. */ if (i == peer->onchain.to_us_idx) - watch_tx(tx, peer, tx, our_main_output_depth, NULL); + watch_tx(tx, topo, + peer, tx, our_main_output_depth, NULL); /* FIXME-OLD #onchain: * @@ -4278,7 +4286,8 @@ static enum watch_result anchor_spent(struct peer *peer, assert(!state_can_io(peer->state)); assert(peer->onchain.resolved != NULL); - watch_tx(tx, peer, tx, check_for_resolution, NULL); + watch_tx(tx, peer->dstate->topology, + peer, tx, check_for_resolution, NULL); return KEEP_WATCHING; @@ -4299,13 +4308,16 @@ unknown_spend: void peer_watch_anchor(struct peer *peer, int depth) { + struct topology *topo = peer->dstate->topology; + log_debug_struct(peer->log, "watching for anchor %s", struct sha256_double, &peer->anchor.txid); log_add(peer->log, " to hit depth %i", depth); peer->anchor.ok_depth = depth; - watch_txid(peer, peer, &peer->anchor.txid, anchor_depthchange, NULL); - watch_txo(peer, peer, &peer->anchor.txid, 0, anchor_spent, NULL); + watch_txid(peer, topo, peer, + &peer->anchor.txid, anchor_depthchange, NULL); + watch_txo(peer, topo, peer, &peer->anchor.txid, 0, anchor_spent, NULL); } struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx, diff --git a/daemon/watch.c b/daemon/watch.c index c111d8258..2891e3da2 100644 --- a/daemon/watch.c +++ b/daemon/watch.c @@ -62,7 +62,7 @@ bool txowatch_eq(const struct txowatch *w, const struct txwatch_output *out) static void destroy_txowatch(struct txowatch *w) { - txowatch_hash_del(&w->peer->dstate->txowatches, w); + txowatch_hash_del(&w->topo->txowatches, w); } const struct sha256_double *txwatch_keyof(const struct txwatch *w) @@ -82,10 +82,11 @@ bool txwatch_eq(const struct txwatch *w, const struct sha256_double *txid) static void destroy_txwatch(struct txwatch *w) { - txwatch_hash_del(&w->dstate->txwatches, w); + txwatch_hash_del(&w->topo->txwatches, w); } struct txwatch *watch_txid_(const tal_t *ctx, + struct topology *topo, struct peer *peer, const struct sha256_double *txid, enum watch_result (*cb)(struct peer *peer, @@ -97,26 +98,27 @@ struct txwatch *watch_txid_(const tal_t *ctx, struct txwatch *w; w = tal(ctx, struct txwatch); + w->topo = topo; w->depth = 0; w->txid = *txid; - w->dstate = peer->dstate; w->peer = peer; w->cb = cb; w->cbdata = cb_arg; - txwatch_hash_add(&w->dstate->txwatches, w); + txwatch_hash_add(&w->topo->txwatches, w); tal_add_destructor(w, destroy_txwatch); return w; } -bool watching_txid(struct lightningd_state *dstate, +bool watching_txid(const struct topology *topo, const struct sha256_double *txid) { - return txwatch_hash_get(&dstate->txwatches, txid) != NULL; + return txwatch_hash_get(&topo->txwatches, txid) != NULL; } struct txwatch *watch_tx_(const tal_t *ctx, + struct topology *topo, struct peer *peer, const struct bitcoin_tx *tx, enum watch_result (*cb)(struct peer *peer, @@ -128,10 +130,11 @@ struct txwatch *watch_tx_(const tal_t *ctx, struct sha256_double txid; bitcoin_txid(tx, &txid); - return watch_txid(ctx, peer, &txid, cb, cb_arg); + return watch_txid(ctx, topo, peer, &txid, cb, cb_arg); } struct txowatch *watch_txo_(const tal_t *ctx, + struct topology *topo, struct peer *peer, const struct sha256_double *txid, unsigned int output, @@ -143,23 +146,24 @@ struct txowatch *watch_txo_(const tal_t *ctx, { struct txowatch *w = tal(ctx, struct txowatch); + w->topo = topo; w->out.txid = *txid; w->out.index = output; w->peer = peer; w->cb = cb; w->cbdata = cbdata; - txowatch_hash_add(&w->peer->dstate->txowatches, w); + txowatch_hash_add(&w->topo->txowatches, w); tal_add_destructor(w, destroy_txowatch); return w; } -void txwatch_fire(struct lightningd_state *dstate, +void txwatch_fire(struct topology *topo, const struct sha256_double *txid, unsigned int depth) { - struct txwatch *txw = txwatch_hash_get(&dstate->txwatches, txid); + struct txwatch *txw = txwatch_hash_get(&topo->txwatches, txid); if (txw && depth != txw->depth) { enum watch_result r; @@ -182,7 +186,7 @@ void txwatch_fire(struct lightningd_state *dstate, } } -void txowatch_fire(struct lightningd_state *dstate, +void txowatch_fire(struct topology *topo, const struct txowatch *txow, const struct bitcoin_tx *tx, size_t input_num) @@ -212,18 +216,19 @@ void txowatch_fire(struct lightningd_state *dstate, fatal("txowatch callback %p returned %i\n", txow->cb, r); } -void watch_topology_changed(struct lightningd_state *dstate) +void watch_topology_changed(struct topology *topo) { struct txwatch_hash_iter i; struct txwatch *w; bool needs_rerun; + struct lightningd_state *dstate = tal_parent(topo); again: /* Iterating a htable during deletes is safe, but might skip entries. */ needs_rerun = false; - for (w = txwatch_hash_first(&dstate->txwatches, &i); + for (w = txwatch_hash_first(&topo->txwatches, &i); w; - w = txwatch_hash_next(&dstate->txwatches, &i)) { + w = txwatch_hash_next(&topo->txwatches, &i)) { size_t depth; depth = get_tx_depth(dstate, &w->txid); diff --git a/daemon/watch.h b/daemon/watch.h index 7858b02dd..17c7fabf8 100644 --- a/daemon/watch.h +++ b/daemon/watch.h @@ -23,6 +23,8 @@ struct txwatch_output { /* Watching an output */ struct txowatch { + struct topology *topo; + /* Peer who owns us. */ struct peer *peer; @@ -46,7 +48,7 @@ HTABLE_DEFINE_TYPE(struct txowatch, txowatch_keyof, txo_hash, txowatch_eq, txowatch_hash); struct txwatch { - struct lightningd_state *dstate; + struct topology *topo; /* Peer who owns us. */ struct peer *peer; @@ -70,6 +72,7 @@ HTABLE_DEFINE_TYPE(struct txwatch, txwatch_keyof, txid_hash, txwatch_eq, struct txwatch *watch_txid_(const tal_t *ctx, + struct topology *topo, struct peer *peer, const struct sha256_double *txid, enum watch_result (*cb)(struct peer *peer, @@ -78,8 +81,8 @@ struct txwatch *watch_txid_(const tal_t *ctx, void *), void *cbdata); -#define watch_txid(ctx, peer, txid, cb, cbdata) \ - watch_txid_((ctx), (peer), (txid), \ +#define watch_txid(ctx, topo, peer, txid, cb, cbdata) \ + watch_txid_((ctx), (topo), (peer), (txid), \ typesafe_cb_preargs(enum watch_result, void *, \ (cb), (cbdata), \ struct peer *, \ @@ -88,6 +91,7 @@ struct txwatch *watch_txid_(const tal_t *ctx, (cbdata)) struct txwatch *watch_tx_(const tal_t *ctx, + struct topology *topo, struct peer *peer, const struct bitcoin_tx *tx, enum watch_result (*cb)(struct peer *peer, @@ -96,8 +100,8 @@ struct txwatch *watch_tx_(const tal_t *ctx, void *), void *cbdata); -#define watch_tx(ctx, peer, tx, cb, cbdata) \ - watch_tx_((ctx), (peer), (tx), \ +#define watch_tx(ctx, topo, peer, tx, cb, cbdata) \ + watch_tx_((ctx), (topo), (peer), (tx), \ typesafe_cb_preargs(enum watch_result, void *, \ (cb), (cbdata), \ struct peer *, \ @@ -106,6 +110,7 @@ struct txwatch *watch_tx_(const tal_t *ctx, (cbdata)) struct txowatch *watch_txo_(const tal_t *ctx, + struct topology *topo, struct peer *peer, const struct sha256_double *txid, unsigned int output, @@ -115,8 +120,8 @@ struct txowatch *watch_txo_(const tal_t *ctx, void *), void *cbdata); -#define watch_txo(ctx, peer, txid, outnum, cb, cbdata) \ - watch_txo_((ctx), (peer), (txid), (outnum), \ +#define watch_txo(ctx, topo, peer, txid, outnum, cb, cbdata) \ + watch_txo_((ctx), (topo), (peer), (txid), (outnum), \ typesafe_cb_preargs(enum watch_result, void *, \ (cb), (cbdata), \ struct peer *, \ @@ -124,16 +129,16 @@ struct txowatch *watch_txo_(const tal_t *ctx, size_t), \ (cbdata)) -void txwatch_fire(struct lightningd_state *dstate, +void txwatch_fire(struct topology *topo, const struct sha256_double *txid, unsigned int depth); -void txowatch_fire(struct lightningd_state *dstate, +void txowatch_fire(struct topology *topo, const struct txowatch *txow, const struct bitcoin_tx *tx, size_t input_num); -bool watching_txid(struct lightningd_state *dstate, +bool watching_txid(const struct topology *topo, const struct sha256_double *txid); -void watch_topology_changed(struct lightningd_state *dstate); +void watch_topology_changed(struct topology *topo); #endif /* LIGHTNING_DAEMON_WATCH_H */ diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index f0bd3da2d..f82c3a32c 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -88,8 +88,6 @@ static struct lightningd *new_lightningd(const tal_t *ctx) ld->dstate.portnum = DEFAULT_PORT; ld->dstate.testnet = true; timers_init(&ld->dstate.timers, time_mono()); - txwatch_hash_init(&ld->dstate.txwatches); - txowatch_hash_init(&ld->dstate.txowatches); list_head_init(&ld->dstate.wallet); list_head_init(&ld->dstate.addresses); ld->dstate.dev_never_routefail = false;