mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
6324980484
If a channel goes offline while the count of outstanding outgoing HTLCs exceeds the limit that we enforce against the peer, then the channel could never be brought online again because `add_htlc` called by `channel_force_htlcs` in `channeld/full_channel.c` would return `CHANNEL_ERR_TOO_MANY_HTLCS`. The protocol specification actually does allow us to exceed the limits that we are enforcing against the peer; we are only prohibited from exceeding the limits that the peer is enforcing against us. `add_htlc` takes an `enforce_aggregate_limits` parameter that appears to have been intended for `channel_force_htlcs` to exempt the local node from obeying the limits that it is enforcing against the peer, but this parameter was only being respected for the total HTLC value-in-flight check but not for the HTLC count check. This commit respects the parameter for the HTLC count check as well and resolves the problem of "Could not restore HTLCs". Fixes: #5636 Changelog-Fixed: channeld: Channel reinitialization no longer fails when the number of outstanding outgoing HTLCs exceeds `max_accepted_htlcs`.
1586 lines
48 KiB
C
1586 lines
48 KiB
C
#include "config.h"
|
|
#include <bitcoin/psbt.h>
|
|
#include <bitcoin/script.h>
|
|
#include <ccan/array_size/array_size.h>
|
|
#include <channeld/commit_tx.h>
|
|
#include <channeld/full_channel.h>
|
|
#include <common/blockheight_states.h>
|
|
#include <common/features.h>
|
|
#include <common/fee_states.h>
|
|
#include <common/htlc_trim.h>
|
|
#include <common/htlc_tx.h>
|
|
#include <common/htlc_wire.h>
|
|
#include <common/keyset.h>
|
|
#include <common/memleak.h>
|
|
#include <common/status.h>
|
|
#include <common/type_to_string.h>
|
|
#include <stdio.h>
|
|
/* Needs to be at end, since it doesn't include its own hdrs */
|
|
#include "full_channel_error_names_gen.h"
|
|
|
|
#if DEVELOPER
|
|
static void memleak_help_htlcmap(struct htable *memtable,
|
|
struct htlc_map *htlcs)
|
|
{
|
|
memleak_scan_htable(memtable, &htlcs->raw);
|
|
}
|
|
#endif /* DEVELOPER */
|
|
|
|
/* This is a dangerous thing! Because we apply HTLCs in many places
|
|
* in bulk, we can temporarily go negative. You must check balance_ok()
|
|
* at the end! */
|
|
struct balance {
|
|
s64 msat;
|
|
};
|
|
|
|
static void to_balance(struct balance *balance,
|
|
const struct amount_msat msat)
|
|
{
|
|
balance->msat = msat.millisatoshis; /* Raw: balance */
|
|
assert(balance->msat >= 0);
|
|
}
|
|
|
|
/* What does adding the HTLC do to the balance for this side (subtracts) */
|
|
static void balance_add_htlc(struct balance *balance,
|
|
const struct htlc *htlc,
|
|
enum side side)
|
|
{
|
|
if (htlc_owner(htlc) == side)
|
|
balance->msat -= htlc->amount.millisatoshis; /* Raw: balance */
|
|
}
|
|
|
|
/* What does removing the HTLC do to the balance for this side (adds) */
|
|
static void balance_remove_htlc(struct balance *balance,
|
|
const struct htlc *htlc,
|
|
enum side side)
|
|
{
|
|
enum side paid_to;
|
|
|
|
/* Fulfilled HTLCs are paid to recipient, otherwise returns to owner */
|
|
if (htlc->r)
|
|
paid_to = !htlc_owner(htlc);
|
|
else
|
|
paid_to = htlc_owner(htlc);
|
|
|
|
if (side == paid_to)
|
|
balance->msat += htlc->amount.millisatoshis; /* Raw: balance */
|
|
}
|
|
|
|
static bool balance_ok(const struct balance *balance,
|
|
struct amount_msat *msat)
|
|
WARN_UNUSED_RESULT;
|
|
|
|
static bool balance_ok(const struct balance *balance,
|
|
struct amount_msat *msat)
|
|
{
|
|
if (balance->msat < 0)
|
|
return false;
|
|
*msat = amount_msat(balance->msat);
|
|
return true;
|
|
}
|
|
|
|
struct channel *new_full_channel(const tal_t *ctx,
|
|
const struct channel_id *cid,
|
|
const struct bitcoin_outpoint *funding,
|
|
u32 minimum_depth,
|
|
const struct height_states *blockheight_states,
|
|
u32 lease_expiry,
|
|
struct amount_sat funding_sats,
|
|
struct amount_msat local_msat,
|
|
const struct fee_states *fee_states TAKES,
|
|
const struct channel_config *local,
|
|
const struct channel_config *remote,
|
|
const struct basepoints *local_basepoints,
|
|
const struct basepoints *remote_basepoints,
|
|
const struct pubkey *local_funding_pubkey,
|
|
const struct pubkey *remote_funding_pubkey,
|
|
const struct channel_type *type TAKES,
|
|
bool option_wumbo,
|
|
enum side opener)
|
|
{
|
|
struct channel *channel = new_initial_channel(ctx,
|
|
cid,
|
|
funding,
|
|
minimum_depth,
|
|
blockheight_states,
|
|
lease_expiry,
|
|
funding_sats,
|
|
local_msat,
|
|
fee_states,
|
|
local, remote,
|
|
local_basepoints,
|
|
remote_basepoints,
|
|
local_funding_pubkey,
|
|
remote_funding_pubkey,
|
|
type,
|
|
option_wumbo,
|
|
opener);
|
|
|
|
if (channel) {
|
|
channel->htlcs = tal(channel, struct htlc_map);
|
|
htlc_map_init(channel->htlcs);
|
|
memleak_add_helper(channel->htlcs, memleak_help_htlcmap);
|
|
tal_add_destructor(channel->htlcs, htlc_map_clear);
|
|
}
|
|
return channel;
|
|
}
|
|
|
|
static void htlc_arr_append(const struct htlc ***arr, const struct htlc *htlc)
|
|
{
|
|
if (!arr)
|
|
return;
|
|
tal_arr_expand(arr, htlc);
|
|
}
|
|
|
|
static void dump_htlc(const struct htlc *htlc, const char *prefix)
|
|
{
|
|
enum htlc_state remote_state;
|
|
|
|
if (htlc->state <= RCVD_REMOVE_ACK_REVOCATION)
|
|
remote_state = htlc->state + 10;
|
|
else
|
|
remote_state = htlc->state - 10;
|
|
|
|
status_debug("%s: HTLC %s %"PRIu64" = %s/%s %s",
|
|
prefix,
|
|
htlc_owner(htlc) == LOCAL ? "LOCAL" : "REMOTE",
|
|
htlc->id,
|
|
htlc_state_name(htlc->state),
|
|
htlc_state_name(remote_state),
|
|
htlc->r ? "FULFILLED" : htlc->failed ? "FAILED"
|
|
: "");
|
|
}
|
|
|
|
void dump_htlcs(const struct channel *channel, const char *prefix)
|
|
{
|
|
#ifdef SUPERVERBOSE
|
|
struct htlc_map_iter it;
|
|
const struct htlc *htlc;
|
|
|
|
for (htlc = htlc_map_first(channel->htlcs, &it);
|
|
htlc;
|
|
htlc = htlc_map_next(channel->htlcs, &it)) {
|
|
dump_htlc(htlc, prefix);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Returns up to three arrays:
|
|
* committed: HTLCs currently committed.
|
|
* pending_removal: HTLCs pending removal (subset of committed)
|
|
* pending_addition: HTLCs pending addition (no overlap with committed)
|
|
*
|
|
* Also returns number of HTLCs for other side.
|
|
*/
|
|
static size_t gather_htlcs(const tal_t *ctx,
|
|
const struct channel *channel,
|
|
enum side side,
|
|
const struct htlc ***committed,
|
|
const struct htlc ***pending_removal,
|
|
const struct htlc ***pending_addition)
|
|
{
|
|
struct htlc_map_iter it;
|
|
const struct htlc *htlc;
|
|
const int committed_flag = HTLC_FLAG(side, HTLC_F_COMMITTED);
|
|
const int pending_flag = HTLC_FLAG(side, HTLC_F_PENDING);
|
|
size_t num_other_side = 0;
|
|
|
|
*committed = tal_arr(ctx, const struct htlc *, 0);
|
|
if (pending_removal)
|
|
*pending_removal = tal_arr(ctx, const struct htlc *, 0);
|
|
if (pending_addition)
|
|
*pending_addition = tal_arr(ctx, const struct htlc *, 0);
|
|
|
|
if (!channel->htlcs)
|
|
return num_other_side;
|
|
|
|
for (htlc = htlc_map_first(channel->htlcs, &it);
|
|
htlc;
|
|
htlc = htlc_map_next(channel->htlcs, &it)) {
|
|
if (htlc_has(htlc, committed_flag)) {
|
|
#ifdef SUPERVERBOSE
|
|
dump_htlc(htlc, "COMMITTED");
|
|
#endif
|
|
htlc_arr_append(committed, htlc);
|
|
if (htlc_has(htlc, pending_flag)) {
|
|
#ifdef SUPERVERBOSE
|
|
dump_htlc(htlc, "REMOVING");
|
|
#endif
|
|
htlc_arr_append(pending_removal, htlc);
|
|
} else if (htlc_owner(htlc) != side)
|
|
num_other_side++;
|
|
} else if (htlc_has(htlc, pending_flag)) {
|
|
htlc_arr_append(pending_addition, htlc);
|
|
#ifdef SUPERVERBOSE
|
|
dump_htlc(htlc, "ADDING");
|
|
#endif
|
|
if (htlc_owner(htlc) != side)
|
|
num_other_side++;
|
|
}
|
|
}
|
|
return num_other_side;
|
|
}
|
|
|
|
static bool sum_offered_msatoshis(struct amount_msat *total,
|
|
const struct htlc **htlcs,
|
|
enum side side)
|
|
{
|
|
size_t i;
|
|
|
|
*total = AMOUNT_MSAT(0);
|
|
for (i = 0; i < tal_count(htlcs); i++) {
|
|
if (htlc_owner(htlcs[i]) == side) {
|
|
if (!amount_msat_add(total, *total, htlcs[i]->amount))
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void add_htlcs(struct bitcoin_tx ***txs,
|
|
const struct htlc **htlcmap,
|
|
const struct channel *channel,
|
|
const struct keyset *keyset,
|
|
enum side side)
|
|
{
|
|
struct bitcoin_outpoint outpoint;
|
|
u32 feerate_per_kw = channel_feerate(channel, side);
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
|
|
/* Get txid of commitment transaction */
|
|
bitcoin_txid((*txs)[0], &outpoint.txid);
|
|
|
|
for (outpoint.n = 0; outpoint.n < tal_count(htlcmap); outpoint.n++) {
|
|
const struct htlc *htlc = htlcmap[outpoint.n];
|
|
struct bitcoin_tx *tx;
|
|
struct ripemd160 ripemd;
|
|
const u8 *wscript;
|
|
|
|
if (!htlc)
|
|
continue;
|
|
|
|
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);
|
|
tx = htlc_timeout_tx(*txs, chainparams, &outpoint,
|
|
wscript,
|
|
htlc->amount,
|
|
htlc->expiry.locktime,
|
|
channel->config[!side].to_self_delay,
|
|
feerate_per_kw,
|
|
keyset,
|
|
option_anchor_outputs);
|
|
} else {
|
|
ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8));
|
|
wscript = htlc_received_wscript(tmpctx, &ripemd,
|
|
&htlc->expiry, keyset,
|
|
option_anchor_outputs);
|
|
tx = htlc_success_tx(*txs, chainparams, &outpoint,
|
|
wscript,
|
|
htlc->amount,
|
|
channel->config[!side].to_self_delay,
|
|
feerate_per_kw,
|
|
keyset,
|
|
option_anchor_outputs);
|
|
}
|
|
|
|
/* Append to array. */
|
|
tal_arr_expand(txs, tx);
|
|
}
|
|
}
|
|
|
|
/* FIXME: We could cache these. */
|
|
struct bitcoin_tx **channel_txs(const tal_t *ctx,
|
|
const struct htlc ***htlcmap,
|
|
struct wally_tx_output *direct_outputs[NUM_SIDES],
|
|
const u8 **funding_wscript,
|
|
const struct channel *channel,
|
|
const struct pubkey *per_commitment_point,
|
|
u64 commitment_number,
|
|
enum side side)
|
|
{
|
|
struct bitcoin_tx **txs;
|
|
const struct htlc **committed;
|
|
struct keyset keyset;
|
|
|
|
if (!derive_keyset(per_commitment_point,
|
|
&channel->basepoints[side],
|
|
&channel->basepoints[!side],
|
|
channel_has(channel, OPT_STATIC_REMOTEKEY),
|
|
&keyset))
|
|
return NULL;
|
|
|
|
/* Figure out what @side will already be committed to. */
|
|
gather_htlcs(ctx, channel, side, &committed, NULL, NULL);
|
|
|
|
/* Generating and saving witness script required to spend
|
|
* the funding output */
|
|
*funding_wscript = bitcoin_redeem_2of2(ctx,
|
|
&channel->funding_pubkey[side],
|
|
&channel->funding_pubkey[!side]);
|
|
|
|
txs = tal_arr(ctx, struct bitcoin_tx *, 1);
|
|
txs[0] = commit_tx(
|
|
ctx, &channel->funding,
|
|
channel->funding_sats,
|
|
&channel->funding_pubkey[side],
|
|
&channel->funding_pubkey[!side],
|
|
channel->opener,
|
|
channel->config[!side].to_self_delay,
|
|
channel->lease_expiry,
|
|
channel_blockheight(channel, side),
|
|
&keyset, channel_feerate(channel, side),
|
|
channel->config[side].dust_limit, channel->view[side].owed[side],
|
|
channel->view[side].owed[!side], committed, htlcmap, direct_outputs,
|
|
commitment_number ^ channel->commitment_number_obscurer,
|
|
channel_has(channel, OPT_ANCHOR_OUTPUTS),
|
|
side);
|
|
|
|
/* Set the remote/local pubkeys on the commitment tx psbt */
|
|
psbt_input_add_pubkey(txs[0]->psbt, 0,
|
|
&channel->funding_pubkey[side]);
|
|
psbt_input_add_pubkey(txs[0]->psbt, 0,
|
|
&channel->funding_pubkey[!side]);
|
|
|
|
add_htlcs(&txs, *htlcmap, channel, &keyset, side);
|
|
|
|
tal_free(committed);
|
|
return txs;
|
|
}
|
|
|
|
/* If @side is faced with these HTLCs, how much will it have left
|
|
* above reserve (eg. to pay fees). Returns false if would be < 0. */
|
|
static bool get_room_above_reserve(const struct channel *channel,
|
|
const struct channel_view *view,
|
|
const struct htlc **adding,
|
|
const struct htlc **removing,
|
|
enum side side,
|
|
struct amount_msat *remainder)
|
|
{
|
|
/* Reserve is set by the *other* side */
|
|
struct amount_sat reserve = channel->config[!side].channel_reserve;
|
|
struct balance balance;
|
|
|
|
to_balance(&balance, view->owed[side]);
|
|
|
|
for (size_t i = 0; i < tal_count(removing); i++)
|
|
balance_remove_htlc(&balance, removing[i], side);
|
|
|
|
for (size_t i = 0; i < tal_count(adding); i++)
|
|
balance_add_htlc(&balance, adding[i], side);
|
|
|
|
/* Can happen if amount completely exceeds capacity */
|
|
if (!balance_ok(&balance, remainder)) {
|
|
status_debug("Failed to add %zu remove %zu htlcs",
|
|
tal_count(adding), tal_count(removing));
|
|
return false;
|
|
}
|
|
|
|
if (!amount_msat_sub_sat(remainder, *remainder, reserve)) {
|
|
status_debug("%s cannot afford htlc: would make balance %s"
|
|
" below reserve %s",
|
|
side_to_str(side),
|
|
type_to_string(tmpctx, struct amount_msat,
|
|
remainder),
|
|
type_to_string(tmpctx, struct amount_sat,
|
|
&reserve));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static size_t num_untrimmed_htlcs(enum side side,
|
|
struct amount_sat dust_limit,
|
|
u32 feerate,
|
|
bool option_static_remotekey,
|
|
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)
|
|
+ commit_tx_num_untrimmed(adding, feerate, dust_limit,
|
|
option_static_remotekey, side)
|
|
- commit_tx_num_untrimmed(removing, feerate, dust_limit,
|
|
option_static_remotekey, side);
|
|
}
|
|
|
|
static struct amount_sat fee_for_htlcs(const struct channel *channel,
|
|
const struct htlc **committed,
|
|
const struct htlc **adding,
|
|
const struct htlc **removing,
|
|
enum side side)
|
|
{
|
|
u32 feerate = channel_feerate(channel, side);
|
|
struct amount_sat dust_limit = channel->config[side].dust_limit;
|
|
size_t untrimmed;
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
|
|
untrimmed = num_untrimmed_htlcs(side, dust_limit, feerate,
|
|
option_anchor_outputs,
|
|
committed, adding, removing);
|
|
|
|
return commit_tx_base_fee(feerate, untrimmed, option_anchor_outputs);
|
|
}
|
|
|
|
static bool htlc_dust(const struct channel *channel,
|
|
const struct htlc **committed,
|
|
const struct htlc **adding,
|
|
const struct htlc **removing,
|
|
enum side side,
|
|
u32 feerate,
|
|
struct amount_msat *trim_total)
|
|
{
|
|
struct amount_sat dust_limit = channel->config[side].dust_limit;
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
struct amount_msat trim_rmvd = AMOUNT_MSAT(0);
|
|
|
|
if (!commit_tx_amount_trimmed(committed, feerate,
|
|
dust_limit,
|
|
option_anchor_outputs,
|
|
side, trim_total))
|
|
return false;
|
|
if (!commit_tx_amount_trimmed(adding, feerate,
|
|
dust_limit,
|
|
option_anchor_outputs,
|
|
side, trim_total))
|
|
return false;
|
|
if (!commit_tx_amount_trimmed(removing, feerate,
|
|
dust_limit,
|
|
option_anchor_outputs,
|
|
side, &trim_rmvd))
|
|
return false;
|
|
|
|
return amount_msat_sub(trim_total, *trim_total, trim_rmvd);
|
|
}
|
|
|
|
/*
|
|
* There is a corner case where the opener can spend so much that the
|
|
* non-opener can't add any non-dust HTLCs (since the opener would
|
|
* have to pay the additional fee, but it can't afford to). This
|
|
* leads to the channel starving at the feast! This was reported by
|
|
* ACINQ's @t-bast
|
|
* (https://github.com/lightningnetwork/lightning-rfc/issues/728) and
|
|
* demonstrated with Core Lightning by @m-schmoock
|
|
* (https://github.com/ElementsProject/lightning/pull/3498).
|
|
*
|
|
* To mostly avoid this situation, at least from our side, we apply an
|
|
* additional constraint when we're opener trying to add an HTLC: make
|
|
* sure we can afford one more HTLC, even if fees increase by 100%.
|
|
*
|
|
* We could do this for the peer, as well, by rejecting their HTLC
|
|
* immediately in this case. But rejecting a remote HTLC here causes
|
|
* us to get upset with them and close the channel: we're not well
|
|
* architected to reject HTLCs in channeld (it's usually lightningd's
|
|
* job, but it doesn't have all the channel balance change calculation
|
|
* logic. So we look after ourselves for now, and hope other nodes start
|
|
* self-regulating too.
|
|
*
|
|
* This mitigation will become BOLT #2 standard by:
|
|
* https://github.com/lightningnetwork/lightning-rfc/issues/740
|
|
*/
|
|
static bool local_opener_has_fee_headroom(const struct channel *channel,
|
|
struct amount_msat remainder,
|
|
const struct htlc **committed,
|
|
const struct htlc **adding,
|
|
const struct htlc **removing)
|
|
{
|
|
u32 feerate = channel_feerate(channel, LOCAL);
|
|
size_t untrimmed;
|
|
struct amount_sat fee;
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
|
|
assert(channel->opener == LOCAL);
|
|
|
|
/* How many untrimmed at current feerate? Increasing feerate can
|
|
* only *reduce* this number, so use current feerate here! */
|
|
untrimmed = num_untrimmed_htlcs(LOCAL, channel->config[LOCAL].dust_limit,
|
|
feerate,
|
|
option_anchor_outputs,
|
|
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);
|
|
if (amount_msat_greater_eq_sat(remainder, fee))
|
|
return true;
|
|
|
|
status_debug("Adding HTLC would leave us only %s: we need %s for"
|
|
" another HTLC if fees increase by 100%% to %uperkw",
|
|
type_to_string(tmpctx, struct amount_msat, &remainder),
|
|
type_to_string(tmpctx, struct amount_sat, &fee),
|
|
feerate + feerate);
|
|
return false;
|
|
}
|
|
|
|
static enum channel_add_err add_htlc(struct channel *channel,
|
|
enum htlc_state state,
|
|
u64 id,
|
|
struct amount_msat amount,
|
|
u32 cltv_expiry,
|
|
const struct sha256 *payment_hash,
|
|
const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
|
|
const struct pubkey *blinding TAKES,
|
|
struct htlc **htlcp,
|
|
bool enforce_aggregate_limits,
|
|
struct amount_sat *htlc_fee,
|
|
bool err_immediate_failures)
|
|
{
|
|
struct htlc *htlc, *old;
|
|
struct amount_msat msat_in_htlcs, committed_msat,
|
|
adding_msat, removing_msat, htlc_dust_amt;
|
|
enum side sender = htlc_state_owner(state), recipient = !sender;
|
|
const struct htlc **committed, **adding, **removing;
|
|
const struct channel_view *view;
|
|
size_t htlc_count;
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
u32 feerate, feerate_ceil;
|
|
|
|
htlc = tal(tmpctx, struct htlc);
|
|
|
|
htlc->id = id;
|
|
htlc->amount = amount;
|
|
htlc->state = state;
|
|
htlc->fail_immediate = false;
|
|
|
|
htlc->rhash = *payment_hash;
|
|
htlc->blinding = tal_dup_or_null(htlc, struct pubkey, blinding);
|
|
htlc->failed = NULL;
|
|
htlc->r = NULL;
|
|
htlc->routing = tal_dup_arr(htlc, u8, routing, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), 0);
|
|
|
|
/* FIXME: Change expiry to simple u32 */
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A receiving node:
|
|
*...
|
|
* - if sending node sets `cltv_expiry` to greater or equal to
|
|
* 500000000:
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (!blocks_to_abs_locktime(cltv_expiry, &htlc->expiry)) {
|
|
return CHANNEL_ERR_INVALID_EXPIRY;
|
|
}
|
|
|
|
old = htlc_get(channel->htlcs, htlc->id, htlc_owner(htlc));
|
|
if (old) {
|
|
if (old->state != htlc->state
|
|
|| !amount_msat_eq(old->amount, htlc->amount)
|
|
|| old->expiry.locktime != htlc->expiry.locktime
|
|
|| !sha256_eq(&old->rhash, &htlc->rhash))
|
|
return CHANNEL_ERR_DUPLICATE_ID_DIFFERENT;
|
|
else
|
|
return CHANNEL_ERR_DUPLICATE;
|
|
}
|
|
|
|
/* We're always considering the recipient's view of the channel here */
|
|
view = &channel->view[recipient];
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A receiving node:
|
|
* - receiving an `amount_msat` equal to 0, OR less than its own
|
|
* `htlc_minimum_msat`:
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (amount_msat_eq(htlc->amount, AMOUNT_MSAT(0))) {
|
|
return CHANNEL_ERR_HTLC_BELOW_MINIMUM;
|
|
}
|
|
if (amount_msat_less(htlc->amount, channel->config[recipient].htlc_minimum)) {
|
|
return CHANNEL_ERR_HTLC_BELOW_MINIMUM;
|
|
}
|
|
|
|
/* FIXME: There used to be a requirement that we not send more than
|
|
* 2^32 msat, *but* only electrum enforced it. Remove in next version:
|
|
*
|
|
* A sending node:
|
|
*...
|
|
* - for channels with `chain_hash` identifying the Bitcoin blockchain:
|
|
* - MUST set the four most significant bytes of `amount_msat` to 0.
|
|
*/
|
|
if (sender == LOCAL
|
|
&& amount_msat_greater(htlc->amount, chainparams->max_payment)
|
|
&& !channel->option_wumbo) {
|
|
return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED;
|
|
}
|
|
|
|
/* Figure out what receiver will already be committed to. */
|
|
htlc_count = gather_htlcs(tmpctx, channel, recipient, &committed, &removing, &adding);
|
|
htlc_arr_append(&adding, htlc);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* - if a sending node adds more than receiver `max_accepted_htlcs`
|
|
* HTLCs to its local commitment transaction...
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (htlc_count + 1 > channel->config[recipient].max_accepted_htlcs) {
|
|
return CHANNEL_ERR_TOO_MANY_HTLCS;
|
|
}
|
|
|
|
/* Also *we* should not add more htlc's we configured. This
|
|
* mitigates attacks in which a peer can force the opener of
|
|
* the channel to pay unnecessary onchain fees during a fee
|
|
* spike with large commitment transactions.
|
|
*/
|
|
if (enforce_aggregate_limits && sender == LOCAL
|
|
&& htlc_count + 1 > channel->config[LOCAL].max_accepted_htlcs) {
|
|
return CHANNEL_ERR_TOO_MANY_HTLCS;
|
|
}
|
|
|
|
/* These cannot overflow with HTLC amount limitations, but
|
|
* maybe adding could later if they try to add a maximal HTLC. */
|
|
if (!sum_offered_msatoshis(&committed_msat,
|
|
committed, htlc_owner(htlc))
|
|
|| !sum_offered_msatoshis(&removing_msat,
|
|
removing, htlc_owner(htlc))
|
|
|| !sum_offered_msatoshis(&adding_msat,
|
|
adding, htlc_owner(htlc))) {
|
|
return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED;
|
|
}
|
|
|
|
if (!amount_msat_add(&msat_in_htlcs, committed_msat, adding_msat)
|
|
|| !amount_msat_sub(&msat_in_htlcs, msat_in_htlcs, removing_msat)) {
|
|
return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* - if a sending node... adds more than receiver
|
|
* `max_htlc_value_in_flight_msat` worth of offered HTLCs to its
|
|
* local commitment transaction:
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
|
|
/* We don't enforce this for channel_force_htlcs: some might already
|
|
* be fulfilled/failed */
|
|
if (enforce_aggregate_limits
|
|
&& amount_msat_greater(msat_in_htlcs,
|
|
channel->config[recipient].max_htlc_value_in_flight)) {
|
|
return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A receiving node:
|
|
*...
|
|
* - receiving an `amount_msat` that the sending node cannot afford at
|
|
* the current `feerate_per_kw` (while maintaining its channel
|
|
* reserve and any `to_local_anchor` and `to_remote_anchor` costs):
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (enforce_aggregate_limits) {
|
|
struct amount_msat remainder;
|
|
struct amount_sat fee = fee_for_htlcs(channel,
|
|
committed,
|
|
adding,
|
|
removing,
|
|
recipient);
|
|
/* set fee output pointer if given */
|
|
if (htlc_fee)
|
|
*htlc_fee = fee;
|
|
|
|
/* This is a little subtle:
|
|
*
|
|
* The change is being applied to the receiver but it will
|
|
* come back to the sender after revoke_and_ack. So the check
|
|
* here is that the remainder to the sender doesn't go below the
|
|
* sender's reserve. */
|
|
if (!get_room_above_reserve(channel, view,
|
|
adding, removing, sender,
|
|
&remainder))
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
|
|
/* 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
|
|
&& channel->opener == sender
|
|
&& !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660)))
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
|
|
if (channel->opener== sender) {
|
|
if (amount_msat_less_sat(remainder, fee)) {
|
|
status_debug("Cannot afford fee %s with %s above reserve",
|
|
type_to_string(tmpctx, struct amount_sat,
|
|
&fee),
|
|
type_to_string(tmpctx, struct amount_msat,
|
|
&remainder));
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
}
|
|
|
|
if (sender == LOCAL
|
|
&& !local_opener_has_fee_headroom(channel,
|
|
remainder,
|
|
committed,
|
|
adding,
|
|
removing)) {
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
}
|
|
}
|
|
|
|
/* Try not to add a payment which will take opener into fees
|
|
* on either our side or theirs. */
|
|
if (sender == LOCAL) {
|
|
if (!get_room_above_reserve(channel, view,
|
|
adding, removing,
|
|
channel->opener,
|
|
&remainder))
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
|
|
if (option_anchor_outputs
|
|
&& channel->opener != sender
|
|
&& !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660)))
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
|
|
/* Should be able to afford both their own commit tx
|
|
* fee, and other's commit tx fee, which are subtly
|
|
* different! */
|
|
fee = fee_for_htlcs(channel,
|
|
committed,
|
|
adding,
|
|
removing,
|
|
channel->opener);
|
|
/* set fee output pointer if given */
|
|
if (htlc_fee && amount_sat_greater(fee, *htlc_fee))
|
|
*htlc_fee = fee;
|
|
if (amount_msat_less_sat(remainder, fee)) {
|
|
status_debug("Funder could not afford own fee %s with %s above reserve",
|
|
type_to_string(tmpctx,
|
|
struct amount_sat,
|
|
&fee),
|
|
type_to_string(tmpctx,
|
|
struct amount_msat,
|
|
&remainder));
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
}
|
|
fee = fee_for_htlcs(channel,
|
|
committed,
|
|
adding,
|
|
removing,
|
|
!channel->opener);
|
|
/* set fee output pointer if given */
|
|
if (htlc_fee && amount_sat_greater(fee, *htlc_fee))
|
|
*htlc_fee = fee;
|
|
if (amount_msat_less_sat(remainder, fee)) {
|
|
status_debug("Funder could not afford peer's fee %s with %s above reserve",
|
|
type_to_string(tmpctx,
|
|
struct amount_sat,
|
|
&fee),
|
|
type_to_string(tmpctx,
|
|
struct amount_msat,
|
|
&remainder));
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
}
|
|
}
|
|
}
|
|
|
|
htlc_dust_amt = AMOUNT_MSAT(0);
|
|
feerate = channel_feerate(channel, recipient);
|
|
/* Note that we check for trimmed htlcs at an
|
|
* *accelerated* rate, so that future feerate changes
|
|
* don't suddenly surprise us */
|
|
feerate_ceil = htlc_trim_feerate_ceiling(feerate);
|
|
|
|
if (!htlc_dust(channel, committed,
|
|
adding, removing, recipient,
|
|
feerate_ceil, &htlc_dust_amt))
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
|
|
if (amount_msat_greater(htlc_dust_amt,
|
|
channel->config[LOCAL].max_dust_htlc_exposure_msat)) {
|
|
/* BOLT-919 #2:
|
|
* A node:
|
|
* - upon an incoming HTLC:
|
|
* - if a HTLC's `amount_msat` is inferior to the
|
|
* counterparty's `dust_limit_satoshis` plus the HTLC-timeout fee
|
|
* at the `dust_buffer_feerate`: ...
|
|
* - SHOULD fail this HTLC once it's committed
|
|
* - SHOULD NOT reveal a preimage for this HTLC
|
|
*/
|
|
/* Note: Marking this as 'fail_immediate' and
|
|
* NOT returning an ERR will fail this HTLC
|
|
* once it's committed */
|
|
htlc->fail_immediate = true;
|
|
if (err_immediate_failures)
|
|
return CHANNEL_ERR_DUST_FAILURE;
|
|
}
|
|
|
|
|
|
/* Also check the sender, as they'll eventually have the same
|
|
* constraint */
|
|
htlc_dust_amt = AMOUNT_MSAT(0);
|
|
feerate = channel_feerate(channel, sender);
|
|
feerate_ceil = htlc_trim_feerate_ceiling(feerate);
|
|
if (!htlc_dust(channel, committed, adding,
|
|
removing, sender, feerate_ceil,
|
|
&htlc_dust_amt))
|
|
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
|
|
|
|
if (amount_msat_greater(htlc_dust_amt,
|
|
channel->config[LOCAL].max_dust_htlc_exposure_msat)) {
|
|
htlc->fail_immediate = true;
|
|
if (err_immediate_failures)
|
|
return CHANNEL_ERR_DUST_FAILURE;
|
|
}
|
|
dump_htlc(htlc, "NEW:");
|
|
htlc_map_add(channel->htlcs, tal_steal(channel, htlc));
|
|
if (htlcp)
|
|
*htlcp = htlc;
|
|
|
|
return CHANNEL_ERR_ADD_OK;
|
|
}
|
|
|
|
enum channel_add_err channel_add_htlc(struct channel *channel,
|
|
enum side sender,
|
|
u64 id,
|
|
struct amount_msat amount,
|
|
u32 cltv_expiry,
|
|
const struct sha256 *payment_hash,
|
|
const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
|
|
const struct pubkey *blinding TAKES,
|
|
struct htlc **htlcp,
|
|
struct amount_sat *htlc_fee,
|
|
bool err_immediate_failures)
|
|
{
|
|
enum htlc_state state;
|
|
|
|
if (sender == LOCAL)
|
|
state = SENT_ADD_HTLC;
|
|
else
|
|
state = RCVD_ADD_HTLC;
|
|
|
|
/* BOLT #2:
|
|
* - MUST increase the value of `id` by 1 for each successive offer.
|
|
*/
|
|
/* This is a weak (bit cheap) check: */
|
|
if (htlc_get(channel->htlcs, id+1, sender))
|
|
status_broken("Peer sent out-of-order HTLC ids (is that you, old c-lightning node?)");
|
|
|
|
return add_htlc(channel, state, id, amount, cltv_expiry,
|
|
payment_hash, routing, blinding,
|
|
htlcp, true, htlc_fee, err_immediate_failures);
|
|
}
|
|
|
|
struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id)
|
|
{
|
|
return htlc_get(channel->htlcs, id, sender);
|
|
}
|
|
|
|
enum channel_remove_err channel_fulfill_htlc(struct channel *channel,
|
|
enum side owner,
|
|
u64 id,
|
|
const struct preimage *preimage,
|
|
struct htlc **htlcp)
|
|
{
|
|
struct sha256 hash;
|
|
struct htlc *htlc;
|
|
|
|
htlc = channel_get_htlc(channel, owner, id);
|
|
if (!htlc)
|
|
return CHANNEL_ERR_NO_SUCH_ID;
|
|
|
|
if (htlc->r)
|
|
return CHANNEL_ERR_ALREADY_FULFILLED;
|
|
|
|
sha256(&hash, preimage, sizeof(*preimage));
|
|
/* BOLT #2:
|
|
*
|
|
* - if the `payment_preimage` value in `update_fulfill_htlc`
|
|
* doesn't SHA256 hash to the corresponding HTLC `payment_hash`:
|
|
* - MUST send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (!sha256_eq(&hash, &htlc->rhash))
|
|
return CHANNEL_ERR_BAD_PREIMAGE;
|
|
|
|
htlc->r = tal_dup(htlc, struct preimage, preimage);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* - if the `id` does not correspond to an HTLC in its current
|
|
* commitment transaction:
|
|
* - MUST send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) {
|
|
status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s",
|
|
htlc->id, htlc_state_name(htlc->state));
|
|
return CHANNEL_ERR_HTLC_UNCOMMITTED;
|
|
}
|
|
|
|
/* We enforce a stricter check, forcing state machine to be linear,
|
|
* based on: */
|
|
/* BOLT #2:
|
|
*
|
|
* A node:
|
|
*...
|
|
* - until the corresponding HTLC is irrevocably committed in both
|
|
* sides' commitment transactions:
|
|
* - MUST NOT send an `update_fulfill_htlc`, `update_fail_htlc`, or
|
|
* `update_fail_malformed_htlc`.
|
|
*/
|
|
if (htlc->state == SENT_ADD_ACK_REVOCATION)
|
|
htlc->state = RCVD_REMOVE_HTLC;
|
|
else if (htlc->state == RCVD_ADD_ACK_REVOCATION)
|
|
htlc->state = SENT_REMOVE_HTLC;
|
|
else {
|
|
status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s",
|
|
htlc->id, htlc_state_name(htlc->state));
|
|
return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE;
|
|
}
|
|
|
|
dump_htlc(htlc, "FULFILL:");
|
|
|
|
if (htlcp)
|
|
*htlcp = htlc;
|
|
|
|
return CHANNEL_ERR_REMOVE_OK;
|
|
}
|
|
|
|
enum channel_remove_err channel_fail_htlc(struct channel *channel,
|
|
enum side owner, u64 id,
|
|
struct htlc **htlcp)
|
|
{
|
|
struct htlc *htlc;
|
|
|
|
htlc = channel_get_htlc(channel, owner, id);
|
|
if (!htlc)
|
|
return CHANNEL_ERR_NO_SUCH_ID;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* A receiving node:
|
|
* - if the `id` does not correspond to an HTLC in its current
|
|
* commitment transaction:
|
|
* - MUST send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) {
|
|
status_unusual("channel_fail_htlc: %"PRIu64" in state %s",
|
|
htlc->id, htlc_state_name(htlc->state));
|
|
return CHANNEL_ERR_HTLC_UNCOMMITTED;
|
|
}
|
|
|
|
/* FIXME: Technically, they can fail this before we're committed to
|
|
* it. This implies a non-linear state machine. */
|
|
if (htlc->state == SENT_ADD_ACK_REVOCATION)
|
|
htlc->state = RCVD_REMOVE_HTLC;
|
|
else if (htlc->state == RCVD_ADD_ACK_REVOCATION)
|
|
htlc->state = SENT_REMOVE_HTLC;
|
|
else {
|
|
status_unusual("channel_fail_htlc: %"PRIu64" in state %s",
|
|
htlc->id, htlc_state_name(htlc->state));
|
|
return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE;
|
|
}
|
|
|
|
dump_htlc(htlc, "FAIL:");
|
|
if (htlcp)
|
|
*htlcp = htlc;
|
|
return CHANNEL_ERR_REMOVE_OK;
|
|
}
|
|
|
|
static void htlc_incstate(struct channel *channel,
|
|
struct htlc *htlc,
|
|
enum side sidechanged,
|
|
struct balance owed[NUM_SIDES])
|
|
{
|
|
int preflags, postflags;
|
|
const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED);
|
|
|
|
status_debug("htlc %"PRIu64": %s->%s", htlc->id,
|
|
htlc_state_name(htlc->state),
|
|
htlc_state_name(htlc->state+1));
|
|
|
|
preflags = htlc_state_flags(htlc->state);
|
|
postflags = htlc_state_flags(htlc->state + 1);
|
|
/* You can't change sides. */
|
|
assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))
|
|
== (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)));
|
|
|
|
htlc->state++;
|
|
|
|
/* If we've added or removed, adjust balances. */
|
|
if (!(preflags & committed_f) && (postflags & committed_f)) {
|
|
status_debug("htlc added %s: local %"PRId64" remote %"PRId64,
|
|
side_to_str(sidechanged),
|
|
owed[LOCAL].msat, owed[REMOTE].msat);
|
|
balance_add_htlc(&owed[LOCAL], htlc, LOCAL);
|
|
balance_add_htlc(&owed[REMOTE], htlc, REMOTE);
|
|
status_debug("-> local %"PRId64" remote %"PRId64,
|
|
owed[LOCAL].msat, owed[REMOTE].msat);
|
|
} else if ((preflags & committed_f) && !(postflags & committed_f)) {
|
|
status_debug("htlc added %s: local %"PRId64" remote %"PRId64,
|
|
side_to_str(sidechanged),
|
|
owed[LOCAL].msat, owed[REMOTE].msat);
|
|
balance_remove_htlc(&owed[LOCAL], htlc, LOCAL);
|
|
balance_remove_htlc(&owed[REMOTE], htlc, REMOTE);
|
|
status_debug("-> local %"PRId64" remote %"PRId64,
|
|
owed[LOCAL].msat, owed[REMOTE].msat);
|
|
}
|
|
}
|
|
|
|
/* Returns true if a change was made. */
|
|
static bool fee_incstate(struct channel *channel,
|
|
enum side sidechanged,
|
|
enum htlc_state hstate)
|
|
{
|
|
int preflags, postflags;
|
|
|
|
preflags = htlc_state_flags(hstate);
|
|
postflags = htlc_state_flags(hstate + 1);
|
|
|
|
/* You can't change sides. */
|
|
assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))
|
|
== (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)));
|
|
|
|
/* These only advance through ADDING states. */
|
|
if (!(htlc_state_flags(hstate) & HTLC_ADDING))
|
|
return false;
|
|
|
|
if (!inc_fee_state(channel->fee_states, hstate))
|
|
return false;
|
|
|
|
status_debug("Feerate: %s->%s %s now %u",
|
|
htlc_state_name(hstate),
|
|
htlc_state_name(hstate+1),
|
|
side_to_str(sidechanged),
|
|
*channel->fee_states->feerate[hstate+1]);
|
|
return true;
|
|
}
|
|
|
|
static bool blockheight_incstate(struct channel *channel,
|
|
enum side sidechanged,
|
|
enum htlc_state hstate)
|
|
{
|
|
int preflags, postflags;
|
|
|
|
preflags = htlc_state_flags(hstate);
|
|
postflags = htlc_state_flags(hstate + 1);
|
|
|
|
/* You can't change sides. */
|
|
assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))
|
|
== (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)));
|
|
|
|
/* These only advance through ADDING states. */
|
|
if (!(htlc_state_flags(hstate) & HTLC_ADDING))
|
|
return false;
|
|
|
|
if (!inc_height_state(channel->blockheight_states, hstate))
|
|
return false;
|
|
|
|
status_debug("Blockheight: %s->%s %s now %u",
|
|
htlc_state_name(hstate),
|
|
htlc_state_name(hstate+1),
|
|
side_to_str(sidechanged),
|
|
*channel->blockheight_states->height[hstate+1]);
|
|
return true;
|
|
}
|
|
|
|
/* Returns flags which were changed. */
|
|
static int change_htlcs(struct channel *channel,
|
|
enum side sidechanged,
|
|
const enum htlc_state *htlc_states,
|
|
size_t n_hstates,
|
|
const struct htlc ***htlcs,
|
|
const char *prefix)
|
|
{
|
|
struct htlc_map_iter it;
|
|
struct htlc *h;
|
|
int cflags = 0;
|
|
int i;
|
|
struct balance owed[NUM_SIDES];
|
|
|
|
for (i = 0; i < NUM_SIDES; i++)
|
|
to_balance(&owed[i], channel->view[sidechanged].owed[i]);
|
|
|
|
for (h = htlc_map_first(channel->htlcs, &it);
|
|
h;
|
|
h = htlc_map_next(channel->htlcs, &it)) {
|
|
for (i = 0; i < n_hstates; i++) {
|
|
if (h->state == htlc_states[i]) {
|
|
htlc_incstate(channel, h, sidechanged, owed);
|
|
dump_htlc(h, prefix);
|
|
htlc_arr_append(htlcs, h);
|
|
cflags |= (htlc_state_flags(htlc_states[i])
|
|
^ htlc_state_flags(h->state));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < NUM_SIDES; i++) {
|
|
if (!balance_ok(&owed[i], &channel->view[sidechanged].owed[i])) {
|
|
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
|
"%s: %s balance underflow: %s -> %"PRId64,
|
|
side_to_str(sidechanged),
|
|
side_to_str(i),
|
|
type_to_string(tmpctx, struct amount_msat,
|
|
&channel->view[sidechanged].owed[i]),
|
|
owed[i].msat);
|
|
}
|
|
}
|
|
|
|
/* Update fees and blockheight (do backwards, to avoid
|
|
* double-increment!). */
|
|
for (i = n_hstates - 1; i >= 0; i--) {
|
|
if (fee_incstate(channel, sidechanged, htlc_states[i]))
|
|
cflags |= (htlc_state_flags(htlc_states[i])
|
|
^ htlc_state_flags(htlc_states[i]+1));
|
|
|
|
if (blockheight_incstate(channel, sidechanged, htlc_states[i]))
|
|
cflags |= (htlc_state_flags(htlc_states[i])
|
|
^ htlc_state_flags(htlc_states[i]+1));
|
|
}
|
|
|
|
return cflags;
|
|
}
|
|
|
|
/* FIXME: The sender's requirements are *implied* by this, not stated! */
|
|
/* BOLT #2:
|
|
*
|
|
* A receiving node:
|
|
*...
|
|
* - if the sender cannot afford the new fee rate on the receiving node's
|
|
* current commitment transaction:
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
u32 approx_max_feerate(const struct channel *channel)
|
|
{
|
|
size_t num;
|
|
u64 weight;
|
|
struct amount_sat avail;
|
|
const struct htlc **committed, **adding, **removing;
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
|
|
gather_htlcs(tmpctx, channel, !channel->opener,
|
|
&committed, &removing, &adding);
|
|
|
|
/* 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);
|
|
|
|
/* Available is their view */
|
|
avail = amount_msat_to_sat_round_down(channel->view[!channel->opener].owed[channel->opener]);
|
|
|
|
/* 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
|
|
&& !amount_sat_sub(&avail, avail, AMOUNT_SAT(660))) {
|
|
avail = AMOUNT_SAT(0);
|
|
} else {
|
|
/* We should never go below reserve. */
|
|
if (!amount_sat_sub(&avail, avail,
|
|
channel->config[!channel->opener].channel_reserve))
|
|
avail = AMOUNT_SAT(0);
|
|
}
|
|
|
|
return avail.satoshis / weight * 1000; /* Raw: once-off reverse feerate*/
|
|
}
|
|
|
|
/* Is the sum of trimmed htlcs, as this new feerate, above our
|
|
* max allowed htlc dust limit? */
|
|
static struct amount_msat htlc_calculate_dust(const struct channel *channel,
|
|
u32 feerate_per_kw,
|
|
enum side side)
|
|
{
|
|
const struct htlc **committed, **adding, **removing;
|
|
struct amount_msat acc_dust = AMOUNT_MSAT(0);
|
|
|
|
gather_htlcs(tmpctx, channel, side,
|
|
&committed, &removing, &adding);
|
|
|
|
htlc_dust(channel, committed, adding, removing,
|
|
side, feerate_per_kw, &acc_dust);
|
|
|
|
return acc_dust;
|
|
}
|
|
|
|
bool htlc_dust_ok(const struct channel *channel,
|
|
u32 feerate_per_kw,
|
|
enum side side)
|
|
{
|
|
struct amount_msat total_dusted;
|
|
|
|
total_dusted = htlc_calculate_dust(channel, feerate_per_kw, side);
|
|
|
|
return amount_msat_greater_eq(
|
|
channel->config[LOCAL].max_dust_htlc_exposure_msat,
|
|
total_dusted);
|
|
}
|
|
|
|
bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw)
|
|
{
|
|
struct amount_sat needed, fee;
|
|
struct amount_sat dust_limit = channel->config[!channel->opener].dust_limit;
|
|
size_t untrimmed;
|
|
const struct htlc **committed, **adding, **removing;
|
|
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
|
|
|
gather_htlcs(tmpctx, channel, !channel->opener,
|
|
&committed, &removing, &adding);
|
|
|
|
untrimmed = commit_tx_num_untrimmed(committed, feerate_per_kw, dust_limit,
|
|
option_anchor_outputs,
|
|
!channel->opener)
|
|
+ commit_tx_num_untrimmed(adding, feerate_per_kw, dust_limit,
|
|
option_anchor_outputs,
|
|
!channel->opener)
|
|
- commit_tx_num_untrimmed(removing, feerate_per_kw, dust_limit,
|
|
option_anchor_outputs,
|
|
!channel->opener);
|
|
|
|
fee = commit_tx_base_fee(feerate_per_kw, untrimmed,
|
|
option_anchor_outputs);
|
|
|
|
/* 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
|
|
&& !amount_sat_add(&fee, fee, AMOUNT_SAT(660)))
|
|
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
|
"Cannot add 660 sats to %s for anchor",
|
|
type_to_string(tmpctx, struct amount_sat,
|
|
&fee));
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* - if the sender cannot afford the new fee rate on the receiving
|
|
* node's current commitment transaction:
|
|
* - SHOULD send a `warning` and close the connection, or send an
|
|
* `error` and fail the channel.
|
|
*/
|
|
/* Note: sender == opener */
|
|
|
|
/* How much does it think it has? Must be >= reserve + fee */
|
|
if (!amount_sat_add(&needed, fee,
|
|
channel->config[!channel->opener].channel_reserve))
|
|
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
|
"Cannot add fee %s and reserve %s",
|
|
type_to_string(tmpctx, struct amount_sat,
|
|
&fee),
|
|
type_to_string(tmpctx, struct amount_sat,
|
|
&channel->config[!channel->opener].channel_reserve));
|
|
|
|
status_debug("We need %s at feerate %u for %zu untrimmed htlcs: we have %s/%s",
|
|
type_to_string(tmpctx, struct amount_sat, &needed),
|
|
feerate_per_kw, untrimmed,
|
|
type_to_string(tmpctx, struct amount_msat,
|
|
&channel->view[LOCAL].owed[channel->opener]),
|
|
type_to_string(tmpctx, struct amount_msat,
|
|
&channel->view[REMOTE].owed[channel->opener]));
|
|
return amount_msat_greater_eq_sat(channel->view[!channel->opener].owed[channel->opener],
|
|
needed);
|
|
}
|
|
|
|
bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw)
|
|
{
|
|
if (!can_opener_afford_feerate(channel, feerate_per_kw))
|
|
return false;
|
|
|
|
/* BOLT-919 #2:
|
|
* - if the `dust_balance_on_holder_tx` at the
|
|
* new `dust_buffer_feerate` is superior to
|
|
* the `max_dust_htlc_exposure_msat`:
|
|
* ...
|
|
* - MAY fail the channel
|
|
*/
|
|
if (!htlc_dust_ok(channel, feerate_per_kw, REMOTE) ||
|
|
!htlc_dust_ok(channel, feerate_per_kw, LOCAL))
|
|
return false;
|
|
|
|
status_debug("Setting %s feerate to %u",
|
|
side_to_str(!channel->opener), feerate_per_kw);
|
|
|
|
start_fee_update(channel->fee_states, channel->opener, feerate_per_kw);
|
|
return true;
|
|
}
|
|
|
|
void channel_update_blockheight(struct channel *channel,
|
|
u32 blockheight)
|
|
{
|
|
status_debug("Setting %s blockheight to %u",
|
|
side_to_str(!channel->opener), blockheight);
|
|
|
|
start_height_update(channel->blockheight_states, channel->opener,
|
|
blockheight);
|
|
}
|
|
|
|
bool channel_sending_commit(struct channel *channel,
|
|
const struct htlc ***htlcs)
|
|
{
|
|
int change;
|
|
const enum htlc_state states[] = { SENT_ADD_HTLC,
|
|
SENT_REMOVE_REVOCATION,
|
|
SENT_ADD_REVOCATION,
|
|
SENT_REMOVE_HTLC };
|
|
status_debug("Trying commit");
|
|
|
|
change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states),
|
|
htlcs, "sending_commit");
|
|
if (!change)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool channel_rcvd_revoke_and_ack(struct channel *channel,
|
|
const struct htlc ***htlcs)
|
|
{
|
|
int change;
|
|
const enum htlc_state states[] = { SENT_ADD_COMMIT,
|
|
SENT_REMOVE_ACK_COMMIT,
|
|
SENT_ADD_ACK_COMMIT,
|
|
SENT_REMOVE_COMMIT };
|
|
|
|
status_debug("Received revoke_and_ack");
|
|
change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states),
|
|
htlcs, "rcvd_revoke_and_ack");
|
|
|
|
/* Their ack can queue changes on our side. */
|
|
return (change & HTLC_LOCAL_F_PENDING);
|
|
}
|
|
|
|
/* FIXME: We can actually merge these two... */
|
|
bool channel_rcvd_commit(struct channel *channel, const struct htlc ***htlcs)
|
|
{
|
|
int change;
|
|
const enum htlc_state states[] = { RCVD_ADD_REVOCATION,
|
|
RCVD_REMOVE_HTLC,
|
|
RCVD_ADD_HTLC,
|
|
RCVD_REMOVE_REVOCATION };
|
|
|
|
status_debug("Received commit");
|
|
change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states),
|
|
htlcs, "rcvd_commit");
|
|
if (!change)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool channel_sending_revoke_and_ack(struct channel *channel)
|
|
{
|
|
int change;
|
|
const enum htlc_state states[] = { RCVD_ADD_ACK_COMMIT,
|
|
RCVD_REMOVE_COMMIT,
|
|
RCVD_ADD_COMMIT,
|
|
RCVD_REMOVE_ACK_COMMIT };
|
|
status_debug("Sending revoke_and_ack");
|
|
change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), NULL,
|
|
"sending_revoke_and_ack");
|
|
|
|
/* Our ack can queue changes on their side. */
|
|
return (change & HTLC_REMOTE_F_PENDING);
|
|
}
|
|
|
|
size_t num_channel_htlcs(const struct channel *channel)
|
|
{
|
|
struct htlc_map_iter it;
|
|
const struct htlc *htlc;
|
|
size_t n = 0;
|
|
|
|
for (htlc = htlc_map_first(channel->htlcs, &it);
|
|
htlc;
|
|
htlc = htlc_map_next(channel->htlcs, &it)) {
|
|
/* FIXME: Clean these out! */
|
|
if (!htlc_is_dead(htlc))
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES],
|
|
struct htlc *htlc)
|
|
{
|
|
enum side side;
|
|
|
|
for (side = 0; side < NUM_SIDES; side++) {
|
|
/* Did it ever add it? */
|
|
if (!htlc_has(htlc, HTLC_FLAG(side, HTLC_F_WAS_COMMITTED)))
|
|
continue;
|
|
|
|
/* Add it. */
|
|
balance_add_htlc(&view_owed[side][LOCAL], htlc, LOCAL);
|
|
balance_add_htlc(&view_owed[side][REMOTE], htlc, REMOTE);
|
|
|
|
/* If it is no longer committed, remove it (depending
|
|
* on fail || fulfill). */
|
|
if (htlc_has(htlc, HTLC_FLAG(side, HTLC_F_COMMITTED)))
|
|
continue;
|
|
|
|
if (!htlc->failed && !htlc->r) {
|
|
status_broken("%s HTLC %"PRIu64
|
|
" %s neither fail nor fulfill?",
|
|
htlc_state_owner(htlc->state) == LOCAL
|
|
? "out" : "in",
|
|
htlc->id,
|
|
htlc_state_name(htlc->state));
|
|
return false;
|
|
}
|
|
balance_remove_htlc(&view_owed[side][LOCAL], htlc, LOCAL);
|
|
balance_remove_htlc(&view_owed[side][REMOTE], htlc, REMOTE);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool pending_updates(const struct channel *channel,
|
|
enum side side,
|
|
bool uncommitted_ok)
|
|
{
|
|
struct htlc_map_iter it;
|
|
const struct htlc *htlc;
|
|
|
|
/* Initiator might have fee changes or blockheight updates in play. */
|
|
if (side == channel->opener) {
|
|
if (!feerate_changes_done(channel->fee_states, uncommitted_ok))
|
|
return true;
|
|
|
|
if (!blockheight_changes_done(channel->blockheight_states,
|
|
uncommitted_ok))
|
|
return true;
|
|
}
|
|
|
|
for (htlc = htlc_map_first(channel->htlcs, &it);
|
|
htlc;
|
|
htlc = htlc_map_next(channel->htlcs, &it)) {
|
|
int flags = htlc_state_flags(htlc->state);
|
|
|
|
/* If it's still being added, its owner added it. */
|
|
if (flags & HTLC_ADDING) {
|
|
/* It might be OK if it's added, but not committed */
|
|
if (uncommitted_ok
|
|
&& (flags & HTLC_FLAG(!side, HTLC_F_PENDING)))
|
|
continue;
|
|
if (htlc_owner(htlc) == side)
|
|
return true;
|
|
/* If it's being removed, non-owner removed it */
|
|
} else if (htlc_state_flags(htlc->state) & HTLC_REMOVING) {
|
|
/* It might be OK if it's removed, but not committed */
|
|
if (uncommitted_ok
|
|
&& (flags & HTLC_FLAG(!side, HTLC_F_PENDING)))
|
|
continue;
|
|
if (htlc_owner(htlc) != side)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool channel_force_htlcs(struct channel *channel,
|
|
const struct existing_htlc **htlcs)
|
|
{
|
|
struct balance view_owed[NUM_SIDES][NUM_SIDES];
|
|
|
|
/* You'd think, since we traverse HTLCs in ID order, this would never
|
|
* go negative. But this ignores the fact that HTLCs ids from each
|
|
* side have no correlation with each other. Copy into struct balance,
|
|
* to allow transient underflow. */
|
|
for (int view = 0; view < NUM_SIDES; view++) {
|
|
for (int side = 0; side < NUM_SIDES; side++) {
|
|
to_balance(&view_owed[view][side],
|
|
channel->view[view].owed[side]);
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < tal_count(htlcs); i++) {
|
|
enum channel_add_err e;
|
|
struct htlc *htlc;
|
|
|
|
status_debug("Restoring HTLC %zu/%zu:"
|
|
" id=%"PRIu64" amount=%s cltv=%u"
|
|
" payment_hash=%s %s",
|
|
i, tal_count(htlcs),
|
|
htlcs[i]->id,
|
|
type_to_string(tmpctx, struct amount_msat,
|
|
&htlcs[i]->amount),
|
|
htlcs[i]->cltv_expiry,
|
|
type_to_string(tmpctx, struct sha256,
|
|
&htlcs[i]->payment_hash),
|
|
htlcs[i]->payment_preimage ? "(have preimage)"
|
|
: htlcs[i]->failed ? "(failed)" : "");
|
|
|
|
e = add_htlc(channel, htlcs[i]->state,
|
|
htlcs[i]->id, htlcs[i]->amount,
|
|
htlcs[i]->cltv_expiry,
|
|
&htlcs[i]->payment_hash,
|
|
htlcs[i]->onion_routing_packet,
|
|
htlcs[i]->blinding,
|
|
&htlc, false, NULL, false);
|
|
if (e != CHANNEL_ERR_ADD_OK) {
|
|
status_broken("%s HTLC %"PRIu64" failed error %u",
|
|
htlc_state_owner(htlcs[i]->state) == LOCAL
|
|
? "out" : "in", htlcs[i]->id, e);
|
|
return false;
|
|
}
|
|
if (htlcs[i]->payment_preimage)
|
|
htlc->r = tal_dup(htlc, struct preimage,
|
|
htlcs[i]->payment_preimage);
|
|
if (htlcs[i]->failed)
|
|
htlc->failed = tal_steal(htlc, htlcs[i]->failed);
|
|
|
|
if (!adjust_balance(view_owed, htlc))
|
|
return false;
|
|
}
|
|
|
|
/* Convert back and check */
|
|
for (int view = 0; view < NUM_SIDES; view++) {
|
|
for (int side = 0; side < NUM_SIDES; side++) {
|
|
if (!balance_ok(&view_owed[view][side],
|
|
&channel->view[view].owed[side])) {
|
|
status_broken("view %s[%s] balance underflow:"
|
|
" %"PRId64,
|
|
side_to_str(view),
|
|
side_to_str(side),
|
|
view_owed[view][side].msat);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
const char *channel_add_err_name(enum channel_add_err e)
|
|
{
|
|
static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)];
|
|
|
|
for (size_t i = 0; enum_channel_add_err_names[i].name; i++) {
|
|
if (enum_channel_add_err_names[i].v == e)
|
|
return enum_channel_add_err_names[i].name;
|
|
}
|
|
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
|
|
return invalidbuf;
|
|
}
|
|
|
|
const char *channel_remove_err_name(enum channel_remove_err e)
|
|
{
|
|
static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)];
|
|
|
|
for (size_t i = 0; enum_channel_remove_err_names[i].name; i++) {
|
|
if (enum_channel_remove_err_names[i].v == e)
|
|
return enum_channel_remove_err_names[i].name;
|
|
}
|
|
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
|
|
return invalidbuf;
|
|
}
|