htlc_wire: be stricter in marshaling/unmarshaling struct failed_htlc.

There are three cases:
1. failcode is 0, scid is NULL, failreason is the onion to fwd.
2. failcode is non-zero, but UPDATE bit not set.  scid is NULL, failreason NULL.
3. failcode has UPDATE bit set.  scid is non-NULL, failreason is NULL.

Assert these on marshaling, and only send the parts we need so unmarshal is
always canonical.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-07-27 06:55:37 +09:30 committed by Christian Decker
parent 3c651f19a8
commit f76203727d

View File

@ -30,12 +30,18 @@ void towire_failed_htlc(u8 **pptr, const struct failed_htlc *failed)
assert(!failed->failcode || !tal_len(failed->failreason));
towire_u64(pptr, failed->id);
towire_u16(pptr, failed->failcode);
if (failed->failcode & UPDATE)
if (failed->failcode & UPDATE) {
assert(!failed->failreason);
towire_short_channel_id(pptr, failed->scid);
else
} else {
assert(!failed->scid);
towire_u16(pptr, tal_count(failed->failreason));
towire_u8_array(pptr, failed->failreason, tal_count(failed->failreason));
if (!failed->failcode) {
assert(failed->failreason);
towire_u16(pptr, tal_count(failed->failreason));
towire_u8_array(pptr, failed->failreason,
tal_count(failed->failreason));
}
}
}
void towire_htlc_state(u8 **pptr, const enum htlc_state hstate)
@ -87,22 +93,26 @@ void fromwire_fulfilled_htlc(const u8 **cursor, size_t *max,
struct failed_htlc *fromwire_failed_htlc(const tal_t *ctx, const u8 **cursor, size_t *max)
{
u16 failreason_len;
struct failed_htlc *failed = tal(ctx, struct failed_htlc);
failed->id = fromwire_u64(cursor, max);
failed->failcode = fromwire_u16(cursor, max);
if (failed->failcode & UPDATE) {
failed->scid = tal(failed, struct short_channel_id);
fromwire_short_channel_id(cursor, max, failed->scid);
} else
if (failed->failcode == 0) {
u16 failreason_len;
failed->scid = NULL;
failreason_len = fromwire_u16(cursor, max);
if (failreason_len)
failreason_len = fromwire_u16(cursor, max);
failed->failreason = tal_arr(failed, u8, failreason_len);
else
fromwire_u8_array(cursor, max, failed->failreason,
failreason_len);
} else {
failed->failreason = NULL;
fromwire_u8_array(cursor, max, failed->failreason, failreason_len);
if (failed->failcode & UPDATE) {
failed->scid = tal(failed, struct short_channel_id);
fromwire_short_channel_id(cursor, max, failed->scid);
} else {
failed->scid = NULL;
}
}
return failed;
}