text: #include <bitcoin/chainparams.h>
  #include <ccan/cast/cast.h>
  #include <ccan/err/err.h>
  #include <ccan/tal/str/str.h>
  #include <common/bech32_util.h>
  #include <common/bolt12.h>
  #include <common/bolt12_merkle.h>
  #include <common/features.h>
  #include <common/iso4217.h>
  #include <common/setup.h>
  #include <common/type_to_string.h>
  #include <common/version.h>
  #include <inttypes.h>
  #include <secp256k1_schnorrsig.h>
  #include <stdio.h>
  #include <sys/socket.h>
  #include <sys/types.h>
  #include <sys/un.h>
  #include <time.h>
  #include <unistd.h>
  
  #define NO_ERROR 0
  #define ERROR_BAD_DECODE 1
  #define ERROR_USAGE 3
  
  static bool well_formed = true;
  
  /* Tal wrappers for opt. */
  static void *opt_allocfn(size_t size)
  {
  	return tal_arr_label(NULL, char, size, TAL_LABEL("opt_allocfn", ""));
  }
  
  static void *tal_reallocfn(void *ptr, size_t size)
  {
  	if (!ptr)
  		return opt_allocfn(size);
  	tal_resize_(&ptr, 1, size, false);
  	return ptr;
  }
  
  static void tal_freefn(void *ptr)
  {
  	tal_free(ptr);
  }
  
  static char *fmt_time(const tal_t *ctx, u64 time)
  {
  	/* ctime is not sane.  Take pointer, returns \n in string. */
  	time_t t = time;
  	const char *p = ctime(&t);
  
  	return tal_fmt(ctx, "%.*s", (int)strcspn(p, "\n"), p);
  }
  
  static bool must_str(bool expected, const char *complaint, const char *fieldname)
  {
  	if (!expected) {
  		fprintf(stderr, "%s %s\n", complaint, fieldname);
  		well_formed = false;
  		return false;
  	}
  	return true;
  }
  
  #define must_have(obj, field) \
  	must_str((obj)->field != NULL, "Missing", stringify(field))
  #define must_not_have(obj, field) \
  	must_str((obj)->field == NULL, "Unnecessary", stringify(field))
  
  static void print_chains(const struct bitcoin_blkid *chains)
  {
  	printf("chains:");
  	for (size_t i = 0; i < tal_count(chains); i++) {
  		printf(" %s", type_to_string(tmpctx, struct bitcoin_blkid, &chains[i]));
  	}
  	printf("\n");
  }
  
  static bool print_amount(const struct bitcoin_blkid *chains,
  			 const char *iso4217, u64 amount)
  {
  	const char *currency;
  	unsigned int minor_unit;
  	bool ok = true;
  
  	/* BOLT-offers #12:
  	 * - if the currency for `amount` is that of the first entry in `chains`:
  	 *   - MUST specify `amount` in multiples of the minimum
  	 *     lightning-payable unit (e.g. milli-satoshis for bitcoin).
  	 * - otherwise:
  	 *   - MUST specify `iso4217` as an ISO 4712 three-letter code.
  	 *   - MUST specify `amount` in the currency unit adjusted by the
  	 *     ISO 4712 exponent (e.g. USD cents).
  	 */
  	if (!iso4217) {
  		if (tal_count(chains) == 0)
  			currency = "bc";
  		else {
  			const struct chainparams *ch;
  
  			ch = chainparams_by_chainhash(&chains[0]);
  			if (!ch) {
  				currency = tal_fmt(tmpctx, "UNKNOWN CHAINHASH %s",
  						   type_to_string(tmpctx,
  								  struct bitcoin_blkid,
  								  &chains[0]));
  				ok = false;
  			} else
  				currency = ch->bip173_name;
  		}
  		minor_unit = 11;
  	} else {
  		const struct iso4217_name_and_divisor *iso;
  		iso = find_iso4217(iso4217, tal_bytelen(iso4217));
  		if (iso) {
  			minor_unit = iso->minor_unit;
  			currency = iso->name;
  		} else {
  			minor_unit = 0;
  			currency = tal_fmt(tmpctx, "%.*s (UNKNOWN CURRENCY)",
  					   (int)tal_bytelen(iso4217), iso4217);
  			ok = false;
  		}
  	}
  
  	if (!minor_unit)
  		printf("amount: %"PRIu64"%s\n", amount, currency);
  	else {
  		u64 minor_div = 1;
  		for (size_t i = 0; i < minor_unit; i++)
  			minor_div *= 10;
  		printf("amount: %"PRIu64".%.*"PRIu64"%s\n",
  		       amount / minor_div, minor_unit, amount % minor_div,
  		       currency);
  	}
  
  	return ok;
  }
  
  static void print_description(const char *description)
  {
  	printf("description: %.*s\n",
  	       (int)tal_bytelen(description), description);
  }
  
  static void print_vendor(const char *vendor)
  {
  	printf("vendor: %.*s\n", (int)tal_bytelen(vendor), vendor);
  }
  
  static void print_node_id(const struct pubkey32 *node_id)
  {
  	printf("node_id: %s\n", type_to_string(tmpctx, struct pubkey32, node_id));
  }
  
  static void print_quantity_min(u64 min)
  {
  	printf("quantity_min: %"PRIu64"\n", min);
  }
  
  static void print_quantity_max(u64 max)
  {
  	printf("quantity_max: %"PRIu64"\n", max);
  }
  
  static bool print_recurrance(const struct tlv_offer_recurrence *recurrence,
  			     const struct tlv_offer_recurrence_paywindow *paywindow,
  			     const u32 *limit,
  			     const struct tlv_offer_recurrence_base *base)
  {
  	const char *unit;
  	bool ok = true;
  
  	/* BOLT-offers #12:
  	 * Thus, each payment has:
  	 * 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months),
  	 *    3 (years).
  	 * 2. A `period`, defining how often (in `time_unit`) it has to be paid.
  	 * 3. An optional `recurrence_limit` of total payments to be paid.
  	 * 4. An optional `recurrence_base`:
  	 *    * `basetime`, defining when the first period starts
  	 *       in seconds since 1970-01-01 UTC.
  	 *    * `start_any_period` if non-zero, meaning you don't have to start
  	 *       paying at the period indicated by `basetime`, but can use
  	 *       `recurrence_start` to indicate what period you are starting at.
  	 * 5. An optional `recurrence_paywindow`:
  	 *    * `seconds_before`, defining how many seconds prior to the start of
  	 *       the period a payment will be accepted.
  	 *    * `proportional_amount`, if set indicating that a payment made
  	 *       during the period itself will be charged proportionally to the
  	 *       remaining time in the period (e.g. 150 seconds into a 1500
  	 *       second period gives a 10% discount).
  	 *    * `seconds_after`, defining how many seconds after the start of the
  	 *       period a payment will be accepted.
  	 *   If this field is missing, payment will be accepted during the prior
  	 *   period and the paid-for period.
  	 */
  	switch (recurrence->time_unit) {
  	case 0:
  		unit = "seconds";
  		break;
  	case 1:
  		unit = "days";
  		break;
  	case 2:
  		unit = "months";
  		break;
  	case 3:
  		unit = "years";
  		break;
  	default:
  		fprintf(stderr, "recurrence: unknown time_unit %u", recurrence->time_unit);
  		unit = "";
  		ok = false;
  	}
  	printf("recurrence: every %u %s", recurrence->period, unit);
  	if (limit)
  		printf(" limit %u", *limit);
  	if (base) {
  		printf(" start %"PRIu64" (%s)",
  		       base->basetime,
  		       fmt_time(tmpctx, base->basetime));
  		if (base->start_any_period)
  			printf(" (can start any period)");
  	}
  	if (paywindow) {
  		printf(" paywindow -%u to +%u",
  		       paywindow->seconds_before, paywindow->seconds_after);
  		if (paywindow->proportional_amount)
  			printf(" (pay proportional)");
  	}
  	printf("\n");
  
  	return ok;
  }
  
  static void print_absolute_expiry(u64 expiry)
  {
  	printf("absolute_expiry: %"PRIu64" (%s)\n",
  	       expiry, fmt_time(tmpctx, expiry));
  }
  
  static void print_features(const u8 *features)
  {
  	printf("features:");
  	for (size_t i = 0; i < tal_bytelen(features) * CHAR_BIT; i++) {
  		if (feature_is_set(features, i))
  			printf(" %zu", i);
  	}
  	printf("\n");
  }
  
  static bool print_blindedpaths(struct blinded_path **paths,
  			       struct blinded_payinfo **blindedpay)
  {
  	size_t bp_idx = 0;
  
  	for (size_t i = 0; i < tal_count(paths); i++) {
  		struct onionmsg_path **p = paths[i]->path;
  		printf("blindedpath %zu/%zu: blinding %s",
  		       i, tal_count(paths),
  		       type_to_string(tmpctx, struct pubkey,
  				      &paths[i]->blinding));
  		printf("blindedpath %zu/%zu: path ",
  		       i, tal_count(paths));
  		for (size_t j = 0; j < tal_count(p); j++) {
  			printf(" %s:%s",
  			       type_to_string(tmpctx, struct pubkey,
  					      &p[j]->node_id),
  			       tal_hex(tmpctx, p[j]->enctlv));
  			if (blindedpay) {
  				if (bp_idx < tal_count(blindedpay))
  					printf("fee=%u/%u,cltv=%u,features=%s",
  					       blindedpay[bp_idx]->fee_base_msat,
  					       blindedpay[bp_idx]->fee_proportional_millionths,
  					       blindedpay[bp_idx]->cltv_expiry_delta,
  					       tal_hex(tmpctx,
  						       blindedpay[bp_idx]->features));
  				bp_idx++;
  			}
  		}
  		printf("\n");
  	}
  	if (blindedpay && tal_count(blindedpay) != bp_idx) {
  		fprintf(stderr, "Expected %zu blindedpay fields, got %zu\n",
  			bp_idx, tal_count(blindedpay));
  		return false;
  	}
  	return true;
  }
  
  static void print_send_invoice(void)
  {
  	printf("send_invoice\n");
  }
  
  static void print_refund_for(const struct sha256 *payment_hash)
  {
  	printf("refund_for: %s\n",
  	       type_to_string(tmpctx, struct sha256, payment_hash));
  }
  
  static bool print_signature(const char *messagename,
  			    const char *fieldname,
  			    const struct tlv_field *fields,
  			    const struct pubkey32 *node_id,
  			    const struct bip340sig *sig)
  {
  	struct sha256 m, shash;
  
  	/* No key, it's already invalid */
  	if (!node_id)
  		return false;
  
  	merkle_tlv(fields, &m);
  	sighash_from_merkle(messagename, fieldname, &m, &shash);
  	if (secp256k1_schnorrsig_verify(secp256k1_ctx,
  					sig->u8,
  					shash.u.u8,
  					&node_id->pubkey) != 1) {
  		fprintf(stderr, "%s: INVALID\n", fieldname);
  		return false;
  	}
  	printf("%s: %s\n",
  	       fieldname,
  	       type_to_string(tmpctx, struct bip340sig, sig));
  	return true;
  }
  
  static void print_offer_id(const struct sha256 *offer_id)
  {
  	printf("offer_id: %s\n",
  	       type_to_string(tmpctx, struct sha256, offer_id));
  }
  
  static void print_quantity(u64 q)
  {
  	printf("quantity: %"PRIu64"\n", q);
  }
  
  static void print_recurrence_counter(const u32 *recurrence_counter,
  				     const u32 *recurrence_start)
  {
  	printf("recurrence_counter: %u", *recurrence_counter);
  	if (recurrence_start)
  		printf(" (start +%u)", *recurrence_start);
  	printf("\n");
  }
  
  static bool print_recurrence_counter_with_base(const u32 *recurrence_counter,
  					       const u32 *recurrence_start,
  					       const u64 *recurrence_base)
  {
  	if (!recurrence_base) {
  		fprintf(stderr, "Missing recurrence_base\n");
  		return false;
  	}
  	printf("recurrence_counter: %u", *recurrence_counter);
  	if (recurrence_start)
  		printf(" (start +%u)", *recurrence_start);
  	printf(" (base %"PRIu64")\n", *recurrence_base);
  	return true;
  }
  
  static void print_payer_key(const struct pubkey32 *payer_key,
  			    const u8 *payer_info)
  {
  	printf("payer_key: %s",
  	       type_to_string(tmpctx, struct pubkey32, payer_key));
  	if (payer_info)
  		printf(" (payer_info %s)", tal_hex(tmpctx, payer_info));
  	printf("\n");
  }
  
  static void print_payer_note(const char *payer_note)
  {
  	printf("payer_note: %.*s\n",
  	       (int)tal_bytelen(payer_note), payer_note);
  }
  
  static void print_timestamp(u64 timestamp)
  {
  	printf("timestamp: %"PRIu64" (%s)\n",
  	       timestamp, fmt_time(tmpctx, timestamp));
  }
  
  static void print_payment_hash(const struct sha256 *payment_hash)
  {
  	printf("payment_hash: %s\n",
  	       type_to_string(tmpctx, struct sha256, payment_hash));
  }
  
  static void print_cltv(u32 cltv)
  {
  	printf("min_final_cltv_expiry: %u\n", cltv);
  }
  
  static void print_relative_expiry(u64 *timestamp, u32 *relative)
  {
  	/* Ignore if already malformed */
  	if (!timestamp)
  		return;
  
  	/* BOLT-offers #12:
  	 * - if `relative_expiry` is present:
  	 *   - MUST reject the invoice if the current time since 1970-01-01 UTC
  	 *     is greater than `timestamp` plus `seconds_from_timestamp`.
  	 *  - otherwise:
  	 *    - MUST reject the invoice if the current time since 1970-01-01 UTC
  	 *      is greater than `timestamp` plus 7200.
  	 */
  	if (!relative)
  		printf("relative_expiry: %u (%s) (default)\n",
  		       BOLT12_DEFAULT_REL_EXPIRY,
  		       fmt_time(tmpctx, *timestamp + BOLT12_DEFAULT_REL_EXPIRY));
  	else
  		printf("relative_expiry: %u (%s)\n", *relative,
  		       fmt_time(tmpctx, *timestamp + *relative));
  }
  
  static void print_fallbacks(const struct tlv_invoice_fallbacks *fallbacks)
  {
  	for (size_t i = 0; i < tal_count(fallbacks->fallbacks); i++) {
  		/* FIXME: format properly! */
  		printf("fallback: %u %s\n",
  		       fallbacks->fallbacks[i]->version,
  		       tal_hex(tmpctx, fallbacks->fallbacks[i]->address));
  	}
  }
  
  static bool print_extra_fields(const struct tlv_field *fields)
  {
  	bool ok = true;
  
  	for (size_t i = 0; i < tal_count(fields); i++) {
  		if (fields[i].meta)
  			continue;
  		if (fields[i].numtype % 2) {
  			printf("UNKNOWN EVEN field %"PRIu64": %s\n",
  			       fields[i].numtype,
  			       tal_hexstr(tmpctx, fields[i].value, fields[i].length));
  			ok = false;
  		} else {
  			printf("Unknown field %"PRIu64": %s\n",
  			       fields[i].numtype,
  			       tal_hexstr(tmpctx, fields[i].value, fields[i].length));
  		}
  	}
  	return ok;
  }
  
  int main(int argc, char *argv[])
  {
  	const tal_t *ctx = tal(NULL, char);
  	const char *method;
  	char *hrp;
  	u8 *data;
  	char *fail;
  
  	common_setup(argv[0]);
  
  	opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
  	opt_register_noarg("--help|-h", opt_usage_and_exit,
  			   "<decode> <bolt12>", "Show this message");
  	opt_register_version();
  
  	opt_early_parse(argc, argv, opt_log_stderr_exit);
  	opt_parse(&argc, argv, opt_log_stderr_exit);
  
  	method = argv[1];
  	if (!method)
  		errx(ERROR_USAGE, "Need at least one argument\n%s",
  		     opt_usage(argv[0], NULL));
  
  	if (!streq(method, "decode"))
  		errx(ERROR_USAGE, "Need decode argument\n%s",
  		     opt_usage(argv[0], NULL));
  
  	if (!argv[2])
  		errx(ERROR_USAGE, "Need argument\n%s",
  		     opt_usage(argv[0], NULL));
  
  	if (!from_bech32_charset(ctx, argv[2], strlen(argv[2]), &hrp, &data))
  		errx(ERROR_USAGE, "Bad bech32 string\n%s",
  		     opt_usage(argv[0], NULL));
  
  	if (streq(hrp, "lno")) {
  		const struct tlv_offer *offer
  			= offer_decode(ctx, argv[2], strlen(argv[2]),
  				       NULL, NULL, &fail);
  		if (!offer)
  			errx(ERROR_BAD_DECODE, "Bad offer: %s", fail);
  
  		if (offer->send_invoice)
  			print_send_invoice();
  		if (offer->chains)
  			print_chains(offer->chains);
  		if (offer->refund_for)
  			print_refund_for(offer->refund_for);
  		if (offer->amount)
  			well_formed &= print_amount(offer->chains,
  						    offer->currency,
  						    *offer->amount);
  		if (must_have(offer, description))
  			print_description(offer->description);
  		if (offer->vendor)
  			print_vendor(offer->vendor);
  		if (must_have(offer, node_id))
  			print_node_id(offer->node_id);
  		if (offer->quantity_min)
  			print_quantity_min(*offer->quantity_min);
  		if (offer->quantity_max)
  			print_quantity_max(*offer->quantity_max);
  		if (offer->recurrence)
  			well_formed &= print_recurrance(offer->recurrence,
  							offer->recurrence_paywindow,
  							offer->recurrence_limit,
  							offer->recurrence_base);
  		if (offer->absolute_expiry)
  			print_absolute_expiry(*offer->absolute_expiry);
  		if (offer->features)
  			print_features(offer->features);
  		if (offer->paths)
  			print_blindedpaths(offer->paths, NULL);
  		if (offer->signature && offer->node_id)
  			well_formed &= print_signature("offer", "signature",
  						       offer->fields,
  						       offer->node_id,
  						       offer->signature);
  		if (!print_extra_fields(offer->fields))
  			well_formed = false;
  	} else if (streq(hrp, "lnr")) {
  		const struct tlv_invoice_request *invreq
  			= invrequest_decode(ctx, argv[2], strlen(argv[2]),
  					    NULL, NULL, &fail);
  		if (!invreq)
  			errx(ERROR_BAD_DECODE, "Bad invoice_request: %s", fail);
  
  		if (invreq->chains)
  			print_chains(invreq->chains);
  		if (must_have(invreq, payer_key))
  			print_payer_key(invreq->payer_key, invreq->payer_info);
  		if (invreq->payer_note)
  			print_payer_note(invreq->payer_note);
  		if (must_have(invreq, offer_id))
  			print_offer_id(invreq->offer_id);
  		if (must_have(invreq, amount))
  			well_formed &= print_amount(invreq->chains,
  						    NULL,
  						    *invreq->amount);
  		if (invreq->features)
  			print_features(invreq->features);
  		if (invreq->quantity)
  			print_quantity(*invreq->quantity);
  		/* Note: old format didn't include this, so we don't complain! */
  		if (invreq->payer_signature)
  			well_formed &= print_signature("invoice_request",
  						       "payer_signature",
  						       invreq->fields,
  						       invreq->payer_key,
  						       invreq->payer_signature);
  		if (invreq->recurrence_counter) {
  			print_recurrence_counter(invreq->recurrence_counter,
  						 invreq->recurrence_start);
  			/* Old form included recurrence_signature */
  			if (invreq->recurrence_signature)
  				well_formed &= print_signature("invoice_request",
  							       "recurrence_signature",
  							       invreq->fields,
  							       invreq->payer_key,
  							       invreq->recurrence_signature);
  			else /* New form definitely should have this! */
  				must_have(invreq, payer_signature);
  		} else {
  			must_not_have(invreq, recurrence_start);
  			must_not_have(invreq, recurrence_signature);
  		}
  		if (!print_extra_fields(invreq->fields))
  			well_formed = false;
  	} else if (streq(hrp, "lni")) {
  		const struct tlv_invoice *invoice
  			= invoice_decode(ctx, argv[2], strlen(argv[2]),
  					 NULL, NULL, &fail);
  		if (!invoice)
  			errx(ERROR_BAD_DECODE, "Bad invoice: %s", fail);
  
  		if (invoice->chains)
  			print_chains(invoice->chains);
  
  		if (invoice->offer_id) {
  			print_offer_id(invoice->offer_id);
  		}
  		if (must_have(invoice, amount))
  			well_formed &= print_amount(invoice->chains,
  						    NULL,
  						    *invoice->amount);
  		if (must_have(invoice, description))
  			print_description(invoice->description);
  		if (invoice->features)
  			print_features(invoice->features);
  		if (invoice->paths) {
  			must_have(invoice, blindedpay);
  			well_formed &= print_blindedpaths(invoice->paths,
  							  invoice->blindedpay);
  		} else
  			must_not_have(invoice, blindedpay);
  		if (invoice->vendor)
  			print_vendor(invoice->vendor);
  		if (must_have(invoice, node_id))
  			print_node_id(invoice->node_id);
  		if (invoice->quantity)
  			print_quantity(*invoice->quantity);
  		if (invoice->refund_for) {
  			print_refund_for(invoice->refund_for);
  			if (must_have(invoice, refund_signature))
  				well_formed &= print_signature("invoice",
  							       "refund_signature",
  							       invoice->fields,
  							       invoice->payer_key,
  							       invoice->refund_signature);
  		} else {
  			must_not_have(invoice, refund_signature);
  		}
  		if (invoice->recurrence_counter) {
  			well_formed &=
  				print_recurrence_counter_with_base(invoice->recurrence_counter,
  								   invoice->recurrence_start,
  								   invoice->recurrence_basetime);
  		} else {
  			must_not_have(invoice, recurrence_start);
  			must_not_have(invoice, recurrence_basetime);
  		}
  		if (must_have(invoice, payer_key))
  			print_payer_key(invoice->payer_key, invoice->payer_info);
  		if (must_have(invoice, timestamp))
  			print_timestamp(*invoice->timestamp);
  		if (invoice->payer_note)
  			print_payer_note(invoice->payer_note);
  		print_relative_expiry(invoice->timestamp,
  				      invoice->relative_expiry);
  		if (must_have(invoice, payment_hash))
  			print_payment_hash(invoice->payment_hash);
  		if (must_have(invoice, cltv))
  			print_cltv(*invoice->cltv);
  		if (invoice->fallbacks)
  			print_fallbacks(invoice->fallbacks);
  		if (must_have(invoice, signature))
  			well_formed &= print_signature("invoice", "signature",
  						       invoice->fields,
  						       invoice->node_id,
  						       invoice->signature);
  		if (!print_extra_fields(invoice->fields))
  			well_formed = false;
  	} else
  		errx(ERROR_BAD_DECODE, "Unknown prefix %s", hrp);
  
  	tal_free(ctx);
  	common_shutdown();
  
  	if (well_formed)
  		return NO_ERROR;
  	else
  		return ERROR_BAD_DECODE;
  }
  