watch: make it easier for them to self-delete.

Rather than keeping a pointer so they can free themselves, make it
explicit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-06-30 09:10:11 +09:30
parent 3ba25dd994
commit b8571c1ac8
3 changed files with 130 additions and 85 deletions

View File

@ -1154,9 +1154,10 @@ struct anchor_watch {
struct oneshot *timer; struct oneshot *timer;
}; };
static void anchor_depthchange(struct peer *peer, unsigned int depth, static enum watch_result anchor_depthchange(struct peer *peer,
const struct sha256_double *txid, unsigned int depth,
void *unused) const struct sha256_double *txid,
void *unused)
{ {
struct anchor_watch *w = peer->anchor.watches; struct anchor_watch *w = peer->anchor.watches;
@ -1175,6 +1176,7 @@ static void anchor_depthchange(struct peer *peer, unsigned int depth,
/* Since this gets called on every new block, check HTLCs here. */ /* Since this gets called on every new block, check HTLCs here. */
check_htlc_expiry(peer); check_htlc_expiry(peer);
return KEEP_WATCHING;
} }
/* Yay, segwit! We can just compare txids, even though we don't have both /* Yay, segwit! We can just compare txids, even though we don't have both
@ -1474,10 +1476,10 @@ static void resolve_cheating(struct peer *peer)
broadcast_tx(peer, steal_tx); broadcast_tx(peer, steal_tx);
} }
static void our_htlc_spent(struct peer *peer, static enum watch_result our_htlc_spent(struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
size_t input_num, size_t input_num,
ptrint_t *pi) ptrint_t *pi)
{ {
struct htlc *h; struct htlc *h;
struct sha256 sha; struct sha256 sha;
@ -1503,7 +1505,8 @@ static void our_htlc_spent(struct peer *peer,
/* Our timeout tx has all-zeroes, so we can distinguish it. */ /* Our timeout tx has all-zeroes, so we can distinguish it. */
if (memeqzero(tx->input[input_num].witness[1], sizeof(preimage))) if (memeqzero(tx->input[input_num].witness[1], sizeof(preimage)))
return; /* They might try to race us. */
return KEEP_WATCHING;
memcpy(&preimage, tx->input[input_num].witness[1], sizeof(preimage)); memcpy(&preimage, tx->input[input_num].witness[1], sizeof(preimage));
sha256(&sha, &preimage, sizeof(preimage)); sha256(&sha, &preimage, sizeof(preimage));
@ -1526,20 +1529,21 @@ static void our_htlc_spent(struct peer *peer,
* preimage; the knowledge is not revocable. * preimage; the knowledge is not revocable.
*/ */
peer->closing_onchain.resolved[i] = irrevocably_resolved(peer); peer->closing_onchain.resolved[i] = irrevocably_resolved(peer);
return DELETE_WATCH;
} }
static void our_htlc_depth(struct peer *peer, static enum watch_result our_htlc_depth(struct peer *peer,
unsigned int depth, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
bool our_commit, bool our_commit,
size_t i) size_t i)
{ {
struct htlc *h; struct htlc *h;
u32 height; u32 height;
/* Must be in a block. */ /* Must be in a block. */
if (depth == 0) if (depth == 0)
return; return KEEP_WATCHING;
height = get_block_height(peer->dstate); height = get_block_height(peer->dstate);
h = htlc_by_index(peer->closing_onchain.ci, i); h = htlc_by_index(peer->closing_onchain.ci, i);
@ -1554,11 +1558,11 @@ static void our_htlc_depth(struct peer *peer,
*/ */
if (height < abs_locktime_to_blocks(&h->expiry)) if (height < abs_locktime_to_blocks(&h->expiry))
return; return KEEP_WATCHING;
if (our_commit) { if (our_commit) {
if (depth < rel_locktime_to_blocks(&peer->remote.locktime)) if (depth < rel_locktime_to_blocks(&peer->remote.locktime))
return; return KEEP_WATCHING;
} }
/* BOLT #onchain: /* BOLT #onchain:
@ -1566,27 +1570,29 @@ static void our_htlc_depth(struct peer *peer,
* If the output has *timed out* and not been *resolved*, the node * If the output has *timed out* and not been *resolved*, the node
* MUST *resolve* the output by spending it. * MUST *resolve* the output by spending it.
*/ */
/* FIXME: we should simply delete this watch if HTLC is fulfilled. */
if (!peer->closing_onchain.resolved[i]) { if (!peer->closing_onchain.resolved[i]) {
peer->closing_onchain.resolved[i] peer->closing_onchain.resolved[i]
= htlc_timeout_tx(peer, peer->closing_onchain.ci, i); = htlc_timeout_tx(peer, peer->closing_onchain.ci, i);
broadcast_tx(peer, peer->closing_onchain.resolved[i]); broadcast_tx(peer, peer->closing_onchain.resolved[i]);
} }
return DELETE_WATCH;
} }
static void our_htlc_depth_ourcommit(struct peer *peer, static enum watch_result our_htlc_depth_ourcommit(struct peer *peer,
unsigned int depth, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
ptrint_t *i) ptrint_t *i)
{ {
our_htlc_depth(peer, depth, txid, true, ptr2int(i)); return our_htlc_depth(peer, depth, txid, true, ptr2int(i));
} }
static void our_htlc_depth_theircommit(struct peer *peer, static enum watch_result our_htlc_depth_theircommit(struct peer *peer,
unsigned int depth, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
ptrint_t *i) ptrint_t *i)
{ {
our_htlc_depth(peer, depth, txid, false, ptr2int(i)); return our_htlc_depth(peer, depth, txid, false, ptr2int(i));
} }
static void resolve_our_htlcs(struct peer *peer, static void resolve_our_htlcs(struct peer *peer,
@ -1644,10 +1650,10 @@ void our_htlc_fulfilled(struct peer *peer, struct htlc *htlc,
} }
} }
static void their_htlc_depth(struct peer *peer, static enum watch_result their_htlc_depth(struct peer *peer,
unsigned int depth, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
ptrint_t *pi) ptrint_t *pi)
{ {
u32 height; u32 height;
struct htlc *h; struct htlc *h;
@ -1655,7 +1661,7 @@ static void their_htlc_depth(struct peer *peer,
/* Must be in a block. */ /* Must be in a block. */
if (depth == 0) if (depth == 0)
return; return KEEP_WATCHING;
height = get_block_height(peer->dstate); height = get_block_height(peer->dstate);
h = htlc_by_index(peer->closing_onchain.ci, i); h = htlc_by_index(peer->closing_onchain.ci, i);
@ -1667,9 +1673,10 @@ static void their_htlc_depth(struct peer *peer,
*/ */
if (height < abs_locktime_to_blocks(&h->expiry)) if (height < abs_locktime_to_blocks(&h->expiry))
return; return KEEP_WATCHING;
peer->closing_onchain.resolved[i] = irrevocably_resolved(peer); peer->closing_onchain.resolved[i] = irrevocably_resolved(peer);
return DELETE_WATCH;
} }
static void resolve_their_htlcs(struct peer *peer, static void resolve_their_htlcs(struct peer *peer,
@ -1691,18 +1698,16 @@ static void resolve_their_htlcs(struct peer *peer,
} }
} }
static void our_main_output_depth(struct peer *peer, static enum watch_result our_main_output_depth(struct peer *peer,
unsigned int depth, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
void *unused) void *unused)
{ {
/* Not past CSV timeout? */ /* Not past CSV timeout? */
if (depth < rel_locktime_to_blocks(&peer->remote.locktime)) if (depth < rel_locktime_to_blocks(&peer->remote.locktime))
return; return KEEP_WATCHING;
/* Already done? (FIXME: Delete after first time) */ assert(!peer->closing_onchain.resolved[0]);
if (peer->closing_onchain.resolved[0])
return;
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -1715,6 +1720,7 @@ static void our_main_output_depth(struct peer *peer,
*/ */
peer->closing_onchain.resolved[0] = bitcoin_spend_ours(peer); peer->closing_onchain.resolved[0] = bitcoin_spend_ours(peer);
broadcast_tx(peer, peer->closing_onchain.resolved[0]); broadcast_tx(peer, peer->closing_onchain.resolved[0]);
return DELETE_WATCH;
} }
/* BOLT #onchain: /* BOLT #onchain:
@ -1832,10 +1838,10 @@ static void resolve_mutual_close(struct peer *peer)
} }
/* Called every time the tx spending the funding tx changes depth. */ /* Called every time the tx spending the funding tx changes depth. */
static void check_for_resolution(struct peer *peer, static enum watch_result check_for_resolution(struct peer *peer,
unsigned int depth, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
void *unused) void *unused)
{ {
size_t i, n = tal_count(peer->closing_onchain.resolved); size_t i, n = tal_count(peer->closing_onchain.resolved);
size_t forever = peer->dstate->config.forever_confirms; size_t forever = peer->dstate->config.forever_confirms;
@ -1848,7 +1854,7 @@ static void check_for_resolution(struct peer *peer,
*/ */
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (!peer->closing_onchain.resolved[i]) if (!peer->closing_onchain.resolved[i])
return; return KEEP_WATCHING;
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -1857,14 +1863,14 @@ static void check_for_resolution(struct peer *peer,
* 100 deep on the most-work blockchain. * 100 deep on the most-work blockchain.
*/ */
if (depth < forever) if (depth < forever)
return; return KEEP_WATCHING;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct sha256_double txid; struct sha256_double txid;
bitcoin_txid(peer->closing_onchain.resolved[i], &txid); bitcoin_txid(peer->closing_onchain.resolved[i], &txid);
if (get_tx_depth(peer->dstate, &txid) < forever) if (get_tx_depth(peer->dstate, &txid) < forever)
return; return KEEP_WATCHING;
} }
/* BOLT #onchain: /* BOLT #onchain:
@ -1880,14 +1886,16 @@ static void check_for_resolution(struct peer *peer,
io_break(peer); io_break(peer);
else else
io_wake(peer); io_wake(peer);
return DELETE_WATCH;
} }
/* We assume the tx is valid! Don't do a blockchain.info and feed this /* We assume the tx is valid! Don't do a blockchain.info and feed this
* invalid transactions! */ * invalid transactions! */
static void anchor_spent(struct peer *peer, static enum watch_result anchor_spent(struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
size_t input_num, size_t input_num,
void *unused) void *unused)
{ {
struct sha256_double txid; struct sha256_double txid;
Pkt *err; Pkt *err;
@ -1943,7 +1951,7 @@ static void anchor_spent(struct peer *peer,
"anchor_spent"); "anchor_spent");
/* No longer call into the state machine. */ /* No longer call into the state machine. */
peer->anchor.watches->depthok = INPUT_NONE; peer->anchor.watches->depthok = INPUT_NONE;
return; return DELETE_WATCH;
} }
/* BOLT #onchain: /* BOLT #onchain:
@ -1970,6 +1978,7 @@ static void anchor_spent(struct peer *peer,
/* No longer call into the state machine. */ /* No longer call into the state machine. */
peer->anchor.watches->depthok = INPUT_NONE; peer->anchor.watches->depthok = INPUT_NONE;
return KEEP_WATCHING;
} }
static void anchor_timeout(struct anchor_watch *w) static void anchor_timeout(struct anchor_watch *w)

View File

@ -88,9 +88,10 @@ static void destroy_txwatch(struct txwatch *w)
struct txwatch *watch_txid_(const tal_t *ctx, struct txwatch *watch_txid_(const tal_t *ctx,
struct peer *peer, struct peer *peer,
const struct sha256_double *txid, const struct sha256_double *txid,
void (*cb)(struct peer *peer, unsigned int depth, enum watch_result (*cb)(struct peer *peer,
const struct sha256_double *txid, unsigned int depth,
void *arg), const struct sha256_double *,
void *arg),
void *cb_arg) void *cb_arg)
{ {
struct txwatch *w; struct txwatch *w;
@ -118,9 +119,10 @@ bool watching_txid(struct lightningd_state *dstate,
struct txwatch *watch_tx_(const tal_t *ctx, struct txwatch *watch_tx_(const tal_t *ctx,
struct peer *peer, struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
void (*cb)(struct peer *peer, unsigned int depth, enum watch_result (*cb)(struct peer *peer,
const struct sha256_double *txid, unsigned int depth,
void *arg), const struct sha256_double *,
void *arg),
void *cb_arg) void *cb_arg)
{ {
struct sha256_double txid; struct sha256_double txid;
@ -133,10 +135,10 @@ struct txowatch *watch_txo_(const tal_t *ctx,
struct peer *peer, struct peer *peer,
const struct sha256_double *txid, const struct sha256_double *txid,
unsigned int output, unsigned int output,
void (*cb)(struct peer *peer, enum watch_result (*cb)(struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
size_t input_num, size_t input_num,
void *), void *),
void *cbdata) void *cbdata)
{ {
struct txowatch *w = tal(ctx, struct txowatch); struct txowatch *w = tal(ctx, struct txowatch);
@ -160,6 +162,7 @@ void txwatch_fire(struct lightningd_state *dstate,
struct txwatch *txw = txwatch_hash_get(&dstate->txwatches, txid); struct txwatch *txw = txwatch_hash_get(&dstate->txwatches, txid);
if (txw && depth != txw->depth) { if (txw && depth != txw->depth) {
enum watch_result r;
log_debug(txw->peer->log, log_debug(txw->peer->log,
"Got depth change %u for %02x%02x%02x...\n", "Got depth change %u for %02x%02x%02x...\n",
txw->depth, txw->depth,
@ -167,7 +170,15 @@ void txwatch_fire(struct lightningd_state *dstate,
txw->txid.sha.u.u8[1], txw->txid.sha.u.u8[1],
txw->txid.sha.u.u8[2]); txw->txid.sha.u.u8[2]);
txw->depth = depth; txw->depth = depth;
txw->cb(txw->peer, txw->depth, &txw->txid, txw->cbdata); 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);
} }
} }
@ -177,6 +188,7 @@ void txowatch_fire(struct lightningd_state *dstate,
size_t input_num) size_t input_num)
{ {
struct sha256_double txid; struct sha256_double txid;
enum watch_result r;
bitcoin_txid(tx, &txid); bitcoin_txid(tx, &txid);
log_debug(txow->peer->log, log_debug(txow->peer->log,
@ -189,7 +201,15 @@ void txowatch_fire(struct lightningd_state *dstate,
txid.sha.u.u8[1], txid.sha.u.u8[1],
txid.sha.u.u8[2], txid.sha.u.u8[2],
txid.sha.u.u8[3]); txid.sha.u.u8[3]);
txow->cb(txow->peer, tx, input_num, txow->cbdata); r = txow->cb(txow->peer, tx, input_num, txow->cbdata);
switch (r) {
case DELETE_WATCH:
tal_free(txow);
return;
case KEEP_WATCHING:
return;
}
fatal("txowatch callback %p returned %i\n", txow->cb, r);
} }
void watch_topology_changed(struct lightningd_state *dstate) void watch_topology_changed(struct lightningd_state *dstate)
@ -208,9 +228,18 @@ again:
depth = get_tx_depth(dstate, &w->txid); depth = get_tx_depth(dstate, &w->txid);
if (depth != w->depth) { if (depth != w->depth) {
enum watch_result r;
w->depth = depth; w->depth = depth;
w->cb(w->peer, w->depth, &w->txid, w->cbdata);
needs_rerun = true; 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);
} }
} }
if (needs_rerun) if (needs_rerun)

View File

@ -11,6 +11,11 @@
struct bitcoin_tx; struct bitcoin_tx;
struct lightningd_state; struct lightningd_state;
enum watch_result {
DELETE_WATCH = -1,
KEEP_WATCHING = -2
};
struct txwatch_output { struct txwatch_output {
struct sha256_double txid; struct sha256_double txid;
unsigned int index; unsigned int index;
@ -25,10 +30,10 @@ struct txowatch {
struct txwatch_output out; struct txwatch_output out;
/* A new tx. */ /* A new tx. */
void (*cb)(struct peer *peer, enum watch_result (*cb)(struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
size_t input_num, size_t input_num,
void *cbdata); void *cbdata);
void *cbdata; void *cbdata;
}; };
@ -51,9 +56,9 @@ struct txwatch {
unsigned int depth; unsigned int depth;
/* A new depth (0 if kicked out, otherwise 1 = tip, etc.) */ /* A new depth (0 if kicked out, otherwise 1 = tip, etc.) */
void (*cb)(struct peer *peer, unsigned int depth, enum watch_result (*cb)(struct peer *peer, unsigned int depth,
const struct sha256_double *txid, const struct sha256_double *txid,
void *cbdata); void *cbdata);
void *cbdata; void *cbdata;
}; };
@ -67,14 +72,15 @@ HTABLE_DEFINE_TYPE(struct txwatch, txwatch_keyof, txid_hash, txwatch_eq,
struct txwatch *watch_txid_(const tal_t *ctx, struct txwatch *watch_txid_(const tal_t *ctx,
struct peer *peer, struct peer *peer,
const struct sha256_double *txid, const struct sha256_double *txid,
void (*cb)(struct peer *peer, unsigned int depth, enum watch_result (*cb)(struct peer *peer,
const struct sha256_double *txid, unsigned int depth,
void *), const struct sha256_double*,
void *),
void *cbdata); void *cbdata);
#define watch_txid(ctx, peer, txid, cb, cbdata) \ #define watch_txid(ctx, peer, txid, cb, cbdata) \
watch_txid_((ctx), (peer), (txid), \ watch_txid_((ctx), (peer), (txid), \
typesafe_cb_preargs(void, void *, \ typesafe_cb_preargs(enum watch_result, void *, \
(cb), (cbdata), \ (cb), (cbdata), \
struct peer *, \ struct peer *, \
unsigned int depth, \ unsigned int depth, \
@ -84,14 +90,15 @@ struct txwatch *watch_txid_(const tal_t *ctx,
struct txwatch *watch_tx_(const tal_t *ctx, struct txwatch *watch_tx_(const tal_t *ctx,
struct peer *peer, struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
void (*cb)(struct peer *peer, unsigned int depth, enum watch_result (*cb)(struct peer *peer,
const struct sha256_double *txid, unsigned int depth,
void *), const struct sha256_double *,
void *),
void *cbdata); void *cbdata);
#define watch_tx(ctx, peer, tx, cb, cbdata) \ #define watch_tx(ctx, peer, tx, cb, cbdata) \
watch_tx_((ctx), (peer), (tx), \ watch_tx_((ctx), (peer), (tx), \
typesafe_cb_preargs(void, void *, \ typesafe_cb_preargs(enum watch_result, void *, \
(cb), (cbdata), \ (cb), (cbdata), \
struct peer *, \ struct peer *, \
unsigned int depth, \ unsigned int depth, \
@ -102,15 +109,15 @@ struct txowatch *watch_txo_(const tal_t *ctx,
struct peer *peer, struct peer *peer,
const struct sha256_double *txid, const struct sha256_double *txid,
unsigned int output, unsigned int output,
void (*cb)(struct peer *peer, enum watch_result (*cb)(struct peer *peer,
const struct bitcoin_tx *tx, const struct bitcoin_tx *tx,
size_t input_num, size_t input_num,
void *), void *),
void *cbdata); void *cbdata);
#define watch_txo(ctx, peer, txid, outnum, cb, cbdata) \ #define watch_txo(ctx, peer, txid, outnum, cb, cbdata) \
watch_txo_((ctx), (peer), (txid), (outnum), \ watch_txo_((ctx), (peer), (txid), (outnum), \
typesafe_cb_preargs(void, void *, \ typesafe_cb_preargs(enum watch_result, void *, \
(cb), (cbdata), \ (cb), (cbdata), \
struct peer *, \ struct peer *, \
const struct bitcoin_tx *, \ const struct bitcoin_tx *, \