pubkey: don't carry around DER encoding.

We just wrap the libsecp256k1 structure, and convert to DER on demand.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2016-07-01 11:19:28 +09:30
parent 69cb158edd
commit 42bed80145
12 changed files with 185 additions and 100 deletions

View File

@@ -282,7 +282,7 @@ secp256k1/libsecp256k1.la:
lightning.pb-c.c lightning.pb-c.h: lightning.proto lightning.pb-c.c lightning.pb-c.h: lightning.proto
$(PROTOCC) lightning.proto --c_out=. $(PROTOCC) lightning.proto --c_out=.
$(TEST_PROGRAMS): % : %.o $(BITCOIN_OBJS) $(CCAN_OBJS) version.o libsecp256k1.a $(TEST_PROGRAMS): % : %.o $(BITCOIN_OBJS) $(CCAN_OBJS) utils.o version.o libsecp256k1.a
ccan/config.h: ccan/tools/configurator/configurator ccan/config.h: ccan/tools/configurator/configurator
if $< > $@.new; then mv $@.new $@; else rm $@.new; exit 1; fi if $< > $@.new; then mv $@.new $@; else rm $@.new; exit 1; fi

View File

@@ -1,39 +1,44 @@
#include "privkey.h" #include "privkey.h"
#include "pubkey.h" #include "pubkey.h"
#include "utils.h"
#include <assert.h> #include <assert.h>
#include <ccan/mem/mem.h> #include <ccan/mem/mem.h>
#include <ccan/str/hex/hex.h> #include <ccan/str/hex/hex.h>
#include <ccan/structeq/structeq.h>
bool pubkey_from_der(secp256k1_context *secpctx, bool pubkey_from_der(secp256k1_context *secpctx,
const u8 *der, size_t len, const u8 *der, size_t len,
struct pubkey *key) struct pubkey *key)
{ {
if (len != sizeof(key->der)) if (len != PUBKEY_DER_LEN)
return false; return false;
memcpy(key->der, memcheck(der, sizeof(key->der)), sizeof(key->der)); if (!secp256k1_ec_pubkey_parse(secpctx, &key->pubkey,
if (!secp256k1_ec_pubkey_parse(secpctx, &key->pubkey, key->der, memcheck(der, len), len))
sizeof(key->der)))
return false; return false;
return true; return true;
} }
void pubkey_to_der(secp256k1_context *secpctx, u8 der[PUBKEY_DER_LEN],
const struct pubkey *key)
{
size_t outlen = PUBKEY_DER_LEN;
if (!secp256k1_ec_pubkey_serialize(secpctx, der, &outlen,
&key->pubkey,
SECP256K1_EC_COMPRESSED))
abort();
assert(outlen == PUBKEY_DER_LEN);
}
/* Pubkey from privkey */ /* Pubkey from privkey */
bool pubkey_from_privkey(secp256k1_context *secpctx, bool pubkey_from_privkey(secp256k1_context *secpctx,
const struct privkey *privkey, const struct privkey *privkey,
struct pubkey *key, struct pubkey *key,
unsigned int compressed_flags) unsigned int compressed_flags)
{ {
size_t outlen;
if (!secp256k1_ec_pubkey_create(secpctx, &key->pubkey, privkey->secret)) if (!secp256k1_ec_pubkey_create(secpctx, &key->pubkey, privkey->secret))
return false; return false;
if (!secp256k1_ec_pubkey_serialize(secpctx, key->der, &outlen,
&key->pubkey, compressed_flags))
return false;
assert(outlen == sizeof(key->der));
return true; return true;
} }
@@ -41,7 +46,7 @@ bool pubkey_from_hexstr(secp256k1_context *secpctx,
const char *derstr, size_t slen, struct pubkey *key) const char *derstr, size_t slen, struct pubkey *key)
{ {
size_t dlen; size_t dlen;
unsigned char der[sizeof(key->der)]; unsigned char der[PUBKEY_DER_LEN];
dlen = hex_data_size(slen); dlen = hex_data_size(slen);
if (dlen != sizeof(der)) if (dlen != sizeof(der))
@@ -53,7 +58,16 @@ bool pubkey_from_hexstr(secp256k1_context *secpctx,
return pubkey_from_der(secpctx, der, dlen, key); return pubkey_from_der(secpctx, der, dlen, key);
} }
char *pubkey_to_hexstr(const tal_t *ctx, secp256k1_context *secpctx,
const struct pubkey *key)
{
unsigned char der[PUBKEY_DER_LEN];
pubkey_to_der(secpctx, der, key);
return tal_hexstr(ctx, der, sizeof(der));
}
bool pubkey_eq(const struct pubkey *a, const struct pubkey *b) bool pubkey_eq(const struct pubkey *a, const struct pubkey *b)
{ {
return memcmp(a->der, b->der, sizeof(a->der)) == 0; return structeq(&a->pubkey, &b->pubkey);
} }

View File

@@ -7,9 +7,9 @@
struct privkey; struct privkey;
#define PUBKEY_DER_LEN 33
struct pubkey { struct pubkey {
/* DER-encoded key (as hashed by bitcoin, for addresses) */
u8 der[33];
/* Unpacked pubkey (as used by libsecp256k1 internally) */ /* Unpacked pubkey (as used by libsecp256k1 internally) */
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
}; };
@@ -18,6 +18,10 @@ struct pubkey {
bool pubkey_from_hexstr(secp256k1_context *secpctx, bool pubkey_from_hexstr(secp256k1_context *secpctx,
const char *derstr, size_t derlen, struct pubkey *key); const char *derstr, size_t derlen, struct pubkey *key);
/* Convert from hex string of DER (scriptPubKey from validateaddress) */
char *pubkey_to_hexstr(const tal_t *ctx, secp256k1_context *secpctx,
const struct pubkey *key);
/* Pubkey from privkey */ /* Pubkey from privkey */
bool pubkey_from_privkey(secp256k1_context *secpctx, bool pubkey_from_privkey(secp256k1_context *secpctx,
const struct privkey *privkey, const struct privkey *privkey,
@@ -28,6 +32,10 @@ bool pubkey_from_privkey(secp256k1_context *secpctx,
bool pubkey_from_der(secp256k1_context *secpctx, bool pubkey_from_der(secp256k1_context *secpctx,
const u8 *der, size_t len, struct pubkey *key); const u8 *der, size_t len, struct pubkey *key);
/* Pubkey to DER encoding: must be valid pubkey. */
void pubkey_to_der(secp256k1_context *secpctx, u8 der[PUBKEY_DER_LEN],
const struct pubkey *key);
/* Are these keys equal? */ /* Are these keys equal? */
bool pubkey_eq(const struct pubkey *a, const struct pubkey *b); bool pubkey_eq(const struct pubkey *a, const struct pubkey *b);
#endif /* LIGHTNING_PUBKEY_H */ #endif /* LIGHTNING_PUBKEY_H */

View File

@@ -110,14 +110,24 @@ static void add_number(u8 **script, u32 num)
} }
} }
static void add_push_key(u8 **scriptp, const struct pubkey *key) static void add_push_key(u8 **scriptp,
secp256k1_context *secpctx,
const struct pubkey *key)
{ {
add_push_bytes(scriptp, key->der, sizeof(key->der)); u8 der[PUBKEY_DER_LEN];
pubkey_to_der(secpctx, der, key);
add_push_bytes(scriptp, der, sizeof(der));
} }
static u8 *stack_key(const tal_t *ctx, const struct pubkey *key) static u8 *stack_key(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key)
{ {
return tal_dup_arr(ctx, u8, key->der, sizeof(key->der), 0); u8 der[PUBKEY_DER_LEN];
pubkey_to_der(secpctx, der, key);
return tal_dup_arr(ctx, u8, der, sizeof(der), 0);
} }
/* Bitcoin wants DER encoding. */ /* Bitcoin wants DER encoding. */
@@ -151,26 +161,31 @@ static u8 *stack_number(const tal_t *ctx, unsigned int num)
return tal_dup_arr(ctx, u8, &val, 1, 0); return tal_dup_arr(ctx, u8, &val, 1, 0);
} }
/* FIXME: permute? */
/* Is a < b? (If equal we don't care) */ /* Is a < b? (If equal we don't care) */
static bool key_less(const struct pubkey *a, const struct pubkey *b) static bool key_less(secp256k1_context *secpctx,
const struct pubkey *a, const struct pubkey *b)
{ {
return memcmp(a->der, b->der, sizeof(a->der)) < 0; u8 a_der[PUBKEY_DER_LEN], b_der[PUBKEY_DER_LEN];
pubkey_to_der(secpctx, a_der, a);
pubkey_to_der(secpctx, b_der, b);
return memcmp(a_der, b_der, sizeof(a_der)) < 0;
} }
/* tal_count() gives the length of the script. */ /* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_2of2(const tal_t *ctx, u8 *bitcoin_redeem_2of2(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key1, const struct pubkey *key1,
const struct pubkey *key2) const struct pubkey *key2)
{ {
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
add_number(&script, 2); add_number(&script, 2);
if (key_less(key1, key2)) { if (key_less(secpctx, key1, key2)) {
add_push_key(&script, key1); add_push_key(&script, secpctx, key1);
add_push_key(&script, key2); add_push_key(&script, secpctx, key2);
} else { } else {
add_push_key(&script, key2); add_push_key(&script, secpctx, key2);
add_push_key(&script, key1); add_push_key(&script, secpctx, key1);
} }
add_number(&script, 2); add_number(&script, 2);
add_op(&script, OP_CHECKMULTISIG); add_op(&script, OP_CHECKMULTISIG);
@@ -178,10 +193,12 @@ u8 *bitcoin_redeem_2of2(const tal_t *ctx,
} }
/* tal_count() gives the length of the script. */ /* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_single(const tal_t *ctx, const struct pubkey *key) u8 *bitcoin_redeem_single(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key)
{ {
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
add_push_key(&script, key); add_push_key(&script, secpctx, key);
add_op(&script, OP_CHECKSIG); add_op(&script, OP_CHECKSIG);
return script; return script;
} }
@@ -200,15 +217,19 @@ u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript)
} }
/* Create the redeemscript for a P2SH + P2WPKH (for signing tx) */ /* Create the redeemscript for a P2SH + P2WPKH (for signing tx) */
u8 *bitcoin_redeem_p2wpkh(const tal_t *ctx, const struct pubkey *key) u8 *bitcoin_redeem_p2wpkh(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key)
{ {
struct ripemd160 keyhash; struct ripemd160 keyhash;
u8 der[PUBKEY_DER_LEN];
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
/* BIP141: BIP16 redeemScript pushed in the scriptSig is exactly a /* BIP141: BIP16 redeemScript pushed in the scriptSig is exactly a
* push of a version byte plus a push of a witness program. */ * push of a version byte plus a push of a witness program. */
add_number(&script, 0); add_number(&script, 0);
hash160(&keyhash, key->der, sizeof(key->der)); pubkey_to_der(secpctx, der, key);
hash160(&keyhash, der, sizeof(der));
add_push_bytes(&script, &keyhash, sizeof(keyhash)); add_push_bytes(&script, &keyhash, sizeof(keyhash));
return script; return script;
} }
@@ -220,7 +241,7 @@ void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx,
const struct bitcoin_signature *sig, const struct bitcoin_signature *sig,
const struct pubkey *key) const struct pubkey *key)
{ {
u8 *redeemscript = bitcoin_redeem_p2wpkh(ctx, key); u8 *redeemscript = bitcoin_redeem_p2wpkh(ctx, secpctx, key);
/* BIP141: The scriptSig must be exactly a push of the BIP16 redeemScript /* BIP141: The scriptSig must be exactly a push of the BIP16 redeemScript
* or validation fails. */ * or validation fails. */
@@ -233,7 +254,7 @@ void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx,
* a public key. */ * a public key. */
input->witness = tal_arr(ctx, u8 *, 2); input->witness = tal_arr(ctx, u8 *, 2);
input->witness[0] = stack_sig(input->witness, secpctx, sig); input->witness[0] = stack_sig(input->witness, secpctx, sig);
input->witness[1] = stack_key(input->witness, key); input->witness[1] = stack_key(input->witness, secpctx, key);
} }
/* Create an output script for a 32-byte witness. */ /* Create an output script for a 32-byte witness. */
@@ -249,13 +270,17 @@ u8 *scriptpubkey_p2wsh(const tal_t *ctx, const u8 *witnessscript)
} }
/* Create an output script for a 20-byte witness. */ /* Create an output script for a 20-byte witness. */
u8 *scriptpubkey_p2wpkh(const tal_t *ctx, const struct pubkey *key) u8 *scriptpubkey_p2wpkh(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key)
{ {
struct ripemd160 h; struct ripemd160 h;
u8 der[PUBKEY_DER_LEN];
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
add_op(&script, OP_0); add_op(&script, OP_0);
hash160(&h, key->der, sizeof(key->der)); pubkey_to_der(secpctx, der, key);
hash160(&h, der, sizeof(der));
add_push_bytes(&script, &h, sizeof(h)); add_push_bytes(&script, &h, sizeof(h));
return script; return script;
} }
@@ -274,7 +299,7 @@ u8 **bitcoin_witness_2of2(const tal_t *ctx,
witness[0] = stack_number(witness, 0); witness[0] = stack_number(witness, 0);
/* sig order should match key order. */ /* sig order should match key order. */
if (key_less(key1, key2)) { if (key_less(secpctx, key1, key2)) {
witness[1] = stack_sig(witness, secpctx, sig1); witness[1] = stack_sig(witness, secpctx, sig1);
witness[2] = stack_sig(witness, secpctx, sig2); witness[2] = stack_sig(witness, secpctx, sig2);
} else { } else {
@@ -282,12 +307,13 @@ u8 **bitcoin_witness_2of2(const tal_t *ctx,
witness[2] = stack_sig(witness, secpctx, sig1); witness[2] = stack_sig(witness, secpctx, sig1);
} }
witness[3] = bitcoin_redeem_2of2(witness, key1, key2); witness[3] = bitcoin_redeem_2of2(witness, secpctx, key1, key2);
return witness; return witness;
} }
/* Create a script for our HTLC output: sending. */ /* Create a script for our HTLC output: sending. */
u8 *bitcoin_redeem_htlc_send(const tal_t *ctx, u8 *bitcoin_redeem_htlc_send(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *ourkey, const struct pubkey *ourkey,
const struct pubkey *theirkey, const struct pubkey *theirkey,
const struct abs_locktime *htlc_abstimeout, const struct abs_locktime *htlc_abstimeout,
@@ -321,7 +347,7 @@ u8 *bitcoin_redeem_htlc_send(const tal_t *ctx,
/* If either matched... */ /* If either matched... */
add_op(&script, OP_IF); add_op(&script, OP_IF);
add_push_key(&script, theirkey); add_push_key(&script, secpctx, theirkey);
add_op(&script, OP_ELSE); add_op(&script, OP_ELSE);
@@ -331,7 +357,7 @@ u8 *bitcoin_redeem_htlc_send(const tal_t *ctx,
add_number(&script, locktime->locktime); add_number(&script, locktime->locktime);
add_op(&script, OP_CHECKSEQUENCEVERIFY); add_op(&script, OP_CHECKSEQUENCEVERIFY);
add_op(&script, OP_2DROP); add_op(&script, OP_2DROP);
add_push_key(&script, ourkey); add_push_key(&script, secpctx, ourkey);
add_op(&script, OP_ENDIF); add_op(&script, OP_ENDIF);
add_op(&script, OP_CHECKSIG); add_op(&script, OP_CHECKSIG);
@@ -341,6 +367,7 @@ u8 *bitcoin_redeem_htlc_send(const tal_t *ctx,
/* Create a script for our HTLC output: receiving. */ /* Create a script for our HTLC output: receiving. */
u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx, u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *ourkey, const struct pubkey *ourkey,
const struct pubkey *theirkey, const struct pubkey *theirkey,
const struct abs_locktime *htlc_abstimeout, const struct abs_locktime *htlc_abstimeout,
@@ -372,7 +399,7 @@ u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx,
/* Drop extra hash as well as locktime. */ /* Drop extra hash as well as locktime. */
add_op(&script, OP_2DROP); add_op(&script, OP_2DROP);
add_push_key(&script, ourkey); add_push_key(&script, secpctx, ourkey);
add_op(&script, OP_ELSE); add_op(&script, OP_ELSE);
@@ -389,7 +416,7 @@ u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx,
add_op(&script, OP_DROP); add_op(&script, OP_DROP);
add_op(&script, OP_ENDIF); add_op(&script, OP_ENDIF);
add_push_key(&script, theirkey); add_push_key(&script, secpctx, theirkey);
add_op(&script, OP_ENDIF); add_op(&script, OP_ENDIF);
add_op(&script, OP_CHECKSIG); add_op(&script, OP_CHECKSIG);
@@ -398,13 +425,17 @@ u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx,
} }
/* Create scriptcode (fake witness, basically) for P2WPKH */ /* Create scriptcode (fake witness, basically) for P2WPKH */
u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key) u8 *p2wpkh_scriptcode(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key)
{ {
struct sha256 h; struct sha256 h;
struct ripemd160 pkhash; struct ripemd160 pkhash;
u8 der[PUBKEY_DER_LEN];
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
sha256(&h, key->der, sizeof(key->der)); pubkey_to_der(secpctx, der, key);
sha256(&h, der, sizeof(der));
ripemd160(&pkhash, h.u.u8, sizeof(h)); ripemd160(&pkhash, h.u.u8, sizeof(h));
/* BIP143: /* BIP143:
* *
@@ -439,6 +470,7 @@ bool is_p2sh(const u8 *script, size_t script_len)
/* A common script pattern: A can have it with secret, or B can have /* A common script pattern: A can have it with secret, or B can have
* it after delay. */ * it after delay. */
u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx, u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *delayed_key, const struct pubkey *delayed_key,
const struct rel_locktime *locktime, const struct rel_locktime *locktime,
const struct pubkey *key_if_secret_known, const struct pubkey *key_if_secret_known,
@@ -456,7 +488,7 @@ u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx,
add_op(&script, OP_IF); add_op(&script, OP_IF);
/* They can collect the funds. */ /* They can collect the funds. */
add_push_key(&script, key_if_secret_known); add_push_key(&script, secpctx, key_if_secret_known);
add_op(&script, OP_ELSE); add_op(&script, OP_ELSE);
@@ -464,7 +496,7 @@ u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx,
add_number(&script, locktime->locktime); add_number(&script, locktime->locktime);
add_op(&script, OP_CHECKSEQUENCEVERIFY); add_op(&script, OP_CHECKSEQUENCEVERIFY);
add_op(&script, OP_DROP); add_op(&script, OP_DROP);
add_push_key(&script, delayed_key); add_push_key(&script, secpctx, delayed_key);
add_op(&script, OP_ENDIF); add_op(&script, OP_ENDIF);
add_op(&script, OP_CHECKSIG); add_op(&script, OP_CHECKSIG);

View File

@@ -21,15 +21,19 @@ struct bitcoin_signature {
/* tal_count() gives the length of the script. */ /* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_2of2(const tal_t *ctx, u8 *bitcoin_redeem_2of2(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key1, const struct pubkey *key1,
const struct pubkey *key2); const struct pubkey *key2);
/* tal_count() gives the length of the script. */ /* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_single(const tal_t *ctx, const struct pubkey *key); u8 *bitcoin_redeem_single(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key);
/* A common script pattern: A can have it with secret, or B can have /* A common script pattern: A can have it with secret, or B can have
* it after delay. */ * it after delay. */
u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx, u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *delayed_key, const struct pubkey *delayed_key,
const struct rel_locktime *locktime, const struct rel_locktime *locktime,
const struct pubkey *key_if_secret_known, const struct pubkey *key_if_secret_known,
@@ -39,7 +43,9 @@ u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx,
u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript); u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript);
/* Create the redeemscript for a P2SH + P2WPKH. */ /* Create the redeemscript for a P2SH + P2WPKH. */
u8 *bitcoin_redeem_p2wpkh(const tal_t *ctx, const struct pubkey *key); u8 *bitcoin_redeem_p2wpkh(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key);
/* Create a witness which spends the 2of2. */ /* Create a witness which spends the 2of2. */
void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx, void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx,
@@ -49,10 +55,13 @@ void bitcoin_witness_p2sh_p2wpkh(const tal_t *ctx,
const struct pubkey *key); const struct pubkey *key);
/* Create scriptcode (fake witness, basically) for P2WPKH */ /* Create scriptcode (fake witness, basically) for P2WPKH */
u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key); u8 *p2wpkh_scriptcode(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key);
/* Create a script for our HTLC output: sending. */ /* Create a script for our HTLC output: sending. */
u8 *bitcoin_redeem_htlc_send(const tal_t *ctx, u8 *bitcoin_redeem_htlc_send(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *ourkey, const struct pubkey *ourkey,
const struct pubkey *theirkey, const struct pubkey *theirkey,
const struct abs_locktime *htlc_abstimeout, const struct abs_locktime *htlc_abstimeout,
@@ -62,6 +71,7 @@ u8 *bitcoin_redeem_htlc_send(const tal_t *ctx,
/* Create a script for our HTLC output: receiving. */ /* Create a script for our HTLC output: receiving. */
u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx, u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *ourkey, const struct pubkey *ourkey,
const struct pubkey *theirkey, const struct pubkey *theirkey,
const struct abs_locktime *htlc_abstimeout, const struct abs_locktime *htlc_abstimeout,
@@ -73,7 +83,9 @@ u8 *bitcoin_redeem_htlc_recv(const tal_t *ctx,
u8 *scriptpubkey_p2wsh(const tal_t *ctx, const u8 *witnessscript); u8 *scriptpubkey_p2wsh(const tal_t *ctx, const u8 *witnessscript);
/* Create an output script for a 20-byte witness program. */ /* Create an output script for a 20-byte witness program. */
u8 *scriptpubkey_p2wpkh(const tal_t *ctx, const struct pubkey *key); u8 *scriptpubkey_p2wpkh(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *key);
/* Create a witness which spends the 2of2. */ /* Create a witness which spends the 2of2. */
u8 **bitcoin_witness_2of2(const tal_t *ctx, u8 **bitcoin_witness_2of2(const tal_t *ctx,

View File

@@ -11,12 +11,14 @@
#include <assert.h> #include <assert.h>
static bool add_htlc(struct bitcoin_tx *tx, size_t n, static bool add_htlc(struct bitcoin_tx *tx, size_t n,
secp256k1_context *secpctx,
const struct htlc *h, const struct htlc *h,
const struct pubkey *ourkey, const struct pubkey *ourkey,
const struct pubkey *theirkey, const struct pubkey *theirkey,
const struct sha256 *rhash, const struct sha256 *rhash,
const struct rel_locktime *locktime, const struct rel_locktime *locktime,
u8 *(*scriptpubkeyfn)(const tal_t *, u8 *(*scriptpubkeyfn)(const tal_t *,
secp256k1_context *,
const struct pubkey *, const struct pubkey *,
const struct pubkey *, const struct pubkey *,
const struct abs_locktime *, const struct abs_locktime *,
@@ -27,7 +29,7 @@ static bool add_htlc(struct bitcoin_tx *tx, size_t n,
assert(!tx->output[n].script); assert(!tx->output[n].script);
tx->output[n].script = scriptpubkey_p2wsh(tx, tx->output[n].script = scriptpubkey_p2wsh(tx,
scriptpubkeyfn(tx, ourkey, theirkey, scriptpubkeyfn(tx, secpctx, ourkey, theirkey,
&h->expiry, locktime, rhash, &h->expiry, locktime, rhash,
&h->rhash)); &h->rhash));
tx->output[n].script_length = tal_count(tx->output[n].script); tx->output[n].script_length = tal_count(tx->output[n].script);
@@ -36,6 +38,7 @@ static bool add_htlc(struct bitcoin_tx *tx, size_t n,
} }
struct bitcoin_tx *create_commit_tx(const tal_t *ctx, struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *our_final, const struct pubkey *our_final,
const struct pubkey *their_final, const struct pubkey *their_final,
const struct rel_locktime *our_locktime, const struct rel_locktime *our_locktime,
@@ -77,7 +80,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
/* First output is a P2WSH to a complex redeem script /* First output is a P2WSH to a complex redeem script
* (usu. for this side) */ * (usu. for this side) */
redeemscript = bitcoin_redeem_secret_or_delay(tx, self, redeemscript = bitcoin_redeem_secret_or_delay(tx, secpctx, self,
locktime, locktime,
other, other,
rhash); rhash);
@@ -86,7 +89,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
tx->output[0].amount = cstate->side[side].pay_msat / 1000; tx->output[0].amount = cstate->side[side].pay_msat / 1000;
/* Second output is a P2WPKH payment to other side. */ /* Second output is a P2WPKH payment to other side. */
tx->output[1].script = scriptpubkey_p2wpkh(tx, other); tx->output[1].script = scriptpubkey_p2wpkh(tx, secpctx, other);
tx->output[1].script_length = tal_count(tx->output[1].script); tx->output[1].script_length = tal_count(tx->output[1].script);
tx->output[1].amount = cstate->side[!side].pay_msat / 1000; tx->output[1].amount = cstate->side[!side].pay_msat / 1000;
@@ -96,7 +99,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
/* HTLCs this side sent. */ /* HTLCs this side sent. */
for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) { for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) {
if (!add_htlc(tx, num, cstate->side[side].htlcs[i], if (!add_htlc(tx, num, secpctx, cstate->side[side].htlcs[i],
self, other, rhash, locktime, self, other, rhash, locktime,
bitcoin_redeem_htlc_send)) bitcoin_redeem_htlc_send))
return tal_free(tx); return tal_free(tx);
@@ -104,7 +107,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
} }
/* HTLCs this side has received. */ /* HTLCs this side has received. */
for (i = 0; i < tal_count(cstate->side[!side].htlcs); i++) { for (i = 0; i < tal_count(cstate->side[!side].htlcs); i++) {
if (!add_htlc(tx, num, cstate->side[!side].htlcs[i], if (!add_htlc(tx, num, secpctx, cstate->side[!side].htlcs[i],
self, other, rhash, locktime, self, other, rhash, locktime,
bitcoin_redeem_htlc_recv)) bitcoin_redeem_htlc_recv))
return tal_free(tx); return tal_free(tx);

View File

@@ -12,6 +12,7 @@ struct rel_locktime;
/* Create commitment tx to spend the anchor tx output; doesn't fill in /* Create commitment tx to spend the anchor tx output; doesn't fill in
* input scriptsig. */ * input scriptsig. */
struct bitcoin_tx *create_commit_tx(const tal_t *ctx, struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
secp256k1_context *secpctx,
const struct pubkey *our_final, const struct pubkey *our_final,
const struct pubkey *their_final, const struct pubkey *their_final,
const struct rel_locktime *our_locktime, const struct rel_locktime *our_locktime,

View File

@@ -274,12 +274,13 @@ void log_add(struct log *log, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
#define to_string(ctx, structtype, ptr) \ #define to_string(ctx, lr, structtype, ptr) \
to_string_((ctx), stringify(structtype), \ to_string_((ctx), lr, stringify(structtype), \
((void)sizeof((ptr) == (structtype *)NULL), \ ((void)sizeof((ptr) == (structtype *)NULL), \
((union loggable_structs)((const structtype *)ptr)))) ((union loggable_structs)((const structtype *)ptr))))
static char *to_string_(const tal_t *ctx, static char *to_string_(const tal_t *ctx,
struct log_record *lr,
const char *structname, const char *structname,
union loggable_structs u) union loggable_structs u)
{ {
@@ -287,7 +288,7 @@ static char *to_string_(const tal_t *ctx,
/* GCC checks we're one of these, so we should be. */ /* GCC checks we're one of these, so we should be. */
if (streq(structname, "struct pubkey")) if (streq(structname, "struct pubkey"))
s = tal_hexstr(ctx, u.pubkey->der, sizeof(u.pubkey->der)); s = pubkey_to_hexstr(ctx, lr->dstate->secpctx, u.pubkey);
else if (streq(structname, "struct sha256_double")) else if (streq(structname, "struct sha256_double"))
s = tal_hexstr(ctx, u.sha256_double, sizeof(*u.sha256_double)); s = tal_hexstr(ctx, u.sha256_double, sizeof(*u.sha256_double));
else if (streq(structname, "struct sha256")) else if (streq(structname, "struct sha256"))
@@ -318,11 +319,11 @@ static char *to_string_(const tal_t *ctx,
" rval=%s" " rval=%s"
" src=%s }", " src=%s }",
h->id, h->msatoshis, h->id, h->msatoshis,
to_string(ctx, struct abs_locktime, &h->expiry), to_string(ctx, lr, struct abs_locktime, &h->expiry),
to_string(ctx, struct sha256, &h->rhash), to_string(ctx, lr, struct sha256, &h->rhash),
h->r ? tal_hexstr(ctx, h->r, sizeof(*h->r)) h->r ? tal_hexstr(ctx, h->r, sizeof(*h->r))
: "UNKNOWN", : "UNKNOWN",
h->src ? to_string(ctx, struct pubkey, h->src ? to_string(ctx, lr, struct pubkey,
&h->src->peer->id) &h->src->peer->id)
: "local"); : "local");
} }
@@ -345,7 +346,7 @@ void log_struct_(struct log *log, int level,
va_end(ap); va_end(ap);
/* GCC checks we're one of these, so we should be. */ /* GCC checks we're one of these, so we should be. */
s = to_string_(ctx, structname, u); s = to_string_(ctx, log->lr, structname, u);
if (!s) if (!s)
fatal("Logging unknown type %s", structname); fatal("Logging unknown type %s", structname);

View File

@@ -22,20 +22,6 @@
#include <ccan/tal/str/str.h> #include <ccan/tal/str/str.h>
#include <inttypes.h> #include <inttypes.h>
#define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0)
static void dump_tx(const char *str, const struct bitcoin_tx *tx)
{
u8 *linear = linearize_tx(NULL, tx);
printf("%s:%s\n", str, tal_hexstr(linear, linear, tal_count(linear)));
tal_free(linear);
}
static void dump_key(const char *str, const struct pubkey *key)
{
printf("%s:%s\n", str, tal_hexstr(NULL, key->der, sizeof(key->der)));
}
/* Wrap (and own!) member inside Pkt */ /* Wrap (and own!) member inside Pkt */
static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg) static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg)
{ {
@@ -150,8 +136,10 @@ void queue_pkt_open_commit_sig(struct peer *peer)
open_commit_sig__init(s); open_commit_sig__init(s);
dump_tx("Creating sig for:", peer->remote.commit->tx); log_debug_struct(peer->log, "Creating sig for %s",
dump_key("Using key:", &peer->local.commitkey); struct bitcoin_tx, peer->remote.commit->tx);
log_add_struct(peer->log, " using key %s",
struct pubkey, &peer->local.commitkey);
peer->remote.commit->sig = tal(peer->remote.commit, peer->remote.commit->sig = tal(peer->remote.commit,
struct bitcoin_signature); struct bitcoin_signature);
@@ -281,7 +269,7 @@ void queue_pkt_commit(struct peer *peer)
* changes except unacked fee changes to the remote commitment * changes except unacked fee changes to the remote commitment
* before generating `sig`. */ * before generating `sig`. */
ci->cstate = copy_cstate(ci, peer->remote.staging_cstate); ci->cstate = copy_cstate(ci, peer->remote.staging_cstate);
ci->tx = create_commit_tx(ci, ci->tx = create_commit_tx(ci, peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.locktime, &peer->local.locktime,
@@ -445,7 +433,8 @@ void queue_pkt_close_clearing(struct peer *peer)
CloseClearing *c = tal(peer, CloseClearing); CloseClearing *c = tal(peer, CloseClearing);
close_clearing__init(c); close_clearing__init(c);
redeemscript = bitcoin_redeem_single(c, &peer->local.finalkey); redeemscript = bitcoin_redeem_single(c, peer->dstate->secpctx,
&peer->local.finalkey);
peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript); peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript);
c->scriptpubkey.data = tal_dup_arr(c, u8, c->scriptpubkey.data = tal_dup_arr(c, u8,
@@ -526,7 +515,8 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt)
/* Witness script for anchor. */ /* Witness script for anchor. */
peer->anchor.witnessscript peer->anchor.witnessscript
= bitcoin_redeem_2of2(peer, &peer->local.commitkey, = bitcoin_redeem_2of2(peer, peer->dstate->secpctx,
&peer->local.commitkey,
&peer->remote.commitkey); &peer->remote.commitkey);
return NULL; return NULL;
} }
@@ -769,7 +759,7 @@ Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt)
*/ */
/* (We already applied them to staging_cstate as we went) */ /* (We already applied them to staging_cstate as we went) */
ci->cstate = copy_cstate(ci, peer->local.staging_cstate); ci->cstate = copy_cstate(ci, peer->local.staging_cstate);
ci->tx = create_commit_tx(ci, ci->tx = create_commit_tx(ci, peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.locktime, &peer->local.locktime,

View File

@@ -416,6 +416,7 @@ static void peer_start_clearing(struct peer *peer)
/* If they started close, we might not have sent ours. */ /* If they started close, we might not have sent ours. */
if (!peer->closing.our_script) { if (!peer->closing.our_script) {
u8 *redeemscript = bitcoin_redeem_single(peer, u8 *redeemscript = bitcoin_redeem_single(peer,
peer->dstate->secpctx,
&peer->local.finalkey); &peer->local.finalkey);
peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript); peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript);
@@ -586,6 +587,7 @@ static const struct bitcoin_tx *htlc_fulfill_tx(const struct peer *peer,
assert(htlc->r); assert(htlc->r);
wscript = bitcoin_redeem_htlc_recv(peer, wscript = bitcoin_redeem_htlc_recv(peer,
peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.finalkey, &peer->remote.finalkey,
&htlc->expiry, &htlc->expiry,
@@ -602,7 +604,9 @@ static const struct bitcoin_tx *htlc_fulfill_tx(const struct peer *peer,
/* Using a new output address here would be useless: they can tell /* Using a new output address here would be useless: they can tell
* it's their HTLC, and that we collected it via rval. */ * it's their HTLC, and that we collected it via rval. */
tx->output[0].script = scriptpubkey_p2sh(tx, tx->output[0].script = scriptpubkey_p2sh(tx,
bitcoin_redeem_single(tx, &peer->local.finalkey)); bitcoin_redeem_single(tx,
peer->dstate->secpctx,
&peer->local.finalkey));
tx->output[0].script_length = tal_count(tx->output[0].script); tx->output[0].script_length = tal_count(tx->output[0].script);
log_debug(peer->log, "Pre-witness txlen = %zu\n", log_debug(peer->log, "Pre-witness txlen = %zu\n",
@@ -1404,6 +1408,7 @@ static const struct bitcoin_tx *htlc_timeout_tx(const struct peer *peer,
htlc = htlc_by_index(ci, i); htlc = htlc_by_index(ci, i);
wscript = bitcoin_redeem_htlc_send(peer, wscript = bitcoin_redeem_htlc_send(peer,
peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.finalkey, &peer->remote.finalkey,
&htlc->expiry, &htlc->expiry,
@@ -1422,7 +1427,9 @@ static const struct bitcoin_tx *htlc_timeout_tx(const struct peer *peer,
/* Using a new output address here would be useless: they can tell /* Using a new output address here would be useless: they can tell
* it's our HTLC, and that we collected it via timeout. */ * it's our HTLC, and that we collected it via timeout. */
tx->output[0].script = scriptpubkey_p2sh(tx, tx->output[0].script = scriptpubkey_p2sh(tx,
bitcoin_redeem_single(tx, &peer->local.finalkey)); bitcoin_redeem_single(tx,
peer->dstate->secpctx,
&peer->local.finalkey));
tx->output[0].script_length = tal_count(tx->output[0].script); tx->output[0].script_length = tal_count(tx->output[0].script);
log_unusual(peer->log, "Pre-witness txlen = %zu\n", log_unusual(peer->log, "Pre-witness txlen = %zu\n",
@@ -1550,6 +1557,7 @@ static void resolve_cheating(struct peer *peer)
peer->closing_onchain.resolved[0] = steal_tx; peer->closing_onchain.resolved[0] = steal_tx;
wscripts[n++] wscripts[n++]
= bitcoin_redeem_secret_or_delay(wscripts, = bitcoin_redeem_secret_or_delay(wscripts,
peer->dstate->secpctx,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.locktime, &peer->local.locktime,
&peer->local.finalkey, &peer->local.finalkey,
@@ -1570,6 +1578,7 @@ static void resolve_cheating(struct peer *peer)
if (!htlc_is_ours(ci, i)) { if (!htlc_is_ours(ci, i)) {
wscripts[n] wscripts[n]
= bitcoin_redeem_htlc_send(wscripts, = bitcoin_redeem_htlc_send(wscripts,
peer->dstate->secpctx,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.finalkey, &peer->local.finalkey,
&h->expiry, &h->expiry,
@@ -1579,6 +1588,7 @@ static void resolve_cheating(struct peer *peer)
} else { } else {
wscripts[n] wscripts[n]
= bitcoin_redeem_htlc_recv(wscripts, = bitcoin_redeem_htlc_recv(wscripts,
peer->dstate->secpctx,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.finalkey, &peer->local.finalkey,
&h->expiry, &h->expiry,
@@ -2291,14 +2301,12 @@ struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee)
} }
log_debug(peer->log, log_debug(peer->log,
"creating close-tx with fee %"PRIu64": to %02x%02x%02x%02x/%02x%02x%02x%02x, amounts %u/%u", "creating close-tx with fee %"PRIu64" amounts %u/%u to ",
fee, fee,
peer->local.finalkey.der[0], peer->local.finalkey.der[1],
peer->local.finalkey.der[2], peer->local.finalkey.der[3],
peer->remote.finalkey.der[0], peer->remote.finalkey.der[1],
peer->remote.finalkey.der[2], peer->remote.finalkey.der[3],
cstate.side[OURS].pay_msat / 1000, cstate.side[OURS].pay_msat / 1000,
cstate.side[THEIRS].pay_msat / 1000); cstate.side[THEIRS].pay_msat / 1000);
log_add_struct(peer->log, "%s", struct pubkey, &peer->local.finalkey);
log_add_struct(peer->log, "/%s", struct pubkey, &peer->remote.finalkey);
return create_close_tx(peer->dstate->secpctx, peer, return create_close_tx(peer->dstate->secpctx, peer,
peer->closing.our_script, peer->closing.our_script,
@@ -2396,6 +2404,7 @@ const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer)
/* The redeemscript for a commit tx is fairly complex. */ /* The redeemscript for a commit tx is fairly complex. */
witnessscript = bitcoin_redeem_secret_or_delay(peer, witnessscript = bitcoin_redeem_secret_or_delay(peer,
peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.locktime, &peer->remote.locktime,
&peer->remote.finalkey, &peer->remote.finalkey,
@@ -2411,7 +2420,9 @@ const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer)
&commit->output[p2wsh_out].amount); &commit->output[p2wsh_out].amount);
tx->output[0].script = scriptpubkey_p2sh(tx, tx->output[0].script = scriptpubkey_p2sh(tx,
bitcoin_redeem_single(tx, &peer->local.finalkey)); bitcoin_redeem_single(tx,
peer->dstate->secpctx,
&peer->local.finalkey));
tx->output[0].script_length = tal_count(tx->output[0].script); tx->output[0].script_length = tal_count(tx->output[0].script);
/* Witness length can vary, due to DER encoding of sigs, but we /* Witness length can vary, due to DER encoding of sigs, but we
@@ -2787,6 +2798,7 @@ bool setup_first_commit(struct peer *peer)
return false; return false;
peer->local.commit->tx = create_commit_tx(peer->local.commit, peer->local.commit->tx = create_commit_tx(peer->local.commit,
peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.locktime, &peer->local.locktime,
@@ -2800,6 +2812,7 @@ bool setup_first_commit(struct peer *peer)
&peer->local.commit->map); &peer->local.commit->map);
peer->remote.commit->tx = create_commit_tx(peer->remote.commit, peer->remote.commit->tx = create_commit_tx(peer->remote.commit,
peer->dstate->secpctx,
&peer->local.finalkey, &peer->local.finalkey,
&peer->remote.finalkey, &peer->remote.finalkey,
&peer->local.locktime, &peer->local.locktime,
@@ -2830,6 +2843,17 @@ static void json_add_abstime(struct json_result *response,
json_object_end(response); json_object_end(response);
} }
static void json_add_pubkey(struct json_result *response,
secp256k1_context *secpctx,
const char *id,
const struct pubkey *key)
{
u8 der[PUBKEY_DER_LEN];
pubkey_to_der(secpctx, der, key);
json_add_hex(response, id, der, sizeof(der));
}
static void json_add_htlcs(struct json_result *response, static void json_add_htlcs(struct json_result *response,
const char *id, const char *id,
const struct channel_oneside *side) const struct channel_oneside *side)
@@ -2869,8 +2893,8 @@ static void json_getpeers(struct command *cmd,
/* This is only valid after crypto setup. */ /* This is only valid after crypto setup. */
if (p->state != STATE_INIT) if (p->state != STATE_INIT)
json_add_hex(response, "peerid", json_add_pubkey(response, cmd->dstate->secpctx,
p->id.der, sizeof(p->id.der)); "peerid", &p->id);
json_add_bool(response, "connected", p->conn && !p->fake_close); json_add_bool(response, "connected", p->conn && !p->fake_close);

View File

@@ -40,12 +40,13 @@ void wallet_add_signed_input(struct lightningd_state *dstate,
struct bitcoin_signature sig; struct bitcoin_signature sig;
assert(input_num < tx->input_count); assert(input_num < tx->input_count);
redeemscript = bitcoin_redeem_p2wpkh(tx, &w->pubkey); redeemscript = bitcoin_redeem_p2wpkh(tx, dstate->secpctx, &w->pubkey);
sig.stype = SIGHASH_ALL; sig.stype = SIGHASH_ALL;
sign_tx_input(dstate->secpctx, tx, input_num, sign_tx_input(dstate->secpctx, tx, input_num,
redeemscript, tal_count(redeemscript), redeemscript, tal_count(redeemscript),
p2wpkh_scriptcode(redeemscript, &w->pubkey), p2wpkh_scriptcode(redeemscript, dstate->secpctx,
&w->pubkey),
&w->privkey, &w->privkey,
&w->pubkey, &w->pubkey,
&sig.sig); &sig.sig);
@@ -83,7 +84,8 @@ static void json_newaddr(struct command *cmd,
struct sha256 h; struct sha256 h;
new_keypair(cmd->dstate, &w->privkey, &w->pubkey); new_keypair(cmd->dstate, &w->privkey, &w->pubkey);
redeemscript = bitcoin_redeem_p2wpkh(cmd, &w->pubkey); redeemscript = bitcoin_redeem_p2wpkh(cmd, cmd->dstate->secpctx,
&w->pubkey);
sha256(&h, redeemscript, tal_count(redeemscript)); sha256(&h, redeemscript, tal_count(redeemscript));
ripemd160(&w->p2sh, h.u.u8, sizeof(h)); ripemd160(&w->p2sh, h.u.u8, sizeof(h));

View File

@@ -48,14 +48,12 @@ BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct pubkey *key) const struct pubkey *key)
{ {
BitcoinPubkey *p = tal(ctx, BitcoinPubkey); BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
struct pubkey check;
bitcoin_pubkey__init(p); bitcoin_pubkey__init(p);
p->key.len = sizeof(key->der); p->key.len = PUBKEY_DER_LEN;
p->key.data = tal_dup_arr(p, u8, key->der, p->key.len, 0); p->key.data = tal_arr(p, u8, p->key.len);
assert(pubkey_from_der(secpctx, p->key.data, p->key.len, &check)); pubkey_to_der(secpctx, p->key.data, key);
assert(pubkey_eq(&check, key));
return p; return p;
} }