Browse Source

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 <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
5eb50345ae
  1. 67
      daemon/peer.c
  2. 15
      daemon/secrets.c
  3. 5
      daemon/secrets.h
  4. 2
      daemon/test/test.sh

67
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,

15
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)

5
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);

2
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 <<EOF
@ -185,6 +186,7 @@ log-level=debug
bitcoind-poll=1
min-expiry=900
bitcoin-datadir=$DATADIR
locktime=600
EOF
if [ -n "$GDB1" ]; then

Loading…
Cancel
Save