offers: import latest variant from draft.

In particular, this changes the name of a field in invoice_request:
`payer_signature` becomes simply `signature`.  So we allow both for
now, and send the old one unless deprecated_apis is disabled.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-03-22 19:20:13 +10:30
parent e36d4d1143
commit 726b6878d1
10 changed files with 96 additions and 52 deletions

View File

@@ -205,7 +205,7 @@ void merkle_tlv(const struct tlv_field *fields, struct sha256 *merkle)
* Merkle-root; "lightning" is the literal 9-byte ASCII string, * Merkle-root; "lightning" is the literal 9-byte ASCII string,
* `messagename` is the name of the TLV stream being signed (i.e. "offer", * `messagename` is the name of the TLV stream being signed (i.e. "offer",
* "invoice_request" or "invoice") and the `fieldname` is the TLV field * "invoice_request" or "invoice") and the `fieldname` is the TLV field
* containing the signature (e.g. "signature" or "payer_signature"). * containing the signature (e.g. "signature" or "refund_signature").
*/ */
void sighash_from_merkle(const char *messagename, void sighash_from_merkle(const char *messagename,
const char *fieldname, const char *fieldname,

View File

@@ -60,6 +60,9 @@ void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
/* Generated stub for towire_sha256 */ /* Generated stub for towire_sha256 */
void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED) void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
{ fprintf(stderr, "towire_sha256 called!\n"); abort(); } { fprintf(stderr, "towire_sha256 called!\n"); abort(); }
/* Generated stub for towire_tu16 */
void towire_tu16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_tu16 called!\n"); abort(); }
/* Generated stub for towire_tu32 */ /* Generated stub for towire_tu32 */
void towire_tu32(u8 **pptr UNNEEDED, u32 v UNNEEDED) void towire_tu32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
{ fprintf(stderr, "towire_tu32 called!\n"); abort(); } { fprintf(stderr, "towire_tu32 called!\n"); abort(); }

View File

@@ -422,13 +422,13 @@ static void print_relative_expiry(u64 *created_at, u32 *relative)
fmt_time(tmpctx, *created_at + *relative)); fmt_time(tmpctx, *created_at + *relative));
} }
static void print_fallbacks(const struct tlv_invoice_fallbacks *fallbacks) static void print_fallbacks(struct fallback_address **fallbacks)
{ {
for (size_t i = 0; i < tal_count(fallbacks->fallbacks); i++) { for (size_t i = 0; i < tal_count(fallbacks); i++) {
/* FIXME: format properly! */ /* FIXME: format properly! */
printf("fallback: %u %s\n", printf("fallback: %u %s\n",
fallbacks->fallbacks[i]->version, fallbacks[i]->version,
tal_hex(tmpctx, fallbacks->fallbacks[i]->address)); tal_hex(tmpctx, fallbacks[i]->address));
} }
} }
@@ -556,12 +556,20 @@ int main(int argc, char *argv[])
print_features(invreq->features); print_features(invreq->features);
if (invreq->quantity) if (invreq->quantity)
print_quantity(*invreq->quantity); print_quantity(*invreq->quantity);
if (must_have(invreq, payer_signature)) if (must_have(invreq, signature)) {
well_formed &= print_signature("invoice_request", if (!print_signature("invoice_request",
"payer_signature", "signature",
invreq->fields, invreq->fields,
invreq->payer_key, invreq->payer_key,
invreq->payer_signature); invreq->signature)) {
/* FIXME: We temporarily allow the old "payer_signature" name */
well_formed &= print_signature("invoice_request",
"payer_signature",
invreq->fields,
invreq->payer_key,
invreq->signature);
}
}
if (invreq->recurrence_counter) { if (invreq->recurrence_counter) {
print_recurrence_counter(invreq->recurrence_counter, print_recurrence_counter(invreq->recurrence_counter,
invreq->recurrence_start); invreq->recurrence_start);

View File

@@ -3,6 +3,7 @@
#include <ccan/json_escape/json_escape.h> #include <ccan/json_escape/json_escape.h>
#include <ccan/take/take.h> #include <ccan/take/take.h>
#include <common/bolt12_merkle.h> #include <common/bolt12_merkle.h>
#include <common/configdir.h>
#include <common/json_command.h> #include <common/json_command.h>
#include <common/json_helpers.h> #include <common/json_helpers.h>
#include <common/json_tok.h> #include <common/json_tok.h>
@@ -466,16 +467,21 @@ static struct command_result *json_createinvoicerequest(struct command *cmd,
} }
/* BOLT-offers #12: /* BOLT-offers #12:
* - MUST set `payer_signature` `sig` as detailed in * - MUST set `signature` `sig` as detailed in
* [Signature Calculation](#signature-calculation) using the `payer_key`. * [Signature Calculation](#signature-calculation) using the `payer_key`.
*/ */
/* This populates the ->fields from our entries */ /* This populates the ->fields from our entries */
invreq->fields = tlv_make_fields(invreq, invoice_request); invreq->fields = tlv_make_fields(invreq, invoice_request);
merkle_tlv(invreq->fields, &merkle); merkle_tlv(invreq->fields, &merkle);
invreq->payer_signature = tal(invreq, struct bip340sig); invreq->signature = tal(invreq, struct bip340sig);
hsm_sign_b12(cmd->ld, "invoice_request", "payer_signature", if (deprecated_apis)
&merkle, invreq->payer_info, invreq->payer_key, hsm_sign_b12(cmd->ld, "invoice_request", "payer_signature",
invreq->payer_signature); &merkle, invreq->payer_info, invreq->payer_key,
invreq->signature);
else
hsm_sign_b12(cmd->ld, "invoice_request", "signature",
&merkle, invreq->payer_info, invreq->payer_key,
invreq->signature);
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_add_string(response, "bolt12", invrequest_encode(tmpctx, invreq)); json_add_string(response, "bolt12", invrequest_encode(tmpctx, invreq));

View File

@@ -1192,11 +1192,14 @@ force_payer_secret(struct command *cmd,
"Could not remarshall invreq %s", tal_hex(tmpctx, msg)); "Could not remarshall invreq %s", tal_hex(tmpctx, msg));
merkle_tlv(sent->invreq->fields, &merkle); merkle_tlv(sent->invreq->fields, &merkle);
sighash_from_merkle("invoice_request", "payer_signature", &merkle, &sha); if (deprecated_apis)
sighash_from_merkle("invoice_request", "payer_signature", &merkle, &sha);
else
sighash_from_merkle("invoice_request", "signature", &merkle, &sha);
sent->invreq->payer_signature = tal(invreq, struct bip340sig); sent->invreq->signature = tal(invreq, struct bip340sig);
if (!secp256k1_schnorrsig_sign(secp256k1_ctx, if (!secp256k1_schnorrsig_sign(secp256k1_ctx,
sent->invreq->payer_signature->u8, sent->invreq->signature->u8,
sha.u.u8, sha.u.u8,
&kp, &kp,
NULL, NULL)) { NULL, NULL)) {

View File

@@ -16,7 +16,7 @@
#include <plugins/offers_offer.h> #include <plugins/offers_offer.h>
struct point32 id; struct point32 id;
u32 cltv_final; u16 cltv_final;
bool offers_enabled; bool offers_enabled;
static struct command_result *finished(struct command *cmd, static struct command_result *finished(struct command *cmd,
@@ -679,7 +679,7 @@ static void json_add_b12_invoice(struct json_stream *js,
if (invoice->fallbacks) if (invoice->fallbacks)
valid &= json_add_fallbacks(js, valid &= json_add_fallbacks(js,
invoice->chain, invoice->chain,
invoice->fallbacks->fallbacks); invoice->fallbacks);
/* BOLT-offers #12: /* BOLT-offers #12:
* - if the offer contained `refund_for`: * - if the offer contained `refund_for`:
@@ -769,23 +769,38 @@ static void json_add_invoice_request(struct json_stream *js,
tal_bytelen(invreq->payer_note)); tal_bytelen(invreq->payer_note));
/* BOLT-offers #12: /* BOLT-offers #12:
* - MUST fail the request if there is no `payer_signature` field. * - MUST fail the request if there is no `signature` field.
* - MUST fail the request if `payer_signature` is not correct. * - MUST fail the request if `signature` is not correct.
*/ */
if (invreq->payer_signature) { if (invreq->signature) {
if (invreq->payer_key if (invreq->payer_key
&& !bolt12_check_signature(invreq->fields, && !bolt12_check_signature(invreq->fields,
"invoice_request", "invoice_request",
"payer_signature", "signature",
invreq->payer_key, invreq->payer_key,
invreq->payer_signature)) { invreq->signature)) {
json_add_string(js, "warning_invoice_request_invalid_payer_signature", bool sig_valid;
"Bad payer_signature");
valid = false; if (deprecated_apis) {
/* The old name? */
sig_valid = bolt12_check_signature(invreq->fields,
"invoice_request",
"payer_signature",
invreq->payer_key,
invreq->signature);
} else {
sig_valid = false;
}
if (!sig_valid) {
json_add_string(js, "warning_invoice_request_invalid_signature",
"Bad signature");
valid = false;
}
} }
} else { } else {
json_add_string(js, "warning_invoice_request_missing_payer_signature", json_add_string(js, "warning_invoice_request_missing_signature",
"Missing payer_signature"); "Missing signature");
valid = false; valid = false;
} }
@@ -836,7 +851,7 @@ static const char *init(struct plugin *p,
rpc_scan(p, "listconfigs", rpc_scan(p, "listconfigs",
take(json_out_obj(NULL, NULL, NULL)), take(json_out_obj(NULL, NULL, NULL)),
"{cltv-final:%,experimental-offers:%}", "{cltv-final:%,experimental-offers:%}",
JSON_SCAN(json_to_number, &cltv_final), JSON_SCAN(json_to_u16, &cltv_final),
JSON_SCAN(json_to_bool, &offers_enabled)); JSON_SCAN(json_to_bool, &offers_enabled));
return NULL; return NULL;

View File

@@ -417,7 +417,7 @@ static struct command_result *check_previous_invoice(struct command *cmd,
} }
/* BOLT-offers #12: /* BOLT-offers #12:
* - MUST fail the request if `payer_signature` is not correct. * - MUST fail the request if `signature` is not correct.
*/ */
static bool check_payer_sig(const struct tlv_invoice_request *invreq, static bool check_payer_sig(const struct tlv_invoice_request *invreq,
const struct point32 *payer_key, const struct point32 *payer_key,
@@ -425,6 +425,17 @@ static bool check_payer_sig(const struct tlv_invoice_request *invreq,
{ {
struct sha256 merkle, sighash; struct sha256 merkle, sighash;
merkle_tlv(invreq->fields, &merkle); merkle_tlv(invreq->fields, &merkle);
sighash_from_merkle("invoice_request", "signature", &merkle, &sighash);
if (secp256k1_schnorrsig_verify(secp256k1_ctx,
sig->u8,
sighash.u.u8, &payer_key->pubkey) == 1)
return true;
if (!deprecated_apis)
return false;
/* Try old name */
sighash_from_merkle("invoice_request", "payer_signature", sighash_from_merkle("invoice_request", "payer_signature",
&merkle, &sighash); &merkle, &sighash);
@@ -714,13 +725,13 @@ static struct command_result *listoffers_done(struct command *cmd,
return err; return err;
} }
err = invreq_must_have(cmd, ir, payer_signature); err = invreq_must_have(cmd, ir, signature);
if (err) if (err)
return err; return err;
if (!check_payer_sig(ir->invreq, if (!check_payer_sig(ir->invreq,
ir->invreq->payer_key, ir->invreq->payer_key,
ir->invreq->payer_signature)) { ir->invreq->signature)) {
return fail_invreq(cmd, ir, "bad payer_signature"); return fail_invreq(cmd, ir, "bad signature");
} }
if (ir->offer->recurrence) { if (ir->offer->recurrence) {
@@ -806,7 +817,7 @@ static struct command_result *listoffers_done(struct command *cmd,
ir->inv->payment_hash = tal(ir->inv, struct sha256); ir->inv->payment_hash = tal(ir->inv, struct sha256);
sha256(ir->inv->payment_hash, &ir->preimage, sizeof(ir->preimage)); sha256(ir->inv->payment_hash, &ir->preimage, sizeof(ir->preimage));
ir->inv->cltv = tal_dup(ir->inv, u32, &cltv_final); ir->inv->cltv = tal_dup(ir->inv, u16, &cltv_final);
ir->inv->created_at = tal(ir->inv, u64); ir->inv->created_at = tal(ir->inv, u64);
*ir->inv->created_at = time_now().ts.tv_sec; *ir->inv->created_at = time_now().ts.tv_sec;

View File

@@ -3,7 +3,7 @@
#include "config.h" #include "config.h"
#include <plugins/libplugin.h> #include <plugins/libplugin.h>
extern u32 cltv_final; extern u16 cltv_final;
/* We got an onionmessage with an invreq! */ /* We got an onionmessage with an invreq! */
struct command_result *handle_invoice_request(struct command *cmd, struct command_result *handle_invoice_request(struct command *cmd,

View File

@@ -64,8 +64,8 @@ tlvtype,invoice_request,payer_info,50
tlvdata,invoice_request,payer_info,blob,byte,... tlvdata,invoice_request,payer_info,blob,byte,...
tlvtype,invoice_request,replace_invoice,56 tlvtype,invoice_request,replace_invoice,56
tlvdata,invoice_request,replace_invoice,payment_hash,sha256, tlvdata,invoice_request,replace_invoice,payment_hash,sha256,
tlvtype,invoice_request,payer_signature,240 tlvtype,invoice_request,signature,240
tlvdata,invoice_request,payer_signature,sig,bip340sig, tlvdata,invoice_request,signature,sig,bip340sig,
tlvtype,invoice,chain,3 tlvtype,invoice,chain,3
tlvdata,invoice,chain,chain,chain_hash, tlvdata,invoice,chain,chain,chain_hash,
tlvtype,invoice,offer_id,4 tlvtype,invoice,offer_id,4
@@ -101,8 +101,6 @@ tlvtype,invoice,payer_key,38
tlvdata,invoice,payer_key,key,point32, tlvdata,invoice,payer_key,key,point32,
tlvtype,invoice,payer_note,39 tlvtype,invoice,payer_note,39
tlvdata,invoice,payer_note,note,utf8,... tlvdata,invoice,payer_note,note,utf8,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,created_at,40 tlvtype,invoice,created_at,40
tlvdata,invoice,created_at,timestamp,tu64, tlvdata,invoice,created_at,timestamp,tu64,
tlvtype,invoice,payment_hash,42 tlvtype,invoice,payment_hash,42
@@ -110,10 +108,11 @@ tlvdata,invoice,payment_hash,payment_hash,sha256,
tlvtype,invoice,relative_expiry,44 tlvtype,invoice,relative_expiry,44
tlvdata,invoice,relative_expiry,seconds_from_creation,tu32, tlvdata,invoice,relative_expiry,seconds_from_creation,tu32,
tlvtype,invoice,cltv,46 tlvtype,invoice,cltv,46
tlvdata,invoice,cltv,min_final_cltv_expiry,tu32, tlvdata,invoice,cltv,min_final_cltv_expiry,tu16,
tlvtype,invoice,fallbacks,48 tlvtype,invoice,fallbacks,48
tlvdata,invoice,fallbacks,num,byte, tlvdata,invoice,fallbacks,fallbacks,fallback_address,...
tlvdata,invoice,fallbacks,fallbacks,fallback_address,num tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,refund_signature,52 tlvtype,invoice,refund_signature,52
tlvdata,invoice,refund_signature,payer_signature,bip340sig, tlvdata,invoice,refund_signature,payer_signature,bip340sig,
tlvtype,invoice,replace_invoice,56 tlvtype,invoice,replace_invoice,56
1 tlvtype,offer,chains,2
64 tlvdata,invoice_request,payer_info,blob,byte,...
65 tlvtype,invoice_request,replace_invoice,56
66 tlvdata,invoice_request,replace_invoice,payment_hash,sha256,
67 tlvtype,invoice_request,payer_signature,240 tlvtype,invoice_request,signature,240
68 tlvdata,invoice_request,payer_signature,sig,bip340sig, tlvdata,invoice_request,signature,sig,bip340sig,
69 tlvtype,invoice,chain,3
70 tlvdata,invoice,chain,chain,chain_hash,
71 tlvtype,invoice,offer_id,4
101 tlvdata,invoice,payer_key,key,point32,
102 tlvtype,invoice,payer_note,39
103 tlvdata,invoice,payer_note,note,utf8,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
104 tlvtype,invoice,created_at,40
105 tlvdata,invoice,created_at,timestamp,tu64,
106 tlvtype,invoice,payment_hash,42
108 tlvtype,invoice,relative_expiry,44
109 tlvdata,invoice,relative_expiry,seconds_from_creation,tu32,
110 tlvtype,invoice,cltv,46
111 tlvdata,invoice,cltv,min_final_cltv_expiry,tu32, tlvdata,invoice,cltv,min_final_cltv_expiry,tu16,
112 tlvtype,invoice,fallbacks,48
113 tlvdata,invoice,fallbacks,num,byte, tlvdata,invoice,fallbacks,fallbacks,fallback_address,...
114 tlvdata,invoice,fallbacks,fallbacks,fallback_address,num tlvtype,invoice,payer_info,50
115 tlvdata,invoice,payer_info,blob,byte,...
116 tlvtype,invoice,refund_signature,52
117 tlvdata,invoice,refund_signature,payer_signature,bip340sig,
118 tlvtype,invoice,replace_invoice,56

View File

@@ -64,8 +64,8 @@ tlvtype,invoice_request,payer_info,50
tlvdata,invoice_request,payer_info,blob,byte,... tlvdata,invoice_request,payer_info,blob,byte,...
tlvtype,invoice_request,replace_invoice,56 tlvtype,invoice_request,replace_invoice,56
tlvdata,invoice_request,replace_invoice,payment_hash,sha256, tlvdata,invoice_request,replace_invoice,payment_hash,sha256,
tlvtype,invoice_request,payer_signature,240 tlvtype,invoice_request,signature,240
tlvdata,invoice_request,payer_signature,sig,bip340sig, tlvdata,invoice_request,signature,sig,bip340sig,
tlvtype,invoice,chain,3 tlvtype,invoice,chain,3
tlvdata,invoice,chain,chain,chain_hash, tlvdata,invoice,chain,chain,chain_hash,
tlvtype,invoice,offer_id,4 tlvtype,invoice,offer_id,4
@@ -101,8 +101,6 @@ tlvtype,invoice,payer_key,38
tlvdata,invoice,payer_key,key,point32, tlvdata,invoice,payer_key,key,point32,
tlvtype,invoice,payer_note,39 tlvtype,invoice,payer_note,39
tlvdata,invoice,payer_note,note,utf8,... tlvdata,invoice,payer_note,note,utf8,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,created_at,40 tlvtype,invoice,created_at,40
tlvdata,invoice,created_at,timestamp,tu64, tlvdata,invoice,created_at,timestamp,tu64,
tlvtype,invoice,payment_hash,42 tlvtype,invoice,payment_hash,42
@@ -110,10 +108,11 @@ tlvdata,invoice,payment_hash,payment_hash,sha256,
tlvtype,invoice,relative_expiry,44 tlvtype,invoice,relative_expiry,44
tlvdata,invoice,relative_expiry,seconds_from_creation,tu32, tlvdata,invoice,relative_expiry,seconds_from_creation,tu32,
tlvtype,invoice,cltv,46 tlvtype,invoice,cltv,46
tlvdata,invoice,cltv,min_final_cltv_expiry,tu32, tlvdata,invoice,cltv,min_final_cltv_expiry,tu16,
tlvtype,invoice,fallbacks,48 tlvtype,invoice,fallbacks,48
tlvdata,invoice,fallbacks,num,byte, tlvdata,invoice,fallbacks,fallbacks,fallback_address,...
tlvdata,invoice,fallbacks,fallbacks,fallback_address,num tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,refund_signature,52 tlvtype,invoice,refund_signature,52
tlvdata,invoice,refund_signature,payer_signature,bip340sig, tlvdata,invoice,refund_signature,payer_signature,bip340sig,
tlvtype,invoice,replace_invoice,56 tlvtype,invoice,replace_invoice,56
1 tlvtype,offer,chains,2
64 tlvdata,invoice_request,payer_info,blob,byte,...
65 tlvtype,invoice_request,replace_invoice,56
66 tlvdata,invoice_request,replace_invoice,payment_hash,sha256,
67 tlvtype,invoice_request,payer_signature,240 tlvtype,invoice_request,signature,240
68 tlvdata,invoice_request,payer_signature,sig,bip340sig, tlvdata,invoice_request,signature,sig,bip340sig,
69 tlvtype,invoice,chain,3
70 tlvdata,invoice,chain,chain,chain_hash,
71 tlvtype,invoice,offer_id,4
101 tlvdata,invoice,payer_key,key,point32,
102 tlvtype,invoice,payer_note,39
103 tlvdata,invoice,payer_note,note,utf8,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
104 tlvtype,invoice,created_at,40
105 tlvdata,invoice,created_at,timestamp,tu64,
106 tlvtype,invoice,payment_hash,42
108 tlvtype,invoice,relative_expiry,44
109 tlvdata,invoice,relative_expiry,seconds_from_creation,tu32,
110 tlvtype,invoice,cltv,46
111 tlvdata,invoice,cltv,min_final_cltv_expiry,tu32, tlvdata,invoice,cltv,min_final_cltv_expiry,tu16,
112 tlvtype,invoice,fallbacks,48
113 tlvdata,invoice,fallbacks,num,byte, tlvdata,invoice,fallbacks,fallbacks,fallback_address,...
114 tlvdata,invoice,fallbacks,fallbacks,fallback_address,num tlvtype,invoice,payer_info,50
115 tlvdata,invoice,payer_info,blob,byte,...
116 tlvtype,invoice,refund_signature,52
117 tlvdata,invoice,refund_signature,payer_signature,bip340sig,
118 tlvtype,invoice,replace_invoice,56