diff --git a/onchaind/onchain.c b/onchaind/onchain.c index e0b2b8cab..618d05947 100644 --- a/onchaind/onchain.c +++ b/onchaind/onchain.c @@ -502,8 +502,55 @@ static void handle_htlc_onchain_fulfill(struct tracked_output *out, status_failed(STATUS_FAIL_INTERNAL_ERROR, "FIXME: %s", __func__); } +static void resolve_htlc_tx(struct tracked_output ***outs, + size_t out_index, + const struct bitcoin_tx *htlc_tx, + const struct sha256_double *htlc_txid, + u32 tx_blockheight) +{ + struct tracked_output *out; + struct bitcoin_tx *tx; + u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[LOCAL], + &keyset->self_revocation_key, + &keyset->self_delayed_payment_key); + + + /* BOLT #5: + * + * A node SHOULD resolve its own HTLC transaction output by spending + * it to a convenient address. A node MUST wait until the + * `OP_CHECKSEQUENCEVERIFY` delay has passed (as specified by the + * other node's `open_channel` `to_self_delay` field) before spending + * the output. + */ + out = new_tracked_output(outs, htlc_txid, tx_blockheight, + (*outs)[out_index]->resolved->tx_type, + 0, htlc_tx->output[0].amount, + DELAYED_OUTPUT_TO_US, + NULL, NULL, NULL); + + /* BOLT #3: + * + * ## HTLC-Timeout and HTLC-Success Transactions + * + * These HTLC transactions are almost identical, except the + * HTLC-Timeout transaction is timelocked. + * + * ... to collect the output the local node uses an input with + * nSequence `to_self_delay` and a witness stack ` + * 0` + */ + tx = tx_to_us(*outs, out, to_self_delay[LOCAL], 0, NULL, 0, + wscript, + &delayed_payment_privkey, + &keyset->self_delayed_payment_key); + + propose_resolution(out, tx, to_self_delay[LOCAL], + OUR_DELAYED_RETURN_TO_WALLET); +} + /* An output has been spent: see if it resolves something we care about. */ -static void output_spent(struct tracked_output **outs, +static void output_spent(struct tracked_output ***outs, const struct bitcoin_tx *tx, u32 input_num, u32 tx_blockheight) @@ -512,23 +559,30 @@ static void output_spent(struct tracked_output **outs, bitcoin_txid(tx, &txid); - for (size_t i = 0; i < tal_count(outs); i++) { - if (outs[i]->resolved) + for (size_t i = 0; i < tal_count(*outs); i++) { + struct tracked_output *out = (*outs)[i]; + if (out->resolved) continue; - if (tx->input[input_num].index != outs[i]->outnum) + if (tx->input[input_num].index != out->outnum) continue; - if (!structeq(&tx->input[input_num].txid, &outs[i]->txid)) + if (!structeq(&tx->input[input_num].txid, &out->txid)) continue; /* Was this our resolution? */ - if (resolved_by_proposal(outs[i], &txid)) + if (resolved_by_proposal(out, &txid)) { + /* If it's our htlc tx, we need to resolve that, too. */ + if (out->resolved->tx_type == OUR_HTLC_SUCCESS_TX + || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX) + resolve_htlc_tx(outs, i, tx, &txid, + tx_blockheight); return; + } - switch (outs[i]->output_type) { + switch (out->output_type) { case OUTPUT_TO_US: case DELAYED_OUTPUT_TO_US: - unknown_spend(outs[i], tx); + unknown_spend(out, tx); break; case THEIR_HTLC: @@ -538,7 +592,7 @@ static void output_spent(struct tracked_output **outs, case OUR_HTLC: /* The only way they can spend this: fulfill */ - handle_htlc_onchain_fulfill(outs[i], tx); + handle_htlc_onchain_fulfill(out, tx); break; case FUNDING_OUTPUT: @@ -552,8 +606,8 @@ static void output_spent(struct tracked_output **outs, case DELAYED_OUTPUT_TO_THEM: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Tracked spend of %s/%s?", - tx_type_name(outs[i]->tx_type), - output_type_name(outs[i]->output_type)); + tx_type_name(out->tx_type), + output_type_name(out->output_type)); } return; } @@ -703,7 +757,7 @@ static void wait_for_resolved(struct tracked_output **outs) tx_new_depth(outs, &txid, depth); else if (fromwire_onchain_spent(msg, NULL, tx, &input_num, &tx_blockheight)) - output_spent(outs, tx, input_num, tx_blockheight); + output_spent(&outs, tx, input_num, tx_blockheight); else if (fromwire_onchain_known_preimage(msg, NULL, &preimage)) handle_preimage(outs, &preimage); else @@ -1033,7 +1087,7 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx, * If the output is spent (as recommended), the output * is *resolved* by the spending transaction */ propose_resolution(out, to_us, to_self_delay[LOCAL], - OUR_UNILATERAL_TO_US_RETURN_TO_WALLET); + OUR_DELAYED_RETURN_TO_WALLET); script[LOCAL] = NULL; continue; diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 555f64d33..9bc33547f 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -26,8 +26,8 @@ enum tx_type { OUR_HTLC_TIMEOUT_TX, OUR_HTLC_SUCCESS_TX, - /* When we spend the to-us output (after cltv_expiry) */ - OUR_UNILATERAL_TO_US_RETURN_TO_WALLET, + /* When we spend a delayed output (after cltv_expiry) */ + OUR_DELAYED_RETURN_TO_WALLET, /* Special type for marking outputs as resolved by self. */ SELF, @@ -45,7 +45,7 @@ enum output_type { OUTPUT_TO_US, DELAYED_OUTPUT_TO_THEM, - /* OUR_UNILATERAL */ + /* OUR_UNILATERAL, or OUR_HTLC_TIMEOUT_TX */ DELAYED_OUTPUT_TO_US, OUTPUT_TO_THEM, diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index c1b9082b6..7f5743528 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -429,13 +429,13 @@ class LightningDTests(BaseLightningDTests): l1.daemon.wait_for_log('Their unilateral tx, old commit point') l1.daemon.wait_for_log('-> ONCHAIND_THEIR_UNILATERAL') l2.daemon.wait_for_log('-> ONCHAIND_OUR_UNILATERAL') - l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_UNILATERAL_TO_US_RETURN_TO_WALLET (.*) in 6 blocks') + l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET (.*) in 6 blocks') # Now, mine 6 blocks so it sends out the spending tx. bitcoind.rpc.generate(6) # It should send the to-wallet tx. - l2.daemon.wait_for_log('Broadcasting OUR_UNILATERAL_TO_US_RETURN_TO_WALLET') + l2.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET') l2.daemon.wait_for_log('sendrawtx exit 0') # 100 after l1 sees tx, it should be done. @@ -486,7 +486,7 @@ class LightningDTests(BaseLightningDTests): l1.daemon.wait_for_log('-> ONCHAIND_THEIR_UNILATERAL') l2.daemon.wait_for_log('OUR_UNILATERAL/THEIR_HTLC') - # l2 should fulfill HTLC onchain + # l2 should fulfill HTLC onchain, and spend to-us (any order) l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks') l2.daemon.wait_for_log('sendrawtx exit 0') @@ -495,9 +495,14 @@ class LightningDTests(BaseLightningDTests): l1.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill') l1.has_failed() - # After 5 more blocks, l2 can spend to-us - l1.bitcoin.rpc.generate(5) - l2.daemon.wait_for_log('Broadcasting OUR_UNILATERAL_TO_US_RETURN_TO_WALLET') + # After 4 more blocks, l2 can spend to-us. + l1.bitcoin.rpc.generate(4) + l2.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve OUR_UNILATERAL/DELAYED_OUTPUT_TO_US') + l2.daemon.wait_for_log('sendrawtx exit 0') + + # One more, HTLC tx is now spentable. + l1.bitcoin.rpc.generate(1) + l2.daemon.wait_for_log('Broadcasting OUR_DELAYED_RETURN_TO_WALLET .* to resolve OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US') l2.daemon.wait_for_log('sendrawtx exit 0') # 100 blocks after last spend, l2 should be done. @@ -575,6 +580,10 @@ class LightningDTests(BaseLightningDTests): bitcoind.rpc.generate(1) # l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US') l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks') + bitcoind.rpc.generate(1) + l2.daemon.wait_for_log('Propose handling OUR_HTLC_SUCCESS_TX/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* in 6 blocks') + bitcoind.rpc.generate(6) + l2.daemon.wait_for_log('sendrawtx exit 0') # FIXME: This doesn't work :( # FIXME: sendpay command should time out!