p2tr script utilities

This commit is contained in:
Greg Sanders 2023-07-11 01:54:43 +09:30 committed by Rusty Russell
parent 0097e2c666
commit 3c689cdaff
2 changed files with 110 additions and 2 deletions

View file

@ -310,6 +310,69 @@ u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version,
return script;
}
u8 *scriptpubkey_raw_p2tr(const tal_t *ctx, const struct pubkey *output_pubkey)
{
int ok;
secp256k1_xonly_pubkey x_key;
unsigned char x_key_bytes[32];
u8 *script = tal_arr(ctx, u8, 0);
add_op(&script, OP_1);
ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx,
&x_key,
/* pk_parity */ NULL,
&(output_pubkey->pubkey));
assert(ok);
ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx,
x_key_bytes,
&x_key);
assert(ok);
script_push_bytes(&script, x_key_bytes, sizeof(x_key_bytes));
assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2TR_LEN);
return script;
}
u8 *scriptpubkey_raw_p2tr_derkey(const tal_t *ctx, const u8 output_der[33])
{
struct pubkey tr_key;
if (!pubkey_from_der(output_der, 33, &tr_key)) {
abort();
}
return scriptpubkey_raw_p2tr(ctx, &tr_key);
}
u8 *scriptpubkey_p2tr(const tal_t *ctx, const struct pubkey *inner_pubkey)
{
unsigned char key_bytes[33];
unsigned char tweaked_key_bytes[33];
size_t out_len = sizeof(key_bytes);
u8 *script = tal_arr(ctx, u8, 0);
add_op(&script, OP_1);
secp256k1_ec_pubkey_serialize(secp256k1_ctx, key_bytes, &out_len, &inner_pubkey->pubkey, SECP256K1_EC_COMPRESSED);
/* Only commit to inner pubkey in tweak */
if (wally_ec_public_key_bip341_tweak(key_bytes, 33, /* merkle_root*/ NULL, 0, 0 /* flags */, tweaked_key_bytes, sizeof(tweaked_key_bytes)) != WALLY_OK)
abort();
/* Cut off the first byte from the serialized compressed key */
script_push_bytes(&script, tweaked_key_bytes + 1, sizeof(tweaked_key_bytes) - 1);
assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2TR_LEN);
return script;
}
u8 *scriptpubkey_p2tr_derkey(const tal_t *ctx, const u8 inner_der[33])
{
struct pubkey tr_key;
if (!pubkey_from_der(inner_der, 33, &tr_key)) {
abort();
}
return scriptpubkey_p2tr(ctx, &tr_key);
}
/* BOLT #3:
*
* #### `to_remote` Output
@ -481,10 +544,33 @@ bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr)
return true;
}
bool is_p2tr(const u8 *script, u8 xonly_pubkey[32])
{
size_t script_len = tal_count(script);
if (script_len != BITCOIN_SCRIPTPUBKEY_P2TR_LEN)
return false;
if (script[0] != OP_1)
return false;
/* x-only pubkey */
if (script[1] != OP_PUSHBYTES(32))
return false;
if (xonly_pubkey)
memcpy(xonly_pubkey, script+2, 32);
return true;
}
bool is_known_scripttype(const u8 *script)
{
return is_p2wpkh(script, NULL) || is_p2wsh(script, NULL)
|| is_p2sh(script, NULL) || is_p2pkh(script, NULL);
|| is_p2sh(script, NULL) || is_p2pkh(script, NULL)
|| is_p2tr(script, NULL);
}
bool is_known_segwit_scripttype(const u8 *script)
{
return is_p2wpkh(script, NULL) || is_p2wsh(script, NULL)
|| is_p2tr(script, NULL);
}
u8 **bitcoin_witness_sig_and_element(const tal_t *ctx,

View file

@ -63,6 +63,19 @@ u8 *scriptpubkey_p2wpkh_derkey(const tal_t *ctx, const u8 der[33]);
u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version,
const u8 *wprog, size_t wprog_size);
/* Create an output script for a "raw"(perhaps already tweaked) taproot output pubkey */
u8 *scriptpubkey_raw_p2tr(const tal_t *ctx, const struct pubkey *output_pubkey);
/* Same as above, but compressed key is DER-encoded. */
u8 *scriptpubkey_raw_p2tr_derkey(const tal_t *ctx, const u8 output_der[33]);
/* Create an output script for an internal taproot pubkey. Results in different script than
* scriptpubkey_raw_p2tr! TODO support merkle root tweaking */
u8 *scriptpubkey_p2tr(const tal_t *ctx, const struct pubkey *inner_pubkey);
/* Same as above, but compressed key is DER-encoded. TODO support merkle root tweaking */
u8 *scriptpubkey_p2tr_derkey(const tal_t *ctx, const u8 inner_der[33]);
/* To-remotekey with csv max(lease_expiry - blockheight, 1) delay. */
u8 *bitcoin_wscript_to_remote_anchored(const tal_t *ctx,
const struct pubkey *remote_key,
@ -157,9 +170,15 @@ bool is_p2wsh(const u8 *script, struct sha256 *addr);
/* Is this (version 0) pay to witness pubkey hash? (extract addr if not NULL) */
bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr);
/* Is this one of the four above script types? */
/* Is this a taproot output? (extract xonly_pubkey bytes if not NULL) */
bool is_p2tr(const u8 *script, u8 xonly_pubkey[32]);
/* Is this one of the above script types? */
bool is_known_scripttype(const u8 *script);
/* Is this a witness script type? */
bool is_known_segwit_scripttype(const u8 *script);
/* Is this a to-remote witness script (used for option_anchor_outputs)? */
bool is_to_remote_anchored_witness_script(const u8 *script, size_t script_len);
@ -184,4 +203,7 @@ void script_push_bytes(u8 **scriptp, const void *mem, size_t len);
/* OP_0 + PUSH(32-byte-hash) */
#define BITCOIN_SCRIPTPUBKEY_P2WSH_LEN (1 + 1 + 32)
/* OP_1 + PUSH(32-byte-key) */
#define BITCOIN_SCRIPTPUBKEY_P2TR_LEN (1 + 1 + 32)
#endif /* LIGHTNING_BITCOIN_SCRIPT_H */