mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 06:41:44 +01:00
p2tr script utilities
This commit is contained in:
parent
0097e2c666
commit
3c689cdaff
2 changed files with 110 additions and 2 deletions
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue