peer: make closing_onchain.resolved[] in tx-output order.

At the moment, for our or their unilateral close, we create a resolved[]
entry for our output, their output, and each HTLC, in cstate order.  Some
of these outputs might not exist (too small), so it's actually better
to simply keep a resolved[] entry for each of the tx's actual outputs.

(We already changed the steal resolved[] array to work like this, but
these are trickier, since we rely on that order if we need to fulfill an
on-chain HTLC).

It also helps as we are weaning off knowing the cstate and permutation
mapping for each commitment transaction.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-08-18 14:23:46 +09:30
parent 4319f3ac70
commit 2e9a039789

View File

@ -1290,11 +1290,12 @@ static bool fulfill_onchain(struct peer *peer, struct htlc *htlc)
for (i = 0; i < tal_count(ci->cstate->side[THEIRS].htlcs); i++) { for (i = 0; i < tal_count(ci->cstate->side[THEIRS].htlcs); i++) {
if (ci->cstate->side[THEIRS].htlcs[i] == htlc) { if (ci->cstate->side[THEIRS].htlcs[i] == htlc) {
/* Already irrevocably resolved? */ /* Already irrevocably resolved? */
if (peer->closing_onchain.resolved[i]) assert(ci->map[i] != -1);
if (peer->closing_onchain.resolved[ci->map[i]])
return false; return false;
peer->closing_onchain.resolved[i] peer->closing_onchain.resolved[ci->map[i]]
= htlc_fulfill_tx(peer, ci, i); = htlc_fulfill_tx(peer, ci, i);
broadcast_tx(peer, peer->closing_onchain.resolved[i]); broadcast_tx(peer, peer->closing_onchain.resolved[ci->map[i]]);
return true; return true;
} }
} }
@ -2277,6 +2278,7 @@ static enum watch_result our_htlc_spent(struct peer *peer,
struct sha256 sha; struct sha256 sha;
struct rval preimage; struct rval preimage;
size_t i = ptr2int(pi); size_t i = ptr2int(pi);
const struct commit_info *ci = peer->closing_onchain.ci;
/* It should be spending the HTLC we expect. */ /* It should be spending the HTLC we expect. */
assert(peer->closing_onchain.ci->map[i] == tx->input[input_num].index); assert(peer->closing_onchain.ci->map[i] == tx->input[input_num].index);
@ -2322,7 +2324,8 @@ static enum watch_result our_htlc_spent(struct peer *peer,
* the redemption transaction itself once we've extracted the * the redemption transaction itself once we've extracted the
* preimage; the knowledge is not revocable. * preimage; the knowledge is not revocable.
*/ */
peer->closing_onchain.resolved[i] = irrevocably_resolved(peer); assert(ci->map[i] >= 0);
peer->closing_onchain.resolved[ci->map[i]] = irrevocably_resolved(peer);
return DELETE_WATCH; return DELETE_WATCH;
} }
@ -2354,6 +2357,7 @@ static enum watch_result our_htlc_depth(struct peer *peer,
bool our_commit, bool our_commit,
size_t i) size_t i)
{ {
const struct commit_info *ci = peer->closing_onchain.ci;
struct htlc *h; struct htlc *h;
u32 height; u32 height;
@ -2387,14 +2391,15 @@ static enum watch_result our_htlc_depth(struct peer *peer,
* 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. */ /* FIXME: we should simply delete this watch if HTLC is fulfilled. */
if (!peer->closing_onchain.resolved[i]) { assert(ci->map[i] >= 0);
peer->closing_onchain.resolved[i] if (!peer->closing_onchain.resolved[ci->map[i]]) {
peer->closing_onchain.resolved[ci->map[i]]
= htlc_timeout_tx(peer, peer->closing_onchain.ci, i); = htlc_timeout_tx(peer, peer->closing_onchain.ci, i);
watch_tx(peer->closing_onchain.resolved[i], watch_tx(peer->closing_onchain.resolved[ci->map[i]],
peer, peer,
peer->closing_onchain.resolved[i], peer->closing_onchain.resolved[ci->map[i]],
our_htlc_timeout_depth, int2ptr(i)); our_htlc_timeout_depth, int2ptr(i));
broadcast_tx(peer, peer->closing_onchain.resolved[i]); broadcast_tx(peer, peer->closing_onchain.resolved[ci->map[i]]);
} }
return DELETE_WATCH; return DELETE_WATCH;
} }
@ -2427,11 +2432,9 @@ static void resolve_our_htlcs(struct peer *peer,
bitcoin_txid(tx, &txid); bitcoin_txid(tx, &txid);
for (i = start; i < start + num; i++) { for (i = start; i < start + num; i++) {
/* Doesn't exist? Resolved by tx itself. */ /* Doesn't exist? Ignore. */
if (ci->map[i] == -1) { if (ci->map[i] == -1)
resolved[i] = tx;
continue; continue;
}
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -2459,6 +2462,7 @@ static enum watch_result their_htlc_depth(struct peer *peer,
u32 height; u32 height;
struct htlc *h; struct htlc *h;
size_t i = ptr2int(pi); size_t i = ptr2int(pi);
const struct commit_info *ci = peer->closing_onchain.ci;
/* Must be in a block. */ /* Must be in a block. */
if (depth == 0) if (depth == 0)
@ -2476,7 +2480,7 @@ static enum watch_result their_htlc_depth(struct peer *peer,
if (height < abs_locktime_to_blocks(&h->expiry)) if (height < abs_locktime_to_blocks(&h->expiry))
return KEEP_WATCHING; return KEEP_WATCHING;
peer->closing_onchain.resolved[i] = irrevocably_resolved(peer); peer->closing_onchain.resolved[ci->map[i]] = irrevocably_resolved(peer);
return DELETE_WATCH; return DELETE_WATCH;
} }
@ -2491,11 +2495,9 @@ static void resolve_their_htlcs(struct peer *peer,
for (i = start; i < start + num; i++) { for (i = start; i < start + num; i++) {
struct htlc *htlc; struct htlc *htlc;
/* Doesn't exist? Resolved by tx itself. */ /* Doesn't exist? Ignore. */
if (ci->map[i] == -1) { if (ci->map[i] == -1)
resolved[i] = tx;
continue; continue;
}
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -2506,9 +2508,9 @@ static void resolve_their_htlcs(struct peer *peer,
*/ */
htlc = htlc_by_index(ci, i); htlc = htlc_by_index(ci, i);
if (htlc->r) { if (htlc->r) {
peer->closing_onchain.resolved[i] peer->closing_onchain.resolved[ci->map[i]]
= htlc_fulfill_tx(peer, ci, i); = htlc_fulfill_tx(peer, ci, i);
broadcast_tx(peer, peer->closing_onchain.resolved[i]); broadcast_tx(peer, peer->closing_onchain.resolved[ci->map[i]]);
} else { } else {
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -2525,11 +2527,13 @@ static enum watch_result our_main_output_depth(struct peer *peer,
const struct sha256_double *txid, const struct sha256_double *txid,
void *unused) void *unused)
{ {
const struct commit_info *ci = peer->closing_onchain.ci;
/* 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 KEEP_WATCHING; return KEEP_WATCHING;
assert(!peer->closing_onchain.resolved[0]); assert(!peer->closing_onchain.resolved[ci->map[0]]);
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -2540,8 +2544,8 @@ static enum watch_result our_main_output_depth(struct peer *peer,
* recommended), the output is *resolved* by the spending * recommended), the output is *resolved* by the spending
* transaction * transaction
*/ */
peer->closing_onchain.resolved[0] = bitcoin_spend_ours(peer); peer->closing_onchain.resolved[ci->map[0]] = bitcoin_spend_ours(peer);
broadcast_tx(peer, peer->closing_onchain.resolved[0]); broadcast_tx(peer, peer->closing_onchain.resolved[ci->map[0]]);
return DELETE_WATCH; return DELETE_WATCH;
} }
@ -2584,7 +2588,7 @@ static void resolve_our_unilateral(struct peer *peer,
size_t num_ours, num_theirs; size_t num_ours, num_theirs;
peer->closing_onchain.resolved peer->closing_onchain.resolved
= tal_arrz(tx, const struct bitcoin_tx *, tal_count(ci->map)); = tal_arrz(tx, const struct bitcoin_tx *, tx->output_count);
/* This only works because we always watch for a long time before /* This only works because we always watch for a long time before
* freeing peer, by which time this has resolved. We could create * freeing peer, by which time this has resolved. We could create
@ -2599,6 +2603,7 @@ static void resolve_our_unilateral(struct peer *peer,
* other node's `open_channel` `delay` field) before spending the * other node's `open_channel` `delay` field) before spending the
* output. * output.
*/ */
if (ci->map[0] >= 0)
watch_tx(tx, peer, tx, our_main_output_depth, NULL); watch_tx(tx, peer, tx, our_main_output_depth, NULL);
/* BOLT #onchain: /* BOLT #onchain:
@ -2606,7 +2611,8 @@ static void resolve_our_unilateral(struct peer *peer,
* 2. _B's main output_: No action required, this output is considered * 2. _B's main output_: No action required, this output is considered
* *resolved* by the *commitment tx*. * *resolved* by the *commitment tx*.
*/ */
peer->closing_onchain.resolved[1] = tx; if (ci->map[1] >= 0)
peer->closing_onchain.resolved[ci->map[1]] = tx;
num_ours = tal_count(ci->cstate->side[OURS].htlcs); num_ours = tal_count(ci->cstate->side[OURS].htlcs);
num_theirs = tal_count(ci->cstate->side[THEIRS].htlcs); num_theirs = tal_count(ci->cstate->side[THEIRS].htlcs);
@ -2651,7 +2657,7 @@ static void resolve_their_unilateral(struct peer *peer,
ci = peer->closing_onchain.ci; ci = peer->closing_onchain.ci;
peer->closing_onchain.resolved peer->closing_onchain.resolved
= tal_arrz(tx, const struct bitcoin_tx *, tal_count(ci->map)); = tal_arrz(tx, const struct bitcoin_tx *, tx->output_count);
/* BOLT #onchain: /* BOLT #onchain:
* *
@ -2659,14 +2665,16 @@ static void resolve_their_unilateral(struct peer *peer,
* simple P2WPKH output. This output is considered * simple P2WPKH output. This output is considered
* *resolved* by the *commitment tx*. * *resolved* by the *commitment tx*.
*/ */
peer->closing_onchain.resolved[1] = tx; if (ci->map[1] >= 0)
peer->closing_onchain.resolved[ci->map[1]] = tx;
/* BOLT #onchain: /* BOLT #onchain:
* *
* 2. _B's main output_: No action required, this output is * 2. _B's main output_: No action required, this output is
* considered *resolved* by the *commitment tx*. * considered *resolved* by the *commitment tx*.
*/ */
peer->closing_onchain.resolved[0] = tx; if (ci->map[0] >= 0)
peer->closing_onchain.resolved[ci->map[0]] = tx;
num_ours = tal_count(ci->cstate->side[OURS].htlcs); num_ours = tal_count(ci->cstate->side[OURS].htlcs);
num_theirs = tal_count(ci->cstate->side[THEIRS].htlcs); num_theirs = tal_count(ci->cstate->side[THEIRS].htlcs);