diff --git a/common/blindedpay.c b/common/blindedpay.c index b542bb26a..d959f8f55 100644 --- a/common/blindedpay.c +++ b/common/blindedpay.c @@ -7,6 +7,7 @@ u8 **blinded_onion_hops(const tal_t *ctx, struct amount_msat final_amount, u32 final_cltv, + struct amount_msat total_amount, const struct blinded_path *path) { u8 **onions = tal_arr(ctx, u8 *, tal_count(path->path)); @@ -25,12 +26,12 @@ u8 **blinded_onion_hops(const tal_t *ctx, * - MUST include the `blinding_point` provided by the * recipient in `current_blinding_point` * - If it is the final node: - * - MUST include `amt_to_forward` and `outgoing_cltv_value`. - * - MUST include `total_amount_msat` when using `basic_mpp`. + * - MUST include `amt_to_forward`, `outgoing_cltv_value` and `total_amount_msat`. * - MUST NOT include any other tlv field. */ onions[i] = onion_blinded_hop(onions, final ? &final_amount : NULL, + final ? &total_amount : NULL, final ? &final_cltv : NULL, path->path[i]->encrypted_recipient_data, first ? &path->blinding : NULL); diff --git a/common/blindedpay.h b/common/blindedpay.h index 5ef1b0ddf..fa99483aa 100644 --- a/common/blindedpay.h +++ b/common/blindedpay.h @@ -12,6 +12,7 @@ struct blinded_path; * @ctx: context to allocate from * @final_amount: amount we want to reach the end * @final_cltv: cltv we want to at end + * @total_amount: amount of all parts together. * @payinfo: fee and other restriction info * * This calls onion_nonfinal_hop and onion_final_hop to create onion @@ -20,6 +21,7 @@ struct blinded_path; u8 **blinded_onion_hops(const tal_t *ctx, struct amount_msat final_amount, u32 final_cltv, + struct amount_msat total_amount, const struct blinded_path *path); #endif /* LIGHTNING_COMMON_BLINDEDPAY_H */ diff --git a/common/onion_decode.c b/common/onion_decode.c index 0f6419d3a..544ad864f 100644 --- a/common/onion_decode.c +++ b/common/onion_decode.c @@ -102,8 +102,8 @@ static bool handle_blinded_terminal(struct onion_payload *p, } /* BOLT-route-blinding #4: - * - MUST return an error if `amt_to_forward` or - * `outgoing_cltv_value` are not present. + * - MUST return an error if `amt_to_forward`, `outgoing_cltv_value` + * or `total_amount_msat` are not present. * - MUST return an error if `amt_to_forward` is below what it expects * for the payment. */ @@ -117,6 +117,11 @@ static bool handle_blinded_terminal(struct onion_payload *p, return false; } + if (!tlv->total_amount_msat) { + *failtlvtype = TLV_TLV_PAYLOAD_TOTAL_AMOUNT_MSAT; + return false; + } + p->amt_to_forward = amount_msat(*tlv->amt_to_forward); p->outgoing_cltv = *tlv->outgoing_cltv_value; diff --git a/common/onion_encode.c b/common/onion_encode.c index 711b8dc9c..f5facf75e 100644 --- a/common/onion_encode.c +++ b/common/onion_encode.c @@ -103,6 +103,7 @@ u8 *onion_final_hop(const tal_t *ctx, u8 *onion_blinded_hop(const tal_t *ctx, const struct amount_msat *amt_to_forward, + const struct amount_msat *total_amount_msat, const u32 *outgoing_cltv_value, const u8 *enctlv, const struct pubkey *blinding) @@ -114,6 +115,11 @@ u8 *onion_blinded_hop(const tal_t *ctx, = cast_const(u64 *, &amt_to_forward->millisatoshis); /* Raw: TLV convert */ } + if (total_amount_msat) { + tlv->total_amount_msat + = cast_const(u64 *, + &total_amount_msat->millisatoshis); /* Raw: TLV convert */ + } tlv->outgoing_cltv_value = cast_const(u32 *, outgoing_cltv_value); tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); tlv->blinding_point = cast_const(struct pubkey *, blinding); diff --git a/common/onion_encode.h b/common/onion_encode.h index ac2129325..2892cbc8c 100644 --- a/common/onion_encode.h +++ b/common/onion_encode.h @@ -53,8 +53,9 @@ u8 *onion_final_hop(const tal_t *ctx, * generic interface, as used by blindedpay.h */ u8 *onion_blinded_hop(const tal_t *ctx, const struct amount_msat *amt_to_forward, + const struct amount_msat *total_amount_msat, const u32 *outgoing_cltv_value, const u8 *enctlv, const struct pubkey *blinding) - NON_NULL_ARGS(4); + NON_NULL_ARGS(5); #endif /* LIGHTNING_COMMON_ONION_ENCODE_H */ diff --git a/common/test/run-route_blinding_onion_test.c b/common/test/run-route_blinding_onion_test.c index b22397727..f3eec3f17 100644 --- a/common/test/run-route_blinding_onion_test.c +++ b/common/test/run-route_blinding_onion_test.c @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) } /* FIXME: These amounts / scid should be in test vectors! */ - onionhops = blinded_onion_hops(tmpctx, AMOUNT_MSAT(200), 700, bpath); + onionhops = blinded_onion_hops(tmpctx, AMOUNT_MSAT(200), 700, AMOUNT_MSAT(200), bpath); assert(mk_short_channel_id(&initscid, 0, 0, 10)); /* Prepend Alice: poor thing doesn't speak blinding! */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 69158a769..2bb9531fe 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -92,20 +92,33 @@ static bool htlc_out_update_state(struct channel *channel, return true; } +/* BOLT-route-blinding #4: + * - if `blinding_point` is set in the incoming `update_add_htlc`: + * - MUST return an `invalid_onion_blinding` error. + * - if `current_blinding_point` is set in the onion payload and it is not the + * final node: + * - MUST return an `invalid_onion_blinding` error. + */ +static bool blind_error_return(const struct htlc_in *hin) +{ + if (hin->blinding) + return true; + + if (hin->payload + && hin->payload->blinding + && !hin->payload->final) + return true; + + return false; +} + static struct failed_htlc *mk_failed_htlc_badonion(const tal_t *ctx, const struct htlc_in *hin, enum onion_wire badonion) { struct failed_htlc *f = tal(ctx, struct failed_htlc); - /* BOLT-route-blinding #4: - * - If `blinding_point` is set in the incoming `update_add_htlc`: - * - MUST return `invalid_onion_blinding` for any local error or - * other downstream errors. - */ - /* FIXME: That's not enough! Don't leak information about forward - * failures either! */ - if (hin->blinding || (hin->payload && hin->payload->blinding)) + if (blind_error_return(hin)) badonion = WIRE_INVALID_ONION_BLINDING; f->id = hin->key.id; @@ -123,12 +136,7 @@ static struct failed_htlc *mk_failed_htlc(const tal_t *ctx, { struct failed_htlc *f = tal(ctx, struct failed_htlc); - /* BOLT-route-blinding #4: - * - If `blinding_point` is set in the incoming `update_add_htlc`: - * - MUST return `invalid_onion_blinding` for any local error or - * other downstream errors. - */ - if (hin->blinding) { + if (blind_error_return(hin)) { return mk_failed_htlc_badonion(ctx, hin, WIRE_INVALID_ONION_BLINDING); } diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 41951f961..fc20bf6fd 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -1671,7 +1671,8 @@ static void payment_add_blindedpath(const tal_t *ctx, { /* It's a bit of a weird API for us, so we convert it back to * the struct tlv_tlv_payload */ - u8 **tlvs = blinded_onion_hops(tmpctx, final_amt, final_cltv, bpath); + u8 **tlvs = blinded_onion_hops(tmpctx, final_amt, final_cltv, + final_amt, bpath); for (size_t i = 0; i < tal_count(tlvs); i++) { const u8 *cursor = tlvs[i]; diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index 00a806748..a5aaddfc9 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -12,6 +12,7 @@ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, struct amount_msat final_amount UNNEEDED, u32 final_cltv UNNEEDED, + struct amount_msat total_amount UNNEEDED, const struct blinded_path *path UNNEEDED) { fprintf(stderr, "blinded_onion_hops called!\n"); abort(); } /* Generated stub for command_finished */