mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-23 06:55:13 +01:00
Processing blocks is rather slow at the moment, but one thing we can do, is to prevent copying all output scripts, when really all we are interested in are the couple of outputs that are P2WSH. This builds the foundation of that by adding a method to introspect the script without having to clone it first, saving us some allocations, and deallocations. Changelog-Changed: core: Processing blocks should now be faster
1001 lines
27 KiB
C
1001 lines
27 KiB
C
#include "config.h"
|
|
#include <assert.h>
|
|
#include <bitcoin/address.h>
|
|
#include <bitcoin/locktime.h>
|
|
#include <bitcoin/preimage.h>
|
|
#include <bitcoin/pubkey.h>
|
|
#include <bitcoin/script.h>
|
|
#include <ccan/endian/endian.h>
|
|
#include <ccan/mem/mem.h>
|
|
#include <common/utils.h>
|
|
#include <sodium/randombytes.h>
|
|
|
|
/* Bitcoin's OP_HASH160 is RIPEMD(SHA256()) */
|
|
static void hash160(struct ripemd160 *redeemhash, const void *mem, size_t len)
|
|
{
|
|
struct sha256 h;
|
|
|
|
sha256(&h, mem, len);
|
|
ripemd160(redeemhash, h.u.u8, sizeof(h));
|
|
}
|
|
|
|
static void add(u8 **scriptp, const void *mem, size_t len)
|
|
{
|
|
size_t oldlen = tal_count(*scriptp);
|
|
tal_resize(scriptp, oldlen + len);
|
|
memcpy(*scriptp + oldlen, mem, len);
|
|
}
|
|
|
|
static void add_op(u8 **scriptp, u8 op)
|
|
{
|
|
add(scriptp, &op, 1);
|
|
}
|
|
|
|
void script_push_bytes(u8 **scriptp, const void *mem, size_t len)
|
|
{
|
|
if (len < 76)
|
|
add_op(scriptp, OP_PUSHBYTES(len));
|
|
else if (len < 256) {
|
|
char c = len;
|
|
add_op(scriptp, OP_PUSHDATA1);
|
|
add(scriptp, &c, 1);
|
|
} else if (len < 65536) {
|
|
le16 v = cpu_to_le16(len);
|
|
add_op(scriptp, OP_PUSHDATA2);
|
|
add(scriptp, &v, 2);
|
|
} else {
|
|
le32 v = cpu_to_le32(len);
|
|
add_op(scriptp, OP_PUSHDATA4);
|
|
add(scriptp, &v, 4);
|
|
}
|
|
|
|
add(scriptp, memcheck(mem, len), len);
|
|
}
|
|
|
|
static void add_number(u8 **script, u32 num)
|
|
{
|
|
if (num == 0)
|
|
add_op(script, 0);
|
|
else if (num <= 16)
|
|
add_op(script, 0x50 + num);
|
|
else {
|
|
le64 n = cpu_to_le64(num);
|
|
|
|
/* Beware: encoding is signed! */
|
|
if (num <= 0x0000007F)
|
|
script_push_bytes(script, &n, 1);
|
|
else if (num <= 0x00007FFF)
|
|
script_push_bytes(script, &n, 2);
|
|
else if (num <= 0x007FFFFF)
|
|
script_push_bytes(script, &n, 3);
|
|
else if (num <= 0x7FFFFFFF)
|
|
script_push_bytes(script, &n, 4);
|
|
else
|
|
script_push_bytes(script, &n, 5);
|
|
}
|
|
}
|
|
|
|
static void add_push_key(u8 **scriptp, const struct pubkey *key)
|
|
{
|
|
u8 der[PUBKEY_CMPR_LEN];
|
|
pubkey_to_der(der, key);
|
|
|
|
script_push_bytes(scriptp, der, sizeof(der));
|
|
}
|
|
|
|
static void add_push_sig(u8 **scriptp, const struct bitcoin_signature *sig)
|
|
{
|
|
u8 der[73];
|
|
size_t len = signature_to_der(der, sig);
|
|
|
|
script_push_bytes(scriptp, der, len);
|
|
}
|
|
|
|
static u8 *stack_key(const tal_t *ctx, const struct pubkey *key)
|
|
{
|
|
u8 der[PUBKEY_CMPR_LEN];
|
|
pubkey_to_der(der, key);
|
|
|
|
return tal_dup_arr(ctx, u8, der, sizeof(der), 0);
|
|
}
|
|
|
|
/* Bitcoin wants DER encoding. */
|
|
static u8 *stack_sig(const tal_t *ctx, const struct bitcoin_signature *sig)
|
|
{
|
|
u8 der[73];
|
|
size_t len = signature_to_der(der, sig);
|
|
|
|
return tal_dup_arr(ctx, u8, der, len, 0);
|
|
}
|
|
|
|
static u8 *stack_preimage(const tal_t *ctx, const struct preimage *preimage)
|
|
{
|
|
return tal_dup_arr(ctx, u8, preimage->r, sizeof(preimage->r), 0);
|
|
}
|
|
|
|
/* Bitcoin script stack values are a special, special snowflake.
|
|
*
|
|
* They're little endian values, but 0 is an empty value. We only
|
|
* handle single byte values here. */
|
|
static u8 *stack_number(const tal_t *ctx, unsigned int num)
|
|
{
|
|
u8 val;
|
|
|
|
if (num == 0)
|
|
return tal_arr(ctx, u8, 0);
|
|
|
|
val = num;
|
|
assert(val == num);
|
|
|
|
/* We use tal_dup_arr since we want tal_count() to work */
|
|
return tal_dup_arr(ctx, u8, &val, 1, 0);
|
|
}
|
|
|
|
/* tal_count() gives the length of the script. */
|
|
u8 *bitcoin_redeem_2of2(const tal_t *ctx,
|
|
const struct pubkey *key1,
|
|
const struct pubkey *key2)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
add_number(&script, 2);
|
|
if (pubkey_cmp(key1, key2) < 0) {
|
|
add_push_key(&script, key1);
|
|
add_push_key(&script, key2);
|
|
} else {
|
|
add_push_key(&script, key2);
|
|
add_push_key(&script, key1);
|
|
}
|
|
add_number(&script, 2);
|
|
add_op(&script, OP_CHECKMULTISIG);
|
|
return script;
|
|
}
|
|
|
|
u8 *scriptpubkey_p2sh_hash(const tal_t *ctx, const struct ripemd160 *redeemhash)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
add_op(&script, OP_HASH160);
|
|
script_push_bytes(&script, redeemhash->u.u8, sizeof(redeemhash->u.u8));
|
|
add_op(&script, OP_EQUAL);
|
|
assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2SH_LEN);
|
|
return script;
|
|
}
|
|
|
|
/* Create p2sh for this redeem script. */
|
|
u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript)
|
|
{
|
|
struct ripemd160 redeemhash;
|
|
|
|
hash160(&redeemhash, redeemscript, tal_count(redeemscript));
|
|
return scriptpubkey_p2sh_hash(ctx, &redeemhash);
|
|
}
|
|
|
|
/* Create an output script using p2pkh */
|
|
u8 *scriptpubkey_p2pkh(const tal_t *ctx, const struct bitcoin_address *addr)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
add_op(&script, OP_DUP);
|
|
add_op(&script, OP_HASH160);
|
|
script_push_bytes(&script, &addr->addr, sizeof(addr->addr));
|
|
add_op(&script, OP_EQUALVERIFY);
|
|
add_op(&script, OP_CHECKSIG);
|
|
assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2PKH_LEN);
|
|
return script;
|
|
}
|
|
|
|
u8 *scriptpubkey_opreturn_padded(const tal_t *ctx)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
u8 random[20];
|
|
randombytes_buf(random, sizeof(random));
|
|
|
|
add_op(&script, OP_RETURN);
|
|
script_push_bytes(&script, random, sizeof(random));
|
|
return script;
|
|
}
|
|
|
|
/* Create an input script which spends p2pkh */
|
|
u8 *bitcoin_redeem_p2pkh(const tal_t *ctx, const struct pubkey *pubkey,
|
|
const struct bitcoin_signature *sig)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
add_push_sig(&script, sig);
|
|
add_push_key(&script, pubkey);
|
|
|
|
return script;
|
|
}
|
|
|
|
/* Create the redeemscript for a P2SH + P2WPKH (for signing tx) */
|
|
u8 *bitcoin_redeem_p2sh_p2wpkh(const tal_t *ctx, const struct pubkey *key)
|
|
{
|
|
struct ripemd160 keyhash;
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
/* BIP141: BIP16 redeemScript pushed in the scriptSig is exactly a
|
|
* push of a version byte plus a push of a witness program. */
|
|
add_number(&script, 0);
|
|
pubkey_to_hash160(key, &keyhash);
|
|
script_push_bytes(&script, &keyhash, sizeof(keyhash));
|
|
|
|
assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN);
|
|
return script;
|
|
}
|
|
|
|
u8 *bitcoin_scriptsig_redeem(const tal_t *ctx,
|
|
const u8 *redeemscript TAKES)
|
|
{
|
|
u8 *script;
|
|
|
|
/* BIP141: The scriptSig must be exactly a push of the BIP16
|
|
* redeemScript or validation fails. */
|
|
script = tal_arr(ctx, u8, 0);
|
|
script_push_bytes(&script, redeemscript,
|
|
tal_count(redeemscript));
|
|
|
|
if (taken(redeemscript))
|
|
tal_free(redeemscript);
|
|
|
|
return script;
|
|
}
|
|
|
|
u8 *bitcoin_scriptsig_p2sh_p2wpkh(const tal_t *ctx, const struct pubkey *key)
|
|
{
|
|
u8 *redeemscript =
|
|
bitcoin_redeem_p2sh_p2wpkh(NULL, key);
|
|
return bitcoin_scriptsig_redeem(ctx, take(redeemscript));
|
|
}
|
|
|
|
u8 **bitcoin_witness_p2wpkh(const tal_t *ctx,
|
|
const struct bitcoin_signature *sig,
|
|
const struct pubkey *key)
|
|
{
|
|
u8 **witness;
|
|
|
|
/* BIP141: The witness must consist of exactly 2 items (≤ 520
|
|
* bytes each). The first one a signature, and the second one
|
|
* a public key. */
|
|
witness = tal_arr(ctx, u8 *, 2);
|
|
witness[0] = stack_sig(witness, sig);
|
|
witness[1] = stack_key(witness, key);
|
|
return witness;
|
|
}
|
|
|
|
/* Create an output script for a 32-byte witness. */
|
|
u8 *scriptpubkey_p2wsh(const tal_t *ctx, const u8 *witnessscript)
|
|
{
|
|
struct sha256 h;
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
add_op(&script, OP_0);
|
|
sha256(&h, witnessscript, tal_count(witnessscript));
|
|
script_push_bytes(&script, h.u.u8, sizeof(h.u.u8));
|
|
assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2WSH_LEN);
|
|
return script;
|
|
}
|
|
|
|
/* Create an output script for a 20-byte witness. */
|
|
u8 *scriptpubkey_p2wpkh(const tal_t *ctx, const struct pubkey *key)
|
|
{
|
|
struct ripemd160 h;
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
add_op(&script, OP_0);
|
|
pubkey_to_hash160(key, &h);
|
|
script_push_bytes(&script, &h, sizeof(h));
|
|
return script;
|
|
}
|
|
|
|
u8 *scriptpubkey_p2wpkh_derkey(const tal_t *ctx, const u8 der[33])
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
struct ripemd160 h;
|
|
|
|
add_op(&script, OP_0);
|
|
hash160(&h, der, PUBKEY_CMPR_LEN);
|
|
script_push_bytes(&script, &h, sizeof(h));
|
|
return script;
|
|
}
|
|
|
|
u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version,
|
|
const u8 *wprog, size_t wprog_size)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
add_number(&script, version);
|
|
script_push_bytes(&script, wprog, wprog_size);
|
|
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
|
|
*
|
|
* If `option_anchors` applies to the commitment
|
|
* transaction, the `to_remote` output is encumbered by a one
|
|
* block csv lock.
|
|
* <remotepubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY
|
|
*/
|
|
/* BOLT- #3
|
|
* ##### Leased channel (`option_will_fund`)
|
|
*
|
|
* If a `lease` applies to the channel, the `to_remote` output
|
|
* of the `initiator` ensures the `leasor` funds are not
|
|
* spendable until the lease expires.
|
|
*
|
|
* <remote_pubkey> OP_CHECKSIGVERIFY MAX(1, lease_end - blockheight) OP_CHECKSEQUENCEVERIFY
|
|
*/
|
|
|
|
u8 *bitcoin_wscript_to_remote_anchored(const tal_t *ctx,
|
|
const struct pubkey *remote_key,
|
|
u32 csv_lock)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
add_push_key(&script, remote_key);
|
|
add_op(&script, OP_CHECKSIGVERIFY);
|
|
add_number(&script, csv_lock);
|
|
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
|
|
|
assert(is_to_remote_anchored_witness_script(script, tal_bytelen(script)));
|
|
return script;
|
|
}
|
|
|
|
bool is_to_remote_anchored_witness_script(const u8 *script, size_t script_len)
|
|
{
|
|
size_t len = 34 + 1 + 1 + 1;
|
|
/* With option_will_fund, the pushbytes can be up to 2 bytes more
|
|
*
|
|
* <remote_pubkey> OP_CHECKSIGVERIFY
|
|
* MAX(1, lease_end - blockheight)
|
|
* OP_CHECKSEQUENCEVERIFY
|
|
*/
|
|
if (script_len < len || script_len > len + 2)
|
|
return false;
|
|
if (script[0] != OP_PUSHBYTES(33))
|
|
return false;
|
|
if (script[34] != OP_CHECKSIGVERIFY)
|
|
return false;
|
|
/* FIXME: check for push value */
|
|
if (script[script_len - 1] != OP_CHECKSEQUENCEVERIFY)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/* Create a witness which spends the 2of2. */
|
|
u8 **bitcoin_witness_2of2(const tal_t *ctx,
|
|
const struct bitcoin_signature *sig1,
|
|
const struct bitcoin_signature *sig2,
|
|
const struct pubkey *key1,
|
|
const struct pubkey *key2)
|
|
{
|
|
u8 **witness = tal_arr(ctx, u8 *, 4);
|
|
|
|
/* OP_CHECKMULTISIG has an out-by-one bug, which MBZ */
|
|
witness[0] = stack_number(witness, 0);
|
|
|
|
/* sig order should match key order. */
|
|
if (pubkey_cmp(key1, key2) < 0) {
|
|
witness[1] = stack_sig(witness, sig1);
|
|
witness[2] = stack_sig(witness, sig2);
|
|
} else {
|
|
witness[1] = stack_sig(witness, sig2);
|
|
witness[2] = stack_sig(witness, sig1);
|
|
}
|
|
|
|
witness[3] = bitcoin_redeem_2of2(witness, key1, key2);
|
|
return witness;
|
|
}
|
|
|
|
/* Create scriptcode (fake witness, basically) for P2WPKH */
|
|
u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key)
|
|
{
|
|
struct ripemd160 pkhash;
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
pubkey_to_hash160(key, &pkhash);
|
|
|
|
/* BIP143:
|
|
*
|
|
* For P2WPKH witness program, the scriptCode is
|
|
* 0x1976a914{20-byte-pubkey-hash}88ac.
|
|
*/
|
|
|
|
/* PUSH(25): OP_DUP OP_HASH160 PUSH(20) 20-byte-pubkey-hash
|
|
* OP_EQUALVERIFY OP_CHECKSIG */
|
|
add_op(&script, OP_DUP);
|
|
add_op(&script, OP_HASH160);
|
|
script_push_bytes(&script, &pkhash, sizeof(pkhash));
|
|
add_op(&script, OP_EQUALVERIFY);
|
|
add_op(&script, OP_CHECKSIG);
|
|
|
|
return script;
|
|
}
|
|
|
|
bool is_p2pkh(const u8 *script, struct bitcoin_address *addr)
|
|
{
|
|
size_t script_len = tal_count(script);
|
|
|
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2PKH_LEN)
|
|
return false;
|
|
if (script[0] != OP_DUP)
|
|
return false;
|
|
if (script[1] != OP_HASH160)
|
|
return false;
|
|
if (script[2] != OP_PUSHBYTES(20))
|
|
return false;
|
|
if (script[23] != OP_EQUALVERIFY)
|
|
return false;
|
|
if (script[24] != OP_CHECKSIG)
|
|
return false;
|
|
if (addr)
|
|
memcpy(addr, script+3, 20);
|
|
return true;
|
|
}
|
|
|
|
bool is_p2sh(const u8 *script, struct ripemd160 *addr)
|
|
{
|
|
size_t script_len = tal_count(script);
|
|
|
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2SH_LEN)
|
|
return false;
|
|
if (script[0] != OP_HASH160)
|
|
return false;
|
|
if (script[1] != OP_PUSHBYTES(20))
|
|
return false;
|
|
if (script[22] != OP_EQUAL)
|
|
return false;
|
|
if (addr)
|
|
memcpy(addr, script+2, 20);
|
|
return true;
|
|
}
|
|
|
|
bool is_p2wsh(const u8 *script, struct sha256 *addr)
|
|
{
|
|
size_t script_len = tal_count(script);
|
|
|
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)
|
|
return false;
|
|
if (script[0] != OP_0)
|
|
return false;
|
|
if (script[1] != OP_PUSHBYTES(sizeof(struct sha256)))
|
|
return false;
|
|
if (addr)
|
|
memcpy(addr, script+2, sizeof(struct sha256));
|
|
return true;
|
|
}
|
|
|
|
bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr)
|
|
{
|
|
size_t script_len = tal_count(script);
|
|
|
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN)
|
|
return false;
|
|
if (script[0] != OP_0)
|
|
return false;
|
|
if (script[1] != OP_PUSHBYTES(sizeof(struct ripemd160)))
|
|
return false;
|
|
if (addr)
|
|
memcpy(addr, script+2, sizeof(*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_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,
|
|
const struct bitcoin_signature *sig,
|
|
const void *elem, size_t elemsize,
|
|
const u8 *witnessscript)
|
|
{
|
|
u8 **witness = tal_arr(ctx, u8 *, 3);
|
|
|
|
witness[0] = stack_sig(witness, sig);
|
|
witness[1] = tal_dup_arr(witness, u8, elem, elemsize, 0);
|
|
witness[2] = tal_dup_talarr(witness, u8, witnessscript);
|
|
|
|
return witness;
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* This output sends funds back to the owner of this commitment transaction and
|
|
* thus must be timelocked using `OP_CHECKSEQUENCEVERIFY`. It can be claimed, without delay,
|
|
* by the other party if they know the revocation private key. The output is a
|
|
* version-0 P2WSH, with a witness script:
|
|
*
|
|
* OP_IF
|
|
* # Penalty transaction
|
|
* <revocationpubkey>
|
|
* OP_ELSE
|
|
* `to_self_delay`
|
|
* OP_CHECKSEQUENCEVERIFY
|
|
* OP_DROP
|
|
* <local_delayedpubkey>
|
|
* OP_ENDIF
|
|
* OP_CHECKSIG
|
|
*/
|
|
/* BOLT- #3
|
|
* ##### Leased channel (`option_will_fund`)
|
|
* If a `lease` applies to the channel, the `to_local` output of the `accepter`
|
|
* ensures the `leasor` funds are not spendable until the lease expires.
|
|
*
|
|
* In a leased channel, the `to_local` output that pays the `accepter` node
|
|
* is modified so that its CSV is equal to the greater of the
|
|
* `to_self_delay` or the `lease_end` - `blockheight`.
|
|
*
|
|
* OP_IF
|
|
* # Penalty transaction
|
|
* <revocationpubkey>
|
|
* OP_ELSE
|
|
* MAX(`to_self_delay`, `lease_end` - `blockheight`)
|
|
* OP_CHECKSEQUENCEVERIFY
|
|
* OP_DROP
|
|
* <local_delayedpubkey>
|
|
* OP_ENDIF
|
|
* OP_CHECKSIG
|
|
*/
|
|
u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay,
|
|
u32 lease_remaining,
|
|
const struct pubkey *revocation_pubkey,
|
|
const struct pubkey *local_delayedkey)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
add_op(&script, OP_IF);
|
|
add_push_key(&script, revocation_pubkey);
|
|
add_op(&script, OP_ELSE);
|
|
add_number(&script, max_unsigned(lease_remaining, to_self_delay));
|
|
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
|
add_op(&script, OP_DROP);
|
|
add_push_key(&script, local_delayedkey);
|
|
add_op(&script, OP_ENDIF);
|
|
add_op(&script, OP_CHECKSIG);
|
|
return script;
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* #### Offered HTLC Outputs
|
|
*
|
|
* This output sends funds to either an HTLC-timeout transaction after the
|
|
* HTLC-timeout or to the remote node using the payment preimage or the
|
|
* revocation key. The output is a P2WSH, with a witness script (no
|
|
* option_anchors):
|
|
*
|
|
* # To remote node with revocation key
|
|
* OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
|
|
* OP_IF
|
|
* OP_CHECKSIG
|
|
* OP_ELSE
|
|
* <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
|
|
* OP_NOTIF
|
|
* # To local node via HTLC-timeout transaction (timelocked).
|
|
* OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
|
|
* OP_ELSE
|
|
* # To remote node with preimage.
|
|
* OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
|
|
* OP_CHECKSIG
|
|
* OP_ENDIF
|
|
* OP_ENDIF
|
|
*
|
|
* Or, with `option_anchors`:
|
|
*
|
|
* # To remote node with revocation key
|
|
* OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
|
|
* OP_IF
|
|
* OP_CHECKSIG
|
|
* OP_ELSE
|
|
* <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
|
|
* OP_NOTIF
|
|
* # To local node via HTLC-timeout transaction (timelocked).
|
|
* OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
|
|
* OP_ELSE
|
|
* # To remote node with preimage.
|
|
* OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
|
|
* OP_CHECKSIG
|
|
* OP_ENDIF
|
|
* 1 OP_CHECKSEQUENCEVERIFY OP_DROP
|
|
* OP_ENDIF
|
|
*/
|
|
u8 *bitcoin_wscript_htlc_offer_ripemd160(const tal_t *ctx,
|
|
const struct pubkey *localhtlckey,
|
|
const struct pubkey *remotehtlckey,
|
|
const struct ripemd160 *payment_ripemd,
|
|
const struct pubkey *revocationkey,
|
|
bool option_anchor_outputs,
|
|
bool option_anchors_zero_fee_htlc_tx)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
struct ripemd160 ripemd;
|
|
|
|
add_op(&script, OP_DUP);
|
|
add_op(&script, OP_HASH160);
|
|
pubkey_to_hash160(revocationkey, &ripemd);
|
|
script_push_bytes(&script, &ripemd, sizeof(ripemd));
|
|
add_op(&script, OP_EQUAL);
|
|
add_op(&script, OP_IF);
|
|
add_op(&script, OP_CHECKSIG);
|
|
add_op(&script, OP_ELSE);
|
|
add_push_key(&script, remotehtlckey);
|
|
add_op(&script, OP_SWAP);
|
|
add_op(&script, OP_SIZE);
|
|
add_number(&script, 32);
|
|
add_op(&script, OP_EQUAL);
|
|
add_op(&script, OP_NOTIF);
|
|
add_op(&script, OP_DROP);
|
|
add_number(&script, 2);
|
|
add_op(&script, OP_SWAP);
|
|
add_push_key(&script, localhtlckey);
|
|
add_number(&script, 2);
|
|
add_op(&script, OP_CHECKMULTISIG);
|
|
add_op(&script, OP_ELSE);
|
|
add_op(&script, OP_HASH160);
|
|
script_push_bytes(&script,
|
|
payment_ripemd->u.u8, sizeof(payment_ripemd->u.u8));
|
|
add_op(&script, OP_EQUALVERIFY);
|
|
add_op(&script, OP_CHECKSIG);
|
|
add_op(&script, OP_ENDIF);
|
|
if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) {
|
|
add_number(&script, 1);
|
|
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
|
add_op(&script, OP_DROP);
|
|
}
|
|
add_op(&script, OP_ENDIF);
|
|
|
|
return script;
|
|
}
|
|
|
|
u8 *bitcoin_wscript_htlc_offer(const tal_t *ctx,
|
|
const struct pubkey *localhtlckey,
|
|
const struct pubkey *remotehtlckey,
|
|
const struct sha256 *payment_hash,
|
|
const struct pubkey *revocationkey,
|
|
bool option_anchor_outputs,
|
|
bool option_anchors_zero_fee_htlc_tx)
|
|
{
|
|
struct ripemd160 ripemd;
|
|
|
|
ripemd160(&ripemd, payment_hash->u.u8, sizeof(payment_hash->u));
|
|
return bitcoin_wscript_htlc_offer_ripemd160(ctx, localhtlckey,
|
|
remotehtlckey,
|
|
&ripemd, revocationkey,
|
|
option_anchor_outputs,
|
|
option_anchors_zero_fee_htlc_tx);
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* #### Received HTLC Outputs
|
|
*
|
|
* This output sends funds to either the remote node after the HTLC-timeout or
|
|
* using the revocation key, or to an HTLC-success transaction with a
|
|
* successful payment preimage. The output is a P2WSH, with a witness script
|
|
* (no `option_anchors`):
|
|
*
|
|
* # To remote node with revocation key
|
|
* OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
|
|
* OP_IF
|
|
* OP_CHECKSIG
|
|
* OP_ELSE
|
|
* <remote_htlcpubkey> OP_SWAP
|
|
* OP_SIZE 32 OP_EQUAL
|
|
* OP_IF
|
|
* # To local node via HTLC-success transaction.
|
|
* OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
|
|
* 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
|
|
* OP_ELSE
|
|
* # To remote node after timeout.
|
|
* OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
|
|
* OP_CHECKSIG
|
|
* OP_ENDIF
|
|
* OP_ENDIF
|
|
*
|
|
* Or, with `option_anchors`:
|
|
*
|
|
* # To remote node with revocation key
|
|
* OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
|
|
* OP_IF
|
|
* OP_CHECKSIG
|
|
* OP_ELSE
|
|
* <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
|
|
* OP_IF
|
|
* # To local node via HTLC-success transaction.
|
|
* OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
|
|
* 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
|
|
* OP_ELSE
|
|
* # To remote node after timeout.
|
|
* OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
|
|
* OP_CHECKSIG
|
|
* OP_ENDIF
|
|
* 1 OP_CHECKSEQUENCEVERIFY OP_DROP
|
|
* OP_ENDIF
|
|
*/
|
|
u8 *bitcoin_wscript_htlc_receive_ripemd(const tal_t *ctx,
|
|
const struct abs_locktime *htlc_abstimeout,
|
|
const struct pubkey *localhtlckey,
|
|
const struct pubkey *remotehtlckey,
|
|
const struct ripemd160 *payment_ripemd,
|
|
const struct pubkey *revocationkey,
|
|
bool option_anchor_outputs,
|
|
bool option_anchors_zero_fee_htlc_tx)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
struct ripemd160 ripemd;
|
|
|
|
add_op(&script, OP_DUP);
|
|
add_op(&script, OP_HASH160);
|
|
pubkey_to_hash160(revocationkey, &ripemd);
|
|
script_push_bytes(&script, &ripemd, sizeof(ripemd));
|
|
add_op(&script, OP_EQUAL);
|
|
add_op(&script, OP_IF);
|
|
add_op(&script, OP_CHECKSIG);
|
|
add_op(&script, OP_ELSE);
|
|
add_push_key(&script, remotehtlckey);
|
|
add_op(&script, OP_SWAP);
|
|
add_op(&script, OP_SIZE);
|
|
add_number(&script, 32);
|
|
add_op(&script, OP_EQUAL);
|
|
add_op(&script, OP_IF);
|
|
add_op(&script, OP_HASH160);
|
|
script_push_bytes(&script,
|
|
payment_ripemd->u.u8, sizeof(payment_ripemd->u.u8));
|
|
add_op(&script, OP_EQUALVERIFY);
|
|
add_number(&script, 2);
|
|
add_op(&script, OP_SWAP);
|
|
add_push_key(&script, localhtlckey);
|
|
add_number(&script, 2);
|
|
add_op(&script, OP_CHECKMULTISIG);
|
|
add_op(&script, OP_ELSE);
|
|
add_op(&script, OP_DROP);
|
|
add_number(&script, htlc_abstimeout->locktime);
|
|
add_op(&script, OP_CHECKLOCKTIMEVERIFY);
|
|
add_op(&script, OP_DROP);
|
|
add_op(&script, OP_CHECKSIG);
|
|
add_op(&script, OP_ENDIF);
|
|
if (option_anchor_outputs || option_anchors_zero_fee_htlc_tx) {
|
|
add_number(&script, 1);
|
|
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
|
add_op(&script, OP_DROP);
|
|
}
|
|
add_op(&script, OP_ENDIF);
|
|
|
|
return script;
|
|
}
|
|
|
|
u8 *bitcoin_wscript_htlc_receive(const tal_t *ctx,
|
|
const struct abs_locktime *htlc_abstimeout,
|
|
const struct pubkey *localhtlckey,
|
|
const struct pubkey *remotehtlckey,
|
|
const struct sha256 *payment_hash,
|
|
const struct pubkey *revocationkey,
|
|
bool option_anchor_outputs,
|
|
bool option_anchors_zero_fee_htlc_tx)
|
|
{
|
|
struct ripemd160 ripemd;
|
|
|
|
ripemd160(&ripemd, payment_hash->u.u8, sizeof(payment_hash->u));
|
|
return bitcoin_wscript_htlc_receive_ripemd(ctx, htlc_abstimeout,
|
|
localhtlckey, remotehtlckey,
|
|
&ripemd, revocationkey,
|
|
option_anchor_outputs,
|
|
option_anchors_zero_fee_htlc_tx);
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* ## HTLC-Timeout and HTLC-Success Transactions
|
|
*
|
|
*...
|
|
* * `txin[0]` witness stack: `0 <remotehtlcsig> <localhtlcsig> <payment_preimage>` for HTLC-success, `0 <remotehtlcsig> <localhtlcsig> <>` for HTLC-timeout
|
|
*/
|
|
u8 **bitcoin_witness_htlc_timeout_tx(const tal_t *ctx,
|
|
const struct bitcoin_signature *localhtlcsig,
|
|
const struct bitcoin_signature *remotehtlcsig,
|
|
const u8 *wscript)
|
|
{
|
|
u8 **witness = tal_arr(ctx, u8 *, 5);
|
|
|
|
witness[0] = stack_number(witness, 0);
|
|
witness[1] = stack_sig(witness, remotehtlcsig);
|
|
witness[2] = stack_sig(witness, localhtlcsig);
|
|
witness[3] = stack_number(witness, 0);
|
|
witness[4] = tal_dup_talarr(witness, u8, wscript);
|
|
|
|
return witness;
|
|
}
|
|
|
|
u8 **bitcoin_witness_htlc_success_tx(const tal_t *ctx,
|
|
const struct bitcoin_signature *localhtlcsig,
|
|
const struct bitcoin_signature *remotesig,
|
|
const struct preimage *preimage,
|
|
const u8 *wscript)
|
|
{
|
|
u8 **witness = tal_arr(ctx, u8 *, 5);
|
|
|
|
witness[0] = stack_number(witness, 0);
|
|
witness[1] = stack_sig(witness, remotesig);
|
|
witness[2] = stack_sig(witness, localhtlcsig);
|
|
witness[3] = stack_preimage(witness, preimage);
|
|
witness[4] = tal_dup_talarr(witness, u8, wscript);
|
|
|
|
return witness;
|
|
}
|
|
u8 *bitcoin_wscript_htlc_tx(const tal_t *ctx,
|
|
u16 to_self_delay,
|
|
const struct pubkey *revocation_pubkey,
|
|
const struct pubkey *local_delayedkey)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* The witness script for the output is:
|
|
*
|
|
* OP_IF
|
|
* # Penalty transaction
|
|
* <revocationpubkey>
|
|
* OP_ELSE
|
|
* `to_self_delay`
|
|
* OP_CHECKSEQUENCEVERIFY
|
|
* OP_DROP
|
|
* <local_delayedpubkey>
|
|
* OP_ENDIF
|
|
* OP_CHECKSIG
|
|
*/
|
|
add_op(&script, OP_IF);
|
|
add_push_key(&script, revocation_pubkey);
|
|
add_op(&script, OP_ELSE);
|
|
add_number(&script, to_self_delay);
|
|
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
|
add_op(&script, OP_DROP);
|
|
add_push_key(&script, local_delayedkey);
|
|
add_op(&script, OP_ENDIF);
|
|
add_op(&script, OP_CHECKSIG);
|
|
|
|
return script;
|
|
}
|
|
|
|
u8 *bitcoin_wscript_anchor(const tal_t *ctx,
|
|
const struct pubkey *funding_pubkey)
|
|
{
|
|
u8 *script = tal_arr(ctx, u8, 0);
|
|
|
|
/* BOLT #3:
|
|
* #### `to_local_anchor` and `to_remote_anchor` Output (option_anchors)
|
|
*...
|
|
* <local_funding_pubkey/remote_funding_pubkey> OP_CHECKSIG OP_IFDUP
|
|
* OP_NOTIF
|
|
* OP_16 OP_CHECKSEQUENCEVERIFY
|
|
* OP_ENDIF
|
|
*/
|
|
add_push_key(&script, funding_pubkey);
|
|
add_op(&script, OP_CHECKSIG);
|
|
add_op(&script, OP_IFDUP);
|
|
add_op(&script, OP_NOTIF);
|
|
add_number(&script, 16);
|
|
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
|
add_op(&script, OP_ENDIF);
|
|
|
|
assert(is_anchor_witness_script(script, tal_bytelen(script)));
|
|
return script;
|
|
}
|
|
|
|
bool is_anchor_witness_script(const u8 *script, size_t script_len)
|
|
{
|
|
if (script_len != 34 + 1 + 1 + 1 + 1 + 1 + 1)
|
|
return false;
|
|
if (script[0] != OP_PUSHBYTES(33))
|
|
return false;
|
|
if (script[34] != OP_CHECKSIG)
|
|
return false;
|
|
if (script[35] != OP_IFDUP)
|
|
return false;
|
|
if (script[36] != OP_NOTIF)
|
|
return false;
|
|
if (script[37] != 0x50 + 16)
|
|
return false;
|
|
if (script[38] != OP_CHECKSEQUENCEVERIFY)
|
|
return false;
|
|
if (script[39] != OP_ENDIF)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool scripteq(const u8 *s1, const u8 *s2)
|
|
{
|
|
memcheck(s1, tal_count(s1));
|
|
memcheck(s2, tal_count(s2));
|
|
|
|
if (tal_count(s1) != tal_count(s2))
|
|
return false;
|
|
if (tal_count(s1) == 0)
|
|
return true;
|
|
return memcmp(s1, s2, tal_count(s1)) == 0;
|
|
}
|