diff --git a/daemon/peer.c b/daemon/peer.c index 916a8bb4b..d165963c0 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -703,45 +703,26 @@ static void anchor_depthchange(struct peer *peer, int depth, } } -/* We don't compare scriptSigs: we don't know them anyway! */ -static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb) +/* Yay, segwit! We can just compare txids, even though we don't have both + * signatures. */ +static bool txidmatch(const struct bitcoin_tx *tx, + const struct sha256_double *txid) { - size_t i; + struct sha256_double tx_txid; - if (txa->version != txb->version - || txa->input_count != txb->input_count - || txa->output_count != txb->output_count - || txa->lock_time != txb->lock_time) - return false; - - for (i = 0; i < txa->input_count; i++) { - if (!structeq(&txa->input[i].txid, &txb->input[i].txid) - || txa->input[i].index != txb->input[i].index - || txa->input[i].sequence_number != txb->input[i].sequence_number) - return false; - } - - for (i = 0; i < txa->output_count; i++) { - if (txa->output[i].amount != txb->output[i].amount - || txa->output[i].script_length != txb->output[i].script_length - || memcmp(txa->output[i].script, txb->output[i].script, - txa->output[i].script_length != 0)) - return false; - } - - return true; + bitcoin_txid(tx, &tx_txid); + return structeq(txid, &tx_txid); } -/* We may have two possible "current" commits; this loop will check them both. */ -static bool is_unrevoked_commit(const struct commit_info *ci, - const struct bitcoin_tx *tx) +static struct commit_info *find_commit(struct commit_info *ci, + const struct sha256_double *txid) { - while (ci && !ci->revocation_preimage) { - if (txmatch(ci->tx, tx)) - return true; + while (ci) { + if (txidmatch(ci->tx, txid)) + return ci; ci = ci->prev; } - return false; + return NULL; } static bool is_mutual_close(const struct peer *peer, @@ -792,21 +773,30 @@ static void anchor_spent(struct peer *peer, { struct anchor_watch *w = peer->anchor.watches; union input idata; - + struct sha256_double txid; + assert(input_num < tx->input_count); /* We only ever sign single-input txs. */ if (input_num != 0) fatal("Anchor spend by non-single input tx"); - /* FIXME: change type in idata? */ - idata.btc = (struct bitcoin_event *)tx; - if (is_unrevoked_commit(peer->them.commit, tx)) - state_event(peer, w->theyspent, &idata); - else if (is_mutual_close(peer, tx)) + bitcoin_txid(tx, &txid); + + idata.ci = find_commit(peer->them.commit, &txid); + if (idata.ci) { + if (idata.ci->revocation_preimage) + state_event(peer, w->otherspent, &idata); + else { + idata.tx = idata.ci->tx; + state_event(peer, w->theyspent, &idata); + } + } else if (is_mutual_close(peer, tx)) { watch_tx(peer, peer, tx, close_depth_cb, NULL); - else - state_event(peer, w->otherspent, &idata); + } else { + if (!txidmatch(peer->us.commit->tx, &txid)) + fatal("Unknown tx spend!"); + } } static void anchor_timeout(struct anchor_watch *w) @@ -1224,7 +1214,7 @@ const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer) /* Create a bitcoin steal tx (to steal all their commit's outputs) */ const struct bitcoin_tx *bitcoin_steal(const struct peer *peer, - struct bitcoin_event *btc) + struct commit_info *ci) { FIXME_STUB(peer); } diff --git a/state.c b/state.c index bb7f4a503..5999cbfae 100644 --- a/state.c +++ b/state.c @@ -757,7 +757,7 @@ enum command_status state(struct peer *peer, return next_state_bits(peer, cstatus, bits); /* This can happen multiple times: need to steal ALL */ } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - tx = bitcoin_steal(peer, idata->btc); + tx = bitcoin_steal(peer, idata->ci); if (!tx) return next_state(peer, cstatus, STATE_ERR_INFORMATION_LEAK); @@ -953,7 +953,7 @@ old_commit_spotted: set_peer_cond(peer, PEER_CLOSED); /* If we can't find it, we're lost. */ - tx = bitcoin_steal(peer, idata->btc); + tx = bitcoin_steal(peer, idata->ci); if (!tx) return next_state(peer, cstatus, STATE_ERR_INFORMATION_LEAK); diff --git a/state.h b/state.h index 43e35a44f..bcdeb0269 100644 --- a/state.h +++ b/state.h @@ -30,9 +30,9 @@ static inline bool input_is_pkt(enum state_input input) union input { Pkt *pkt; struct command *cmd; - struct bitcoin_event *btc; struct bitcoin_tx *tx; struct htlc_progress *htlc_prog; + struct commit_info *ci; struct htlc_onchain { /* Which commitment we using. */ struct commit_info *ci; @@ -321,7 +321,7 @@ const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer); /* Create a bitcoin steal tx (to steal all their commit's outputs) */ const struct bitcoin_tx *bitcoin_steal(const struct peer *peer, - struct bitcoin_event *btc); + struct commit_info *ci); /* Create our commit tx */ const struct bitcoin_tx *bitcoin_commit(struct peer *peer);