diff --git a/daemon/peer.c b/daemon/peer.c index 32be7fee4..8880a2ccc 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -644,8 +644,10 @@ struct anchor_watch { static void anchor_depthchange(struct peer *peer, int depth, const struct sha256_double *blkhash, - struct anchor_watch *w) + const struct sha256_double *txid, + void *unused) { + struct anchor_watch *w = peer->anchor.watches; /* Still waiting for it to reach depth? */ if (w->depthok != INPUT_NONE) { /* Beware sign! */ @@ -737,7 +739,10 @@ static bool is_mutual_close(const struct peer *peer, return matches; } -static void close_depth_cb(struct peer *peer, int depth) +static void close_depth_cb(struct peer *peer, int depth, + const struct sha256_double *txid, + const struct sha256_double *blkhash, + void *unused) { if (depth >= peer->dstate->config.forever_confirms) { state_event(peer, BITCOIN_CLOSE_DONE, NULL); @@ -748,8 +753,9 @@ static void close_depth_cb(struct peer *peer, int depth) * invalid transactions! */ static void anchor_spent(struct peer *peer, const struct bitcoin_tx *tx, - struct anchor_watch *w) + void *unused) { + struct anchor_watch *w = peer->anchor.watches; union input idata; /* FIXME: change type in idata? */ @@ -757,7 +763,7 @@ static void anchor_spent(struct peer *peer, if (is_unrevoked_commit(peer->them.commit, tx)) state_event(peer, w->theyspent, &idata); else if (is_mutual_close(peer, tx)) - add_close_tx_watch(peer, peer, tx, close_depth_cb); + watch_tx(peer, peer, tx, close_depth_cb, NULL); else state_event(peer, w->otherspent, &idata); } @@ -789,10 +795,9 @@ void peer_watch_anchor(struct peer *peer, w->theyspent = theyspent; w->otherspent = otherspent; - add_anchor_watch(w, peer, &peer->anchor.txid, peer->anchor.index, - anchor_depthchange, - anchor_spent, - w); + peer_watch_setup(peer); + watch_txid(w, peer, &peer->anchor.txid, anchor_depthchange, NULL); + watch_txo(w, peer, &peer->anchor.txid, 0, anchor_spent, NULL); /* For anchor timeout, expect 20 minutes per block, +2 hours. * @@ -833,6 +838,7 @@ void peer_unwatch_anchor_depth(struct peer *peer, static void commit_tx_depth(struct peer *peer, int depth, const struct sha256_double *blkhash, + const struct sha256_double *txid, ptrint_t *canspend) { log_debug(peer->log, "Commit tx reached depth %i", depth); @@ -899,14 +905,15 @@ void peer_watch_delayed(struct peer *peer, memset(&peer->cur_commit.blockid, 0xFF, sizeof(peer->cur_commit.blockid)); peer->cur_commit.watch - = add_commit_tx_watch(tx, peer, &txid, commit_tx_depth, - int2ptr(canspend)); + = watch_txid(tx, peer, &txid, commit_tx_depth, + int2ptr(canspend)); watch_tx_outputs(peer, tx); } static void spend_tx_done(struct peer *peer, int depth, const struct sha256_double *blkhash, + const struct sha256_double *txid, ptrint_t *done) { log_debug(peer->log, "tx reached depth %i", depth); @@ -930,16 +937,7 @@ void peer_watch_tx(struct peer *peer, const struct bitcoin_tx *tx, enum state_input done) { - struct sha256_double txid; - - bitcoin_txid(tx, &txid); - log_debug(peer->log, "Watching tx %02x%02x%02x%02x...", - txid.sha.u.u8[0], - txid.sha.u.u8[1], - txid.sha.u.u8[2], - txid.sha.u.u8[3]); - - add_commit_tx_watch(tx, peer, &txid, spend_tx_done, int2ptr(done)); + watch_tx(tx, peer, tx, spend_tx_done, int2ptr(done)); } struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee) diff --git a/daemon/test/test.sh b/daemon/test/test.sh index 9aa38dc12..c964ec96a 100755 --- a/daemon/test/test.sh +++ b/daemon/test/test.sh @@ -408,7 +408,7 @@ $CLI generate 1 TIME=$(($EXPIRY + 33)) lcli1 dev-mocktime $TIME lcli2 dev-mocktime $TIME -sleep 1 +sleep 2 check_no_peers lcli1 check_no_peers lcli2 diff --git a/daemon/watch.c b/daemon/watch.c index 7d231fb40..001f7bd75 100644 --- a/daemon/watch.c +++ b/daemon/watch.c @@ -58,28 +58,6 @@ static void destroy_txowatch(struct txowatch *w) txowatch_hash_del(&w->peer->dstate->txowatches, w); } -/* Watch a txo. */ -static void insert_txo_watch(const tal_t *ctx, - struct peer *peer, - const struct sha256_double *txid, - unsigned int txout, - void (*cb)(struct peer *peer, - const struct bitcoin_tx *tx, - void *cbdata), - void *cbdata) -{ - struct txowatch *w = tal(ctx, struct txowatch); - - w->out.txid = *txid; - w->out.index = txout; - w->peer = peer; - w->cb = cb; - w->cbdata = cbdata; - - txowatch_hash_add(&w->peer->dstate->txowatches, w); - tal_add_destructor(w, destroy_txowatch); -} - const struct sha256_double *txwatch_keyof(const struct txwatch *w) { return &w->txid; @@ -100,30 +78,42 @@ static void destroy_txwatch(struct txwatch *w) txwatch_hash_del(&w->dstate->txwatches, w); } -static struct txwatch *insert_txwatch(const tal_t *ctx, - struct peer *peer, - const struct sha256_double *txid, - void (*cb)(struct peer *, int, - const struct sha256_double *, - void *), - void *cbdata) +/* FIXME: This is a hack! */ +void peer_watch_setup(struct peer *peer) +{ + struct sha256 h; + struct ripemd160 redeemhash; + + /* Telling bitcoind to watch the redeemhash address means + * it'll tell is about the anchor itself (spend to that + * address), and any commit txs (spend from that address).*/ + sha256(&h, peer->anchor.redeemscript, + tal_count(peer->anchor.redeemscript)); + ripemd160(&redeemhash, h.u.u8, sizeof(h)); + + bitcoind_watch_addr(peer->dstate, &redeemhash); +} + +struct txwatch *watch_txid_(const tal_t *ctx, + struct peer *peer, + const struct sha256_double *txid, + void (*cb)(struct peer *peer, int depth, + const struct sha256_double *blkhash, + const struct sha256_double *txid, + void *arg), + void *cb_arg) { struct txwatch *w; - /* We could have a null-watch on it because we saw it spend a TXO */ - w = txwatch_hash_get(&peer->dstate->txwatches, txid); - if (w) { - assert(!w->cb); - tal_free(w); - } + assert(!txwatch_hash_get(&peer->dstate->txwatches, txid)); w = tal(ctx, struct txwatch); - w->depth = 0; + w->depth = -1; w->txid = *txid; w->dstate = peer->dstate; w->peer = peer; w->cb = cb; - w->cbdata = cbdata; + w->cbdata = cb_arg; txwatch_hash_add(&w->dstate->txwatches, w); tal_add_destructor(w, destroy_txwatch); @@ -131,8 +121,49 @@ static struct txwatch *insert_txwatch(const tal_t *ctx, return w; } -/* This just serves to avoid us doing bitcoind_txid_lookup repeatedly - * on unknown txs. */ +struct txwatch *watch_tx_(const tal_t *ctx, + struct peer *peer, + const struct bitcoin_tx *tx, + void (*cb)(struct peer *peer, int depth, + const struct sha256_double *blkhash, + const struct sha256_double *txid, + void *arg), + void *cb_arg) +{ + struct sha256_double txid; + + normalized_txid(tx, &txid); + return watch_txid(ctx, peer, &txid, cb, cb_arg); +} + +struct txowatch *watch_txo_(const tal_t *ctx, + struct peer *peer, + const struct sha256_double *txid, + unsigned int output, + void (*cb)(struct peer *peer, + const struct bitcoin_tx *tx, + void *), + void *cbdata) +{ + struct txowatch *w = tal(ctx, struct txowatch); + + 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); + tal_add_destructor(w, destroy_txowatch); + + return w; +} + +struct tx_info { + struct sha256_double blkhash; + int conf; +}; + static void insert_null_txwatch(struct lightningd_state *dstate, const struct sha256_double *txid) { @@ -148,115 +179,100 @@ static void insert_null_txwatch(struct lightningd_state *dstate, tal_add_destructor(w, destroy_txwatch); } -void add_anchor_watch_(const tal_t *ctx, - struct peer *peer, - const struct sha256_double *txid, - unsigned int out, - void (*anchor_cb)(struct peer *peer, int depth, - const struct sha256_double *blkhash, - void *), - void (*spend_cb)(struct peer *peer, - const struct bitcoin_tx *, void *), - void *cbdata) -{ - struct sha256 h; - struct ripemd160 redeemhash; - u8 *redeemscript; - - insert_txwatch(ctx, peer, txid, anchor_cb, cbdata); - insert_txo_watch(ctx, peer, txid, out, spend_cb, cbdata); - - redeemscript = bitcoin_redeem_2of2(ctx, &peer->them.commitkey, - &peer->us.commitkey); - sha256(&h, redeemscript, tal_count(redeemscript)); - ripemd160(&redeemhash, h.u.u8, sizeof(h)); - tal_free(redeemscript); - - /* Telling bitcoind to watch the redeemhash address means - * it'll tell is about the anchor itself (spend to that - * address), and any commit txs (spend from that address).*/ - bitcoind_watch_addr(peer->dstate, &redeemhash); -} - -struct txwatch *add_commit_tx_watch_(const tal_t *ctx, - struct peer *peer, - const struct sha256_double *txid, - void (*cb)(struct peer *peer, int depth, - const struct sha256_double *blkhash, - void *), - void *cbdata) -{ - return insert_txwatch(ctx, peer, txid, cb, cbdata); - - /* We are already watching the anchor txo, so we don't need to - * watch anything else. */ -} - -static void cb_no_arg(struct peer *peer, int depth, - const struct sha256_double *blkhash, void *vcb) -{ - void (*cb)(struct peer *peer, int depth) = vcb; - cb(peer, depth); -} - -void add_close_tx_watch(const tal_t *ctx, - struct peer *peer, - const struct bitcoin_tx *tx, - void (*cb)(struct peer *peer, int depth)) +static void watched_normalized_txid(struct lightningd_state *dstate, + const struct bitcoin_tx *tx, + struct tx_info *txinfo) { + struct txwatch *txw; struct sha256_double txid; - bitcoin_txid(tx, &txid); - insert_txwatch(ctx, peer, &txid, cb_no_arg, cb); + size_t i; + + normalized_txid(tx, &txid); + txw = txwatch_hash_get(&dstate->txwatches, &txid); - /* We are already watching the anchor txo, so we don't need to - * watch anything else. */ -} + /* Reset to real txid for logging. */ + bitcoin_txid(tx, &txid); -static void tx_watched_inputs(struct lightningd_state *dstate, - const struct bitcoin_tx *tx, void *unused) -{ - size_t in; + if (txw) { + if (txinfo->conf != txw->depth) { + log_debug(txw->peer->log, + "Got depth change %u for %02x%02x%02x...\n", + txinfo->conf, + txid.sha.u.u8[0], + txid.sha.u.u8[1], + txid.sha.u.u8[2]); + txw->depth = txinfo->conf; + txw->cb(txw->peer, txw->depth, &txinfo->blkhash, &txid, + txw->cbdata); + } + return; + } - for (in = 0; in < tx->input_count; in++) { + /* Hmm, otherwise it may be new */ + for (i = 0; i < tx->input_count; i++) { + struct txowatch *txo; struct txwatch_output out; - struct txowatch *txow; - - out.txid = tx->input[in].txid; - out.index = tx->input[in].index; - txow = txowatch_hash_get(&dstate->txowatches, &out); - if (txow) - txow->cb(txow->peer, tx, txow->cbdata); + out.txid = tx->input[i].txid; + out.index = tx->input[i].index; + txo = txowatch_hash_get(&dstate->txowatches, &out); + + /* Presumably, this sets a watch on it. */ + if (txo) { + log_debug(txo->peer->log, + "New tx spending %02x%02x%02x output %u:" + " %02x%02x%02x...\n", + out.txid.sha.u.u8[0], + out.txid.sha.u.u8[1], + out.txid.sha.u.u8[2], + out.index, + txid.sha.u.u8[0], + txid.sha.u.u8[1], + txid.sha.u.u8[2]); + txo->cb(txo->peer, tx, txo->cbdata); + return; + } } + + /* OK, not interesting. Put in fake (on original txid). */ + log_debug(dstate->base_log, "Ignoring tx %02x%02x%02x...\n", + txid.sha.u.u8[0], + txid.sha.u.u8[1], + txid.sha.u.u8[2]); + insert_null_txwatch(dstate, &txid); } -static void watched_transaction(struct lightningd_state *dstate, - const struct sha256_double *txid, - int confirmations, - bool is_coinbase, - const struct sha256_double *blkhash) +static void watched_txid(struct lightningd_state *dstate, + const struct sha256_double *txid, + int confirmations, + bool is_coinbase, + const struct sha256_double *blkhash) { struct txwatch *txw; + struct tx_info *txinfo; + + /* Maybe it spent an output we're watching? */ + if (is_coinbase) + return; /* Are we watching this txid directly (or already reported)? */ txw = txwatch_hash_get(&dstate->txwatches, txid); if (txw) { - if (confirmations != txw->depth) { + if (txw->cb && confirmations != txw->depth) { txw->depth = confirmations; - if (txw->cb) - txw->cb(txw->peer, txw->depth, blkhash, - txw->cbdata); + txw->cb(txw->peer, txw->depth, blkhash, txid, + txw->cbdata); } return; } - /* Don't report about this txid twice. */ - insert_null_txwatch(dstate, txid); - - /* Maybe it spent an output we're watching? */ - if (!is_coinbase) - bitcoind_txid_lookup(dstate, txid, tx_watched_inputs, NULL); + txinfo = tal(dstate, struct tx_info); + txinfo->conf = confirmations; + if (blkhash) + txinfo->blkhash = *blkhash; + /* FIXME: Since we don't use segwit, we need to normalize txids. */ + bitcoind_txid_lookup(dstate, txid, watched_normalized_txid, txinfo); } static struct timeout watch_timeout; @@ -267,7 +283,7 @@ static void start_poll_transactions(struct lightningd_state *dstate) log_unusual(dstate->base_log, "Delaying start poll: commands in progress"); } else - bitcoind_poll_transactions(dstate, watched_transaction); + bitcoind_poll_transactions(dstate, watched_txid); refresh_timeout(dstate, &watch_timeout); } diff --git a/daemon/watch.h b/daemon/watch.h index eda5d4d89..dbd829467 100644 --- a/daemon/watch.h +++ b/daemon/watch.h @@ -52,6 +52,7 @@ struct txwatch { /* A new depth (-1 if conflicted), blkhash valid if > 0 */ void (*cb)(struct peer *peer, int depth, const struct sha256_double *blkhash, + const struct sha256_double *txid, void *cbdata); void *cbdata; }; @@ -63,51 +64,65 @@ HTABLE_DEFINE_TYPE(struct txwatch, txwatch_keyof, txid_hash, txwatch_eq, txwatch_hash); -void add_anchor_watch_(const tal_t *ctx, - struct peer *peer, - const struct sha256_double *txid, - unsigned int out, - void (*anchor_cb)(struct peer *peer, int depth, - const struct sha256_double *blkhash, - void *), - void (*spend_cb)(struct peer *peer, - const struct bitcoin_tx *, void *), - void *cbdata); - -#define add_anchor_watch(ctx, peer, txid, out, anchor_cb, spend_cb, cbdata) \ - add_anchor_watch_((ctx), (peer), (txid), (out), \ - typesafe_cb_preargs(void, void *, \ - (anchor_cb), (cbdata), \ - struct peer *, \ - int depth, \ - const struct sha256_double *), \ - typesafe_cb_preargs(void, void *, \ - (spend_cb), (cbdata), \ - struct peer *, \ - const struct bitcoin_tx *), \ - (cbdata)) - -struct txwatch *add_commit_tx_watch_(const tal_t *ctx, - struct peer *peer, - const struct sha256_double *txid, - void (*cb)(struct peer *peer, int depth, - const struct sha256_double *blkhash, - void *), - void *cbdata); - -#define add_commit_tx_watch(ctx, peer, txid, cb, cbdata) \ - add_commit_tx_watch_((ctx), (peer), (txid), \ - typesafe_cb_preargs(void, void *, \ - (cb), (cbdata), \ - struct peer *, \ - int, \ - const struct sha256_double *), \ - (cbdata)) - -void add_close_tx_watch(const tal_t *ctx, - struct peer *peer, - const struct bitcoin_tx *tx, - void (*cb)(struct peer *peer, int depth)); +struct txwatch *watch_txid_(const tal_t *ctx, + struct peer *peer, + const struct sha256_double *txid, + void (*cb)(struct peer *peer, int depth, + const struct sha256_double *blkhash, + const struct sha256_double *txidx, + void *), + void *cbdata); + +#define watch_txid(ctx, peer, txid, cb, cbdata) \ + watch_txid_((ctx), (peer), (txid), \ + typesafe_cb_preargs(void, void *, \ + (cb), (cbdata), \ + struct peer *, \ + int depth, \ + const struct sha256_double *, \ + const struct sha256_double *txidx), \ + (cbdata)) + +struct txwatch *watch_tx_(const tal_t *ctx, + struct peer *peer, + const struct bitcoin_tx *tx, + void (*cb)(struct peer *peer, int depth, + const struct sha256_double *blkhash, + const struct sha256_double *txidx, + void *), + void *cbdata); + +#define watch_tx(ctx, peer, tx, cb, cbdata) \ + watch_tx_((ctx), (peer), (tx), \ + typesafe_cb_preargs(void, void *, \ + (cb), (cbdata), \ + struct peer *, \ + int depth, \ + const struct sha256_double *, \ + const struct sha256_double *), \ + (cbdata)) + +struct txowatch *watch_txo_(const tal_t *ctx, + struct peer *peer, + const struct sha256_double *txid, + unsigned int output, + void (*cb)(struct peer *peer, + const struct bitcoin_tx *tx, + void *), + void *cbdata); + +#define watch_txo(ctx, peer, txid, outnum, cb, cbdata) \ + watch_txo_((ctx), (peer), (txid), (outnum), \ + typesafe_cb_preargs(void, void *, \ + (cb), (cbdata), \ + struct peer *, \ + const struct bitcoin_tx *), \ + (cbdata)) + +void peer_watch_setup(struct peer *peer); + +/* FIXME: Seg witness removes need for this! */ +void normalized_txid(const struct bitcoin_tx *tx, struct sha256_double *txid); void setup_watch_timer(struct lightningd_state *dstate); #endif /* LIGHTNING_DAEMON_WATCH_H */