diff --git a/common/bolt12_merkle.c b/common/bolt12_merkle.c index 575529f61..591685e4e 100644 --- a/common/bolt12_merkle.c +++ b/common/bolt12_merkle.c @@ -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, diff --git a/common/test/run-bolt12_merkle-json.c b/common/test/run-bolt12_merkle-json.c index ebdd325d5..cc653aa9d 100644 --- a/common/test/run-bolt12_merkle-json.c +++ b/common/test/run-bolt12_merkle-json.c @@ -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(); } diff --git a/devtools/bolt12-cli.c b/devtools/bolt12-cli.c index cd8f4878f..de7dedf1b 100644 --- a/devtools/bolt12-cli.c +++ b/devtools/bolt12-cli.c @@ -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)); } } @@ -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); diff --git a/lightningd/offer.c b/lightningd/offer.c index 48739c85f..e251f3b62 100644 --- a/lightningd/offer.c +++ b/lightningd/offer.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -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)); diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index 91f8cc9a8..d63d3680d 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -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)) { diff --git a/plugins/offers.c b/plugins/offers.c index 36bd20a85..4093a7094 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -16,7 +16,7 @@ #include struct point32 id; -u32 cltv_final; +u16 cltv_final; bool offers_enabled; 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) valid &= json_add_fallbacks(js, invoice->chain, - invoice->fallbacks->fallbacks); + invoice->fallbacks); /* BOLT-offers #12: * - 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)); /* 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; } @@ -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; diff --git a/plugins/offers_invreq_hook.c b/plugins/offers_invreq_hook.c index 0b7866603..c5fd0bb5b 100644 --- a/plugins/offers_invreq_hook.c +++ b/plugins/offers_invreq_hook.c @@ -417,7 +417,7 @@ 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, @@ -425,6 +425,17 @@ static bool check_payer_sig(const struct tlv_invoice_request *invreq, { 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); @@ -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) { @@ -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; diff --git a/plugins/offers_invreq_hook.h b/plugins/offers_invreq_hook.h index b33c8d860..da59e52b5 100644 --- a/plugins/offers_invreq_hook.h +++ b/plugins/offers_invreq_hook.h @@ -3,7 +3,7 @@ #include "config.h" #include -extern u32 cltv_final; +extern u16 cltv_final; /* We got an onionmessage with an invreq! */ struct command_result *handle_invoice_request(struct command *cmd, diff --git a/wire/bolt12_exp_wire.csv b/wire/bolt12_exp_wire.csv index 4077edb8d..4b0ce8519 100644 --- a/wire/bolt12_exp_wire.csv +++ b/wire/bolt12_exp_wire.csv @@ -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 @@ -101,8 +101,6 @@ 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 @@ -110,10 +108,11 @@ 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 diff --git a/wire/bolt12_wire.csv b/wire/bolt12_wire.csv index 4077edb8d..4b0ce8519 100644 --- a/wire/bolt12_wire.csv +++ b/wire/bolt12_wire.csv @@ -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 @@ -101,8 +101,6 @@ 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 @@ -110,10 +108,11 @@ 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