Skip to content

Commit

Permalink
offers: import latest variant from draft.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
rustyrussell committed Mar 25, 2022
1 parent e36d4d1 commit 726b687
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 52 deletions.
2 changes: 1 addition & 1 deletion common/bolt12_merkle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
* `messagename` is the name of the TLV stream being signed (i.e. "offer",
* "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,
const char *fieldname,
Expand Down
3 changes: 3 additions & 0 deletions common/test/run-bolt12_merkle-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
/* Generated stub for towire_sha256 */
void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
{ 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 */
void towire_tu32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
{ fprintf(stderr, "towire_tu32 called!\n"); abort(); }
Expand Down
28 changes: 18 additions & 10 deletions devtools/bolt12-cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,13 @@ static void print_relative_expiry(u64 *created_at, u32 *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! */
printf("fallback: %u %s\n",
fallbacks->fallbacks[i]->version,
tal_hex(tmpctx, fallbacks->fallbacks[i]->address));
fallbacks[i]->version,
tal_hex(tmpctx, fallbacks[i]->address));
}
}

Expand Down Expand Up @@ -556,12 +556,20 @@ int main(int argc, char *argv[])
print_features(invreq->features);
if (invreq->quantity)
print_quantity(*invreq->quantity);
if (must_have(invreq, payer_signature))
well_formed &= print_signature("invoice_request",
"payer_signature",
invreq->fields,
invreq->payer_key,
invreq->payer_signature);
if (must_have(invreq, signature)) {
if (!print_signature("invoice_request",
"signature",
invreq->fields,
invreq->payer_key,
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) {
print_recurrence_counter(invreq->recurrence_counter,
invreq->recurrence_start);
Expand Down
16 changes: 11 additions & 5 deletions lightningd/offer.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <ccan/json_escape/json_escape.h>
#include <ccan/take/take.h>
#include <common/bolt12_merkle.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
Expand Down Expand Up @@ -466,16 +467,21 @@ static struct command_result *json_createinvoicerequest(struct command *cmd,
}

/* 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`.
*/
/* This populates the ->fields from our entries */
invreq->fields = tlv_make_fields(invreq, invoice_request);
merkle_tlv(invreq->fields, &merkle);
invreq->payer_signature = tal(invreq, struct bip340sig);
hsm_sign_b12(cmd->ld, "invoice_request", "payer_signature",
&merkle, invreq->payer_info, invreq->payer_key,
invreq->payer_signature);
invreq->signature = tal(invreq, struct bip340sig);
if (deprecated_apis)
hsm_sign_b12(cmd->ld, "invoice_request", "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);
json_add_string(response, "bolt12", invrequest_encode(tmpctx, invreq));
Expand Down
9 changes: 6 additions & 3 deletions plugins/fetchinvoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -1192,11 +1192,14 @@ force_payer_secret(struct command *cmd,
"Could not remarshall invreq %s", tal_hex(tmpctx, msg));

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,
sent->invreq->payer_signature->u8,
sent->invreq->signature->u8,
sha.u.u8,
&kp,
NULL, NULL)) {
Expand Down
41 changes: 28 additions & 13 deletions plugins/offers.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <plugins/offers_offer.h>

struct point32 id;
u32 cltv_final;
u16 cltv_final;
bool offers_enabled;

static struct command_result *finished(struct command *cmd,
Expand Down Expand Up @@ -679,7 +679,7 @@ static void json_add_b12_invoice(struct json_stream *js,
if (invoice->fallbacks)
valid &= json_add_fallbacks(js,
invoice->chain,
invoice->fallbacks->fallbacks);
invoice->fallbacks);

/* BOLT-offers #12:
* - if the offer contained `refund_for`:
Expand Down Expand Up @@ -769,23 +769,38 @@ static void json_add_invoice_request(struct json_stream *js,
tal_bytelen(invreq->payer_note));

/* BOLT-offers #12:
* - MUST fail the request if there is no `payer_signature` field.
* - MUST fail the request if `payer_signature` is not correct.
* - MUST fail the request if there is no `signature` field.
* - MUST fail the request if `signature` is not correct.
*/
if (invreq->payer_signature) {
if (invreq->signature) {
if (invreq->payer_key
&& !bolt12_check_signature(invreq->fields,
"invoice_request",
"payer_signature",
"signature",
invreq->payer_key,
invreq->payer_signature)) {
json_add_string(js, "warning_invoice_request_invalid_payer_signature",
"Bad payer_signature");
valid = false;
invreq->signature)) {
bool sig_valid;

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 {
json_add_string(js, "warning_invoice_request_missing_payer_signature",
"Missing payer_signature");
json_add_string(js, "warning_invoice_request_missing_signature",
"Missing signature");
valid = false;
}

Expand Down Expand Up @@ -836,7 +851,7 @@ static const char *init(struct plugin *p,
rpc_scan(p, "listconfigs",
take(json_out_obj(NULL, NULL, NULL)),
"{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));

return NULL;
Expand Down
21 changes: 16 additions & 5 deletions plugins/offers_invreq_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,25 @@ static struct command_result *check_previous_invoice(struct command *cmd,
}

/* 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,
const struct point32 *payer_key,
const struct bip340sig *sig)
{
struct sha256 merkle, sighash;
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",
&merkle, &sighash);

Expand Down Expand Up @@ -714,13 +725,13 @@ static struct command_result *listoffers_done(struct command *cmd,
return err;
}

err = invreq_must_have(cmd, ir, payer_signature);
err = invreq_must_have(cmd, ir, signature);
if (err)
return err;
if (!check_payer_sig(ir->invreq,
ir->invreq->payer_key,
ir->invreq->payer_signature)) {
return fail_invreq(cmd, ir, "bad payer_signature");
ir->invreq->signature)) {
return fail_invreq(cmd, ir, "bad signature");
}

if (ir->offer->recurrence) {
Expand Down Expand Up @@ -806,7 +817,7 @@ static struct command_result *listoffers_done(struct command *cmd,
ir->inv->payment_hash = tal(ir->inv, struct sha256);
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 = time_now().ts.tv_sec;
Expand Down
2 changes: 1 addition & 1 deletion plugins/offers_invreq_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "config.h"
#include <plugins/libplugin.h>

extern u32 cltv_final;
extern u16 cltv_final;

/* We got an onionmessage with an invreq! */
struct command_result *handle_invoice_request(struct command *cmd,
Expand Down
13 changes: 6 additions & 7 deletions wire/bolt12_exp_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ tlvtype,invoice_request,payer_info,50
tlvdata,invoice_request,payer_info,blob,byte,...
tlvtype,invoice_request,replace_invoice,56
tlvdata,invoice_request,replace_invoice,payment_hash,sha256,
tlvtype,invoice_request,payer_signature,240
tlvdata,invoice_request,payer_signature,sig,bip340sig,
tlvtype,invoice_request,signature,240
tlvdata,invoice_request,signature,sig,bip340sig,
tlvtype,invoice,chain,3
tlvdata,invoice,chain,chain,chain_hash,
tlvtype,invoice,offer_id,4
Expand Down Expand Up @@ -101,19 +101,18 @@ tlvtype,invoice,payer_key,38
tlvdata,invoice,payer_key,key,point32,
tlvtype,invoice,payer_note,39
tlvdata,invoice,payer_note,note,utf8,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,created_at,40
tlvdata,invoice,created_at,timestamp,tu64,
tlvtype,invoice,payment_hash,42
tlvdata,invoice,payment_hash,payment_hash,sha256,
tlvtype,invoice,relative_expiry,44
tlvdata,invoice,relative_expiry,seconds_from_creation,tu32,
tlvtype,invoice,cltv,46
tlvdata,invoice,cltv,min_final_cltv_expiry,tu32,
tlvdata,invoice,cltv,min_final_cltv_expiry,tu16,
tlvtype,invoice,fallbacks,48
tlvdata,invoice,fallbacks,num,byte,
tlvdata,invoice,fallbacks,fallbacks,fallback_address,num
tlvdata,invoice,fallbacks,fallbacks,fallback_address,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,refund_signature,52
tlvdata,invoice,refund_signature,payer_signature,bip340sig,
tlvtype,invoice,replace_invoice,56
Expand Down
13 changes: 6 additions & 7 deletions wire/bolt12_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ tlvtype,invoice_request,payer_info,50
tlvdata,invoice_request,payer_info,blob,byte,...
tlvtype,invoice_request,replace_invoice,56
tlvdata,invoice_request,replace_invoice,payment_hash,sha256,
tlvtype,invoice_request,payer_signature,240
tlvdata,invoice_request,payer_signature,sig,bip340sig,
tlvtype,invoice_request,signature,240
tlvdata,invoice_request,signature,sig,bip340sig,
tlvtype,invoice,chain,3
tlvdata,invoice,chain,chain,chain_hash,
tlvtype,invoice,offer_id,4
Expand Down Expand Up @@ -101,19 +101,18 @@ tlvtype,invoice,payer_key,38
tlvdata,invoice,payer_key,key,point32,
tlvtype,invoice,payer_note,39
tlvdata,invoice,payer_note,note,utf8,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,created_at,40
tlvdata,invoice,created_at,timestamp,tu64,
tlvtype,invoice,payment_hash,42
tlvdata,invoice,payment_hash,payment_hash,sha256,
tlvtype,invoice,relative_expiry,44
tlvdata,invoice,relative_expiry,seconds_from_creation,tu32,
tlvtype,invoice,cltv,46
tlvdata,invoice,cltv,min_final_cltv_expiry,tu32,
tlvdata,invoice,cltv,min_final_cltv_expiry,tu16,
tlvtype,invoice,fallbacks,48
tlvdata,invoice,fallbacks,num,byte,
tlvdata,invoice,fallbacks,fallbacks,fallback_address,num
tlvdata,invoice,fallbacks,fallbacks,fallback_address,...
tlvtype,invoice,payer_info,50
tlvdata,invoice,payer_info,blob,byte,...
tlvtype,invoice,refund_signature,52
tlvdata,invoice,refund_signature,payer_signature,bip340sig,
tlvtype,invoice,replace_invoice,56
Expand Down

0 comments on commit 726b687

Please sign in to comment.