diff --git a/daemon/peer.c b/daemon/peer.c index d9dc5facc..91e72bf74 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -744,7 +744,8 @@ static void close_depth_cb(struct peer *peer, unsigned int depth, } } -static UNNEEDED struct channel_htlc *htlc_by_index(const struct commit_info *ci, size_t index) +static struct channel_htlc *htlc_by_index(const struct commit_info *ci, + size_t index) { if (ci->map[index] == -1) return NULL; @@ -769,6 +770,70 @@ static UNNEEDED bool htlc_a_offered(struct commit_info *ci, size_t index) return index < tal_count(ci->cstate->a.htlcs); } +/* Create a HTLC refund collection */ +static UNNEEDED const struct bitcoin_tx *htlc_timeout_tx(const struct peer *peer, + const struct commit_info *ci, + unsigned int i) +{ + u8 *wscript; + struct channel_htlc *htlc; + struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1); + struct bitcoin_signature sig; + u64 fee, satoshis; + + htlc = htlc_by_index(ci, i); + + wscript = bitcoin_redeem_htlc_send(peer, + &peer->us.finalkey, + &peer->them.finalkey, + &htlc->expiry, + &peer->them.locktime, + &ci->revocation_hash, + &htlc->rhash); + + /* We must set locktime so HTLC expiry can OP_CHECKLOCKTIMEVERIFY */ + tx->lock_time = htlc->expiry.locktime; + tx->input[0].index = 0; + bitcoin_txid(ci->tx, &tx->input[0].txid); + satoshis = htlc->msatoshis / 1000; + tx->input[0].amount = tal_dup(tx->input, u64, &satoshis); + tx->input[0].sequence_number = bitcoin_nsequence(&peer->them.locktime); + + /* Using a new output address here would be useless: they can tell + * it's our HTLC, and that we collected it via timeout. */ + tx->output[0].script = scriptpubkey_p2sh(tx, + bitcoin_redeem_single(tx, &peer->us.finalkey)); + tx->output[0].script_length = tal_count(tx->output[0].script); + + log_unusual(peer->log, "Pre-witness txlen = %zu\n", + measure_tx_cost(tx) / 4); + + assert(measure_tx_cost(tx) == 83 * 4); + + /* Witness length can vary, due to DER encoding of sigs, but we + * use 539 from an example run. */ + /* FIXME: Dynamic fees! */ + fee = fee_by_feerate(83 + 539 / 4, + peer->dstate->config.closing_fee_rate); + + /* FIXME: Fail gracefully in these cases (not worth collecting) */ + if (fee > satoshis || is_dust_amount(satoshis - fee)) + fatal("HTLC refund amount of %"PRIu64" won't cover fee %"PRIu64, + satoshis, fee); + + tx->output[0].amount = satoshis - fee; + + sig.stype = SIGHASH_ALL; + peer_sign_htlc_refund(peer, tx, wscript, &sig.sig); + + tx->input[0].witness = bitcoin_witness_htlc(tx, NULL, &sig, wscript); + + log_unusual(peer->log, "tx cost for htlc timeout tx: %zu", + measure_tx_cost(tx)); + + return tx; +} + /* We assume the tx is valid! Don't do a blockchain.info and feed this * invalid transactions! */ static void anchor_spent(struct peer *peer, diff --git a/daemon/secrets.c b/daemon/secrets.c index a18b2d76c..e1a6d33fa 100644 --- a/daemon/secrets.c +++ b/daemon/secrets.c @@ -84,6 +84,21 @@ void peer_sign_spend(const struct peer *peer, sig); } +void peer_sign_htlc_refund(const struct peer *peer, + struct bitcoin_tx *spend, + const u8 *htlc_witnessscript, + struct signature *sig) +{ + /* Spend tx only has one input: that of the commit tx. */ + sign_tx_input(peer->dstate->secpctx, + spend, 0, + NULL, 0, + htlc_witnessscript, + &peer->secrets->final, + &peer->us.finalkey, + sig); +} + void peer_sign_mutual_close(const struct peer *peer, struct bitcoin_tx *close, struct signature *sig) diff --git a/daemon/secrets.h b/daemon/secrets.h index 63234ae08..0bfe42987 100644 --- a/daemon/secrets.h +++ b/daemon/secrets.h @@ -25,6 +25,11 @@ void peer_sign_spend(const struct peer *peer, const u8 *commit_witnessscript, struct signature *sig); +void peer_sign_htlc_refund(const struct peer *peer, + struct bitcoin_tx *spend, + const u8 *htlc_witnessscript, + struct signature *sig); + void peer_sign_mutual_close(const struct peer *peer, struct bitcoin_tx *close, struct signature *sig); diff --git a/daemon/test/test.sh b/daemon/test/test.sh index fa9426a14..d73245c92 100755 --- a/daemon/test/test.sh +++ b/daemon/test/test.sh @@ -178,6 +178,7 @@ log-level=debug bitcoind-poll=1 min-expiry=900 bitcoin-datadir=$DATADIR +locktime=600 EOF cat > $DIR2/config <