htlcs: add flag to 'fail immediately'

If we're over the dust limit, we fail it immediatey *after* commiting
it, but we need a way to signal this throughout the lifecycle, so we add
it to htlc_in struct and persist it through to the database.

If it's supposed to be failed, we fail after the commit cycle is
completed.
This commit is contained in:
niftynei
2021-09-28 14:08:11 -05:00
committed by Christian Decker
parent 208b161226
commit 42e40c1ced
11 changed files with 53 additions and 14 deletions

View File

@@ -738,7 +738,11 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
#endif
add_err = channel_add_htlc(peer->channel, REMOTE, id, amount,
cltv_expiry, &payment_hash,
onion_routing_packet, blinding, &htlc, NULL);
onion_routing_packet, blinding, &htlc, NULL,
/* We don't immediately fail incoming htlcs,
* instead we wait and fail them after
* they've been committed */
false);
if (add_err != CHANNEL_ERR_ADD_OK)
peer_failed_warn(peer->pps, &peer->channel_id,
"Bad peer_add_htlc: %s",
@@ -1468,6 +1472,7 @@ static void marshall_htlc_info(const tal_t *ctx,
ecdh(a.blinding, &a.blinding_ss);
} else
a.blinding = NULL;
a.fail_immediate = htlc->fail_immediate;
tal_arr_expand(added, a);
} else if (htlc->state == RCVD_REMOVE_COMMIT) {
if (htlc->r) {
@@ -3299,7 +3304,8 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
e = channel_add_htlc(peer->channel, LOCAL, peer->htlc_id,
amount, cltv_expiry, &payment_hash,
onion_routing_packet, take(blinding), NULL, &htlc_fee);
onion_routing_packet, take(blinding), NULL,
&htlc_fee, true);
status_debug("Adding HTLC %"PRIu64" amount=%s cltv=%u gave %s",
peer->htlc_id,
type_to_string(tmpctx, struct amount_msat, &amount),

View File

@@ -28,6 +28,9 @@ struct htlc {
/* Blinding (optional). */
struct pubkey *blinding;
/* Should we immediately fail this htlc? */
bool fail_immediate;
};
static inline bool htlc_has(const struct htlc *h, int flag)

View File

@@ -493,7 +493,8 @@ static enum channel_add_err add_htlc(struct channel *channel,
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
bool enforce_aggregate_limits,
struct amount_sat *htlc_fee)
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;
@@ -508,6 +509,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
htlc->id = id;
htlc->amount = amount;
htlc->state = state;
htlc->fail_immediate = false;
htlc->rhash = *payment_hash;
if (blinding)
@@ -768,7 +770,8 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee)
struct amount_sat *htlc_fee,
bool err_immediate_failures)
{
enum htlc_state state;
@@ -786,7 +789,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
return add_htlc(channel, state, id, amount, cltv_expiry,
payment_hash, routing, blinding,
htlcp, true, htlc_fee);
htlcp, true, htlc_fee, err_immediate_failures);
}
struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id)
@@ -1392,7 +1395,7 @@ bool channel_force_htlcs(struct channel *channel,
&htlcs[i]->payment_hash,
htlcs[i]->onion_routing_packet,
htlcs[i]->blinding,
&htlc, false, NULL);
&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

View File

@@ -103,6 +103,10 @@ u32 actual_feerate(const struct channel *channel,
* @routing: routing information (copied)
* @blinding: optional blinding information for this HTLC.
* @htlcp: optional pointer for resulting htlc: filled in if and only if CHANNEL_ERR_NONE.
* @err_immediate_failures: in some cases (dusty htlcs) we want to immediately
* fail the htlc; for peer incoming don't want to
* error, but rather mark it as failed and fail after
* it's been committed to (so set this to false)
*
* If this returns CHANNEL_ERR_NONE, the fee htlc was added and
* the output amounts adjusted accordingly. Otherwise nothing
@@ -117,7 +121,8 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee);
struct amount_sat *htlc_fee,
bool err_immediate_failures);
/**
* channel_get_htlc: find an HTLC

View File

@@ -165,7 +165,7 @@ static const struct htlc **include_htlcs(struct channel *channel, enum side side
memset(&preimage, i, sizeof(preimage));
sha256(&hash, &preimage, sizeof(preimage));
e = channel_add_htlc(channel, sender, i, msatoshi, 500+i, &hash,
dummy_routing, NULL, NULL, NULL);
dummy_routing, NULL, NULL, NULL, true);
assert(e == CHANNEL_ERR_ADD_OK);
htlcs[i] = channel_get_htlc(channel, sender, i);
}
@@ -257,7 +257,7 @@ static void send_and_fulfill_htlc(struct channel *channel,
sha256(&rhash, &r, sizeof(r));
assert(channel_add_htlc(channel, sender, 1337, msatoshi, 900, &rhash,
dummy_routing, NULL, NULL, NULL)
dummy_routing, NULL, NULL, NULL, true)
== CHANNEL_ERR_ADD_OK);
changed_htlcs = tal_arr(channel, const struct htlc *, 0);

View File

@@ -78,6 +78,7 @@ void towire_added_htlc(u8 **pptr, const struct added_htlc *added)
towire_secret(pptr, &added->blinding_ss);
} else
towire_bool(pptr, false);
towire_bool(pptr, added->fail_immediate);
}
void towire_existing_htlc(u8 **pptr, const struct existing_htlc *existing)
@@ -171,6 +172,7 @@ void fromwire_added_htlc(const u8 **cursor, size_t *max,
fromwire_secret(cursor, max, &added->blinding_ss);
} else
added->blinding = NULL;
added->fail_immediate = fromwire_bool(cursor, max);
}
struct existing_htlc *fromwire_existing_htlc(const tal_t *ctx,

View File

@@ -15,6 +15,7 @@ struct added_htlc {
struct sha256 payment_hash;
u32 cltv_expiry;
u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)];
bool fail_immediate;
/* If this is non-NULL, secret is the resulting shared secret */
struct pubkey *blinding;

View File

@@ -130,7 +130,8 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
const struct secret *shared_secret TAKES,
const struct pubkey *blinding TAKES,
const struct secret *blinding_ss,
const u8 *onion_routing_packet)
const u8 *onion_routing_packet,
bool fail_immediate)
{
struct htlc_in *hin = tal(ctx, struct htlc_in);
@@ -141,6 +142,7 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
hin->cltv_expiry = cltv_expiry;
hin->payment_hash = *payment_hash;
hin->status = NULL;
hin->fail_immediate = fail_immediate;
if (shared_secret)
hin->shared_secret = tal_dup(hin, struct secret, shared_secret);
else

View File

@@ -52,6 +52,8 @@ struct htlc_in {
struct secret blinding_ss;
/* true if we supplied the preimage */
bool *we_filled;
/* true if we immediately fail the htlc (too much dust) */
bool fail_immediate;
/* A simple text annotation shown in `listpeers` */
char *status;
@@ -154,7 +156,8 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
const struct secret *shared_secret TAKES,
const struct pubkey *blinding TAKES,
const struct secret *blinding_ss,
const u8 *onion_routing_packet);
const u8 *onion_routing_packet,
bool fail_immediate);
/* You need to set the ID, then connect_htlc_out this! */
struct htlc_out *new_htlc_out(const tal_t *ctx,

View File

@@ -1171,6 +1171,13 @@ static bool peer_accepted_htlc(const tal_t *ctx,
goto fail;
}
if (hin->fail_immediate && htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION)) {
log_debug(channel->log, "failing immediately, as requested");
/* Failing the htlc, typically done because of htlc dust */
*failmsg = towire_temporary_node_failure(ctx);
goto fail;
}
if (!replay && !htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION)) {
*failmsg = towire_temporary_node_failure(ctx);
goto fail;
@@ -1863,7 +1870,8 @@ static bool channel_added_their_htlc(struct channel *channel,
added->cltv_expiry, &added->payment_hash,
op ? &shared_secret : NULL,
added->blinding, &added->blinding_ss,
added->onion_routing_packet);
added->onion_routing_packet,
added->fail_immediate);
/* Save an incoming htlc to the wallet */
wallet_htlc_save_in(ld->wallet, channel, hin);

View File

@@ -2317,8 +2317,9 @@ void wallet_htlc_save_in(struct wallet *wallet,
" shared_secret,"
" routing_onion,"
" received_time,"
" min_commit_num) VALUES "
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
" min_commit_num, "
" fail_immediate) VALUES "
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
db_bind_u64(stmt, 0, chan->dbid);
db_bind_u64(stmt, 1, in->key.id);
@@ -2345,6 +2346,8 @@ void wallet_htlc_save_in(struct wallet *wallet,
db_bind_u64(stmt, 11, min_unsigned(chan->next_index[LOCAL]-1,
chan->next_index[REMOTE]-1));
db_bind_int(stmt, 12, in->fail_immediate);
db_exec_prepared_v2(stmt);
in->dbid = db_last_insert_id_v2(take(stmt));
}
@@ -2555,6 +2558,8 @@ static bool wallet_stmt2htlc_in(struct channel *channel,
} else
in->we_filled = NULL;
in->fail_immediate = db_column_int(stmt, 14);
return ok;
}
@@ -2683,6 +2688,7 @@ bool wallet_htlcs_load_in_for_channel(struct wallet *wallet,
", shared_secret"
", received_time"
", we_filled"
", fail_immediate"
" FROM channel_htlcs"
" WHERE direction= ?"
" AND channel_id= ?"