Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 51 additions & 11 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <stdio.h>
#include <wally_bip32.h>
#include <wire/peer_wire.h>
#include <wire/tlvstream.h>
#include <wire/wire_sync.h>

/* stdin == requests, 3 == peer, 4 = HSM */
Expand Down Expand Up @@ -621,9 +622,14 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
peer_failed_warn(peer->pps, &peer->channel_id,
"Bad peer_add_htlc %s", tal_hex(msg, msg));
}

add_err = channel_add_htlc(peer->channel, REMOTE, id, amount,
cltv_expiry, &payment_hash,
onion_routing_packet, tlvs->blinded_path, &htlc, NULL,
onion_routing_packet,
take(tlvs->blinded_path), &htlc, NULL,
/* NOTE: It might be better to remove the
* blinded_path from the extra_tlvs */
tlvs->fields,
/* We don't immediately fail incoming htlcs,
* instead we wait and fail them after
* they've been committed */
Expand Down Expand Up @@ -1519,6 +1525,7 @@ static void marshall_htlc_info(const tal_t *ctx,
htlc->routing,
sizeof(a.onion_routing_packet));
a.path_key = htlc->path_key;
a.extra_tlvs = htlc->extra_tlvs;
a.fail_immediate = htlc->fail_immediate;
tal_arr_expand(added, a);
} else if (htlc->state == RCVD_REMOVE_COMMIT) {
Expand Down Expand Up @@ -5113,13 +5120,24 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last)
last[i].id);

if (h->state == SENT_ADD_COMMIT) {
struct tlv_update_add_htlc_tlvs *tlvs;
if (h->path_key) {
struct tlv_update_add_htlc_tlvs *tlvs = NULL;
if (h->extra_tlvs || h->path_key) {
tlvs = tlv_update_add_htlc_tlvs_new(tmpctx);
tlvs->blinded_path = tal_dup(tlvs, struct pubkey,
}
if (h->extra_tlvs) {
tlvs->fields = tal_dup_talarr(tmpctx,
struct tlv_field,
h->extra_tlvs);
}
if (h->path_key) {
/* It is fine to just set the binded_path
* independent of what is in tlv->fields as the
* towire logic will serialize unknown fields
* and known types seperately. */
tlvs->blinded_path = tal_dup(tlvs,
struct pubkey,
h->path_key);
} else
tlvs = NULL;
}
msg = towire_update_add_htlc(NULL, &peer->channel_id,
h->id, h->amount,
&h->rhash,
Expand Down Expand Up @@ -6058,27 +6076,49 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
const char *failstr;
struct amount_sat htlc_fee;
struct pubkey *path_key;
struct tlv_field *extra_tlvs;
struct tlv_update_add_htlc_tlvs *tlvs;
u8 *extra_tlvs_raw;

if (!peer->channel_ready[LOCAL] || !peer->channel_ready[REMOTE])
status_failed(STATUS_FAIL_MASTER_IO,
"funding not locked for offer_htlc");

if (!fromwire_channeld_offer_htlc(tmpctx, inmsg, &amount,
&cltv_expiry, &payment_hash,
onion_routing_packet, &path_key))
onion_routing_packet, &path_key, &extra_tlvs_raw))
master_badmsg(WIRE_CHANNELD_OFFER_HTLC, inmsg);

if (path_key) {

if (extra_tlvs_raw || path_key) {
tlvs = tlv_update_add_htlc_tlvs_new(tmpctx);
tlvs->blinded_path = tal_dup(tlvs, struct pubkey, path_key);
} else
} else {
tlvs = NULL;
}

if (extra_tlvs_raw) {
const u8 *cursor = extra_tlvs_raw;
size_t max = tal_bytelen(extra_tlvs_raw);
u64 failedtype;
const u64 *allowed = cast_const(u64 *, FROMWIRE_TLV_ANY_TYPE);
if (!fromwire_tlv(&cursor, &max, NULL, 0,
tlvs, &tlvs->fields,
allowed, NULL, &failedtype)) {
status_unusual("Malformed TLV type %"PRIu64": %s",
failedtype, tal_hex(tmpctx, extra_tlvs_raw));
}
extra_tlvs = tlvs->fields;
} else {
extra_tlvs = NULL;
}
if (path_key) {
tlvs->blinded_path = tal_dup(tlvs, struct pubkey, path_key);
}

e = channel_add_htlc(peer->channel, LOCAL, peer->htlc_id,
amount, cltv_expiry, &payment_hash,
onion_routing_packet, take(path_key), NULL,
&htlc_fee, true);
&htlc_fee, extra_tlvs, true);
status_debug("Adding HTLC %"PRIu64" amount=%s cltv=%u gave %s",
peer->htlc_id,
fmt_amount_msat(tmpctx, amount),
Expand Down
4 changes: 4 additions & 0 deletions channeld/channeld_htlc.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <common/htlc.h>
#include <common/pseudorand.h>
#include <wire/onion_wire.h>
#include <wire/tlvstream.h>

struct htlc {
/* What's the status. */
Expand All @@ -29,6 +30,9 @@ struct htlc {
/* Blinding (optional). */
struct pubkey *path_key;

/* Any extra tlvs attached to this hltc (optional). */
struct tlv_field *extra_tlvs;

/* Should we immediately fail this htlc? */
bool fail_immediate;
};
Expand Down
2 changes: 2 additions & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ msgdata,channeld_offer_htlc,cltv_expiry,u32,
msgdata,channeld_offer_htlc,payment_hash,sha256,
msgdata,channeld_offer_htlc,onion_routing_packet,u8,1366
msgdata,channeld_offer_htlc,path_key,?pubkey,
msgdata,channeld_offer_htlc,extra_tlvs_len,u16,
msgdata,channeld_offer_htlc,extra_tlvs,u8,extra_tlvs_len

# Reply; synchronous since IDs have to increment.
msgtype,channeld_offer_htlc_reply,1104
Expand Down
16 changes: 14 additions & 2 deletions channeld/full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
struct htlc **htlcp,
bool enforce_aggregate_limits,
struct amount_sat *htlc_fee,
struct tlv_field *extra_tlvs,
bool err_immediate_failures)
{
struct htlc *htlc, *old;
Expand All @@ -613,6 +614,15 @@ static enum channel_add_err add_htlc(struct channel *channel,
htlc->failed = NULL;
htlc->r = NULL;
htlc->routing = tal_dup_arr(htlc, u8, routing, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), 0);
if (extra_tlvs && tal_count(extra_tlvs) > 0) {
htlc->extra_tlvs = tal_dup_talarr(htlc, struct tlv_field, extra_tlvs);
for (size_t i = 0; i < tal_count(extra_tlvs); i++) {
/* We need to attach the value to the correct parent */
htlc->extra_tlvs[i].value = tal_dup_talarr(htlc, u8, htlc->extra_tlvs[i].value);
}
} else {
htlc->extra_tlvs = NULL;
}

/* FIXME: Change expiry to simple u32 */

Expand Down Expand Up @@ -905,6 +915,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
const struct pubkey *path_key TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee,
struct tlv_field *extra_tlvs,
bool err_immediate_failures)
{
enum htlc_state state;
Expand All @@ -923,7 +934,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,

return add_htlc(channel, state, id, amount, cltv_expiry,
payment_hash, routing, path_key,
htlcp, true, htlc_fee, err_immediate_failures);
htlcp, true, htlc_fee, extra_tlvs, err_immediate_failures);
}

struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id)
Expand Down Expand Up @@ -1621,7 +1632,8 @@ bool channel_force_htlcs(struct channel *channel,
&htlcs[i]->payment_hash,
htlcs[i]->onion_routing_packet,
htlcs[i]->path_key,
&htlc, false, NULL, false);
&htlc, false, NULL,
htlcs[i]->extra_tlvs, false);
if (e != CHANNEL_ERR_ADD_OK) {
status_broken("%s HTLC %"PRIu64" failed error %u",
htlc_state_owner(htlcs[i]->state) == LOCAL
Expand Down
3 changes: 2 additions & 1 deletion channeld/full_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ struct channel *new_full_channel(const tal_t *ctx,
* @remote_splice_amnt: how much is being spliced in (or out, if -ve) of remote side.
* @other_anchor_outnum: which output (-1 if none) is the !!side anchor
* @funding_pubkeys: The funding pubkeys (specify NULL to use channel's value).
*
* Returns the unsigned commitment transaction for the committed state
* for @side, followed by the htlc transactions in output order and
* fills in @htlc_map, or NULL on key derivation failure.
Expand Down Expand Up @@ -115,6 +114,7 @@ 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.
* @extra_tlvs: optinal tlvs attached to this HTLC.
* @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
Expand All @@ -134,6 +134,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
const struct pubkey *blinding TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee,
struct tlv_field *extra_tlvs,
bool err_immediate_failures);

/**
Expand Down
4 changes: 2 additions & 2 deletions channeld/test/run-full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,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, true);
dummy_routing, NULL, NULL, NULL, NULL, true);
assert(e == CHANNEL_ERR_ADD_OK);
htlcs[i] = channel_get_htlc(channel, sender, i);
}
Expand Down Expand Up @@ -269,7 +269,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, true)
dummy_routing, NULL, NULL, NULL, NULL, true)
== CHANNEL_ERR_ADD_OK);
htlc = channel_get_htlc(channel, sender, 1337);
assert(htlc);
Expand Down
77 changes: 76 additions & 1 deletion common/htlc_wire.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <ccan/crypto/shachain/shachain.h>
#include <common/htlc_wire.h>
#include <common/onionreply.h>
#include <wire/tlvstream.h>

static struct failed_htlc *failed_htlc_dup(const tal_t *ctx,
const struct failed_htlc *f TAKES)
Expand All @@ -24,6 +25,23 @@ static struct failed_htlc *failed_htlc_dup(const tal_t *ctx,
return newf;
}

/* Helper to duplicate an array of tlv_field (vs an array of tlv_field *) */
struct tlv_field *tlv_field_arr_dup(const tal_t *ctx,
const struct tlv_field *arr TAKES)
{
struct tlv_field *ret;
bool needs_copy = !is_taken(arr);

ret = tal_dup_talarr(ctx, struct tlv_field, arr);
if (needs_copy) {
for (size_t i = 0; i < tal_count(ret); i++) {
/* We need to attach the value to the correct parent */
ret[i].value = tal_dup_talarr(ret, u8, ret[i].value);
}
}
return ret;
}

struct existing_htlc *new_existing_htlc(const tal_t *ctx,
u64 id,
enum htlc_state state,
Expand All @@ -33,7 +51,8 @@ struct existing_htlc *new_existing_htlc(const tal_t *ctx,
const u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
const struct pubkey *path_key TAKES,
const struct preimage *preimage TAKES,
const struct failed_htlc *failed TAKES)
const struct failed_htlc *failed TAKES,
const struct tlv_field *extra_tlvs TAKES)
{
struct existing_htlc *existing = tal(ctx, struct existing_htlc);

Expand All @@ -51,10 +70,26 @@ struct existing_htlc *new_existing_htlc(const tal_t *ctx,
existing->failed = failed_htlc_dup(existing, failed);
else
existing->failed = NULL;
if (extra_tlvs)
existing->extra_tlvs = tlv_field_arr_dup(existing, extra_tlvs);
else
existing->extra_tlvs = NULL;

return existing;
}

static void towire_len_and_tlvstream(u8 **pptr, struct tlv_field *extra_tlvs)
{
/* Making a copy is a bit awful, but it's the easiest way to
* get the length */
u8 *tmp_pptr = tal_arr(tmpctx, u8, 0);
towire_tlvstream_raw(&tmp_pptr, extra_tlvs);

assert(tal_bytelen(tmp_pptr) == (u16)tal_bytelen(tmp_pptr));
towire_u16(pptr, tal_bytelen(tmp_pptr));
towire_u8_array(pptr, tmp_pptr, tal_bytelen(tmp_pptr));
}

/* FIXME: We could adapt tools/generate-wire.py to generate structures
* and code like this. */
void towire_added_htlc(u8 **pptr, const struct added_htlc *added)
Expand All @@ -70,6 +105,11 @@ void towire_added_htlc(u8 **pptr, const struct added_htlc *added)
towire_pubkey(pptr, added->path_key);
} else
towire_bool(pptr, false);
if (added->extra_tlvs) {
towire_bool(pptr, true);
towire_len_and_tlvstream(pptr, added->extra_tlvs);
} else
towire_bool(pptr, false);
towire_bool(pptr, added->fail_immediate);
}

Expand Down Expand Up @@ -97,6 +137,11 @@ void towire_existing_htlc(u8 **pptr, const struct existing_htlc *existing)
towire_pubkey(pptr, existing->path_key);
} else
towire_bool(pptr, false);
if (existing->extra_tlvs) {
towire_bool(pptr, true);
towire_len_and_tlvstream(pptr, existing->extra_tlvs);
} else
towire_bool(pptr, false);
}

void towire_fulfilled_htlc(u8 **pptr, const struct fulfilled_htlc *fulfilled)
Expand Down Expand Up @@ -149,6 +194,28 @@ void towire_shachain(u8 **pptr, const struct shachain *shachain)
}
}

static struct tlv_field *fromwire_len_and_tlvstream(const tal_t *ctx,
const u8 **cursor, size_t *max)
{
struct tlv_field *tlvs = tal_arr(ctx, struct tlv_field, 0);
size_t len = fromwire_u16(cursor, max);

/* Subtle: we are not using fromwire_tal_arrn here, which
* would do this. */
if (len > *max) {
fromwire_fail(cursor, max);
return NULL;
}

/* NOTE: We might consider to be more strict and only allow for
* known tlv types from the tlvs_tlv_update_add_htlc_tlvs
* record. */
if (!fromwire_tlv(cursor, &len, NULL, 0, cast_const(void *, ctx),
&tlvs, FROMWIRE_TLV_ANY_TYPE, NULL, NULL))
return tal_free(tlvs);
return tlvs;
}

void fromwire_added_htlc(const u8 **cursor, size_t *max,
struct added_htlc *added)
{
Expand All @@ -163,6 +230,10 @@ void fromwire_added_htlc(const u8 **cursor, size_t *max,
fromwire_pubkey(cursor, max, added->path_key);
} else
added->path_key = NULL;
if (fromwire_bool(cursor, max)) {
added->extra_tlvs = fromwire_len_and_tlvstream(added, cursor, max);
} else
added->extra_tlvs = NULL;
added->fail_immediate = fromwire_bool(cursor, max);
}

Expand Down Expand Up @@ -192,6 +263,10 @@ struct existing_htlc *fromwire_existing_htlc(const tal_t *ctx,
fromwire_pubkey(cursor, max, existing->path_key);
} else
existing->path_key = NULL;
if (fromwire_bool(cursor, max)) {
existing->extra_tlvs = fromwire_len_and_tlvstream(existing, cursor, max);
} else
existing->extra_tlvs = NULL;
return existing;
}

Expand Down
Loading
Loading