common/bolt12: roll all necessary checks into offer_decode.

Some of these were done by fetchinvoice (and it did some that
offer_decode already did).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-09-21 09:34:14 +09:30
parent fea4eb8968
commit c8c6dd183d
3 changed files with 36 additions and 61 deletions

View file

@ -7,6 +7,7 @@
#include <common/bolt12_merkle.h>
#include <common/configdir.h>
#include <common/features.h>
#include <inttypes.h>
#include <secp256k1_schnorrsig.h>
#include <time.h>
@ -190,6 +191,41 @@ struct tlv_offer *offer_decode(const tal_t *ctx,
if (*fail)
return tal_free(offer);
/* BOLT-offers #12:
* A reader of an offer:
* - if the offer contains any TLV fields greater or equal to 80:
* - MUST NOT respond to the offer.
* - if `offer_features` contains unknown _odd_ bits that are non-zero:
* - MUST ignore the bit.
* - if `offer_features` contains unknown _even_ bits that are non-zero:
* - MUST NOT respond to the offer.
* - SHOULD indicate the unknown bit to the user.
*/
for (size_t i = 0; i < tal_count(offer->fields); i++) {
if (offer->fields[i].numtype > 80) {
*fail = tal_fmt(ctx,
"Offer %"PRIu64" field >= 80",
offer->fields[i].numtype);
return tal_free(offer);
}
}
/* BOLT-offers #12:
* - if `offer_description` is not set:
* - MUST NOT respond to the offer.
* - if `offer_node_id` is not set:
* - MUST NOT respond to the offer.
*/
if (!offer->offer_description) {
*fail = tal_strdup(ctx, "Offer does not contain a description");
return tal_free(offer);
}
if (!offer->offer_node_id) {
*fail = tal_strdup(ctx, "Offer does not contain a node_id");
return tal_free(offer);
}
return offer;
}

View file

@ -28,8 +28,6 @@ char *offer_encode(const tal_t *ctx, const struct tlv_offer *bolt12_tlv);
* @our_features: if non-NULL, feature set to check against.
* @must_be_chain: if non-NULL, chain to enforce.
* @fail: pointer to descriptive error string, set if this returns NULL.
*
* Note: checks signature if present.
*/
struct tlv_offer *offer_decode(const tal_t *ctx, const char *b12, size_t b12len,
const struct feature_set *our_features,

View file

@ -424,7 +424,6 @@ static struct command_result *param_offer(struct command *cmd,
struct tlv_offer **offer)
{
char *fail;
int badf;
*offer = offer_decode(cmd, buffer + tok->start, tok->end - tok->start,
plugin_feature_set(cmd->plugin), chainparams,
@ -434,64 +433,6 @@ static struct command_result *param_offer(struct command *cmd,
tal_fmt(cmd,
"Unparsable offer: %s",
fail));
/* BOLT-offers #12:
* A reader of an offer:
* - if the offer contains any TLV fields greater or equal to 80:
* - MUST NOT respond to the offer.
* - if `offer_features` contains unknown _odd_ bits that are non-zero:
* - MUST ignore the bit.
* - if `offer_features` contains unknown _even_ bits that are non-zero:
* - MUST NOT respond to the offer.
* - SHOULD indicate the unknown bit to the user.
*/
for (size_t i = 0; i < tal_count((*offer)->fields); i++) {
if ((*offer)->fields[i].numtype > 80) {
return command_fail_badparam(cmd, name, buffer, tok,
tal_fmt(tmpctx,
"Offer %"PRIu64
" field >= 80",
(*offer)->fields[i].numtype));
}
}
badf = features_unsupported(plugin_feature_set(cmd->plugin),
(*offer)->offer_features,
BOLT12_OFFER_FEATURE);
if (badf != -1) {
return command_fail_badparam(cmd, name, buffer, tok,
tal_fmt(tmpctx,
"unknown feature %i",
badf));
}
/* BOLT-offers #12:
* - if `offer_description` is not set:
* - MUST NOT respond to the offer.
* - if `offer_node_id` is not set:
* - MUST NOT respond to the offer.
*/
if (!(*offer)->offer_description)
return command_fail_badparam(cmd, name, buffer, tok,
"Offer does not contain a description");
if (!(*offer)->offer_node_id)
return command_fail_badparam(cmd, name, buffer, tok,
"Offer does not contain a node_id");
/* BOLT-offers #12:
* - if `offer_chains` is not set:
* - if the node does not accept bitcoin invoices:
* - MUST NOT respond to the offer
* - otherwise: (`offer_chains` is set):
* - if the node does not accept invoices for any of the `chains`:
* - MUST NOT respond to the offer
*/
if (!bolt12_chains_match((*offer)->offer_chains,
tal_count((*offer)->offer_chains),
chainparams)) {
return command_fail_badparam(cmd, name, buffer, tok,
"Offer for wrong chains");
}
return NULL;
}