mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
common/derive_basepoints: add routines to get a specific secret.
Often we only need a single secret, so it's clearer to have routines to do just that. When we change to the lnd key scheme, there will be no benefit in calculating them all together. This also adds a test! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
b2b85100d7
commit
64008e275a
@ -87,6 +87,85 @@ bool per_commit_point(const struct sha256 *shaseed,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool derive_payment_basepoint(const struct secret *seed,
|
||||
struct pubkey *payment_basepoint,
|
||||
struct secret *payment_secret)
|
||||
{
|
||||
struct keys {
|
||||
struct privkey f, r, h, p, d;
|
||||
struct sha256 shaseed;
|
||||
} keys;
|
||||
|
||||
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
||||
"c-lightning", strlen("c-lightning"));
|
||||
|
||||
if (payment_basepoint) {
|
||||
if (!pubkey_from_privkey(&keys.p, payment_basepoint))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (payment_secret)
|
||||
*payment_secret = keys.p.secret;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool derive_delayed_payment_basepoint(const struct secret *seed,
|
||||
struct pubkey *delayed_payment_basepoint,
|
||||
struct secret *delayed_payment_secret)
|
||||
{
|
||||
struct keys {
|
||||
struct privkey f, r, h, p, d;
|
||||
struct sha256 shaseed;
|
||||
} keys;
|
||||
|
||||
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
||||
"c-lightning", strlen("c-lightning"));
|
||||
|
||||
if (delayed_payment_basepoint) {
|
||||
if (!pubkey_from_privkey(&keys.d, delayed_payment_basepoint))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (delayed_payment_secret)
|
||||
*delayed_payment_secret = keys.d.secret;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool derive_shaseed(const struct secret *seed, struct sha256 *shaseed)
|
||||
{
|
||||
struct keys {
|
||||
struct privkey f, r, h, p, d;
|
||||
struct sha256 shaseed;
|
||||
} keys;
|
||||
|
||||
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
||||
"c-lightning", strlen("c-lightning"));
|
||||
*shaseed = keys.shaseed;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool derive_funding_key(const struct secret *seed,
|
||||
struct pubkey *funding_pubkey,
|
||||
struct privkey *funding_privkey)
|
||||
{
|
||||
struct privkey f;
|
||||
|
||||
hkdf_sha256(&f, sizeof(f), NULL, 0, seed, sizeof(*seed),
|
||||
"c-lightning", strlen("c-lightning"));
|
||||
|
||||
if (funding_pubkey) {
|
||||
if (!pubkey_from_privkey(&f, funding_pubkey))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (funding_privkey)
|
||||
*funding_privkey = f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void towire_basepoints(u8 **pptr, const struct basepoints *b)
|
||||
{
|
||||
towire_pubkey(pptr, &b->revocation);
|
||||
|
@ -38,6 +38,51 @@ bool derive_basepoints(const struct secret *seed,
|
||||
struct secrets *secrets,
|
||||
struct sha256 *shaseed);
|
||||
|
||||
/**
|
||||
* derive_funding_key - give a (per-peer) seed, get just funding key
|
||||
* @seed: (in) seed (derived by master daemon from counter and main seed)
|
||||
* @funding_pubkey: (out) pubkey for funding tx output (if non-NULL)
|
||||
* @funding_privkey: (out) privkey for funding tx output (if non-NULL)
|
||||
*
|
||||
* This is a cut-down version of derive_basepoints.
|
||||
*/
|
||||
bool derive_funding_key(const struct secret *seed,
|
||||
struct pubkey *funding_pubkey,
|
||||
struct privkey *funding_privkey);
|
||||
|
||||
/**
|
||||
* derive_payment_basepoint - give a (per-channel) seed, get just payment basepoint
|
||||
* @seed: (in) seed (derived by master daemon from counter and main seed)
|
||||
* @payment_basepoint: (out) basepoint for payment output (if non-NULL)
|
||||
* @payment_secret: (out) secret for payment basepoint (if non-NULL)
|
||||
*
|
||||
* This is a cut-down version of derive_basepoints.
|
||||
*/
|
||||
bool derive_payment_basepoint(const struct secret *seed,
|
||||
struct pubkey *payment_basepoint,
|
||||
struct secret *payment_secret);
|
||||
|
||||
/**
|
||||
* derive_shaseed - give a (per-peer) seed, get just the shaseed
|
||||
* @seed: (in) seed (derived by master daemon from counter and main seed)
|
||||
* @shaseed: (out) seed for shachain
|
||||
*
|
||||
* This is a cut-down version of derive_basepoints.
|
||||
*/
|
||||
bool derive_shaseed(const struct secret *seed, struct sha256 *shaseed);
|
||||
|
||||
/**
|
||||
* derive_delayed_payment_basepoint - give a (per-channel) seed, get just delayed payment basepoint
|
||||
* @seed: (in) seed (derived by master daemon from counter and main seed)
|
||||
* @delayed_payment_basepoint: (out) basepoint for payment output (if non-NULL)
|
||||
* @delayed_payment_secret: (out) secret for payment basepoint (if non-NULL)
|
||||
*
|
||||
* This is a cut-down version of derive_basepoints.
|
||||
*/
|
||||
bool derive_delayed_payment_basepoint(const struct secret *seed,
|
||||
struct pubkey *delayed_payment_basepoint,
|
||||
struct secret *delayed_payment_secret);
|
||||
|
||||
/**
|
||||
* per_commit_secret - get a secret for this index.
|
||||
* @shaseed: the sha256 seed
|
||||
|
157
common/test/run-derive_basepoints.c
Normal file
157
common/test/run-derive_basepoints.c
Normal file
@ -0,0 +1,157 @@
|
||||
#include "../derive_basepoints.c"
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include <common/utils.h>
|
||||
#include <stdio.h>
|
||||
#include <wally_core.h>
|
||||
|
||||
/* AUTOGENERATED MOCKS START */
|
||||
/* Generated stub for fromwire_pubkey */
|
||||
void fromwire_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct pubkey *pubkey UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_pubkey called!\n"); abort(); }
|
||||
/* Generated stub for towire_pubkey */
|
||||
void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED)
|
||||
{ fprintf(stderr, "towire_pubkey called!\n"); abort(); }
|
||||
/* AUTOGENERATED MOCKS END */
|
||||
|
||||
STRUCTEQ_DEF(basepoints, 0,
|
||||
revocation.pubkey,
|
||||
payment.pubkey,
|
||||
htlc.pubkey,
|
||||
delayed_payment.pubkey);
|
||||
STRUCTEQ_DEF(secrets, 0,
|
||||
funding_privkey.secret.data,
|
||||
revocation_basepoint_secret.data,
|
||||
payment_basepoint_secret.data,
|
||||
htlc_basepoint_secret.data,
|
||||
delayed_payment_basepoint_secret.data);
|
||||
STRUCTEQ_DEF(privkey, 0,
|
||||
secret.data);
|
||||
|
||||
struct info {
|
||||
struct secret seed;
|
||||
struct pubkey funding_pubkey;
|
||||
struct basepoints basepoints;
|
||||
struct secrets secrets;
|
||||
struct sha256 shaseed;
|
||||
};
|
||||
|
||||
/* We get a fresh one each time, to catch uninitialized fields */
|
||||
static struct info *new_info(const tal_t *ctx)
|
||||
{
|
||||
struct info *info = tal(ctx, struct info);
|
||||
memset(&info->seed, 7, sizeof(info->seed));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setup_locale();
|
||||
|
||||
const tal_t *ctx = tal(NULL, char);
|
||||
struct info *baseline, *info;
|
||||
|
||||
secp256k1_ctx = wally_get_secp_context();
|
||||
baseline = new_info(ctx);
|
||||
assert(derive_basepoints(&baseline->seed, &baseline->funding_pubkey,
|
||||
&baseline->basepoints,
|
||||
&baseline->secrets,
|
||||
&baseline->shaseed));
|
||||
|
||||
/* Same seed, same result. */
|
||||
info = new_info(ctx);
|
||||
assert(derive_basepoints(&info->seed, &info->funding_pubkey,
|
||||
&info->basepoints,
|
||||
&info->secrets,
|
||||
&info->shaseed));
|
||||
assert(pubkey_eq(&baseline->funding_pubkey, &info->funding_pubkey));
|
||||
assert(basepoints_eq(&baseline->basepoints, &info->basepoints));
|
||||
assert(secrets_eq(&baseline->secrets, &info->secrets));
|
||||
assert(sha256_eq(&baseline->shaseed, &info->shaseed));
|
||||
|
||||
/* Different seed, different result. */
|
||||
for (size_t i = 0; i < sizeof(info->seed); i++) {
|
||||
for (size_t b = 0; b < CHAR_BIT; b++) {
|
||||
info = new_info(ctx);
|
||||
info->seed.data[i] ^= (1 << b);
|
||||
|
||||
assert(derive_basepoints(&info->seed,
|
||||
&info->funding_pubkey,
|
||||
&info->basepoints,
|
||||
&info->secrets,
|
||||
&info->shaseed));
|
||||
assert(!pubkey_eq(&baseline->funding_pubkey,
|
||||
&info->funding_pubkey));
|
||||
assert(!basepoints_eq(&baseline->basepoints,
|
||||
&info->basepoints));
|
||||
assert(!secrets_eq(&baseline->secrets, &info->secrets));
|
||||
assert(!sha256_eq(&baseline->shaseed, &info->shaseed));
|
||||
}
|
||||
}
|
||||
|
||||
/* Any field can be NULL (except seed). */
|
||||
info = new_info(ctx);
|
||||
assert(derive_basepoints(&info->seed, NULL,
|
||||
&info->basepoints,
|
||||
&info->secrets,
|
||||
&info->shaseed));
|
||||
assert(basepoints_eq(&baseline->basepoints, &info->basepoints));
|
||||
assert(secrets_eq(&baseline->secrets, &info->secrets));
|
||||
assert(sha256_eq(&baseline->shaseed, &info->shaseed));
|
||||
|
||||
info = new_info(ctx);
|
||||
assert(derive_basepoints(&info->seed, &info->funding_pubkey,
|
||||
NULL,
|
||||
&info->secrets,
|
||||
&info->shaseed));
|
||||
assert(pubkey_eq(&baseline->funding_pubkey, &info->funding_pubkey));
|
||||
assert(secrets_eq(&baseline->secrets, &info->secrets));
|
||||
assert(sha256_eq(&baseline->shaseed, &info->shaseed));
|
||||
|
||||
info = new_info(ctx);
|
||||
assert(derive_basepoints(&info->seed, &info->funding_pubkey,
|
||||
&info->basepoints,
|
||||
NULL,
|
||||
&info->shaseed));
|
||||
assert(pubkey_eq(&baseline->funding_pubkey, &info->funding_pubkey));
|
||||
assert(basepoints_eq(&baseline->basepoints, &info->basepoints));
|
||||
assert(sha256_eq(&baseline->shaseed, &info->shaseed));
|
||||
|
||||
info = new_info(ctx);
|
||||
assert(derive_basepoints(&info->seed, &info->funding_pubkey,
|
||||
&info->basepoints,
|
||||
&info->secrets,
|
||||
NULL));
|
||||
assert(pubkey_eq(&baseline->funding_pubkey, &info->funding_pubkey));
|
||||
assert(basepoints_eq(&baseline->basepoints, &info->basepoints));
|
||||
assert(secrets_eq(&baseline->secrets, &info->secrets));
|
||||
|
||||
/* derive_payment_basepoint should give same results. */
|
||||
info = new_info(ctx);
|
||||
assert(derive_payment_basepoint(&info->seed, &info->basepoints.payment,
|
||||
&info->secrets.payment_basepoint_secret));
|
||||
assert(pubkey_eq(&baseline->basepoints.payment,
|
||||
&info->basepoints.payment));
|
||||
assert(secret_eq(&baseline->secrets.payment_basepoint_secret,
|
||||
&info->secrets.payment_basepoint_secret));
|
||||
|
||||
/* derive_funding_key should give same results. */
|
||||
info = new_info(ctx);
|
||||
assert(derive_funding_key(&info->seed, &info->funding_pubkey,
|
||||
&info->secrets.funding_privkey));
|
||||
assert(pubkey_eq(&baseline->funding_pubkey, &info->funding_pubkey));
|
||||
assert(privkey_eq(&baseline->secrets.funding_privkey,
|
||||
&info->secrets.funding_privkey));
|
||||
|
||||
/* derive_shaseed should give same results. */
|
||||
info = new_info(ctx);
|
||||
assert(derive_shaseed(&info->seed, &info->shaseed));
|
||||
assert(sha256_eq(&baseline->shaseed, &info->shaseed));
|
||||
|
||||
tal_free(ctx);
|
||||
wally_cleanup(0);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user