mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-02 12:44:26 +01:00
lightningd: use 33 byte pubkeys internally.
We still use 32 bytes on the wire, but internally don't use x-only. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -128,34 +128,37 @@ void towire_pubkey(u8 **pptr, const struct pubkey *pubkey)
|
||||
|
||||
void fromwire_point32(const u8 **cursor, size_t *max, struct point32 *point32)
|
||||
{
|
||||
u8 raw[32];
|
||||
u8 raw[33];
|
||||
struct pubkey pk;
|
||||
|
||||
if (!fromwire(cursor, max, raw, sizeof(raw)))
|
||||
raw[0] = SECP256K1_TAG_PUBKEY_EVEN;
|
||||
if (!fromwire(cursor, max, raw + 1, sizeof(raw) - 1))
|
||||
return;
|
||||
|
||||
if (secp256k1_xonly_pubkey_parse(secp256k1_ctx,
|
||||
&point32->pubkey,
|
||||
raw) != 1) {
|
||||
if (!pubkey_from_der(raw, sizeof(raw), &pk)) {
|
||||
SUPERVERBOSE("not a valid point");
|
||||
fromwire_fail(cursor, max);
|
||||
}
|
||||
} else
|
||||
point32->pubkey = pk.pubkey;
|
||||
}
|
||||
|
||||
void towire_point32(u8 **pptr, const struct point32 *point32)
|
||||
{
|
||||
u8 output[32];
|
||||
u8 output[33];
|
||||
struct pubkey pk;
|
||||
|
||||
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output,
|
||||
&point32->pubkey);
|
||||
towire(pptr, output, sizeof(output));
|
||||
pk.pubkey = point32->pubkey;
|
||||
pubkey_to_der(output, &pk);
|
||||
towire(pptr, output + 1, sizeof(output) - 1);
|
||||
}
|
||||
|
||||
static char *point32_to_hexstr(const tal_t *ctx, const struct point32 *point32)
|
||||
{
|
||||
u8 output[32];
|
||||
u8 output[33];
|
||||
struct pubkey pk;
|
||||
|
||||
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output,
|
||||
&point32->pubkey);
|
||||
return tal_hexstr(ctx, output, sizeof(output));
|
||||
pk.pubkey = point32->pubkey;
|
||||
pubkey_to_der(output, &pk);
|
||||
return tal_hexstr(ctx, output + 1, sizeof(output) - 1);
|
||||
}
|
||||
REGISTER_TYPE_TO_STRING(point32, point32_to_hexstr);
|
||||
|
||||
@@ -19,11 +19,12 @@ struct pubkey {
|
||||
/* Define pubkey_eq (no padding) */
|
||||
STRUCTEQ_DEF(pubkey, 0, pubkey.data);
|
||||
|
||||
/* FIXME: This is for the deprecated offers: it's represented x-only there */
|
||||
struct point32 {
|
||||
/* Unpacked pubkey (as used by libsecp256k1 internally) */
|
||||
secp256k1_xonly_pubkey pubkey;
|
||||
secp256k1_pubkey pubkey;
|
||||
};
|
||||
/* Define pubkey_eq (no padding) */
|
||||
/* Define point32_eq (no padding) */
|
||||
STRUCTEQ_DEF(point32, 0, pubkey.data);
|
||||
|
||||
/* Convert from hex string of DER (scriptPubKey from validateaddress) */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <bitcoin/chainparams.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/bech32_util.h>
|
||||
@@ -80,11 +81,8 @@ bool bolt12_check_signature(const struct tlv_field *fields,
|
||||
|
||||
merkle_tlv(fields, &m);
|
||||
sighash_from_merkle(messagename, fieldname, &m, &shash);
|
||||
return secp256k1_schnorrsig_verify(secp256k1_ctx,
|
||||
sig->u8,
|
||||
shash.u.u8,
|
||||
sizeof(shash.u.u8),
|
||||
&key->pubkey) == 1;
|
||||
|
||||
return check_schnorr_sig(&shash, &key->pubkey, sig);
|
||||
}
|
||||
|
||||
static char *check_signature(const tal_t *ctx,
|
||||
|
||||
@@ -220,17 +220,23 @@ void sighash_from_merkle(const char *messagename,
|
||||
}
|
||||
|
||||
/* We use the SHA(pubkey | publictweak); so reader cannot figure out the
|
||||
* tweak and derive the base key */
|
||||
* tweak and derive the base key.
|
||||
*
|
||||
* Since key used to be x-only, we don't hash first byte!
|
||||
*/
|
||||
void payer_key_tweak(const struct point32 *bolt12,
|
||||
const u8 *publictweak, size_t publictweaklen,
|
||||
struct sha256 *tweak)
|
||||
{
|
||||
u8 rawkey[32];
|
||||
u8 rawkey[PUBKEY_CMPR_LEN];
|
||||
struct sha256_ctx sha;
|
||||
struct pubkey pk;
|
||||
|
||||
pk.pubkey = bolt12->pubkey;
|
||||
pubkey_to_der(rawkey, &pk);
|
||||
|
||||
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, rawkey, &bolt12->pubkey);
|
||||
sha256_init(&sha);
|
||||
sha256_update(&sha, rawkey, sizeof(rawkey));
|
||||
sha256_update(&sha, rawkey + 1, sizeof(rawkey) - 1);
|
||||
sha256_update(&sha,
|
||||
memcheck(publictweak, publictweaklen),
|
||||
publictweaklen);
|
||||
|
||||
@@ -1296,12 +1296,11 @@ void gossmap_guess_node_id(const struct gossmap *map,
|
||||
const struct point32 *point32,
|
||||
struct node_id *id)
|
||||
{
|
||||
id->k[0] = SECP256K1_TAG_PUBKEY_EVEN;
|
||||
secp256k1_xonly_pubkey_serialize(secp256k1_ctx,
|
||||
id->k + 1,
|
||||
&point32->pubkey);
|
||||
struct pubkey pk;
|
||||
pk.pubkey = point32->pubkey;
|
||||
node_id_from_pubkey(id, &pk);
|
||||
|
||||
/* If we don't find this, let's assume it's odd. */
|
||||
/* If we don't find this, let's assume it's the alternate. */
|
||||
if (!gossmap_find_node(map, id))
|
||||
id->k[0] = SECP256K1_TAG_PUBKEY_ODD;
|
||||
id->k[0] |= 1;
|
||||
}
|
||||
|
||||
@@ -419,10 +419,12 @@ void json_add_point32(struct json_stream *response,
|
||||
const char *fieldname,
|
||||
const struct point32 *key)
|
||||
{
|
||||
u8 output[32];
|
||||
struct pubkey pk;
|
||||
u8 der[PUBKEY_CMPR_LEN];
|
||||
|
||||
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output, &key->pubkey);
|
||||
json_add_hex(response, fieldname, output, sizeof(output));
|
||||
pk.pubkey = key->pubkey;
|
||||
pubkey_to_der(der, &pk);
|
||||
json_add_hex(response, fieldname, der + 1, sizeof(der) - 1);
|
||||
}
|
||||
|
||||
void json_add_bip340sig(struct json_stream *response,
|
||||
|
||||
@@ -31,8 +31,8 @@ bool point32_from_node_id(struct point32 *key, const struct node_id *id)
|
||||
struct pubkey k;
|
||||
if (!pubkey_from_node_id(&k, id))
|
||||
return false;
|
||||
return secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &key->pubkey,
|
||||
NULL, &k.pubkey) == 1;
|
||||
key->pubkey = k.pubkey;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* It's valid if we can convert to a real pubkey. */
|
||||
|
||||
@@ -318,11 +318,7 @@ static bool print_signature(const char *messagename,
|
||||
|
||||
merkle_tlv(fields, &m);
|
||||
sighash_from_merkle(messagename, fieldname, &m, &shash);
|
||||
if (secp256k1_schnorrsig_verify(secp256k1_ctx,
|
||||
sig->u8,
|
||||
shash.u.u8,
|
||||
sizeof(shash.u.u8),
|
||||
&node_id->pubkey) != 1) {
|
||||
if (!check_schnorr_sig(&shash, &node_id->pubkey, sig)) {
|
||||
fprintf(stderr, "%s: INVALID\n", fieldname);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -238,11 +238,11 @@ static void node_schnorrkey(secp256k1_keypair *node_keypair,
|
||||
"Failed to derive keypair");
|
||||
|
||||
if (node_id32) {
|
||||
if (secp256k1_keypair_xonly_pub(secp256k1_ctx,
|
||||
&node_id32->pubkey,
|
||||
NULL, node_keypair) != 1)
|
||||
if (secp256k1_keypair_pub(secp256k1_ctx,
|
||||
&node_id32->pubkey,
|
||||
node_keypair) != 1)
|
||||
hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Failed to derive xonly pub");
|
||||
"Failed to derive keypair pub");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,9 +638,9 @@ static u8 *handle_sign_bolt12(struct hsmd_client *c, const u8 *msg_in)
|
||||
struct point32 bolt12;
|
||||
struct sha256 tweak;
|
||||
|
||||
if (secp256k1_keypair_xonly_pub(secp256k1_ctx,
|
||||
&bolt12.pubkey, NULL,
|
||||
&secretstuff.bolt12) != 1)
|
||||
if (secp256k1_keypair_pub(secp256k1_ctx,
|
||||
&bolt12.pubkey,
|
||||
&secretstuff.bolt12) != 1)
|
||||
hsmd_status_failed(
|
||||
STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Could not derive bolt12 public key.");
|
||||
@@ -1772,8 +1772,8 @@ u8 *hsmd_init(struct secret hsm_secret,
|
||||
node_id_from_pubkey(&node_id, &key);
|
||||
|
||||
/* We also give it the base key for bolt12 payerids */
|
||||
if (secp256k1_keypair_xonly_pub(secp256k1_ctx, &bolt12.pubkey, NULL,
|
||||
&secretstuff.bolt12) != 1)
|
||||
if (secp256k1_keypair_pub(secp256k1_ctx, &bolt12.pubkey,
|
||||
&secretstuff.bolt12) != 1)
|
||||
hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Could derive bolt12 public key.");
|
||||
|
||||
|
||||
@@ -75,8 +75,7 @@ static void hsm_sign_b12(struct lightningd *ld,
|
||||
|
||||
/* Now we sanity-check! */
|
||||
sighash_from_merkle(messagename, fieldname, merkle, &sighash);
|
||||
if (secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8,
|
||||
sighash.u.u8, sizeof(sighash.u.u8), &key->pubkey) != 1)
|
||||
if (!check_schnorr_sig(&sighash, &key->pubkey, sig))
|
||||
fatal("HSM gave bad signature %s for pubkey %s",
|
||||
type_to_string(tmpctx, struct bip340sig, sig),
|
||||
type_to_string(tmpctx, struct point32, key));
|
||||
@@ -397,21 +396,14 @@ static bool payer_key(struct lightningd *ld,
|
||||
struct point32 *key)
|
||||
{
|
||||
struct sha256 tweakhash;
|
||||
secp256k1_pubkey tweaked;
|
||||
|
||||
payer_key_tweak(&ld->bolt12_base, public_tweak, public_tweak_len,
|
||||
&tweakhash);
|
||||
|
||||
/* Tweaking gives a not-x-only pubkey, must then convert. */
|
||||
if (secp256k1_xonly_pubkey_tweak_add(secp256k1_ctx,
|
||||
&tweaked,
|
||||
&ld->bolt12_base.pubkey,
|
||||
tweakhash.u.u8) != 1)
|
||||
return false;
|
||||
|
||||
return secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx,
|
||||
&key->pubkey,
|
||||
NULL, &tweaked) == 1;
|
||||
key->pubkey = ld->bolt12_base.pubkey;
|
||||
return secp256k1_ec_pubkey_tweak_add(secp256k1_ctx,
|
||||
&key->pubkey,
|
||||
tweakhash.u.u8) == 1;
|
||||
}
|
||||
|
||||
static struct command_result *json_createinvoicerequest(struct command *cmd,
|
||||
|
||||
@@ -217,8 +217,7 @@ static struct command_result *handle_invreq_response(struct command *cmd,
|
||||
sighash_from_merkle("invoice", "signature", &merkle, &sighash);
|
||||
|
||||
if (!inv->signature
|
||||
|| secp256k1_schnorrsig_verify(secp256k1_ctx, inv->signature->u8,
|
||||
sighash.u.u8, sizeof(sighash.u.u8), &inv->node_id->pubkey) != 1) {
|
||||
|| !check_schnorr_sig(&sighash, &inv->node_id->pubkey, inv->signature)) {
|
||||
badfield = "signature";
|
||||
goto badinv;
|
||||
}
|
||||
@@ -576,11 +575,13 @@ static void node_id_from_point32(struct node_id *nid,
|
||||
const struct point32 *node32_id,
|
||||
enum nodeid_parity parity)
|
||||
{
|
||||
struct pubkey pk;
|
||||
assert(parity == SECP256K1_TAG_PUBKEY_EVEN
|
||||
|| parity == SECP256K1_TAG_PUBKEY_ODD);
|
||||
|
||||
pk.pubkey = node32_id->pubkey;
|
||||
node_id_from_pubkey(nid, &pk);
|
||||
nid->k[0] = parity;
|
||||
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, nid->k+1,
|
||||
&node32_id->pubkey);
|
||||
}
|
||||
|
||||
/* Create path to node which can carry onion messages (including
|
||||
@@ -1075,9 +1076,9 @@ force_payer_secret(struct command *cmd,
|
||||
|
||||
invreq->payer_key = tal(invreq, struct point32);
|
||||
/* Docs say this only happens if arguments are invalid! */
|
||||
if (secp256k1_keypair_xonly_pub(secp256k1_ctx,
|
||||
&invreq->payer_key->pubkey, NULL,
|
||||
&kp) != 1)
|
||||
if (secp256k1_keypair_pub(secp256k1_ctx,
|
||||
&invreq->payer_key->pubkey,
|
||||
&kp) != 1)
|
||||
plugin_err(cmd->plugin,
|
||||
"secp256k1_keypair_pub failed on %s?",
|
||||
type_to_string(tmpctx, struct secret, payer_secret));
|
||||
@@ -1585,13 +1586,7 @@ static struct command_result *json_sendinvoice(struct command *cmd,
|
||||
* - MUST set `description` the same as the offer.
|
||||
*/
|
||||
sent->inv->node_id = tal(sent->inv, struct point32);
|
||||
|
||||
/* This only fails if pubkey is invalid. */
|
||||
if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx,
|
||||
&sent->inv->node_id->pubkey,
|
||||
NULL,
|
||||
&local_id.pubkey))
|
||||
abort();
|
||||
sent->inv->node_id->pubkey = local_id.pubkey;
|
||||
|
||||
sent->inv->description
|
||||
= tal_dup_talarr(sent->inv, char, sent->offer->description);
|
||||
@@ -1754,12 +1749,11 @@ static struct command_result *json_rawrequest(struct command *cmd,
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
/* Skip over 02/03 in node_id */
|
||||
if (!secp256k1_xonly_pubkey_parse(secp256k1_ctx,
|
||||
&node_id32.pubkey,
|
||||
node_id->k + 1))
|
||||
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &node_id32.pubkey,
|
||||
node_id->k, sizeof(node_id->k)))
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Invalid nodeid");
|
||||
|
||||
/* This is how long we'll wait for a reply for. */
|
||||
sent->wait_timeout = *timeout;
|
||||
sent->cmd = cmd;
|
||||
|
||||
@@ -926,9 +926,7 @@ static const char *init(struct plugin *p,
|
||||
rpc_scan(p, "getinfo",
|
||||
take(json_out_obj(NULL, NULL, NULL)),
|
||||
"{id:%}", JSON_SCAN(json_to_pubkey, &k));
|
||||
if (secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &id.pubkey,
|
||||
NULL, &k.pubkey) != 1)
|
||||
abort();
|
||||
id.pubkey = k.pubkey;
|
||||
|
||||
rpc_scan(p, "listconfigs",
|
||||
take(json_out_obj(NULL, NULL, NULL)),
|
||||
|
||||
@@ -382,11 +382,8 @@ struct command_result *handle_invoice(struct command *cmd,
|
||||
|
||||
merkle_tlv(inv->inv->fields, &m);
|
||||
sighash_from_merkle("invoice", "signature", &m, &shash);
|
||||
if (secp256k1_schnorrsig_verify(secp256k1_ctx,
|
||||
inv->inv->signature->u8,
|
||||
shash.u.u8,
|
||||
sizeof(shash.u.u8),
|
||||
&inv->inv->node_id->pubkey) != 1) {
|
||||
if (!check_schnorr_sig(&shash, &inv->inv->node_id->pubkey,
|
||||
inv->inv->signature)) {
|
||||
return fail_inv(cmd, inv, "Bad signature");
|
||||
}
|
||||
|
||||
|
||||
@@ -432,11 +432,7 @@ static bool check_payer_sig(struct command *cmd,
|
||||
merkle_tlv(invreq->fields, &merkle);
|
||||
sighash_from_merkle("invoice_request", "signature", &merkle, &sighash);
|
||||
|
||||
return secp256k1_schnorrsig_verify(secp256k1_ctx,
|
||||
sig->u8,
|
||||
sighash.u.u8,
|
||||
sizeof(sighash.u.u8),
|
||||
&payer_key->pubkey) == 1;
|
||||
return check_schnorr_sig(&sighash, &payer_key->pubkey, sig);
|
||||
}
|
||||
|
||||
static struct command_result *invreq_amount_by_quantity(struct command *cmd,
|
||||
|
||||
Reference in New Issue
Block a user