diff --git a/bitcoin/script.c b/bitcoin/script.c index ca8c4ad5e..c682a64f9 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -606,7 +606,8 @@ u8 *bitcoin_wscript_htlc_offer_ripemd160(const tal_t *ctx, const struct pubkey *remotehtlckey, const struct ripemd160 *payment_ripemd, const struct pubkey *revocationkey, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { u8 *script = tal_arr(ctx, u8, 0); struct ripemd160 ripemd; @@ -638,7 +639,7 @@ u8 *bitcoin_wscript_htlc_offer_ripemd160(const tal_t *ctx, add_op(&script, OP_EQUALVERIFY); add_op(&script, OP_CHECKSIG); add_op(&script, OP_ENDIF); - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { add_number(&script, 1); add_op(&script, OP_CHECKSEQUENCEVERIFY); add_op(&script, OP_DROP); @@ -653,7 +654,8 @@ u8 *bitcoin_wscript_htlc_offer(const tal_t *ctx, const struct pubkey *remotehtlckey, const struct sha256 *payment_hash, const struct pubkey *revocationkey, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct ripemd160 ripemd; @@ -661,7 +663,8 @@ u8 *bitcoin_wscript_htlc_offer(const tal_t *ctx, return bitcoin_wscript_htlc_offer_ripemd160(ctx, localhtlckey, remotehtlckey, &ripemd, revocationkey, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } /* BOLT #3: @@ -717,7 +720,8 @@ u8 *bitcoin_wscript_htlc_receive_ripemd(const tal_t *ctx, const struct pubkey *remotehtlckey, const struct ripemd160 *payment_ripemd, const struct pubkey *revocationkey, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { u8 *script = tal_arr(ctx, u8, 0); struct ripemd160 ripemd; @@ -752,7 +756,7 @@ u8 *bitcoin_wscript_htlc_receive_ripemd(const tal_t *ctx, add_op(&script, OP_DROP); add_op(&script, OP_CHECKSIG); add_op(&script, OP_ENDIF); - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { add_number(&script, 1); add_op(&script, OP_CHECKSEQUENCEVERIFY); add_op(&script, OP_DROP); @@ -768,7 +772,8 @@ u8 *bitcoin_wscript_htlc_receive(const tal_t *ctx, const struct pubkey *remotehtlckey, const struct sha256 *payment_hash, const struct pubkey *revocationkey, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct ripemd160 ripemd; @@ -776,7 +781,8 @@ u8 *bitcoin_wscript_htlc_receive(const tal_t *ctx, return bitcoin_wscript_htlc_receive_ripemd(ctx, htlc_abstimeout, localhtlckey, remotehtlckey, &ripemd, revocationkey, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } /* BOLT #3: diff --git a/bitcoin/script.h b/bitcoin/script.h index 1ef219c67..04c289b74 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -98,7 +98,8 @@ u8 *bitcoin_wscript_htlc_offer(const tal_t *ctx, const struct pubkey *remotehtlckey, const struct sha256 *payment_hash, const struct pubkey *revocationkey, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); u8 **bitcoin_witness_htlc_timeout_tx(const tal_t *ctx, const struct bitcoin_signature *localsig, const struct bitcoin_signature *remotesig, @@ -109,7 +110,8 @@ u8 *bitcoin_wscript_htlc_receive(const tal_t *ctx, const struct pubkey *remotekey, const struct sha256 *payment_hash, const struct pubkey *revocationkey, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); u8 **bitcoin_witness_htlc_success_tx(const tal_t *ctx, const struct bitcoin_signature *localsig, const struct bitcoin_signature *remotesig, @@ -122,14 +124,16 @@ u8 *bitcoin_wscript_htlc_offer_ripemd160(const tal_t *ctx, const struct pubkey *remotehtlckey, const struct ripemd160 *payment_ripemd, const struct pubkey *revocationkey, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); u8 *bitcoin_wscript_htlc_receive_ripemd(const tal_t *ctx, const struct abs_locktime *htlc_abstimeout, const struct pubkey *localkey, const struct pubkey *remotekey, const struct ripemd160 *payment_ripemd, const struct pubkey *revocationkey, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* BOLT #3 HTLC-success/HTLC-timeout output */ u8 *bitcoin_wscript_htlc_tx(const tal_t *ctx, diff --git a/channeld/channeld.c b/channeld/channeld.c index 04e33fc2f..c48d1ea6f 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1070,9 +1070,8 @@ static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx, wscript = bitcoin_tx_output_get_witscript(tmpctx, txs[0], txs[i+1]->wtx->inputs[0].index); msg = towire_hsmd_sign_remote_htlc_tx(NULL, txs[i + 1], wscript, - &peer->remote_per_commit, - channel_has(peer->channel, - OPT_ANCHOR_OUTPUTS)); + &peer->remote_per_commit, + channel_has_anchors(peer->channel)); msg = hsm_req(tmpctx, take(msg)); if (!fromwire_hsmd_sign_tx_reply(msg, &htlc_sigs[i])) @@ -1599,7 +1598,7 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) /* SIGHASH_ALL is implied. */ commit_sig.sighash_type = SIGHASH_ALL; htlc_sigs = unraw_sigs(tmpctx, raw_sigs, - channel_has(peer->channel, OPT_ANCHOR_OUTPUTS)); + channel_has_anchors(peer->channel)); txs = channel_txs(tmpctx, &htlc_map, NULL, @@ -3759,9 +3758,12 @@ static void init_channel(struct peer *peer) peer->dev_fast_gossip = dev_fast_gossip; #endif - status_debug("option_static_remotekey = %u, option_anchor_outputs = %u", + status_debug("option_static_remotekey = %u," + " option_anchor_outputs = %u" + " option_anchors_zero_fee_htlc_tx = %u", channel_type_has(channel_type, OPT_STATIC_REMOTEKEY), - channel_type_has(channel_type, OPT_ANCHOR_OUTPUTS)); + channel_type_has(channel_type, OPT_ANCHOR_OUTPUTS), + channel_type_has(channel_type, OPT_ANCHORS_ZERO_FEE_HTLC_TX)); /* Keeping an array of pointers is better since it allows us to avoid * extra allocations later. */ diff --git a/channeld/commit_tx.c b/channeld/commit_tx.c index 30f946de7..48ce7427e 100644 --- a/channeld/commit_tx.c +++ b/channeld/commit_tx.c @@ -14,24 +14,29 @@ static bool trim(const struct htlc *htlc, u32 feerate_per_kw, struct amount_sat dust_limit, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, enum side side) { return htlc_is_trimmed(htlc_owner(htlc), htlc->amount, feerate_per_kw, dust_limit, side, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } size_t commit_tx_num_untrimmed(const struct htlc **htlcs, u32 feerate_per_kw, struct amount_sat dust_limit, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, enum side side) { size_t i, n; for (i = n = 0; i < tal_count(htlcs); i++) n += !trim(htlcs[i], feerate_per_kw, dust_limit, - option_anchor_outputs, side); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, + side); return n; } @@ -40,14 +45,17 @@ bool commit_tx_amount_trimmed(const struct htlc **htlcs, u32 feerate_per_kw, struct amount_sat dust_limit, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, enum side side, struct amount_msat *amt) { for (size_t i = 0; i < tal_count(htlcs); i++) { if (trim(htlcs[i], feerate_per_kw, dust_limit, - option_anchor_outputs, side)) + option_anchor_outputs, option_anchors_zero_fee_htlc_tx, + side)) { if (!amount_msat_add(amt, *amt, htlcs[i]->amount)) return false; + } } return true; } @@ -55,7 +63,8 @@ bool commit_tx_amount_trimmed(const struct htlc **htlcs, static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n, const struct htlc *htlc, const struct keyset *keyset, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct ripemd160 ripemd; u8 *wscript, *p2wsh; @@ -63,7 +72,8 @@ static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n, ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); wscript = htlc_offered_wscript(tx, &ripemd, keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); p2wsh = scriptpubkey_p2wsh(tx, wscript); bitcoin_tx_add_output(tx, p2wsh, wscript, amount); SUPERVERBOSE("# HTLC #%" PRIu64 " offered amount %"PRIu64" wscript %s\n", htlc->id, @@ -75,7 +85,8 @@ static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n, static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n, const struct htlc *htlc, const struct keyset *keyset, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct ripemd160 ripemd; u8 *wscript, *p2wsh; @@ -83,7 +94,8 @@ static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n, ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); wscript = htlc_received_wscript(tx, &ripemd, &htlc->expiry, keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); p2wsh = scriptpubkey_p2wsh(tx, wscript); amount = amount_msat_to_sat_round_down(htlc->amount); @@ -115,6 +127,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES], u64 obscured_commitment_number, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, enum side side) { struct amount_sat base_fee; @@ -146,6 +159,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, feerate_per_kw, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, side); /* BOLT #3: @@ -154,7 +168,8 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, * fee](#fee-calculation). */ base_fee = commit_tx_base_fee(feerate_per_kw, untrimmed, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); SUPERVERBOSE("# base commitment transaction fee = %"PRIu64" for %zu untrimmed\n", base_fee.satoshis /* Raw: spec uses raw numbers */, untrimmed); @@ -165,7 +180,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, * of 330 sats from the funder (either `to_local` or * `to_remote`). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660))) /* Can't overflow: feerate is u32. */ abort(); @@ -183,7 +198,9 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, bool ok = true; for (size_t i = 0; i < tal_count(htlcs); i++) { if (!trim(htlcs[i], feerate_per_kw, dust_limit, - option_anchor_outputs, side)) + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, + side)) ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(htlcs[i]->amount)); } if (amount_msat_greater_eq_sat(self_pay, dust_limit)) @@ -219,10 +236,12 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, if (htlc_owner(htlcs[i]) != side) continue; if (trim(htlcs[i], feerate_per_kw, dust_limit, - option_anchor_outputs, side)) + option_anchor_outputs, option_anchors_zero_fee_htlc_tx, + side)) continue; add_offered_htlc_out(tx, n, htlcs[i], keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); (*htlcmap)[n] = htlcs[i]; cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry); n++; @@ -237,10 +256,12 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, if (htlc_owner(htlcs[i]) == side) continue; if (trim(htlcs[i], feerate_per_kw, dust_limit, - option_anchor_outputs, side)) + option_anchor_outputs, option_anchors_zero_fee_htlc_tx, + side)) continue; add_received_htlc_out(tx, n, htlcs[i], keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); (*htlcmap)[n] = htlcs[i]; cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry); n++; @@ -303,7 +324,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, *... * Otherwise, this output is a simple P2WPKH to `remotepubkey`. */ - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { redeem = bitcoin_wscript_to_remote_anchored(tmpctx, &keyset->other_payment_key, (!side) == lessor ? @@ -351,7 +372,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, * * if `to_remote` exists or there are untrimmed HTLCs, add a * [`to_remote_anchor` output] */ - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { if (to_local || untrimmed != 0) { tx_add_anchor_output(tx, local_funding_key); (*htlcmap)[n] = NULL; diff --git a/channeld/commit_tx.h b/channeld/commit_tx.h index fc2db029d..23eacdf54 100644 --- a/channeld/commit_tx.h +++ b/channeld/commit_tx.h @@ -14,6 +14,7 @@ struct keyset; * @option_anchor_outputs: does option_anchor_outputs apply to this channel? * @side: from which side's point of view * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * @option_anchors_zero_fee_htlc_tx: does option_anchors_zero_fee_htlc_tx apply to this channel? * * We need @side because HTLC fees are different for offered and * received HTLCs. @@ -21,6 +22,7 @@ struct keyset; size_t commit_tx_num_untrimmed(const struct htlc **htlcs, u32 feerate_per_kw, struct amount_sat dust_limit, + bool option_anchors_zero_fee_htlc_tx, bool option_anchor_outputs, enum side side); @@ -42,6 +44,7 @@ bool commit_tx_amount_trimmed(const struct htlc **htlcs, u32 feerate_per_kw, struct amount_sat dust_limit, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, enum side side, struct amount_msat *amt); /** @@ -86,6 +89,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES], u64 obscured_commitment_number, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, enum side side); #endif /* LIGHTNING_CHANNELD_COMMIT_TX_H */ diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 02ba567f6..0e56ede20 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -243,8 +243,14 @@ static void add_htlcs(struct bitcoin_tx ***txs, enum side side) { struct bitcoin_outpoint outpoint; - u32 feerate_per_kw = channel_feerate(channel, side); + u32 htlc_feerate_per_kw; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); + + if (channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX)) + htlc_feerate_per_kw = 0; + else + htlc_feerate_per_kw = channel_feerate(channel, side); /* Get txid of commitment transaction */ bitcoin_txid((*txs)[0], &outpoint.txid); @@ -261,27 +267,31 @@ static void add_htlcs(struct bitcoin_tx ***txs, if (htlc_owner(htlc) == side) { ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); wscript = htlc_offered_wscript(tmpctx, &ripemd, keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); tx = htlc_timeout_tx(*txs, chainparams, &outpoint, wscript, htlc->amount, htlc->expiry.locktime, channel->config[!side].to_self_delay, - feerate_per_kw, + htlc_feerate_per_kw, keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } else { ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); wscript = htlc_received_wscript(tmpctx, &ripemd, &htlc->expiry, keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); tx = htlc_success_tx(*txs, chainparams, &outpoint, wscript, htlc->amount, channel->config[!side].to_self_delay, - feerate_per_kw, + htlc_feerate_per_kw, keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } /* Append to array. */ @@ -334,6 +344,7 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, channel->view[side].owed[!side], committed, htlcmap, direct_outputs, commitment_number ^ channel->commitment_number_obscurer, channel_has(channel, OPT_ANCHOR_OUTPUTS), + channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX), side); /* Set the remote/local pubkeys on the commitment tx psbt */ @@ -392,17 +403,24 @@ static bool get_room_above_reserve(const struct channel *channel, static size_t num_untrimmed_htlcs(enum side side, struct amount_sat dust_limit, u32 feerate, - bool option_static_remotekey, + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, const struct htlc **committed, const struct htlc **adding, const struct htlc **removing) { return commit_tx_num_untrimmed(committed, feerate, dust_limit, - option_static_remotekey, side) + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, + side) + commit_tx_num_untrimmed(adding, feerate, dust_limit, - option_static_remotekey, side) + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, + side) - commit_tx_num_untrimmed(removing, feerate, dust_limit, - option_static_remotekey, side); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, + side); } static struct amount_sat fee_for_htlcs(const struct channel *channel, @@ -415,12 +433,16 @@ static struct amount_sat fee_for_htlcs(const struct channel *channel, struct amount_sat dust_limit = channel->config[side].dust_limit; size_t untrimmed; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); untrimmed = num_untrimmed_htlcs(side, dust_limit, feerate, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, committed, adding, removing); - return commit_tx_base_fee(feerate, untrimmed, option_anchor_outputs); + return commit_tx_base_fee(feerate, untrimmed, + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } static bool htlc_dust(const struct channel *channel, @@ -433,21 +455,25 @@ static bool htlc_dust(const struct channel *channel, { struct amount_sat dust_limit = channel->config[side].dust_limit; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); struct amount_msat trim_rmvd = AMOUNT_MSAT(0); if (!commit_tx_amount_trimmed(committed, feerate, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, side, trim_total)) return false; if (!commit_tx_amount_trimmed(adding, feerate, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, side, trim_total)) return false; if (!commit_tx_amount_trimmed(removing, feerate, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, side, &trim_rmvd)) return false; @@ -489,6 +515,7 @@ static bool local_opener_has_fee_headroom(const struct channel *channel, size_t untrimmed; struct amount_sat fee; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); assert(channel->opener == LOCAL); @@ -497,12 +524,14 @@ static bool local_opener_has_fee_headroom(const struct channel *channel, untrimmed = num_untrimmed_htlcs(LOCAL, channel->config[LOCAL].dust_limit, feerate, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, committed, adding, removing); /* Now, how much would it cost us if feerate increases 100% and we added * another HTLC? */ fee = commit_tx_base_fee(2 * feerate, untrimmed + 1, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); if (amount_msat_greater_eq_sat(remainder, fee)) return true; @@ -535,6 +564,7 @@ static enum channel_add_err add_htlc(struct channel *channel, const struct channel_view *view; size_t htlc_count; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); u32 feerate, feerate_ceil; htlc = tal(tmpctx, struct htlc); @@ -704,7 +734,7 @@ static enum channel_add_err add_htlc(struct channel *channel, * of 330 sats from the funder (either `to_local` or * `to_remote`). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && channel->opener == sender && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660))) return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; @@ -738,7 +768,7 @@ static enum channel_add_err add_htlc(struct channel *channel, &remainder)) return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && channel->opener != sender && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660))) return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; @@ -1167,6 +1197,7 @@ u32 approx_max_feerate(const struct channel *channel) struct amount_sat avail; const struct htlc **committed, **adding, **removing; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); gather_htlcs(tmpctx, channel, !channel->opener, &committed, &removing, &adding); @@ -1174,7 +1205,7 @@ u32 approx_max_feerate(const struct channel *channel) /* Assume none are trimmed; this gives lower bound on feerate. */ num = tal_count(committed) + tal_count(adding) - tal_count(removing); - weight = commit_tx_base_weight(num, option_anchor_outputs); + weight = commit_tx_base_weight(num, option_anchor_outputs, option_anchors_zero_fee_htlc_tx); /* Available is their view */ avail = amount_msat_to_sat_round_down(channel->view[!channel->opener].owed[channel->opener]); @@ -1185,7 +1216,7 @@ u32 approx_max_feerate(const struct channel *channel) * of 330 sats from the funder (either `to_local` or * `to_remote`). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && !amount_sat_sub(&avail, avail, AMOUNT_SAT(660))) { avail = AMOUNT_SAT(0); } else { @@ -1236,22 +1267,27 @@ bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw size_t untrimmed; const struct htlc **committed, **adding, **removing; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); gather_htlcs(tmpctx, channel, !channel->opener, &committed, &removing, &adding); untrimmed = commit_tx_num_untrimmed(committed, feerate_per_kw, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, !channel->opener) + commit_tx_num_untrimmed(adding, feerate_per_kw, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, !channel->opener) - commit_tx_num_untrimmed(removing, feerate_per_kw, dust_limit, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, !channel->opener); fee = commit_tx_base_fee(feerate_per_kw, untrimmed, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); /* BOLT #3: * If `option_anchors` applies to the commitment @@ -1259,7 +1295,7 @@ bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw * of 330 sats from the funder (either `to_local` or * `to_remote`). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && !amount_sat_add(&fee, fee, AMOUNT_SAT(660))) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Cannot add 660 sats to %s for anchor", diff --git a/channeld/test/run-commit_tx.c b/channeld/test/run-commit_tx.c index d1eb57212..68983d220 100644 --- a/channeld/test/run-commit_tx.c +++ b/channeld/test/run-commit_tx.c @@ -245,7 +245,8 @@ static void report_htlcs(const struct bitcoin_tx *tx, const struct pubkey *remote_htlckey, const struct pubkey *remote_revocation_key, u32 feerate_per_kw, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { size_t i, n; struct bitcoin_outpoint outpoint; @@ -291,14 +292,17 @@ static void report_htlcs(const struct bitcoin_tx *tx, remote_htlckey, &htlc->rhash, remote_revocation_key, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); htlc_tx[i] = htlc_timeout_tx(htlc_tx, tx->chainparams, &outpoint, wscript[i], htlc->amount, htlc->expiry.locktime, to_self_delay, feerate_per_kw, - &keyset, option_anchor_outputs); + &keyset, + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } else { wscript[i] = bitcoin_wscript_htlc_receive(tmpctx, &htlc->expiry, @@ -306,14 +310,16 @@ static void report_htlcs(const struct bitcoin_tx *tx, remote_htlckey, &htlc->rhash, remote_revocation_key, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); htlc_tx[i] = htlc_success_tx(htlc_tx, tx->chainparams, &outpoint, wscript[i], htlc->amount, to_self_delay, feerate_per_kw, &keyset, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } sign_tx_input(htlc_tx[i], 0, NULL, @@ -344,7 +350,8 @@ static void report_htlcs(const struct bitcoin_tx *tx, remote_revocation_key, &localhtlcsig, &remotehtlcsig[i], - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } else { htlc_success_tx_add_witness(htlc_tx[i], &htlc->expiry, @@ -354,7 +361,8 @@ static void report_htlcs(const struct bitcoin_tx *tx, &remotehtlcsig[i], htlc->r, remote_revocation_key, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } printf("htlc_%s_tx (htlc #%"PRIu64"): %s\n", htlc_owner(htlc) == LOCAL ? "timeout" : "success", @@ -380,6 +388,7 @@ static void report(struct bitcoin_tx *tx, const struct pubkey *remote_revocation_key, u32 feerate_per_kw, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, const struct htlc **htlc_map, size_t total_htlcs) { @@ -425,7 +434,8 @@ static void report(struct bitcoin_tx *tx, remotekey, remote_htlckey, remote_revocation_key, feerate_per_kw, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } #ifdef DEBUG @@ -530,6 +540,7 @@ int main(int argc, const char *argv[]) struct amount_msat to_local, to_remote; const struct htlc **htlcs, **htlc_map, **htlc_map2, **inv_htlcs; bool option_anchor_outputs = false; + bool option_anchors_zero_fee_htlc_tx = false; bool option_static_remotekey = false; /* Allow us to check static-remotekey BOLT 3 vectors, too */ @@ -814,6 +825,7 @@ int main(int argc, const char *argv[]) to_remote, NULL, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); print_superverbose = false; tx2 = commit_tx(tmpctx, @@ -830,6 +842,7 @@ int main(int argc, const char *argv[]) to_remote, NULL, &htlc_map2, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, REMOTE); tx_must_be_eq(tx, tx2); report(tx, wscript, &x_remote_funding_privkey, &remote_funding_pubkey, @@ -845,6 +858,7 @@ int main(int argc, const char *argv[]) &remote_revocation_key, feerate_per_kw, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, htlc_map, 0); @@ -880,6 +894,7 @@ int main(int argc, const char *argv[]) to_remote, htlcs, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); print_superverbose = false; tx2 = commit_tx(tmpctx, @@ -897,6 +912,7 @@ int main(int argc, const char *argv[]) inv_htlcs, &htlc_map2, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, REMOTE); tx_must_be_eq(tx, tx2); report(tx, wscript, &x_remote_funding_privkey, &remote_funding_pubkey, @@ -912,6 +928,7 @@ int main(int argc, const char *argv[]) &remote_revocation_key, feerate_per_kw, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, htlc_map, tal_count(htlcs)); @@ -935,6 +952,7 @@ int main(int argc, const char *argv[]) htlcs, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); /* This is what it would look like for peer generating it! */ tx2 = commit_tx(tmpctx, @@ -952,6 +970,7 @@ int main(int argc, const char *argv[]) inv_htlcs, &htlc_map2, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, REMOTE); tx_must_be_eq(newtx, tx2); #ifdef DEBUG @@ -995,6 +1014,7 @@ int main(int argc, const char *argv[]) htlcs, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); report(tx, wscript, &x_remote_funding_privkey, &remote_funding_pubkey, @@ -1010,6 +1030,7 @@ int main(int argc, const char *argv[]) &remote_revocation_key, feerate_per_kw-1, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, htlc_map, tal_count(htlcs)); @@ -1045,6 +1066,7 @@ int main(int argc, const char *argv[]) htlcs, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); report(newtx, wscript, &x_remote_funding_privkey, &remote_funding_pubkey, @@ -1060,6 +1082,7 @@ int main(int argc, const char *argv[]) &remote_revocation_key, feerate_per_kw, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, htlc_map, tal_count(htlcs)); @@ -1074,7 +1097,8 @@ int main(int argc, const char *argv[]) for (;;) { struct amount_sat base_fee = commit_tx_base_fee(feerate_per_kw, 0, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); /* BOLT #3: * If `option_anchors` applies to the commitment @@ -1082,7 +1106,7 @@ int main(int argc, const char *argv[]) * of 330 sats from the funder (either `to_local` or * `to_remote`). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660))) abort(); @@ -1121,6 +1145,7 @@ int main(int argc, const char *argv[]) htlcs, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); report(tx, wscript, &x_remote_funding_privkey, &remote_funding_pubkey, @@ -1136,6 +1161,7 @@ int main(int argc, const char *argv[]) &remote_revocation_key, feerate_per_kw, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, htlc_map, tal_count(htlcs)); break; @@ -1176,6 +1202,7 @@ int main(int argc, const char *argv[]) to_remote, htlcs, &htlc_map, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, LOCAL); print_superverbose = false; tx2 = commit_tx(tmpctx, @@ -1193,6 +1220,7 @@ int main(int argc, const char *argv[]) inv_htlcs, &htlc_map2, NULL, commitment_number ^ cn_obscurer, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, REMOTE); tx_must_be_eq(tx, tx2); report(tx, wscript, &x_remote_funding_privkey, &remote_funding_pubkey, @@ -1208,6 +1236,7 @@ int main(int argc, const char *argv[]) &remote_revocation_key, feerate_per_kw, option_anchor_outputs, + option_anchors_zero_fee_htlc_tx, htlc_map, tal_count(htlcs)); common_shutdown(); diff --git a/channeld/test/run-full_channel.c b/channeld/test/run-full_channel.c index 395eb43b4..3c42a3a9d 100644 --- a/channeld/test/run-full_channel.c +++ b/channeld/test/run-full_channel.c @@ -362,6 +362,7 @@ int main(int argc, const char *argv[]) const struct htlc **htlc_map, **htlcs; const u8 *funding_wscript, *funding_wscript_alt; bool option_anchor_outputs = false; + bool option_anchors_zero_fee_htlc_tx = false; u32 blockheight = 0; size_t i; @@ -534,7 +535,7 @@ int main(int argc, const char *argv[]) to_local, to_remote, NULL, &htlc_map, NULL, 0x2bb038521914 ^ 42, - option_anchor_outputs, LOCAL); + option_anchor_outputs, option_anchors_zero_fee_htlc_tx, LOCAL); txs = channel_txs(tmpctx, &htlc_map, NULL, &funding_wscript_alt, @@ -662,7 +663,7 @@ int main(int argc, const char *argv[]) &keyset, feerate_per_kw[LOCAL], local_config->dust_limit, to_local, to_remote, htlcs, &htlc_map, NULL, 0x2bb038521914 ^ 42, - option_anchor_outputs, LOCAL); + option_anchor_outputs, option_anchors_zero_fee_htlc_tx, LOCAL); txs = channel_txs(tmpctx, &htlc_map, NULL, &funding_wscript, lchannel, &local_per_commitment_point, 42, diff --git a/common/htlc_trim.c b/common/htlc_trim.c index 711f9ec7d..8f8fabfcc 100644 --- a/common/htlc_trim.c +++ b/common/htlc_trim.c @@ -8,7 +8,8 @@ bool htlc_is_trimmed(enum side htlc_owner, u32 feerate_per_kw, struct amount_sat dust_limit, enum side side, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct amount_sat htlc_fee, htlc_min; @@ -24,7 +25,8 @@ bool htlc_is_trimmed(enum side htlc_owner, */ if (htlc_owner == side) htlc_fee = htlc_timeout_fee(feerate_per_kw, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); /* BOLT #3: * * - for every received HTLC: @@ -36,7 +38,8 @@ bool htlc_is_trimmed(enum side htlc_owner, */ else htlc_fee = htlc_success_fee(feerate_per_kw, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); /* If these overflow, it implies htlc must be less. */ if (!amount_sat_add(&htlc_min, dust_limit, htlc_fee)) diff --git a/common/htlc_trim.h b/common/htlc_trim.h index 0044de45c..777f632a3 100644 --- a/common/htlc_trim.h +++ b/common/htlc_trim.h @@ -10,7 +10,8 @@ bool htlc_is_trimmed(enum side htlc_owner, u32 feerate_per_kw, struct amount_sat dust_limit, enum side side, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Calculate the our htlc-trimming buffer feerate * (max(25%, 10s/vbyte) above feerate_per_kw) */ diff --git a/common/htlc_tx.c b/common/htlc_tx.c index 7427b2e15..798cbb381 100644 --- a/common/htlc_tx.c +++ b/common/htlc_tx.c @@ -13,7 +13,8 @@ struct bitcoin_tx *htlc_tx(const tal_t *ctx, const u8 *htlc_tx_wscript, struct amount_sat htlc_fee, u32 locktime, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { /* BOLT #3: * * locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout @@ -43,7 +44,7 @@ struct bitcoin_tx *htlc_tx(const tal_t *ctx, * * `txin[0]` sequence: `0` (set to `1` for `option_anchors`) */ bitcoin_tx_add_input(tx, commit, - option_anchor_outputs ? 1 : 0, + (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) ? 1 : 0, NULL, amount, NULL, commit_wscript); /* BOLT #3: @@ -54,6 +55,7 @@ struct bitcoin_tx *htlc_tx(const tal_t *ctx, * * `txout[0]` script: version-0 P2WSH with witness script as shown * below */ + /* Note: for option_anchors_zero_fee_htlc_tx, htlc_fee is 0 */ if (!amount_sat_sub(&amount, amount, htlc_fee)) return tal_free(tx); @@ -74,7 +76,8 @@ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx, u16 to_self_delay, u32 feerate_per_kw, const struct keyset *keyset, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { const u8 *htlc_wscript; @@ -90,9 +93,11 @@ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx, amount_msat_to_sat_round_down(htlc_msatoshi), htlc_wscript, htlc_success_fee(feerate_per_kw, - option_anchor_outputs), + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx), 0, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } /* Fill in the witness for HTLC-success tx produced above. */ @@ -104,7 +109,8 @@ void htlc_success_tx_add_witness(struct bitcoin_tx *htlc_success, const struct bitcoin_signature *remotehtlcsig, const struct preimage *payment_preimage, const struct pubkey *revocationkey, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct sha256 hash; u8 *wscript, **witness; @@ -114,7 +120,8 @@ void htlc_success_tx_add_witness(struct bitcoin_tx *htlc_success, htlc_abstimeout, localhtlckey, remotehtlckey, &hash, revocationkey, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); witness = bitcoin_witness_htlc_success_tx(htlc_success, localhtlcsig, remotehtlcsig, @@ -132,7 +139,8 @@ struct bitcoin_tx *htlc_timeout_tx(const tal_t *ctx, u16 to_self_delay, u32 feerate_per_kw, const struct keyset *keyset, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { const u8 *htlc_wscript; @@ -148,9 +156,11 @@ struct bitcoin_tx *htlc_timeout_tx(const tal_t *ctx, amount_msat_to_sat_round_down(htlc_msatoshi), htlc_wscript, htlc_timeout_fee(feerate_per_kw, - option_anchor_outputs), + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx), cltv_expiry, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } /* Fill in the witness for HTLC-timeout tx produced above. */ @@ -161,13 +171,15 @@ void htlc_timeout_tx_add_witness(struct bitcoin_tx *htlc_timeout, const struct pubkey *revocationkey, const struct bitcoin_signature *localhtlcsig, const struct bitcoin_signature *remotehtlcsig, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { u8 **witness; u8 *wscript = bitcoin_wscript_htlc_offer(htlc_timeout, localhtlckey, remotehtlckey, payment_hash, revocationkey, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); witness = bitcoin_witness_htlc_timeout_tx(htlc_timeout, localhtlcsig, remotehtlcsig, wscript); @@ -178,21 +190,24 @@ void htlc_timeout_tx_add_witness(struct bitcoin_tx *htlc_timeout, u8 *htlc_offered_wscript(const tal_t *ctx, const struct ripemd160 *ripemd, const struct keyset *keyset, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { return bitcoin_wscript_htlc_offer_ripemd160(ctx, &keyset->self_htlc_key, &keyset->other_htlc_key, ripemd, &keyset->self_revocation_key, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } u8 *htlc_received_wscript(const tal_t *ctx, const struct ripemd160 *ripemd, const struct abs_locktime *expiry, const struct keyset *keyset, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { return bitcoin_wscript_htlc_receive_ripemd(ctx, expiry, @@ -200,5 +215,6 @@ u8 *htlc_received_wscript(const tal_t *ctx, &keyset->other_htlc_key, ripemd, &keyset->self_revocation_key, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } diff --git a/common/htlc_tx.h b/common/htlc_tx.h index f58608376..67c7f42ad 100644 --- a/common/htlc_tx.h +++ b/common/htlc_tx.h @@ -14,17 +14,23 @@ struct pubkey; struct ripemd160; static inline struct amount_sat htlc_timeout_fee(u32 feerate_per_kw, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { /* BOLT #3: * * The fee for an HTLC-timeout transaction: - *... + * - If `option_anchors_zero_fee_htlc_tx` applies: + * 1. MUST be 0. * - Otherwise, MUST be calculated to match: * 1. Multiply `feerate_per_kw` by 663 (666 if `option_anchor_outputs` * applies) and divide by 1000 (rounding down). */ u32 base; + + if (option_anchors_zero_fee_htlc_tx) + return AMOUNT_SAT(0); + if (option_anchor_outputs) base = 666; else @@ -34,17 +40,23 @@ static inline struct amount_sat htlc_timeout_fee(u32 feerate_per_kw, } static inline struct amount_sat htlc_success_fee(u32 feerate_per_kw, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { /* BOLT #3: * * The fee for an HTLC-success transaction: - *... + * - If `option_anchors_zero_fee_htlc_tx` applies: + * 1. MUST be 0. * - Otherwise, MUST be calculated to match: * 1. Multiply `feerate_per_kw` by 703 (706 if `option_anchor_outputs` * applies) and divide by 1000 (rounding down). */ u32 base; + + if (option_anchors_zero_fee_htlc_tx) + return AMOUNT_SAT(0); + if (option_anchor_outputs) base = 706; else @@ -63,7 +75,8 @@ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx, u16 to_self_delay, u32 feerate_per_kw, const struct keyset *keyset, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Fill in the witness for HTLC-success tx produced above. */ void htlc_success_tx_add_witness(struct bitcoin_tx *htlc_success, @@ -74,7 +87,8 @@ void htlc_success_tx_add_witness(struct bitcoin_tx *htlc_success, const struct bitcoin_signature *remotesig, const struct preimage *payment_preimage, const struct pubkey *revocationkey, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Create HTLC-timeout tx to spend an offered HTLC commitment tx * output; doesn't fill in input witness. */ @@ -87,7 +101,8 @@ struct bitcoin_tx *htlc_timeout_tx(const tal_t *ctx, u16 to_self_delay, u32 feerate_per_kw, const struct keyset *keyset, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Fill in the witness for HTLC-timeout tx produced above. */ void htlc_timeout_tx_add_witness(struct bitcoin_tx *htlc_timeout, @@ -97,8 +112,8 @@ void htlc_timeout_tx_add_witness(struct bitcoin_tx *htlc_timeout, const struct pubkey *revocationkey, const struct bitcoin_signature *localsig, const struct bitcoin_signature *remotesig, - bool option_anchor_outputs); - + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Generate the witness script for an HTLC the other side offered: * scriptpubkey_p2wsh(ctx, wscript) gives the scriptpubkey */ @@ -106,14 +121,16 @@ u8 *htlc_received_wscript(const tal_t *ctx, const struct ripemd160 *ripemd, const struct abs_locktime *expiry, const struct keyset *keyset, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Generate the witness script for an HTLC this side offered: * scriptpubkey_p2wsh(ctx, wscript) gives the scriptpubkey */ u8 *htlc_offered_wscript(const tal_t *ctx, const struct ripemd160 *ripemd, const struct keyset *keyset, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); /* Low-level HTLC tx creator */ struct bitcoin_tx *htlc_tx(const tal_t *ctx, @@ -124,5 +141,6 @@ struct bitcoin_tx *htlc_tx(const tal_t *ctx, const u8 *htlc_tx_wscript, struct amount_sat htlc_fee, u32 locktime, - bool option_anchor_outputs); + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx); #endif /* LIGHTNING_COMMON_HTLC_TX_H */ diff --git a/common/initial_channel.c b/common/initial_channel.c index ec7817c08..80c0b7a9c 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -134,6 +134,7 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx, direct_outputs, side, csv_lock, channel_has(channel, OPT_ANCHOR_OUTPUTS), + channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX), err_reason); if (init_tx) { diff --git a/common/initial_commit_tx.c b/common/initial_commit_tx.c index 5d6ade5b3..73e1a37b4 100644 --- a/common/initial_commit_tx.c +++ b/common/initial_commit_tx.c @@ -88,6 +88,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, enum side side, u32 csv_lock, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, char** err_reason) { struct amount_sat base_fee; @@ -122,15 +123,16 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, * fee](#fee-calculation). */ base_fee = commit_tx_base_fee(feerate_per_kw, untrimmed, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); - /* BOLT: - * If `option_anchor_outputs` applies to the commitment + /* BOLT #3: + * If `option_anchors` applies to the commitment * transaction, also subtract two times the fixed anchor size * of 330 sats from the funder (either `to_local` or * `to_remote`). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660))) { *err_reason = "Funder cannot afford anchor outputs"; return NULL; @@ -246,7 +248,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, u8 *redeem; amount = amount_msat_to_sat_round_down(other_pay); - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { redeem = bitcoin_wscript_to_remote_anchored(tmpctx, &keyset->other_payment_key, (!side) == lessor ? csv_lock : 1); @@ -271,7 +273,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, * * if `to_remote` exists or there are untrimmed HTLCs, add a * [`to_remote_anchor` output] */ - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { if (to_local || untrimmed != 0) { tx_add_anchor_output(tx, &funding_key[side]); output_order[n] = NULL; diff --git a/common/initial_commit_tx.h b/common/initial_commit_tx.h index 4e7e39b3b..6e715831b 100644 --- a/common/initial_commit_tx.h +++ b/common/initial_commit_tx.h @@ -25,7 +25,8 @@ u64 commit_number_obscurer(const struct pubkey *opener_payment_basepoint, /* The base weight of a commitment tx */ static inline size_t commit_tx_base_weight(size_t num_untrimmed_htlcs, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { size_t weight; size_t num_outputs; @@ -36,7 +37,7 @@ static inline size_t commit_tx_base_weight(size_t num_untrimmed_htlcs, * - MUST be calculated to match: * 1. Start with `weight` = 724 (1124 if `option_anchors` applies). */ - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { weight = 1124; num_outputs = 4; } else { @@ -61,11 +62,13 @@ static inline size_t commit_tx_base_weight(size_t num_untrimmed_htlcs, /* Helper to calculate the base fee if we have this many htlc outputs */ static inline struct amount_sat commit_tx_base_fee(u32 feerate_per_kw, size_t num_untrimmed_htlcs, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { return amount_tx_fee(feerate_per_kw, commit_tx_base_weight(num_untrimmed_htlcs, - option_anchor_outputs)); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx)); } /** @@ -107,6 +110,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, enum side side, u32 csv_lock, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, char** err_reason); /* try_subtract_fee - take away this fee from the opener (and return true), or all if insufficient (and return false). */ diff --git a/common/utxo.c b/common/utxo.c index b2192f4a5..a28e99cd3 100644 --- a/common/utxo.c +++ b/common/utxo.c @@ -22,7 +22,7 @@ void towire_utxo(u8 **pptr, const struct utxo *utxo) towire_bool(pptr, utxo->close_info->commitment_point != NULL); if (utxo->close_info->commitment_point) towire_pubkey(pptr, utxo->close_info->commitment_point); - towire_bool(pptr, utxo->close_info->option_anchor_outputs); + towire_bool(pptr, utxo->close_info->option_anchors); towire_u32(pptr, utxo->close_info->csv); } @@ -51,7 +51,7 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) utxo->close_info->commitment_point); } else utxo->close_info->commitment_point = NULL; - utxo->close_info->option_anchor_outputs + utxo->close_info->option_anchors = fromwire_bool(ptr, max); utxo->close_info->csv = fromwire_u32(ptr, max); } else { diff --git a/common/utxo.h b/common/utxo.h index 6c5365c8e..830b86576 100644 --- a/common/utxo.h +++ b/common/utxo.h @@ -11,7 +11,7 @@ struct ext_key; struct unilateral_close_info { u64 channel_id; struct node_id peer_id; - bool option_anchor_outputs; + bool option_anchors; /* NULL if this is an option_static_remotekey commitment */ struct pubkey *commitment_point; u32 csv; @@ -71,8 +71,11 @@ static inline bool utxo_is_csv_locked(const struct utxo *utxo, u32 current_heigh { if (!utxo->close_info) return false; - /* All close outputs are csv locked for option_anchor_outputs */ - if (!utxo->blockheight && utxo->close_info->option_anchor_outputs) + /* BOLT #3: + * If `option_anchors` applies to the commitment transaction, the + * `to_remote` output is encumbered by a one block csv lock. + */ + if (!utxo->blockheight && utxo->close_info->option_anchors) return true; assert(*utxo->blockheight + utxo->close_info->csv > *utxo->blockheight); return *utxo->blockheight + utxo->close_info->csv > current_height; diff --git a/devtools/mkclose.c b/devtools/mkclose.c index f60b6175f..71c1a1a9d 100644 --- a/devtools/mkclose.c +++ b/devtools/mkclose.c @@ -111,7 +111,8 @@ int main(int argc, char *argv[]) argnum++; fee = commit_tx_base_fee(feerate_per_kw, 0, - option_anchor_outputs); + option_anchor_outputs, + false); /* BOLT #3: * If `option_anchors` applies to the commitment * transaction, also subtract two times the fixed anchor size diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 8e12704fc..edbc11bb5 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -492,7 +492,7 @@ static void sign_our_inputs(struct utxo **utxos, struct wally_psbt *psbt) psbt_input_add_pubkey(psbt, j, &pubkey); /* It's actually a P2WSH in this case. */ - if (utxo->close_info && utxo->close_info->option_anchor_outputs) { + if (utxo->close_info && utxo->close_info->option_anchors) { const u8 *wscript = bitcoin_wscript_to_remote_anchored(tmpctx, &pubkey, diff --git a/lightningd/anchorspend.c b/lightningd/anchorspend.c index ac08007e3..eb7ae22c8 100644 --- a/lightningd/anchorspend.c +++ b/lightningd/anchorspend.c @@ -106,7 +106,7 @@ struct anchor_details *create_anchor_details(const tal_t *ctx, struct anchor_details *adet = tal(ctx, struct anchor_details); /* If we don't have an anchor, we can't do anything. */ - if (!channel_has(channel, OPT_ANCHOR_OUTPUTS)) + if (!channel_type_has_anchors(channel->type)) return tal_free(adet); if (!hsm_capable(ld, WIRE_HSMD_SIGN_ANCHORSPEND)) { diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index dc226fb00..ea3747aba 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -750,7 +750,9 @@ static struct command_result *json_feerates(struct command *cmd, /* It actually is negotiated per-channel... */ bool anchor_outputs = feature_offered(cmd->ld->our_features->bits[INIT_FEATURE], - OPT_ANCHOR_OUTPUTS); + OPT_ANCHOR_OUTPUTS) + || feature_offered(cmd->ld->our_features->bits[INIT_FEATURE], + OPT_ANCHORS_ZERO_FEE_HTLC_TX); json_object_start(response, "onchain_fee_estimates"); /* eg 020000000001016f51de645a47baa49a636b8ec974c28bdff0ac9151c0f4eda2dbe3b41dbe711d000000001716001401fad90abcd66697e2592164722de4a95ebee165ffffffff0240420f00000000002200205b8cd3b914cf67cdd8fa6273c930353dd36476734fbd962102c2df53b90880cdb73f890000000000160014c2ccab171c2a5be9dab52ec41b825863024c54660248304502210088f65e054dbc2d8f679de3e40150069854863efa4a45103b2bb63d060322f94702200d3ae8923924a458cffb0b7360179790830027bb6b29715ba03e12fc22365de1012103d745445c9362665f22e0d96e9e766f273f3260dea39c8a76bfa05dd2684ddccf00000000 == weight 702 */ @@ -773,10 +775,10 @@ static struct command_result *json_feerates(struct command *cmd, json_add_u64(response, "htlc_timeout_satoshis", htlc_timeout_fee(htlc_resolution_feerate(cmd->ld->topology), - false).satoshis /* Raw: estimate */); + false, false).satoshis /* Raw: estimate */); json_add_u64(response, "htlc_success_satoshis", htlc_success_fee(htlc_resolution_feerate(cmd->ld->topology), - false).satoshis /* Raw: estimate */); + false, false).satoshis /* Raw: estimate */); json_object_end(response); } diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 68958d3c4..6f6c583bb 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -359,6 +359,7 @@ void peer_start_closingd(struct channel *channel, struct peer_fd *peer_fd) struct lightningd *ld = channel->peer->ld; u32 final_commit_feerate; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); if (!channel->shutdown_scriptpubkey[REMOTE]) { channel_internal_error(channel, @@ -403,7 +404,8 @@ void peer_start_closingd(struct channel *channel, struct peer_fd *peer_fd) final_commit_feerate = get_feerate(channel->fee_states, channel->opener, LOCAL); feelimit = commit_tx_base_fee(final_commit_feerate, 0, - option_anchor_outputs); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); /* If we can't determine feerate, start at half unilateral feerate. */ feerate = mutual_close_feerate(ld->topology); @@ -415,7 +417,7 @@ void peer_start_closingd(struct channel *channel, struct peer_fd *peer_fd) /* We use a feerate if anchor_outputs, otherwise max fee is set by * the final unilateral. */ - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { max_feerate = tal(tmpctx, u32); /* Aim for reasonable max, but use final if we don't know. */ *max_feerate = unilateral_feerate(ld->topology, false); @@ -499,7 +501,8 @@ void peer_start_closingd(struct channel *channel, struct peer_fd *peer_fd) (channel->closing_fee_negotiation_step == 50 && channel->closing_fee_negotiation_step_unit == CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE) /* Always use quickclose with anchors */ - || option_anchor_outputs, + || option_anchor_outputs + || option_anchors_zero_fee_htlc_tx, channel->shutdown_wrong_funding); /* We don't expect a response: it will give us feedback on diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 3dc57bc73..93c3ad20c 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -165,6 +165,11 @@ void json_add_unsaved_channel(struct json_stream *response, OPT_ANCHOR_OUTPUTS)) json_add_string(response, NULL, "option_anchor_outputs"); + if (feature_negotiated(channel->peer->ld->our_features, + channel->peer->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX)) + json_add_string(response, NULL, "option_anchors_zero_fee_htlc_tx"); + json_array_end(response); json_object_end(response); } diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 6ab1d7751..fed5b764b 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -560,7 +560,7 @@ static u8 *sign_htlc_success(const tal_t *ctx, const struct bitcoin_tx *tx, const struct onchain_signing_info *info) { - const bool anchor_outputs = channel_has(info->channel, OPT_ANCHOR_OUTPUTS); + const bool anchor_outputs = channel_type_has_anchors(info->channel->type); assert(info->msgtype == WIRE_ONCHAIND_SPEND_HTLC_SUCCESS); return towire_hsmd_sign_any_local_htlc_tx(ctx, @@ -576,7 +576,7 @@ static u8 *sign_htlc_timeout(const tal_t *ctx, const struct bitcoin_tx *tx, const struct onchain_signing_info *info) { - const bool anchor_outputs = channel_has(info->channel, OPT_ANCHOR_OUTPUTS); + const bool anchor_outputs = channel_type_has_anchors(info->channel->type); assert(info->msgtype == WIRE_ONCHAIND_SPEND_HTLC_TIMEOUT); return towire_hsmd_sign_any_local_htlc_tx(ctx, @@ -592,7 +592,7 @@ static u8 *sign_fulfill(const tal_t *ctx, const struct bitcoin_tx *tx, const struct onchain_signing_info *info) { - const bool anchor_outputs = channel_has(info->channel, OPT_ANCHOR_OUTPUTS); + const bool anchor_outputs = channel_type_has_anchors(info->channel->type); assert(info->msgtype == WIRE_ONCHAIND_SPEND_FULFILL); return towire_hsmd_sign_any_remote_htlc_to_us(ctx, @@ -608,7 +608,7 @@ static u8 *sign_htlc_expired(const tal_t *ctx, const struct bitcoin_tx *tx, const struct onchain_signing_info *info) { - const bool anchor_outputs = channel_has(info->channel, OPT_ANCHOR_OUTPUTS); + const bool anchor_outputs = channel_type_has_anchors(info->channel->type); assert(info->msgtype == WIRE_ONCHAIND_SPEND_HTLC_EXPIRED); return towire_hsmd_sign_any_remote_htlc_to_us(ctx, @@ -867,7 +867,7 @@ static bool consider_onchain_htlc_tx_rebroadcast(struct channel *channel, struct lightningd *ld = channel->peer->ld; /* We can't do much without anchor outputs (we could CPFP?) */ - if (!channel_has(channel, OPT_ANCHOR_OUTPUTS)) + if (!channel_type_has_anchors(channel->type)) return true; /* Note that we can have UTXOs taken from us if there are a lot of @@ -1166,7 +1166,7 @@ static void handle_onchaind_spend_fulfill(struct channel *channel, struct amount_sat out_sats; struct preimage preimage; u64 htlc_id; - const bool anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + const bool anchor_outputs = channel_type_has_anchors(channel->type); info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_FULFILL); info->minblock = 0; @@ -1209,7 +1209,8 @@ static void handle_onchaind_spend_htlc_success(struct channel *channel, u8 **witness; struct bitcoin_signature sig; const struct onchain_witness_element **welements; - const bool anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + const bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + const bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_HTLC_SUCCESS); info->minblock = 0; @@ -1231,7 +1232,7 @@ static void handle_onchaind_spend_htlc_success(struct channel *channel, * * locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout */ tx = htlc_tx(NULL, chainparams, &out, info->wscript, out_sats, htlc_wscript, fee, - 0, anchor_outputs); + 0, option_anchor_outputs, option_anchors_zero_fee_htlc_tx); tal_free(htlc_wscript); if (!tx) { /* Can only happen if fee > out_sats */ @@ -1289,7 +1290,8 @@ static void handle_onchaind_spend_htlc_timeout(struct channel *channel, u8 **witness; struct bitcoin_signature sig; const struct onchain_witness_element **welements; - const bool anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + const bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + const bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_HTLC_TIMEOUT); @@ -1310,7 +1312,7 @@ static void handle_onchaind_spend_htlc_timeout(struct channel *channel, * * locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout */ tx = htlc_tx(NULL, chainparams, &out, info->wscript, out_sats, htlc_wscript, fee, - cltv_expiry, anchor_outputs); + cltv_expiry, option_anchor_outputs, option_anchors_zero_fee_htlc_tx); tal_free(htlc_wscript); if (!tx) { /* Can only happen if fee > out_sats */ @@ -1364,7 +1366,7 @@ static void handle_onchaind_spend_htlc_expired(struct channel *channel, struct amount_sat out_sats; u64 htlc_id; u32 cltv_expiry; - const bool anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + const bool anchor_outputs = channel_type_has_anchors(channel->type); info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_HTLC_EXPIRED); diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index f89f474a6..b4fb28cb3 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -76,6 +76,12 @@ void json_add_uncommitted_channel(struct json_stream *response, uc->peer->their_features, OPT_ANCHOR_OUTPUTS)) json_add_string(response, NULL, "option_anchor_outputs"); + + if (feature_negotiated(uc->peer->ld->our_features, + uc->peer->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX)) + json_add_string(response, NULL, "option_anchors_zero_fee_htlc_tx"); + json_array_end(response); json_object_end(response); } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 59f963b7d..832bfcccb 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -473,7 +473,8 @@ static void json_add_htlcs(struct lightningd *ld, htlc_state_name(hin->hstate)); if (htlc_is_trimmed(REMOTE, hin->msat, local_feerate, channel->our_config.dust_limit, LOCAL, - channel_has(channel, OPT_ANCHOR_OUTPUTS))) + channel_has(channel, OPT_ANCHOR_OUTPUTS), + channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX))) json_add_bool(response, "local_trimmed", true); if (hin->status != NULL) json_add_string(response, "status", hin->status); @@ -496,7 +497,8 @@ static void json_add_htlcs(struct lightningd *ld, htlc_state_name(hout->hstate)); if (htlc_is_trimmed(LOCAL, hout->msat, local_feerate, channel->our_config.dust_limit, LOCAL, - channel_has(channel, OPT_ANCHOR_OUTPUTS))) + channel_has(channel, OPT_ANCHOR_OUTPUTS), + channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX))) json_add_bool(response, "local_trimmed", true); json_object_end(response); } @@ -520,6 +522,7 @@ static struct amount_sat commit_txfee(const struct channel *channel, struct amount_sat dust_limit; struct amount_sat fee; bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX); if (side == LOCAL) dust_limit = channel->our_config.dust_limit; @@ -528,7 +531,7 @@ static struct amount_sat commit_txfee(const struct channel *channel, /* Assume we tried to add "amount" */ if (!htlc_is_trimmed(side, amount, feerate, dust_limit, side, - option_anchor_outputs)) + option_anchor_outputs, option_anchors_zero_fee_htlc_tx)) num_untrimmed_htlcs++; for (hin = htlc_in_map_first(ld->htlcs_in, &ini); @@ -537,7 +540,7 @@ static struct amount_sat commit_txfee(const struct channel *channel, if (hin->key.channel != channel) continue; if (!htlc_is_trimmed(!side, hin->msat, feerate, dust_limit, - side, option_anchor_outputs)) + side, option_anchor_outputs, option_anchors_zero_fee_htlc_tx)) num_untrimmed_htlcs++; } for (hout = htlc_out_map_first(ld->htlcs_out, &outi); @@ -546,7 +549,7 @@ static struct amount_sat commit_txfee(const struct channel *channel, if (hout->key.channel != channel) continue; if (!htlc_is_trimmed(side, hout->msat, feerate, dust_limit, - side, option_anchor_outputs)) + side, option_anchor_outputs, option_anchors_zero_fee_htlc_tx)) num_untrimmed_htlcs++; } @@ -563,9 +566,9 @@ static struct amount_sat commit_txfee(const struct channel *channel, * predictability between implementations. */ fee = commit_tx_base_fee(2 * feerate, num_untrimmed_htlcs + 1, - option_anchor_outputs); + option_anchor_outputs, option_anchors_zero_fee_htlc_tx); - if (option_anchor_outputs) { + if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) { /* BOLT #3: * If `option_anchors` applies to the commitment * transaction, also subtract two times the fixed anchor size @@ -869,6 +872,8 @@ static void json_add_channel(struct lightningd *ld, json_add_string(response, NULL, "option_static_remotekey"); if (channel_has(channel, OPT_ANCHOR_OUTPUTS)) json_add_string(response, NULL, "option_anchor_outputs"); + if (channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX)) + json_add_string(response, NULL, "option_anchors_zero_fee_htlc_tx"); if (channel_has(channel, OPT_ZEROCONF)) json_add_string(response, NULL, "option_zeroconf"); if (channel_has(channel, OPT_SCID_ALIAS)) diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index e7fda243e..de34334ba 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -314,7 +314,8 @@ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED, u32 feerate_per_kw UNNEEDED, struct amount_sat dust_limit UNNEEDED, enum side side UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); } /* Generated stub for htlc_max_possible_send */ struct amount_msat htlc_max_possible_send(const struct channel *channel UNNEEDED) diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index ef6e7b99e..46f56468c 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -544,7 +544,9 @@ static struct amount_sat get_htlc_success_fee(struct tracked_output *out) htlc_amount, to_self_delay[LOCAL], 0, - keyset, option_anchor_outputs); + keyset, + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); /* BOLT #3: * @@ -1822,7 +1824,8 @@ static u8 **derive_htlc_scripts(const struct htlc_stub *htlcs, enum side side) htlc_scripts[i] = htlc_offered_wscript(htlc_scripts, &htlcs[i].ripemd, keyset, - option_anchor_outputs || option_anchors_zero_fee_htlc_tx); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); else { /* FIXME: remove abs_locktime */ struct abs_locktime ltime; @@ -1835,7 +1838,8 @@ static u8 **derive_htlc_scripts(const struct htlc_stub *htlcs, enum side side) &htlcs[i].ripemd, <ime, keyset, - option_anchor_outputs || option_anchors_zero_fee_htlc_tx); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); } } return htlc_scripts; @@ -1883,7 +1887,8 @@ static size_t resolve_our_htlc_ourcommit(struct tracked_output *out, htlc_scripts[matches[i]], htlc_amount, htlcs[matches[i]].cltv_expiry, to_self_delay[LOCAL], 0, keyset, - option_anchor_outputs || option_anchors_zero_fee_htlc_tx); + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); if (set_htlc_timeout_fee(tx, out->remote_htlc_sig, htlc_scripts[matches[i]])) diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index c4a8530c0..0f8cd861b 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -61,14 +61,16 @@ enum wallet_tx_type fromwire_wallet_tx_type(const u8 **cursor UNNEEDED, size_t * u8 *htlc_offered_wscript(const tal_t *ctx UNNEEDED, const struct ripemd160 *ripemd UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_offered_wscript called!\n"); abort(); } /* Generated stub for htlc_received_wscript */ u8 *htlc_received_wscript(const tal_t *ctx UNNEEDED, const struct ripemd160 *ripemd UNNEEDED, const struct abs_locktime *expiry UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_received_wscript called!\n"); abort(); } /* Generated stub for htlc_success_tx */ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx UNNEEDED, @@ -79,7 +81,8 @@ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx UNNEEDED, u16 to_self_delay UNNEEDED, u32 feerate_per_kw UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_success_tx called!\n"); abort(); } /* Generated stub for master_badmsg */ void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) @@ -303,7 +306,8 @@ struct bitcoin_tx *htlc_timeout_tx(const tal_t *ctx, u16 to_self_delay UNNEEDED, u32 feerate_per_kw UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs) + bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx) { struct bitcoin_tx *tx; struct amount_sat in_amount; diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index b604d9b6e..7c4761818 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -95,14 +95,16 @@ void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr u8 *htlc_offered_wscript(const tal_t *ctx UNNEEDED, const struct ripemd160 *ripemd UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_offered_wscript called!\n"); abort(); } /* Generated stub for htlc_received_wscript */ u8 *htlc_received_wscript(const tal_t *ctx UNNEEDED, const struct ripemd160 *ripemd UNNEEDED, const struct abs_locktime *expiry UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_received_wscript called!\n"); abort(); } /* Generated stub for htlc_success_tx */ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx UNNEEDED, @@ -113,7 +115,8 @@ struct bitcoin_tx *htlc_success_tx(const tal_t *ctx UNNEEDED, u16 to_self_delay UNNEEDED, u32 feerate_per_kw UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_success_tx called!\n"); abort(); } /* Generated stub for htlc_timeout_tx */ struct bitcoin_tx *htlc_timeout_tx(const tal_t *ctx UNNEEDED, @@ -125,7 +128,8 @@ struct bitcoin_tx *htlc_timeout_tx(const tal_t *ctx UNNEEDED, u16 to_self_delay UNNEEDED, u32 feerate_per_kw UNNEEDED, const struct keyset *keyset UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_timeout_tx called!\n"); abort(); } /* Generated stub for master_badmsg */ void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) diff --git a/openingd/common.c b/openingd/common.c index 33e5a4df8..fbd2a93b5 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -21,6 +21,7 @@ bool check_config_bounds(const tal_t *ctx, const struct channel_config *remoteconf, const struct channel_config *localconf, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, char **err_reason) { struct amount_sat capacity; @@ -72,7 +73,7 @@ bool check_config_bounds(const tal_t *ctx, * `to_remote_anchor` above its reserve. */ /* (We simply include in "reserve" here if they opened). */ - if (option_anchor_outputs + if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx) && !amount_sat_add(&reserve, reserve, AMOUNT_SAT(660))) { *err_reason = tal_fmt(ctx, "cannot add anchors to reserve %s", @@ -96,7 +97,9 @@ bool check_config_bounds(const tal_t *ctx, /* They have to pay for fees, too. Assuming HTLC is dust, though, * we don't account for an HTLC output. */ - fee = commit_tx_base_fee(feerate_per_kw, 0, option_anchor_outputs); + fee = commit_tx_base_fee(feerate_per_kw, 0, + option_anchor_outputs, + option_anchors_zero_fee_htlc_tx); if (!amount_sat_sub(&capacity, capacity, fee)) { *err_reason = tal_fmt(ctx, "channel_reserve_satoshis %s" " and %s plus fee %s too large for " diff --git a/openingd/common.h b/openingd/common.h index 09be918ae..c48930dd0 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -17,6 +17,7 @@ bool check_config_bounds(const tal_t *ctx, const struct channel_config *remoteconf, const struct channel_config *localconf, bool option_anchor_outputs, + bool option_anchors_zero_fee_htlc_tx, char **err_reason); bool anchors_negotiated(struct feature_set *our_features, diff --git a/openingd/dualopend.c b/openingd/dualopend.c index ae632331c..3fcbb69de 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -2499,8 +2499,12 @@ static void accepter_start(struct state *state, const u8 *oc2_msg) state->min_effective_htlc_capacity, &tx_state->remoteconf, &tx_state->localconf, - anchors_negotiated(state->our_features, - state->their_features), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX), &err_reason)) { negotiation_failed(state, "%s", err_reason); return; @@ -3305,8 +3309,12 @@ static void opener_start(struct state *state, u8 *msg) state->min_effective_htlc_capacity, &tx_state->remoteconf, &tx_state->localconf, - anchors_negotiated(state->our_features, - state->their_features), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX), &err_reason)) { negotiation_failed(state, "%s", err_reason); return; @@ -3615,8 +3623,12 @@ static void rbf_local_start(struct state *state, u8 *msg) state->min_effective_htlc_capacity, &tx_state->remoteconf, &tx_state->localconf, - anchors_negotiated(state->our_features, - state->their_features), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX), &err_reason)) { open_abort(state, "%s", err_reason); return; @@ -3753,8 +3765,12 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg) state->min_effective_htlc_capacity, &tx_state->remoteconf, &tx_state->localconf, - anchors_negotiated(state->our_features, - state->their_features), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX), &err_reason)) { negotiation_failed(state, "%s", err_reason); goto free_rbf_ctx; diff --git a/openingd/openingd.c b/openingd/openingd.c index 87166f2b0..dcf18340b 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -567,8 +567,12 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags, state->min_effective_htlc_capacity, &state->remoteconf, &state->localconf, - anchors_negotiated(state->our_features, - state->their_features), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX), &err_reason)) { negotiation_failed(state, "%s", err_reason); return NULL; @@ -1085,8 +1089,12 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) state->min_effective_htlc_capacity, &state->remoteconf, &state->localconf, - anchors_negotiated(state->our_features, - state->their_features), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX), &err_reason)) { negotiation_failed(state, "%s", err_reason); return NULL; diff --git a/tests/test_closing.py b/tests/test_closing.py index 623b74d7c..d5ebaad1d 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -1455,7 +1455,7 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams): # reconnect with l1, which will fulfill the payment l2.rpc.connect(l1.info['id'], 'localhost', l1.port) - l2.daemon.wait_for_log('got commitsig .*: feerate 11000, blockheight: 0, 0 added, 1 fulfilled, 0 failed, 0 changed') + l2.daemon.wait_for_log('got commitsig .*: feerate {}, blockheight: 0, 0 added, 1 fulfilled, 0 failed, 0 changed'.format(3750 if anchor_expected() else 11000)) # l2 moves on for closed l3 bitcoind.generate_block(1, wait_for_mempool=1) diff --git a/wallet/reservation.c b/wallet/reservation.c index e04a4cd2d..6300662d6 100644 --- a/wallet/reservation.c +++ b/wallet/reservation.c @@ -305,7 +305,7 @@ struct wally_psbt *psbt_using_utxos(const tal_t *ctx, * set to `1` and witness: */ if (utxos[i]->close_info - && utxos[i]->close_info->option_anchor_outputs) + && utxos[i]->close_info->option_anchors) this_nsequence = utxos[i]->close_info->csv; else this_nsequence = nsequence; diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 7ad4c6793..17014a95a 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -234,7 +234,8 @@ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED, u32 feerate_per_kw UNNEEDED, struct amount_sat dust_limit UNNEEDED, enum side side UNNEEDED, - bool option_anchor_outputs UNNEEDED) + bool option_anchor_outputs UNNEEDED, + bool option_anchors_zero_fee_htlc_tx UNNEEDED) { fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); } /* Generated stub for htlc_set_add */ void htlc_set_add(struct lightningd *ld UNNEEDED, @@ -1105,7 +1106,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) u.close_info->channel_id = 42; u.close_info->peer_id = id; u.close_info->commitment_point = &pk; - u.close_info->option_anchor_outputs = false; + u.close_info->option_anchors = false; /* Arbitrarily set scriptpubkey len to 20 */ u.scriptPubkey = tal_arr(w, u8, 20); memset(u.scriptPubkey, 1, 20); @@ -1130,7 +1131,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) CHECK(u.close_info->channel_id == 42 && pubkey_eq(u.close_info->commitment_point, &pk) && node_id_eq(&u.close_info->peer_id, &id) && - u.close_info->option_anchor_outputs == false); + u.close_info->option_anchors == false); /* Attempt to reserve the utxo */ CHECK_MSG(wallet_update_output_status(w, &u.outpoint, @@ -1163,7 +1164,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) u.close_info->channel_id = 42; u.close_info->peer_id = id; u.close_info->commitment_point = NULL; - u.close_info->option_anchor_outputs = true; + u.close_info->option_anchors = true; /* The blockheight has to be set for an option_anchor_output * closed UTXO to be spendable */ u32 *blockheight = tal(w, u32); @@ -1217,7 +1218,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) CHECK(u.close_info->channel_id == 42 && u.close_info->commitment_point == NULL && node_id_eq(&u.close_info->peer_id, &id) && - u.close_info->option_anchor_outputs == true && + u.close_info->option_anchors == true && u.close_info->csv == 1); /* Now un-reserve them */ tal_free(utxos); @@ -1238,7 +1239,7 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) CHECK(u.close_info->channel_id == 42 && u.close_info->commitment_point == NULL && node_id_eq(&u.close_info->peer_id, &id) && - u.close_info->option_anchor_outputs == true && + u.close_info->option_anchors == true && u.close_info->csv > 0); } /* Now un-reserve them */ diff --git a/wallet/wallet.c b/wallet/wallet.c index a231ea2cf..eeb5934a4 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -189,7 +189,7 @@ static bool wallet_add_utxo(struct wallet *w, struct utxo *utxo, db_bind_pubkey(stmt, 8, utxo->close_info->commitment_point); else db_bind_null(stmt, 8); - db_bind_int(stmt, 9, utxo->close_info->option_anchor_outputs); + db_bind_int(stmt, 9, utxo->close_info->option_anchors); } else { db_bind_null(stmt, 6); db_bind_null(stmt, 7); @@ -239,7 +239,7 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt) = db_col_optional(utxo->close_info, stmt, "commitment_point", pubkey); - utxo->close_info->option_anchor_outputs + utxo->close_info->option_anchors = db_col_int(stmt, "option_anchor_outputs"); utxo->close_info->csv = db_col_int(stmt, "csv_lock"); } else { @@ -519,9 +519,11 @@ static bool deep_enough(u32 maxheight, const struct utxo *utxo, u32 current_blockheight) { if (utxo->close_info - && utxo->close_info->option_anchor_outputs) { - /* All option_anchor_output close_infos - * have a csv of at least 1 */ + && utxo->close_info->option_anchors) { + /* BOLT #3: + * If `option_anchors` applies to the commitment transaction, the + * `to_remote` output is encumbered by a one block csv lock. + */ if (!utxo->blockheight) return false; @@ -658,7 +660,8 @@ bool wallet_add_onchaind_utxo(struct wallet *w, else db_bind_null(stmt, 8); - db_bind_int(stmt, 9, channel_has(channel, OPT_ANCHOR_OUTPUTS)); + db_bind_int(stmt, 9, + channel_type_has_anchors(channel->type)); db_bind_int(stmt, 10, blockheight); /* spendheight */ @@ -896,7 +899,7 @@ done: static struct bitcoin_signature * wallet_htlc_sigs_load(const tal_t *ctx, struct wallet *w, u64 channelid, - bool option_anchor_outputs) + bool option_anchors) { struct db_stmt *stmt; struct bitcoin_signature *htlc_sigs = tal_arr(ctx, struct bitcoin_signature, 0); @@ -916,7 +919,7 @@ wallet_htlc_sigs_load(const tal_t *ctx, struct wallet *w, u64 channelid, * transaction, `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is * used as described in [BOLT #5] */ - if (option_anchor_outputs) + if (option_anchors) sig.sighash_type = SIGHASH_SINGLE|SIGHASH_ANYONECANPAY; else sig.sighash_type = SIGHASH_ALL; @@ -1526,8 +1529,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm &last_sig, wallet_htlc_sigs_load(tmpctx, w, db_col_u64(stmt, "id"), - channel_type_has(type, OPT_ANCHOR_OUTPUTS) - || channel_type_has(type, OPT_ANCHORS_ZERO_FEE_HTLC_TX)), + channel_type_has_anchors(type)), &channel_info, take(fee_states), remote_shutdown_scriptpubkey,