From 5eb50345ae873166fdf97b2350934654d839abc5 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 4 May 2016 16:12:47 +0930 Subject: [PATCH] daemon: implement bitcoin_htlc_timeout() This is called when an HTLC times out, and we need to send it back to ourselves. We also adjust the locktime, since in practice we should refuse an HTLC less than our locktime. Signed-off-by: Rusty Russell --- daemon/peer.c | 67 ++++++++++++++++++++++++++++++++++++++++++++- daemon/secrets.c | 15 ++++++++++ daemon/secrets.h | 5 ++++ daemon/test/test.sh | 2 ++ 4 files changed, 88 insertions(+), 1 deletion(-) 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 <