script: Use pkh to construct p2pkh output scripts

So far we always needed to know the public key, which was not the case
for addresses that we don't own. Moving the hashing outside of the
script construction allows us to send to arbitrary addresses. I also
added the hash computation to the pubkey primitives.
This commit is contained in:
Christian Decker
2017-06-14 10:29:10 +02:00
committed by Rusty Russell
parent f10b779c83
commit 40165ba6d5
5 changed files with 24 additions and 6 deletions

View File

@@ -99,3 +99,13 @@ static char *privkey_to_hexstr(const tal_t *ctx, const struct privkey *secret)
} }
REGISTER_TYPE_TO_STRING(privkey, privkey_to_hexstr); REGISTER_TYPE_TO_STRING(privkey, privkey_to_hexstr);
REGISTER_TYPE_TO_HEXSTR(secret); REGISTER_TYPE_TO_HEXSTR(secret);
void pubkey_to_hash160(const struct pubkey *pk, struct ripemd160 *hash)
{
u8 der[PUBKEY_DER_LEN];
struct sha256 h;
pubkey_to_der(der, pk);
sha256(&h, der, sizeof(der));
ripemd160(hash, h.u.u8, sizeof(h));
}

View File

@@ -1,6 +1,8 @@
#ifndef LIGHTNING_BITCOIN_PUBKEY_H #ifndef LIGHTNING_BITCOIN_PUBKEY_H
#define LIGHTNING_BITCOIN_PUBKEY_H #define LIGHTNING_BITCOIN_PUBKEY_H
#include "config.h" #include "config.h"
#include <ccan/crypto/ripemd160/ripemd160.h>
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/short_types/short_types.h> #include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h> #include <ccan/tal/tal.h>
#include <secp256k1.h> #include <secp256k1.h>
@@ -38,4 +40,9 @@ bool pubkey_eq(const struct pubkey *a, const struct pubkey *b);
/* Compare the keys `a` and `b`. Return <0 if `a`<`b`, 0 if equal and >0 otherwise */ /* Compare the keys `a` and `b`. Return <0 if `a`<`b`, 0 if equal and >0 otherwise */
int pubkey_cmp(const struct pubkey *a, const struct pubkey *b); int pubkey_cmp(const struct pubkey *a, const struct pubkey *b);
/**
* pubkey_to_hash160 - Get the hash for p2pkh payments for a given pubkey
*/
void pubkey_to_hash160(const struct pubkey *pk, struct ripemd160 *hash);
#endif /* LIGHTNING_PUBKEY_H */ #endif /* LIGHTNING_PUBKEY_H */

View File

@@ -212,15 +212,13 @@ u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript)
} }
/* Create an output script using p2pkh */ /* Create an output script using p2pkh */
u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct pubkey *pubkey) u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr)
{ {
struct bitcoin_address addr;
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
hash160_key(&addr.addr, pubkey);
add_op(&script, OP_DUP); add_op(&script, OP_DUP);
add_op(&script, OP_HASH160); add_op(&script, OP_HASH160);
add_push_bytes(&script, &addr.addr, sizeof(addr.addr)); add_push_bytes(&script, &addr->addr, sizeof(addr->addr));
add_op(&script, OP_EQUALVERIFY); add_op(&script, OP_EQUALVERIFY);
add_op(&script, OP_CHECKSIG); add_op(&script, OP_CHECKSIG);
return script; return script;

View File

@@ -35,7 +35,7 @@ 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 an output script using p2pkh */ /* Create an output script using p2pkh */
u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct pubkey *pubkey); u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr);
/* Create an input script which spends p2pkh */ /* Create an input script which spends p2pkh */
u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey, u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey,

View File

@@ -1,3 +1,4 @@
#include <bitcoin/address.h>
#include <bitcoin/base58.h> #include <bitcoin/base58.h>
#include <bitcoin/privkey.h> #include <bitcoin/privkey.h>
#include <bitcoin/pubkey.h> #include <bitcoin/pubkey.h>
@@ -52,6 +53,7 @@ int main(void)
u16 funding_outnum; u16 funding_outnum;
u8 *subscript; u8 *subscript;
secp256k1_ecdsa_signature sig; secp256k1_ecdsa_signature sig;
struct bitcoin_address addr;
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN); | SECP256K1_CONTEXT_SIGN);
@@ -118,7 +120,8 @@ int main(void)
printf("funding output: %u\n", funding_outnum); printf("funding output: %u\n", funding_outnum);
subscript = scriptpubkey_p2pkh(funding, &inputkey); pubkey_to_hash160(&inputkey, &addr.addr);
subscript = scriptpubkey_p2pkh(funding, &addr);
sign_tx_input(funding, 0, subscript, NULL, &input_privkey, &inputkey, sign_tx_input(funding, 0, subscript, NULL, &input_privkey, &inputkey,
&sig); &sig);