diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 21d951dbda8a..23a421ff9ecc 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -98,124 +98,32 @@ static bool htlc_out_update_state(struct channel *channel, return true; } -/* FIXME: Do this direclty in callers! */ -static u8 *make_failmsg(const tal_t *ctx, - const struct htlc_in *hin, - enum onion_type failcode, - const u8 *channel_update, - const struct sha256 *sha256, - u32 failheight) +static struct failed_htlc *mk_failed_htlc_badonion(const tal_t *ctx, + const struct htlc_in *hin, + enum onion_type badonion) { - u8 *msg; + struct failed_htlc *f = tal(ctx, struct failed_htlc); - switch (failcode) { - case WIRE_INVALID_REALM: - msg = towire_invalid_realm(ctx); - goto done; - case WIRE_TEMPORARY_NODE_FAILURE: - msg = towire_temporary_node_failure(ctx); - goto done; - case WIRE_PERMANENT_NODE_FAILURE: - msg = towire_permanent_node_failure(ctx); - goto done; - case WIRE_REQUIRED_NODE_FEATURE_MISSING: - msg = towire_required_node_feature_missing(ctx); - goto done; - case WIRE_TEMPORARY_CHANNEL_FAILURE: - msg = towire_temporary_channel_failure(ctx, channel_update); - goto done; - case WIRE_CHANNEL_DISABLED: - msg = towire_channel_disabled(ctx); - goto done; - case WIRE_PERMANENT_CHANNEL_FAILURE: - msg = towire_permanent_channel_failure(ctx); - goto done; - case WIRE_REQUIRED_CHANNEL_FEATURE_MISSING: - msg = towire_required_channel_feature_missing(ctx); - goto done; - case WIRE_UNKNOWN_NEXT_PEER: - msg = towire_unknown_next_peer(ctx); - goto done; - case WIRE_AMOUNT_BELOW_MINIMUM: - msg = towire_amount_below_minimum(ctx, hin->msat, - channel_update); - goto done; - case WIRE_FEE_INSUFFICIENT: - msg = towire_fee_insufficient(ctx, hin->msat, - channel_update); - goto done; - case WIRE_INCORRECT_CLTV_EXPIRY: - msg = towire_incorrect_cltv_expiry(ctx, hin->cltv_expiry, - channel_update); - goto done; - case WIRE_EXPIRY_TOO_SOON: - msg = towire_expiry_too_soon(ctx, channel_update); - goto done; - case WIRE_EXPIRY_TOO_FAR: - msg = towire_expiry_too_far(ctx); - goto done; - case WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS: - assert(failheight); - msg = towire_incorrect_or_unknown_payment_details( - ctx, hin->msat, failheight); - goto done; - case WIRE_FINAL_INCORRECT_CLTV_EXPIRY: - msg = towire_final_incorrect_cltv_expiry(ctx, hin->cltv_expiry); - goto done; - case WIRE_FINAL_INCORRECT_HTLC_AMOUNT: - msg = towire_final_incorrect_htlc_amount(ctx, hin->msat); - goto done; - case WIRE_INVALID_ONION_VERSION: - msg = towire_invalid_onion_version(ctx, sha256); - goto done; - case WIRE_INVALID_ONION_HMAC: - msg = towire_invalid_onion_hmac(ctx, sha256); - goto done; - case WIRE_INVALID_ONION_KEY: - msg = towire_invalid_onion_key(ctx, sha256); - goto done; - case WIRE_INVALID_ONION_PAYLOAD: - /* FIXME: wire this into tlv parser somehow. */ - msg = towire_invalid_onion_payload(ctx, 0, 0); - goto done; - case WIRE_MPP_TIMEOUT: - msg = towire_mpp_timeout(ctx); - goto done; - } - fatal("Asked to create failmsg %u (%s)", - failcode, onion_type_name(failcode)); - -done: - return msg; + f->id = hin->key.id; + f->onion = NULL; + f->badonion = badonion; + f->sha256_of_onion = tal(f, struct sha256); + sha256(f->sha256_of_onion, hin->onion_routing_packet, + sizeof(hin->onion_routing_packet)); + return f; } static struct failed_htlc *mk_failed_htlc(const tal_t *ctx, const struct htlc_in *hin, - enum onion_type failcode, - const struct onionreply *failonion, - const u8 *channel_update) + const struct onionreply *failonion) { struct failed_htlc *f = tal(ctx, struct failed_htlc); f->id = hin->key.id; - if (failcode & BADONION) { - f->onion = NULL; - f->badonion = failcode; - f->sha256_of_onion = tal(f, struct sha256); - sha256(f->sha256_of_onion, hin->onion_routing_packet, - sizeof(hin->onion_routing_packet)); - } else { - f->sha256_of_onion = NULL; - - if (!failonion) { - const u8 *failmsg = make_failmsg(tmpctx, hin, failcode, channel_update, NULL, get_block_height(hin->key.channel->owner->ld->topology)); - failonion = create_onionreply(tmpctx, hin->shared_secret, - failmsg); - } - - /* Wrap onion error */ - f->onion = wrap_onionreply(tmpctx, hin->shared_secret, failonion); - } + f->sha256_of_onion = NULL; + f->badonion = 0; + /* Wrap onion error */ + f->onion = wrap_onionreply(f, hin->shared_secret, failonion); return f; } @@ -223,7 +131,7 @@ static struct failed_htlc *mk_failed_htlc(const tal_t *ctx, static void fail_in_htlc(struct htlc_in *hin, const struct onionreply *failonion TAKES) { - struct failed_htlc failed_htlc; + struct failed_htlc *failed_htlc; assert(!hin->preimage); hin->failonion = dup_onionreply(hin, failonion); @@ -240,20 +148,16 @@ static void fail_in_htlc(struct htlc_in *hin, if (channel_on_chain(hin->key.channel)) return; - failed_htlc.id = hin->key.id; - failed_htlc.sha256_of_onion = NULL; - /* Wrap onion error */ - failed_htlc.onion - = wrap_onionreply(tmpctx, hin->shared_secret, hin->failonion); + failed_htlc = mk_failed_htlc(tmpctx, hin, hin->failonion); subd_send_msg(hin->key.channel->owner, - take(towire_channel_fail_htlc(NULL, &failed_htlc))); + take(towire_channel_fail_htlc(NULL, failed_htlc))); } /* Immediately fail HTLC with a BADONION code */ static void local_fail_in_htlc_badonion(struct htlc_in *hin, enum onion_type badonion) { - struct failed_htlc failed_htlc; + struct failed_htlc *failed_htlc; assert(!hin->preimage); assert(badonion & BADONION); @@ -262,12 +166,7 @@ static void local_fail_in_htlc_badonion(struct htlc_in *hin, htlc_in_update_state(hin->key.channel, hin, SENT_REMOVE_HTLC); htlc_in_check(hin, __func__); - failed_htlc.id = hin->key.id; - failed_htlc.onion = NULL; - failed_htlc.badonion = badonion; - failed_htlc.sha256_of_onion = tal(tmpctx, struct sha256); - sha256(failed_htlc.sha256_of_onion, hin->onion_routing_packet, - sizeof(hin->onion_routing_packet)); + failed_htlc = mk_failed_htlc_badonion(tmpctx, hin, badonion); /* Tell peer, if we can. */ if (!hin->key.channel->owner) @@ -278,7 +177,7 @@ static void local_fail_in_htlc_badonion(struct htlc_in *hin, return; subd_send_msg(hin->key.channel->owner, - take(towire_channel_fail_htlc(NULL, &failed_htlc))); + take(towire_channel_fail_htlc(NULL, failed_htlc))); } /* This is used for cases where we can immediately fail the HTLC. */ @@ -2063,21 +1962,22 @@ static void add_fulfill(u64 id, enum side side, } static void add_fail(struct htlc_in *hin, - enum onion_type failcode, const struct onionreply *failonion, const struct failed_htlc ***failed_htlcs) { struct failed_htlc *newf; - /* We don't save the outgoing channel which failed; probably - * not worth it for this corner case. So we can't set - * hin->failoutchannel to tell channeld what update to send, - * thus we turn those into a WIRE_TEMPORARY_NODE_FAILURE. */ - if (failcode & UPDATE) - failcode = WIRE_TEMPORARY_NODE_FAILURE; + newf = mk_failed_htlc(*failed_htlcs, hin, failonion); + tal_arr_expand(failed_htlcs, newf); +} + +static void add_fail_badonion(struct htlc_in *hin, + enum onion_type badonion, + const struct failed_htlc ***failed_htlcs) +{ + struct failed_htlc *newf; - newf = mk_failed_htlc(*failed_htlcs, hin, failcode, failonion, - NULL); + newf = mk_failed_htlc_badonion(*failed_htlcs, hin, badonion); tal_arr_expand(failed_htlcs, newf); } @@ -2115,9 +2015,10 @@ void peer_htlcs(const tal_t *ctx, hin->cltv_expiry, hin->onion_routing_packet, hin->hstate); - if (hin->failonion || hin->failcode) - add_fail(hin, hin->failcode, - hin->failonion, failed_in); + if (hin->failcode) + add_fail_badonion(hin, hin->failcode, failed_in); + if (hin->failonion) + add_fail(hin, hin->failonion, failed_in); if (hin->preimage) add_fulfill(hin->key.id, REMOTE, hin->preimage, fulfilled_htlcs, fulfilled_sides); diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index f4db0506f1db..de38bbf95cb1 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1323,7 +1323,7 @@ static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx) transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, NULL, 0, onionreply, NULL)), "Update HTLC with failonion failed"); CHECK_MSG( - transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, NULL, 0x2002, NULL, NULL)), + transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, NULL, WIRE_INVALID_ONION_VERSION, NULL, NULL)), "Update HTLC with failcode failed"); CHECK_MSG(transaction_wrap(w->db, wallet_htlc_save_out(w, chan, &out)), diff --git a/wallet/wallet.c b/wallet/wallet.c index 42bf113a3f55..4c203da5e5d6 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1759,12 +1759,15 @@ void wallet_htlc_save_out(struct wallet *wallet, void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, const enum htlc_state new_state, const struct preimage *payment_key, - enum onion_type failcode, + enum onion_type badonion, const struct onionreply *failonion, const u8 *failmsg) { struct db_stmt *stmt; + /* We should only use this for badonion codes */ + assert(!badonion || (badonion & BADONION)); + /* The database ID must be set by a previous call to * `wallet_htlc_save_*` */ assert(htlc_dbid); @@ -1782,7 +1785,7 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, else db_bind_null(stmt, 1); - db_bind_int(stmt, 2, failcode); + db_bind_int(stmt, 2, badonion); if (failonion) db_bind_onionreply(stmt, 3, failonion); @@ -1826,7 +1829,6 @@ static bool wallet_stmt2htlc_in(struct channel *channel, else in->failonion = db_column_onionreply(in, stmt, 8); in->failcode = db_column_int(stmt, 9); - if (db_column_is_null(stmt, 11)) { in->shared_secret = NULL; } else { @@ -1842,6 +1844,21 @@ static bool wallet_stmt2htlc_in(struct channel *channel, in->received_time = db_column_timeabs(stmt, 12); +#ifdef COMPAT_V080 + /* This field is now reserved for badonion codes: the rest should + * use the failonion field. */ + if (in->failcode && !(in->failcode & BADONION)) { + log_broken(channel->log, + "Replacing incoming HTLC %"PRIu64" error " + "%s with WIRE_TEMPORARY_NODE_FAILURE", + in->key.id, onion_type_name(in->failcode)); + in->failcode = 0; + in->failonion = create_onionreply(in, + in->shared_secret, + towire_temporary_node_failure(tmpctx)); + } +#endif + return ok; } diff --git a/wallet/wallet.h b/wallet/wallet.h index 121de2fac2de..1ed03b7eef45 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -581,7 +581,7 @@ void wallet_htlc_save_out(struct wallet *wallet, * @new_state: the state we should transition to * @payment_key: the `payment_key` which hashes to the `payment_hash`, * or NULL if unknown. - * @failcode: the current failure code, or 0. + * @badonion: the current BADONION failure code, or 0. * @failonion: the current failure onion message (from peer), or NULL. * @failmsg: the current local failure message, or NULL. * @@ -592,7 +592,7 @@ void wallet_htlc_save_out(struct wallet *wallet, void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, const enum htlc_state new_state, const struct preimage *payment_key, - enum onion_type failcode, + enum onion_type badonion, const struct onionreply *failonion, const u8 *failmsg);