mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-20 13:54:36 +01:00
common/bolt11_json: extract bolt11->json code.
Our new "decode" command will also handle bolt11. We make a few cleanups: 1. Avoid type_to_string() in JSON, instead use format functions directly. 2. Don't need to escape description now that JSON core does that for us. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
1aa7e8e011
commit
84dc943cf5
11 changed files with 151 additions and 136 deletions
|
@ -310,8 +310,7 @@ bool signature_from_der(const u8 *der, size_t len, struct bitcoin_signature *sig
|
|||
return true;
|
||||
}
|
||||
|
||||
static char *signature_to_hexstr(const tal_t *ctx,
|
||||
const secp256k1_ecdsa_signature *sig)
|
||||
char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig)
|
||||
{
|
||||
u8 der[72];
|
||||
size_t len = 72;
|
||||
|
@ -321,7 +320,7 @@ static char *signature_to_hexstr(const tal_t *ctx,
|
|||
|
||||
return tal_hexstr(ctx, der, len);
|
||||
}
|
||||
REGISTER_TYPE_TO_STRING(secp256k1_ecdsa_signature, signature_to_hexstr);
|
||||
REGISTER_TYPE_TO_STRING(secp256k1_ecdsa_signature, fmt_signature);
|
||||
|
||||
static char *bitcoin_signature_to_hexstr(const tal_t *ctx,
|
||||
const struct bitcoin_signature *sig)
|
||||
|
|
|
@ -142,6 +142,7 @@ void fromwire_bip340sig(const u8 **cursor, size_t *max,
|
|||
struct bip340sig *bip340sig);
|
||||
|
||||
/* Get a hex string sig */
|
||||
char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig);
|
||||
char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig);
|
||||
|
||||
/* For caller convenience, we hand in tag in parts (any can be "") */
|
||||
|
|
|
@ -9,6 +9,7 @@ COMMON_SRC_NOGEN := \
|
|||
common/bip32.c \
|
||||
common/blinding.c \
|
||||
common/bolt11.c \
|
||||
common/bolt11_json.c \
|
||||
common/bolt12.c \
|
||||
common/channel_config.c \
|
||||
common/channel_id.c \
|
||||
|
|
|
@ -297,8 +297,7 @@ static char *decode_n(struct bolt11 *b11,
|
|||
data_length * 5, false);
|
||||
if (!node_id_valid(&b11->receiver_id))
|
||||
return tal_fmt(b11, "n: invalid pubkey %s",
|
||||
type_to_string(tmpctx, struct node_id,
|
||||
&b11->receiver_id));
|
||||
node_id_to_hexstr(tmpctx, &b11->receiver_id));
|
||||
|
||||
*have_n = true;
|
||||
return NULL;
|
||||
|
|
129
common/bolt11_json.c
Normal file
129
common/bolt11_json.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include <bitcoin/address.h>
|
||||
#include <bitcoin/base58.h>
|
||||
#include <bitcoin/chainparams.h>
|
||||
#include <bitcoin/script.h>
|
||||
#include <common/bech32.h>
|
||||
#include <common/bolt11.h>
|
||||
#include <common/bolt11_json.h>
|
||||
#include <common/json.h>
|
||||
#include <common/json_helpers.h>
|
||||
#include <common/json_stream.h>
|
||||
|
||||
static void json_add_fallback(struct json_stream *response,
|
||||
const char *fieldname,
|
||||
const u8 *fallback,
|
||||
const struct chainparams *chain)
|
||||
{
|
||||
struct bitcoin_address pkh;
|
||||
struct ripemd160 sh;
|
||||
struct sha256 wsh;
|
||||
|
||||
json_object_start(response, fieldname);
|
||||
if (is_p2pkh(fallback, &pkh)) {
|
||||
json_add_string(response, "type", "P2PKH");
|
||||
json_add_string(response, "addr",
|
||||
bitcoin_to_base58(tmpctx, chain, &pkh));
|
||||
} else if (is_p2sh(fallback, &sh)) {
|
||||
json_add_string(response, "type", "P2SH");
|
||||
json_add_string(response, "addr",
|
||||
p2sh_to_base58(tmpctx, chain, &sh));
|
||||
} else if (is_p2wpkh(fallback, &pkh)) {
|
||||
char out[73 + strlen(chain->bip173_name)];
|
||||
json_add_string(response, "type", "P2WPKH");
|
||||
if (segwit_addr_encode(out, chain->bip173_name, 0,
|
||||
(const u8 *)&pkh, sizeof(pkh)))
|
||||
json_add_string(response, "addr", out);
|
||||
} else if (is_p2wsh(fallback, &wsh)) {
|
||||
char out[73 + strlen(chain->bip173_name)];
|
||||
json_add_string(response, "type", "P2WSH");
|
||||
if (segwit_addr_encode(out, chain->bip173_name, 0,
|
||||
(const u8 *)&wsh, sizeof(wsh)))
|
||||
json_add_string(response, "addr", out);
|
||||
}
|
||||
json_add_hex_talarr(response, "hex", fallback);
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
void json_add_bolt11(struct json_stream *response,
|
||||
const struct bolt11 *b11)
|
||||
{
|
||||
json_add_string(response, "currency", b11->chain->bip173_name);
|
||||
json_add_u64(response, "created_at", b11->timestamp);
|
||||
json_add_u64(response, "expiry", b11->expiry);
|
||||
json_add_node_id(response, "payee", &b11->receiver_id);
|
||||
if (b11->msat)
|
||||
json_add_amount_msat_compat(response, *b11->msat,
|
||||
"msatoshi", "amount_msat");
|
||||
if (b11->description)
|
||||
json_add_string(response, "description", b11->description);
|
||||
if (b11->description_hash)
|
||||
json_add_sha256(response, "description_hash",
|
||||
b11->description_hash);
|
||||
json_add_num(response, "min_final_cltv_expiry",
|
||||
b11->min_final_cltv_expiry);
|
||||
if (b11->payment_secret)
|
||||
json_add_secret(response, "payment_secret",
|
||||
b11->payment_secret);
|
||||
if (b11->features)
|
||||
json_add_hex_talarr(response, "features", b11->features);
|
||||
if (tal_count(b11->fallbacks)) {
|
||||
json_array_start(response, "fallbacks");
|
||||
for (size_t i = 0; i < tal_count(b11->fallbacks); i++)
|
||||
json_add_fallback(response, NULL,
|
||||
b11->fallbacks[i], b11->chain);
|
||||
json_array_end(response);
|
||||
}
|
||||
|
||||
if (tal_count(b11->routes)) {
|
||||
size_t i, n;
|
||||
|
||||
json_array_start(response, "routes");
|
||||
for (i = 0; i < tal_count(b11->routes); i++) {
|
||||
json_array_start(response, NULL);
|
||||
for (n = 0; n < tal_count(b11->routes[i]); n++) {
|
||||
json_object_start(response, NULL);
|
||||
json_add_node_id(response, "pubkey",
|
||||
&b11->routes[i][n].pubkey);
|
||||
json_add_short_channel_id(response,
|
||||
"short_channel_id",
|
||||
&b11->routes[i][n]
|
||||
.short_channel_id);
|
||||
json_add_u64(response, "fee_base_msat",
|
||||
b11->routes[i][n].fee_base_msat);
|
||||
json_add_u64(response, "fee_proportional_millionths",
|
||||
b11->routes[i][n].fee_proportional_millionths);
|
||||
json_add_num(response, "cltv_expiry_delta",
|
||||
b11->routes[i][n]
|
||||
.cltv_expiry_delta);
|
||||
json_object_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
}
|
||||
|
||||
if (!list_empty(&b11->extra_fields)) {
|
||||
struct bolt11_field *extra;
|
||||
|
||||
json_array_start(response, "extra");
|
||||
list_for_each(&b11->extra_fields, extra, list) {
|
||||
char *data = tal_arr(NULL, char, tal_count(extra->data)+1);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < tal_count(extra->data); i++)
|
||||
data[i] = bech32_charset[extra->data[i]];
|
||||
data[i] = '\0';
|
||||
json_object_start(response, NULL);
|
||||
json_add_string(response, "tag",
|
||||
tal_fmt(data, "%c", extra->tag));
|
||||
json_add_string(response, "data", data);
|
||||
tal_free(data);
|
||||
json_object_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
}
|
||||
|
||||
json_add_sha256(response, "payment_hash", &b11->payment_hash);
|
||||
|
||||
json_add_string(response, "signature", fmt_signature(tmpctx, &b11->sig));
|
||||
}
|
10
common/bolt11_json.h
Normal file
10
common/bolt11_json.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef LIGHTNING_COMMON_BOLT11_JSON_H
|
||||
#define LIGHTNING_COMMON_BOLT11_JSON_H
|
||||
#include "config.h"
|
||||
|
||||
struct bolt11;
|
||||
struct json_stream;
|
||||
|
||||
void json_add_bolt11(struct json_stream *response,
|
||||
const struct bolt11 *b11);
|
||||
#endif /* LIGHTNING_COMMON_BOLT11_JSON_H */
|
|
@ -16,10 +16,6 @@
|
|||
#include <wally_core.h>
|
||||
|
||||
/* AUTOGENERATED MOCKS START */
|
||||
/* Generated stub for type_to_string_ */
|
||||
const char *type_to_string_(const tal_t *ctx UNNEEDED, const char *typename UNNEEDED,
|
||||
union printable_types u UNNEEDED)
|
||||
{ fprintf(stderr, "type_to_string_ called!\n"); abort(); }
|
||||
/* AUTOGENERATED MOCKS END */
|
||||
|
||||
static struct privkey privkey;
|
||||
|
|
|
@ -76,6 +76,7 @@ LIGHTNINGD_COMMON_OBJS := \
|
|||
common/bip32.o \
|
||||
common/blinding.o \
|
||||
common/bolt11.o \
|
||||
common/bolt11_json.o \
|
||||
common/channel_id.o \
|
||||
common/channel_config.o \
|
||||
common/coin_mvt.o \
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
#include "invoice.h"
|
||||
#include <bitcoin/address.h>
|
||||
#include <bitcoin/base58.h>
|
||||
#include <bitcoin/script.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/json_escape/json_escape.h>
|
||||
|
@ -10,6 +7,7 @@
|
|||
#include <common/amount.h>
|
||||
#include <common/bech32.h>
|
||||
#include <common/bolt11.h>
|
||||
#include <common/bolt11_json.h>
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
#include <common/bolt12.h>
|
||||
#include <common/bolt12_merkle.h>
|
||||
|
@ -1391,41 +1389,6 @@ static const struct json_command waitinvoice_command = {
|
|||
};
|
||||
AUTODATA(json_command, &waitinvoice_command);
|
||||
|
||||
static void json_add_fallback(struct json_stream *response,
|
||||
const char *fieldname,
|
||||
const u8 *fallback,
|
||||
const struct chainparams *chain)
|
||||
{
|
||||
struct bitcoin_address pkh;
|
||||
struct ripemd160 sh;
|
||||
struct sha256 wsh;
|
||||
|
||||
json_object_start(response, fieldname);
|
||||
if (is_p2pkh(fallback, &pkh)) {
|
||||
json_add_string(response, "type", "P2PKH");
|
||||
json_add_string(response, "addr",
|
||||
bitcoin_to_base58(tmpctx, chain, &pkh));
|
||||
} else if (is_p2sh(fallback, &sh)) {
|
||||
json_add_string(response, "type", "P2SH");
|
||||
json_add_string(response, "addr",
|
||||
p2sh_to_base58(tmpctx, chain, &sh));
|
||||
} else if (is_p2wpkh(fallback, &pkh)) {
|
||||
char out[73 + strlen(chain->bip173_name)];
|
||||
json_add_string(response, "type", "P2WPKH");
|
||||
if (segwit_addr_encode(out, chain->bip173_name, 0,
|
||||
(const u8 *)&pkh, sizeof(pkh)))
|
||||
json_add_string(response, "addr", out);
|
||||
} else if (is_p2wsh(fallback, &wsh)) {
|
||||
char out[73 + strlen(chain->bip173_name)];
|
||||
json_add_string(response, "type", "P2WSH");
|
||||
if (segwit_addr_encode(out, chain->bip173_name, 0,
|
||||
(const u8 *)&wsh, sizeof(wsh)))
|
||||
json_add_string(response, "addr", out);
|
||||
}
|
||||
json_add_hex_talarr(response, "hex", fallback);
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
static struct command_result *json_decodepay(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
|
@ -1450,89 +1413,7 @@ static struct command_result *json_decodepay(struct command *cmd,
|
|||
}
|
||||
|
||||
response = json_stream_success(cmd);
|
||||
json_add_string(response, "currency", b11->chain->bip173_name);
|
||||
json_add_u64(response, "created_at", b11->timestamp);
|
||||
json_add_u64(response, "expiry", b11->expiry);
|
||||
json_add_node_id(response, "payee", &b11->receiver_id);
|
||||
if (b11->msat)
|
||||
json_add_amount_msat_compat(response, *b11->msat,
|
||||
"msatoshi", "amount_msat");
|
||||
if (b11->description) {
|
||||
struct json_escape *esc = json_escape(NULL, b11->description);
|
||||
json_add_escaped_string(response, "description", take(esc));
|
||||
}
|
||||
if (b11->description_hash)
|
||||
json_add_sha256(response, "description_hash",
|
||||
b11->description_hash);
|
||||
json_add_num(response, "min_final_cltv_expiry",
|
||||
b11->min_final_cltv_expiry);
|
||||
if (b11->payment_secret)
|
||||
json_add_secret(response, "payment_secret",
|
||||
b11->payment_secret);
|
||||
if (b11->features)
|
||||
json_add_hex_talarr(response, "features", b11->features);
|
||||
if (tal_count(b11->fallbacks)) {
|
||||
json_array_start(response, "fallbacks");
|
||||
for (size_t i = 0; i < tal_count(b11->fallbacks); i++)
|
||||
json_add_fallback(response, NULL,
|
||||
b11->fallbacks[i], b11->chain);
|
||||
json_array_end(response);
|
||||
}
|
||||
|
||||
if (tal_count(b11->routes)) {
|
||||
size_t i, n;
|
||||
|
||||
json_array_start(response, "routes");
|
||||
for (i = 0; i < tal_count(b11->routes); i++) {
|
||||
json_array_start(response, NULL);
|
||||
for (n = 0; n < tal_count(b11->routes[i]); n++) {
|
||||
json_object_start(response, NULL);
|
||||
json_add_node_id(response, "pubkey",
|
||||
&b11->routes[i][n].pubkey);
|
||||
json_add_short_channel_id(response,
|
||||
"short_channel_id",
|
||||
&b11->routes[i][n]
|
||||
.short_channel_id);
|
||||
json_add_u64(response, "fee_base_msat",
|
||||
b11->routes[i][n].fee_base_msat);
|
||||
json_add_u64(response, "fee_proportional_millionths",
|
||||
b11->routes[i][n].fee_proportional_millionths);
|
||||
json_add_num(response, "cltv_expiry_delta",
|
||||
b11->routes[i][n]
|
||||
.cltv_expiry_delta);
|
||||
json_object_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
}
|
||||
|
||||
if (!list_empty(&b11->extra_fields)) {
|
||||
struct bolt11_field *extra;
|
||||
|
||||
json_array_start(response, "extra");
|
||||
list_for_each(&b11->extra_fields, extra, list) {
|
||||
char *data = tal_arr(cmd, char, tal_count(extra->data)+1);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < tal_count(extra->data); i++)
|
||||
data[i] = bech32_charset[extra->data[i]];
|
||||
data[i] = '\0';
|
||||
json_object_start(response, NULL);
|
||||
json_add_string(response, "tag",
|
||||
tal_fmt(data, "%c", extra->tag));
|
||||
json_add_string(response, "data", data);
|
||||
tal_free(data);
|
||||
json_object_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
}
|
||||
|
||||
json_add_sha256(response, "payment_hash", &b11->payment_hash);
|
||||
|
||||
json_add_string(response, "signature",
|
||||
type_to_string(cmd, secp256k1_ecdsa_signature,
|
||||
&b11->sig));
|
||||
json_add_bolt11(response, b11);
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
|
|
|
@ -1377,7 +1377,6 @@ static struct command_result *json_listpeers(struct command *cmd,
|
|||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
/* Magic marker: remove at your own peril! */
|
||||
static const struct json_command listpeers_command = {
|
||||
"listpeers",
|
||||
"network",
|
||||
|
|
|
@ -250,6 +250,10 @@ void json_add_amount_sat_compat(struct json_stream *result UNNEEDED,
|
|||
const char *msatfieldname)
|
||||
|
||||
{ fprintf(stderr, "json_add_amount_sat_compat called!\n"); abort(); }
|
||||
/* Generated stub for json_add_bolt11 */
|
||||
void json_add_bolt11(struct json_stream *response UNNEEDED,
|
||||
const struct bolt11 *b11 UNNEEDED)
|
||||
{ fprintf(stderr, "json_add_bolt11 called!\n"); abort(); }
|
||||
/* Generated stub for json_add_log */
|
||||
void json_add_log(struct json_stream *result UNNEEDED,
|
||||
const struct log_book *lr UNNEEDED,
|
||||
|
@ -271,11 +275,6 @@ void json_add_node_id(struct json_stream *response UNNEEDED,
|
|||
void json_add_preimage(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
|
||||
const struct preimage *preimage UNNEEDED)
|
||||
{ fprintf(stderr, "json_add_preimage called!\n"); abort(); }
|
||||
/* Generated stub for json_add_secret */
|
||||
void json_add_secret(struct json_stream *response UNNEEDED,
|
||||
const char *fieldname UNNEEDED,
|
||||
const struct secret *secret UNNEEDED)
|
||||
{ fprintf(stderr, "json_add_secret called!\n"); abort(); }
|
||||
/* Generated stub for json_add_sha256 */
|
||||
void json_add_sha256(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
|
||||
const struct sha256 *hash UNNEEDED)
|
||||
|
|
Loading…
Add table
Reference in a new issue