mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-18 22:54:25 +01:00
common/bolt12_merkle.h: experimental bolt 12 implementation.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -359,4 +359,41 @@ void fromwire_bip340sig(const u8 **cursor, size_t *max,
|
||||
{
|
||||
fromwire_u8_array(cursor, max, bip340sig->u8, sizeof(bip340sig->u8));
|
||||
}
|
||||
|
||||
char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig)
|
||||
{
|
||||
return tal_hexstr(ctx, bip340sig->u8, sizeof(bip340sig->u8));
|
||||
}
|
||||
|
||||
REGISTER_TYPE_TO_HEXSTR(bip340sig);
|
||||
|
||||
/* BIP-340:
|
||||
*
|
||||
* This proposal suggests to include the tag by prefixing the hashed
|
||||
* data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte
|
||||
* long context-specific constant and the ''SHA256'' block size is
|
||||
* also 64 bytes, optimized implementations are possible (identical to
|
||||
* SHA256 itself, but with a modified initial state). Using SHA256 of
|
||||
* the tag name itself is reasonably simple and efficient for
|
||||
* implementations that don't choose to use the optimization.
|
||||
*/
|
||||
|
||||
/* For caller convenience, we hand in tag in parts (any can be "") */
|
||||
void bip340_sighash_init(struct sha256_ctx *sctx,
|
||||
const char *tag1,
|
||||
const char *tag2,
|
||||
const char *tag3)
|
||||
{
|
||||
struct sha256 taghash;
|
||||
|
||||
sha256_init(sctx);
|
||||
sha256_update(sctx, memcheck(tag1, strlen(tag1)), strlen(tag1));
|
||||
sha256_update(sctx, memcheck(tag2, strlen(tag2)), strlen(tag2));
|
||||
sha256_update(sctx, memcheck(tag3, strlen(tag3)), strlen(tag3));
|
||||
sha256_done(sctx, &taghash);
|
||||
|
||||
sha256_init(sctx);
|
||||
sha256_update(sctx, &taghash, sizeof(taghash));
|
||||
sha256_update(sctx, &taghash, sizeof(taghash));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
#define LIGHTNING_BITCOIN_SIGNATURE_H
|
||||
#include "config.h"
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <secp256k1.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct sha256_double;
|
||||
struct sha256_ctx;
|
||||
struct bitcoin_tx;
|
||||
struct pubkey;
|
||||
struct privkey;
|
||||
@@ -138,4 +140,14 @@ struct bip340sig {
|
||||
void towire_bip340sig(u8 **pptr, const struct bip340sig *bip340sig);
|
||||
void fromwire_bip340sig(const u8 **cursor, size_t *max,
|
||||
struct bip340sig *bip340sig);
|
||||
|
||||
/* Get a hex string sig */
|
||||
char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig);
|
||||
|
||||
/* For caller convenience, we hand in tag in parts (any can be "") */
|
||||
void bip340_sighash_init(struct sha256_ctx *sctx,
|
||||
const char *tag1,
|
||||
const char *tag2,
|
||||
const char *tag3);
|
||||
|
||||
#endif /* LIGHTNING_BITCOIN_SIGNATURE_H */
|
||||
|
||||
@@ -86,6 +86,10 @@ endif
|
||||
|
||||
COMMON_SRC_GEN := common/status_wiregen.c common/peer_status_wiregen.c
|
||||
|
||||
ifeq ($(EXPERIMENTAL_FEATURES),1)
|
||||
COMMON_SRC_NOGEN += common/bolt12_merkle.c
|
||||
endif
|
||||
|
||||
COMMON_HEADERS_NOGEN := $(COMMON_SRC_NOGEN:.c=.h) \
|
||||
common/closing_fee.h \
|
||||
common/ecdh.h \
|
||||
|
||||
131
common/bolt12_merkle.c
Normal file
131
common/bolt12_merkle.c
Normal file
@@ -0,0 +1,131 @@
|
||||
#include <bitcoin/signature.h>
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <common/bolt12_merkle.h>
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* TLV types 240 through 1000 are considered signature elements.
|
||||
*/
|
||||
static bool is_signature_field(const struct tlv_field *field)
|
||||
{
|
||||
return field->numtype >= 240 && field->numtype <= 1000;
|
||||
}
|
||||
|
||||
static void sha256_update_bigsize(struct sha256_ctx *ctx, u64 bigsize)
|
||||
{
|
||||
u8 buf[BIGSIZE_MAX_LEN];
|
||||
size_t len;
|
||||
|
||||
len = bigsize_put(buf, bigsize);
|
||||
sha256_update(ctx, buf, len);
|
||||
}
|
||||
|
||||
static void sha256_update_tlvfield(struct sha256_ctx *ctx,
|
||||
const struct tlv_field *field)
|
||||
{
|
||||
/* We don't keep it raw, so reconstruct. */
|
||||
sha256_update_bigsize(ctx, field->numtype);
|
||||
sha256_update_bigsize(ctx, field->length);
|
||||
sha256_update(ctx, field->value, field->length);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* The Merkle Tree's leaves are, in TLV-ascending order:
|
||||
* 1. The SHA256 of: `LnLeaf` followed by the TLV entry.
|
||||
* 2. The SHA256 of: `LnAll` followed all non-signature TLV entries appended
|
||||
* in ascending order.
|
||||
*/
|
||||
|
||||
static void calc_lnall(const struct tlv_field *fields, struct sha256 *hash)
|
||||
{
|
||||
struct sha256_ctx sctx;
|
||||
|
||||
sha256_init(&sctx);
|
||||
sha256_update(&sctx, "LnAll", 5);
|
||||
for (size_t i = 0; i < tal_count(fields); i++) {
|
||||
if (!is_signature_field(&fields[i]))
|
||||
sha256_update_tlvfield(&sctx, &fields[i]);
|
||||
}
|
||||
sha256_done(&sctx, hash);
|
||||
}
|
||||
|
||||
static void calc_lnleaf(const struct tlv_field *field, struct sha256 *hash)
|
||||
{
|
||||
struct sha256_ctx sctx;
|
||||
|
||||
sha256_init(&sctx);
|
||||
sha256_update(&sctx, "LnLeaf", 6);
|
||||
sha256_update_tlvfield(&sctx, field);
|
||||
sha256_done(&sctx, hash);
|
||||
}
|
||||
|
||||
static struct sha256 merkle_pair(const struct sha256 a, const struct sha256 b)
|
||||
{
|
||||
struct sha256 res;
|
||||
struct sha256_ctx sctx;
|
||||
|
||||
sha256_init(&sctx);
|
||||
sha256_update(&sctx, "LnBranch", 8);
|
||||
sha256_update(&sctx, a.u.u8, sizeof(a.u.u8));
|
||||
sha256_update(&sctx, b.u.u8, sizeof(b.u.u8));
|
||||
sha256_done(&sctx, &res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct sha256 merkle_recurse(const struct sha256 *arr, size_t len)
|
||||
{
|
||||
if (len == 1)
|
||||
return arr[0];
|
||||
|
||||
return merkle_pair(merkle_recurse(arr, len / 2),
|
||||
merkle_recurse(arr + len / 2, len - len / 2));
|
||||
}
|
||||
|
||||
void merkle_tlv(const struct tlv_field *fields, struct sha256 *merkle)
|
||||
{
|
||||
struct sha256 lnall, *arr;
|
||||
size_t n;
|
||||
|
||||
calc_lnall(fields, &lnall);
|
||||
arr = tal_arr(NULL, struct sha256, tal_count(fields));
|
||||
|
||||
n = 0;
|
||||
for (size_t i = 0; i < tal_count(fields); i++) {
|
||||
struct sha256 s;
|
||||
if (is_signature_field(&fields[i]))
|
||||
continue;
|
||||
calc_lnleaf(&fields[i], &s);
|
||||
arr[n++] = merkle_pair(s, lnall);
|
||||
}
|
||||
|
||||
*merkle = merkle_recurse(arr, n);
|
||||
tal_free(arr);
|
||||
}
|
||||
|
||||
/* BOLT-offers #12:
|
||||
* All signatures are created as per
|
||||
* [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki),
|
||||
* and tagged as recommended there. Thus to sign a message `msg` with
|
||||
* `tag`, `m` is SHA256(SHA256(`tag`) || SHA256(`tag`) || `msg`). The
|
||||
* notation used here is `SIG(tag,msg,key)`.
|
||||
*
|
||||
* Each form is signed using one or more TLV signature elements; TLV
|
||||
* types 240 through 1000 are considered signature elements. For these
|
||||
* the tag is `lightning` | `messagename` | `fieldname`, and `msg` is the
|
||||
* merkle-root; `lightning` is the literal 9-byte ASCII string,
|
||||
* `messagename` is the name of the TLV stream being signed (i.e. `offer`
|
||||
* or `invoice`) and the `fieldname` is the TLV field containing the
|
||||
* signature (e.g. `signature` or `recurrence_signature`).
|
||||
*/
|
||||
void sighash_from_merkle(const char *messagename,
|
||||
const char *fieldname,
|
||||
const struct sha256 *merkle,
|
||||
struct sha256 *sighash)
|
||||
{
|
||||
struct sha256_ctx sctx;
|
||||
|
||||
bip340_sighash_init(&sctx, "lightning", messagename, fieldname);
|
||||
sha256_update(&sctx, merkle, sizeof(*merkle));
|
||||
sha256_done(&sctx, sighash);
|
||||
}
|
||||
24
common/bolt12_merkle.h
Normal file
24
common/bolt12_merkle.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef LIGHTNING_COMMON_BOLT12_MERKLE_H
|
||||
#define LIGHTNING_COMMON_BOLT12_MERKLE_H
|
||||
#include "config.h"
|
||||
#include <wire/bolt12_exp_wiregen.h>
|
||||
|
||||
/**
|
||||
* merkle_tlv - bolt12-style merkle hash of this tlv minus signature fields
|
||||
* @fields: tal_arr of fields from tlv.
|
||||
* @merkle: returned merkle hash.
|
||||
*/
|
||||
void merkle_tlv(const struct tlv_field *fields, struct sha256 *merkle);
|
||||
|
||||
/**
|
||||
* sighash_from_merkle - bolt12-style signature hash using this merkle root.
|
||||
* @messagename: message name, such as "offer".
|
||||
* @fieldname: field name, such as "recurrence_signature".
|
||||
* @merkle: the merkle root as calculated by merkle_tlv.
|
||||
* @sighash: the returned hash.
|
||||
*/
|
||||
void sighash_from_merkle(const char *messagename,
|
||||
const char *fieldname,
|
||||
const struct sha256 *merkle,
|
||||
struct sha256 *sighash);
|
||||
#endif /* LIGHTNING_COMMON_BOLT12_MERKLE_H */
|
||||
Reference in New Issue
Block a user