From 21e7c3432e8d2c7f1efdf8ed6cde8722ea3d5852 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 17 Oct 2022 11:14:39 +1030 Subject: [PATCH] common/onion: enforce payment constraints. Signed-off-by: Rusty Russell --- common/onion.c | 47 +++++++++++++++++++++++++++-- common/onion.h | 1 - common/test/run-blindedpath_onion.c | 3 ++ common/test/run-onion-test-vector.c | 3 ++ common/test/run-sphinx.c | 3 ++ 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/common/onion.c b/common/onion.c index 7166901e3..4fb0060f3 100644 --- a/common/onion.c +++ b/common/onion.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -312,7 +313,49 @@ struct onion_payload *onion_decode(const tal_t *ctx, goto field_bad; } - p->payment_constraints = tal_steal(p, enc->payment_constraints); + if (enc->payment_constraints) { + /* BOLT-route-blinding #4: + * - MUST return an error if the expiry is greater than + * `encrypted_recipient_data.payment_constraints.max_cltv_expiry`. + */ + if (cltv_expiry > enc->payment_constraints->max_cltv_expiry) { + *failtlvtype = TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; + goto field_bad; + } + + /* BOLT-route-blinding #4: + * - MUST return an error if the amount is below + * `encrypted_recipient_data.payment_constraints.htlc_minimum_msat`. + */ + if (amount_msat_less(amount_in, + amount_msat(enc->payment_constraints->htlc_minimum_msat))) { + *failtlvtype = TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; + goto field_bad; + } + + /* BOLT-route-blinding #4: + * - MUST return an error if the payment uses a feature + * not included in + * `encrypted_recipient_data.payment_constraints.allowed_features`. + */ + /* We don't have any features yet... */ + } + + /* BOLT-route-blinding #4: + * - If `allowed_features` is present: + * - MUST return an error if: + * - `encrypted_recipient_data.allowed_features.features` + * contains an unknown feature bit (even if it is odd). + * - the payment uses a feature not included in + * `encrypted_recipient_data.allowed_features.features`. + */ + /* No features, this is easy */ + if (!memeqzero(enc->allowed_features, + tal_bytelen(enc->allowed_features))) { + *failtlvtype = TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA; + goto field_bad; + } + if (rs->nextcase == ONION_FORWARD) { if (!handle_blinded_forward(p, amount_in, cltv_expiry, tlv, enc, failtlvtype)) @@ -390,7 +433,6 @@ struct onion_payload *onion_decode(const tal_t *ctx, p->payment_metadata = NULL; p->blinding = NULL; - p->payment_constraints = NULL; p->tlv = tal_steal(p, tlv); return p; @@ -405,3 +447,4 @@ fail_no_tlv: tal_free(p); return NULL; } + diff --git a/common/onion.h b/common/onion.h index c49e30101..d20059a99 100644 --- a/common/onion.h +++ b/common/onion.h @@ -14,7 +14,6 @@ struct onion_payload { struct short_channel_id *forward_channel; struct secret *payment_secret; u8 *payment_metadata; - struct tlv_encrypted_data_tlv_payment_constraints *payment_constraints; /* If blinding is set, blinding_ss is the shared secret.*/ struct pubkey *blinding; diff --git a/common/test/run-blindedpath_onion.c b/common/test/run-blindedpath_onion.c index b3b0c752e..81b19f8be 100644 --- a/common/test/run-blindedpath_onion.c +++ b/common/test/run-blindedpath_onion.c @@ -24,6 +24,9 @@ struct amount_msat amount_msat(u64 millisatoshis UNNEEDED) /* Generated stub for amount_msat_eq */ bool amount_msat_eq(struct amount_msat a UNNEEDED, struct amount_msat b UNNEEDED) { fprintf(stderr, "amount_msat_eq called!\n"); abort(); } +/* Generated stub for amount_msat_less */ +bool amount_msat_less(struct amount_msat a UNNEEDED, struct amount_msat b UNNEEDED) +{ fprintf(stderr, "amount_msat_less called!\n"); abort(); } /* Generated stub for amount_sat */ struct amount_sat amount_sat(u64 satoshis UNNEEDED) { fprintf(stderr, "amount_sat called!\n"); abort(); } diff --git a/common/test/run-onion-test-vector.c b/common/test/run-onion-test-vector.c index 7f0d5f4c2..62dde8050 100644 --- a/common/test/run-onion-test-vector.c +++ b/common/test/run-onion-test-vector.c @@ -34,6 +34,9 @@ struct amount_msat amount_msat(u64 millisatoshis UNNEEDED) /* Generated stub for amount_msat_eq */ bool amount_msat_eq(struct amount_msat a UNNEEDED, struct amount_msat b UNNEEDED) { fprintf(stderr, "amount_msat_eq called!\n"); abort(); } +/* Generated stub for amount_msat_less */ +bool amount_msat_less(struct amount_msat a UNNEEDED, struct amount_msat b UNNEEDED) +{ fprintf(stderr, "amount_msat_less called!\n"); abort(); } /* Generated stub for amount_sat */ struct amount_sat amount_sat(u64 satoshis UNNEEDED) { fprintf(stderr, "amount_sat called!\n"); abort(); } diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index 96daa1a8b..861829c81 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -20,6 +20,9 @@ struct amount_msat amount_msat(u64 millisatoshis UNNEEDED) /* Generated stub for amount_msat_eq */ bool amount_msat_eq(struct amount_msat a UNNEEDED, struct amount_msat b UNNEEDED) { fprintf(stderr, "amount_msat_eq called!\n"); abort(); } +/* Generated stub for amount_msat_less */ +bool amount_msat_less(struct amount_msat a UNNEEDED, struct amount_msat b UNNEEDED) +{ fprintf(stderr, "amount_msat_less called!\n"); abort(); } /* Generated stub for amount_sat */ struct amount_sat amount_sat(u64 satoshis UNNEEDED) { fprintf(stderr, "amount_sat called!\n"); abort(); }