mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
script: consistently take the script length in identification functions
Standardizes the is_xxx script function all take a script length, and changes their first-level callers to pass it. This has several knock on benefits: - We remove the repeated tal_count/tal_bytelen calls on the script, in particular the redundant calls that result when we must check for multiple types of script - which is almost all cases. - We remove the dependency on the memory being tal-allocated (It is, in all cases, but theres no reason we need to require that). - We remove all cases where we create a copy of the script just to id it. - We remove all allocations for non-interesting scripts while iterating block txs in process_getfilteredblock_step1(). - We remove all allocations *including for potentially interesting scripts* in topo_add_utxos(). Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
This commit is contained in:
parent
5dee5ce178
commit
aa23c2a2b2
@ -476,10 +476,8 @@ u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key)
|
|||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_p2pkh(const u8 *script, struct bitcoin_address *addr)
|
bool is_p2pkh(const u8 *script, size_t script_len, struct bitcoin_address *addr)
|
||||||
{
|
{
|
||||||
size_t script_len = tal_count(script);
|
|
||||||
|
|
||||||
if (script_len != BITCOIN_SCRIPTPUBKEY_P2PKH_LEN)
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2PKH_LEN)
|
||||||
return false;
|
return false;
|
||||||
if (script[0] != OP_DUP)
|
if (script[0] != OP_DUP)
|
||||||
@ -497,10 +495,8 @@ bool is_p2pkh(const u8 *script, struct bitcoin_address *addr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_p2sh(const u8 *script, struct ripemd160 *addr)
|
bool is_p2sh(const u8 *script, size_t script_len, struct ripemd160 *addr)
|
||||||
{
|
{
|
||||||
size_t script_len = tal_count(script);
|
|
||||||
|
|
||||||
if (script_len != BITCOIN_SCRIPTPUBKEY_P2SH_LEN)
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2SH_LEN)
|
||||||
return false;
|
return false;
|
||||||
if (script[0] != OP_HASH160)
|
if (script[0] != OP_HASH160)
|
||||||
@ -514,10 +510,8 @@ bool is_p2sh(const u8 *script, struct ripemd160 *addr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_p2wsh(const u8 *script, struct sha256 *addr)
|
bool is_p2wsh(const u8 *script, size_t script_len, struct sha256 *addr)
|
||||||
{
|
{
|
||||||
size_t script_len = tal_count(script);
|
|
||||||
|
|
||||||
if (script_len != BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)
|
||||||
return false;
|
return false;
|
||||||
if (script[0] != OP_0)
|
if (script[0] != OP_0)
|
||||||
@ -529,10 +523,8 @@ bool is_p2wsh(const u8 *script, struct sha256 *addr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr)
|
bool is_p2wpkh(const u8 *script, size_t script_len, struct bitcoin_address *addr)
|
||||||
{
|
{
|
||||||
size_t script_len = tal_count(script);
|
|
||||||
|
|
||||||
if (script_len != BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN)
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN)
|
||||||
return false;
|
return false;
|
||||||
if (script[0] != OP_0)
|
if (script[0] != OP_0)
|
||||||
@ -544,10 +536,8 @@ bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_p2tr(const u8 *script, u8 xonly_pubkey[32])
|
bool is_p2tr(const u8 *script, size_t script_len, u8 xonly_pubkey[32])
|
||||||
{
|
{
|
||||||
size_t script_len = tal_count(script);
|
|
||||||
|
|
||||||
if (script_len != BITCOIN_SCRIPTPUBKEY_P2TR_LEN)
|
if (script_len != BITCOIN_SCRIPTPUBKEY_P2TR_LEN)
|
||||||
return false;
|
return false;
|
||||||
if (script[0] != OP_1)
|
if (script[0] != OP_1)
|
||||||
@ -560,17 +550,20 @@ bool is_p2tr(const u8 *script, u8 xonly_pubkey[32])
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_known_scripttype(const u8 *script)
|
bool is_known_scripttype(const u8 *script, size_t script_len)
|
||||||
{
|
{
|
||||||
return is_p2wpkh(script, NULL) || is_p2wsh(script, NULL)
|
return is_p2wpkh(script, script_len, NULL)
|
||||||
|| is_p2sh(script, NULL) || is_p2pkh(script, NULL)
|
|| is_p2wsh(script, script_len, NULL)
|
||||||
|| is_p2tr(script, NULL);
|
|| is_p2sh(script, script_len, NULL)
|
||||||
|
|| is_p2pkh(script, script_len, NULL)
|
||||||
|
|| is_p2tr(script, script_len, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_known_segwit_scripttype(const u8 *script)
|
bool is_known_segwit_scripttype(const u8 *script, size_t script_len)
|
||||||
{
|
{
|
||||||
return is_p2wpkh(script, NULL) || is_p2wsh(script, NULL)
|
return is_p2wpkh(script, script_len, NULL)
|
||||||
|| is_p2tr(script, NULL);
|
|| is_p2wsh(script, script_len, NULL)
|
||||||
|
|| is_p2tr(script, script_len, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 **bitcoin_witness_sig_and_element(const tal_t *ctx,
|
u8 **bitcoin_witness_sig_and_element(const tal_t *ctx,
|
||||||
|
@ -159,25 +159,25 @@ u8 *bitcoin_wscript_anchor(const tal_t *ctx,
|
|||||||
const struct pubkey *funding_pubkey);
|
const struct pubkey *funding_pubkey);
|
||||||
|
|
||||||
/* Is this a pay to pubkey hash? (extract addr if not NULL) */
|
/* Is this a pay to pubkey hash? (extract addr if not NULL) */
|
||||||
bool is_p2pkh(const u8 *script, struct bitcoin_address *addr);
|
bool is_p2pkh(const u8 *script, size_t script_len, struct bitcoin_address *addr);
|
||||||
|
|
||||||
/* Is this a pay to script hash? (extract addr if not NULL) */
|
/* Is this a pay to script hash? (extract addr if not NULL) */
|
||||||
bool is_p2sh(const u8 *script, struct ripemd160 *addr);
|
bool is_p2sh(const u8 *script, size_t script_len, struct ripemd160 *addr);
|
||||||
|
|
||||||
/* Is this (version 0) pay to witness script hash? (extract addr if not NULL) */
|
/* Is this (version 0) pay to witness script hash? (extract addr if not NULL) */
|
||||||
bool is_p2wsh(const u8 *script, struct sha256 *addr);
|
bool is_p2wsh(const u8 *script, size_t script_len, struct sha256 *addr);
|
||||||
|
|
||||||
/* Is this (version 0) pay to witness pubkey hash? (extract addr if not NULL) */
|
/* Is this (version 0) pay to witness pubkey hash? (extract addr if not NULL) */
|
||||||
bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr);
|
bool is_p2wpkh(const u8 *script, size_t script_len, struct bitcoin_address *addr);
|
||||||
|
|
||||||
/* Is this a taproot output? (extract xonly_pubkey bytes if not NULL) */
|
/* Is this a taproot output? (extract xonly_pubkey bytes if not NULL) */
|
||||||
bool is_p2tr(const u8 *script, u8 xonly_pubkey[32]);
|
bool is_p2tr(const u8 *script, size_t script_len, u8 xonly_pubkey[32]);
|
||||||
|
|
||||||
/* Is this one of the above script types? */
|
/* Is this one of the above script types? */
|
||||||
bool is_known_scripttype(const u8 *script);
|
bool is_known_scripttype(const u8 *script, size_t script_len);
|
||||||
|
|
||||||
/* Is this a witness script type? */
|
/* Is this a witness script type? */
|
||||||
bool is_known_segwit_scripttype(const u8 *script);
|
bool is_known_segwit_scripttype(const u8 *script, size_t script_len);
|
||||||
|
|
||||||
/* Is this a to-remote witness script (used for option_anchor_outputs)? */
|
/* 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);
|
bool is_to_remote_anchored_witness_script(const u8 *script, size_t script_len);
|
||||||
|
@ -80,8 +80,12 @@ penalty_tx_create(const tal_t *ctx,
|
|||||||
|
|
||||||
bitcoin_tx_add_output(tx, final_scriptpubkey, NULL, to_them_sats);
|
bitcoin_tx_add_output(tx, final_scriptpubkey, NULL, to_them_sats);
|
||||||
assert((final_index == NULL) == (final_ext_key == NULL));
|
assert((final_index == NULL) == (final_ext_key == NULL));
|
||||||
if (final_index)
|
if (final_index) {
|
||||||
psbt_add_keypath_to_last_output(tx, *final_index, final_ext_key, is_p2tr(final_scriptpubkey, NULL));
|
size_t script_len = tal_bytelen(final_scriptpubkey);
|
||||||
|
bool is_tr = is_p2tr(final_scriptpubkey, script_len, NULL);
|
||||||
|
psbt_add_keypath_to_last_output(tx, *final_index,
|
||||||
|
final_ext_key, is_tr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Worst-case sig is 73 bytes */
|
/* Worst-case sig is 73 bytes */
|
||||||
weight = bitcoin_tx_weight(tx) + 1 + 3 + 73 + 0 + tal_count(wscript);
|
weight = bitcoin_tx_weight(tx) + 1 + 3 + 73 + 0 + tal_count(wscript);
|
||||||
|
@ -7,30 +7,31 @@
|
|||||||
|
|
||||||
char *encode_scriptpubkey_to_addr(const tal_t *ctx,
|
char *encode_scriptpubkey_to_addr(const tal_t *ctx,
|
||||||
const struct chainparams *chainparams,
|
const struct chainparams *chainparams,
|
||||||
const u8 *scriptPubkey)
|
const u8 *scriptpubkey)
|
||||||
{
|
{
|
||||||
char *out;
|
char *out;
|
||||||
size_t scriptLen = tal_bytelen(scriptPubkey);
|
const size_t script_len = tal_bytelen(scriptpubkey);
|
||||||
struct bitcoin_address pkh;
|
struct bitcoin_address pkh;
|
||||||
struct ripemd160 sh;
|
struct ripemd160 sh;
|
||||||
int witver;
|
int witver;
|
||||||
|
|
||||||
if (is_p2pkh(scriptPubkey, &pkh))
|
if (is_p2pkh(scriptpubkey, script_len, &pkh))
|
||||||
return bitcoin_to_base58(ctx, chainparams, &pkh);
|
return bitcoin_to_base58(ctx, chainparams, &pkh);
|
||||||
|
|
||||||
if (is_p2sh(scriptPubkey, &sh))
|
if (is_p2sh(scriptpubkey, script_len, &sh))
|
||||||
return p2sh_to_base58(ctx, chainparams, &sh);
|
return p2sh_to_base58(ctx, chainparams, &sh);
|
||||||
|
|
||||||
out = tal_arr(ctx, char, 73 + strlen(chainparams->onchain_hrp));
|
out = tal_arr(ctx, char, 73 + strlen(chainparams->onchain_hrp));
|
||||||
if (is_p2tr(scriptPubkey, NULL))
|
if (is_p2tr(scriptpubkey, script_len, NULL))
|
||||||
witver = 1;
|
witver = 1;
|
||||||
else if (is_p2wpkh(scriptPubkey, NULL) || is_p2wsh(scriptPubkey, NULL))
|
else if (is_p2wpkh(scriptpubkey, script_len, NULL)
|
||||||
|
|| is_p2wsh(scriptpubkey, script_len, NULL))
|
||||||
witver = 0;
|
witver = 0;
|
||||||
else {
|
else {
|
||||||
return tal_free(out);
|
return tal_free(out);
|
||||||
}
|
}
|
||||||
if (!segwit_addr_encode(out, chainparams->onchain_hrp, witver,
|
if (!segwit_addr_encode(out, chainparams->onchain_hrp, witver,
|
||||||
scriptPubkey + 2, scriptLen - 2))
|
scriptpubkey + 2, script_len - 2))
|
||||||
return tal_free(out);
|
return tal_free(out);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
/* Given a scriptPubkey, return an encoded address for p2pkh/p2w{pkh,sh}/p2tr */
|
/* Given a scriptPubkey, return an encoded address for p2pkh/p2w{pkh,sh}/p2tr */
|
||||||
char *encode_scriptpubkey_to_addr(const tal_t *ctx,
|
char *encode_scriptpubkey_to_addr(const tal_t *ctx,
|
||||||
const struct chainparams *chainparams,
|
const struct chainparams *chainparams,
|
||||||
const u8 *scriptPubkey);
|
const u8 *scriptpubkey);
|
||||||
|
|
||||||
#endif /* LIGHTNING_COMMON_ADDR_H */
|
#endif /* LIGHTNING_COMMON_ADDR_H */
|
||||||
|
@ -1133,6 +1133,7 @@ static void encode_f(u5 **data, const u8 *fallback)
|
|||||||
struct bitcoin_address pkh;
|
struct bitcoin_address pkh;
|
||||||
struct ripemd160 sh;
|
struct ripemd160 sh;
|
||||||
struct sha256 wsh;
|
struct sha256 wsh;
|
||||||
|
const size_t fallback_len = tal_bytelen(fallback);
|
||||||
|
|
||||||
/* BOLT #11:
|
/* BOLT #11:
|
||||||
*
|
*
|
||||||
@ -1140,15 +1141,15 @@ static void encode_f(u5 **data, const u8 *fallback)
|
|||||||
* witness version and program, OR to `17` followed by a
|
* witness version and program, OR to `17` followed by a
|
||||||
* public key hash, OR to `18` followed by a script hash.
|
* public key hash, OR to `18` followed by a script hash.
|
||||||
*/
|
*/
|
||||||
if (is_p2pkh(fallback, &pkh)) {
|
if (is_p2pkh(fallback, fallback_len, &pkh)) {
|
||||||
push_fallback_addr(data, 17, &pkh, sizeof(pkh));
|
push_fallback_addr(data, 17, &pkh, sizeof(pkh));
|
||||||
} else if (is_p2sh(fallback, &sh)) {
|
} else if (is_p2sh(fallback, fallback_len, &sh)) {
|
||||||
push_fallback_addr(data, 18, &sh, sizeof(sh));
|
push_fallback_addr(data, 18, &sh, sizeof(sh));
|
||||||
} else if (is_p2wpkh(fallback, &pkh)) {
|
} else if (is_p2wpkh(fallback, fallback_len, &pkh)) {
|
||||||
push_fallback_addr(data, 0, &pkh, sizeof(pkh));
|
push_fallback_addr(data, 0, &pkh, sizeof(pkh));
|
||||||
} else if (is_p2wsh(fallback, &wsh)) {
|
} else if (is_p2wsh(fallback, fallback_len, &wsh)) {
|
||||||
push_fallback_addr(data, 0, &wsh, sizeof(wsh));
|
push_fallback_addr(data, 0, &wsh, sizeof(wsh));
|
||||||
} else if (tal_count(fallback) > 1
|
} else if (fallback_len > 1
|
||||||
&& fallback[0] >= 0x50
|
&& fallback[0] >= 0x50
|
||||||
&& fallback[0] < (0x50+16)) {
|
&& fallback[0] < (0x50+16)) {
|
||||||
/* Other (future) witness versions: turn OP_N into N */
|
/* Other (future) witness versions: turn OP_N into N */
|
||||||
@ -1157,7 +1158,7 @@ static void encode_f(u5 **data, const u8 *fallback)
|
|||||||
} else {
|
} else {
|
||||||
/* Copy raw. */
|
/* Copy raw. */
|
||||||
push_field(data, 'f',
|
push_field(data, 'f',
|
||||||
fallback, tal_count(fallback) * CHAR_BIT);
|
fallback, fallback_len * CHAR_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,17 +15,18 @@ static void json_add_fallback(struct json_stream *response,
|
|||||||
const struct chainparams *chain)
|
const struct chainparams *chain)
|
||||||
{
|
{
|
||||||
char *addr;
|
char *addr;
|
||||||
|
const size_t fallback_len = tal_bytelen(fallback);
|
||||||
|
|
||||||
json_object_start(response, fieldname);
|
json_object_start(response, fieldname);
|
||||||
if (is_p2pkh(fallback, NULL)) {
|
if (is_p2pkh(fallback, fallback_len, NULL)) {
|
||||||
json_add_string(response, "type", "P2PKH");
|
json_add_string(response, "type", "P2PKH");
|
||||||
} else if (is_p2sh(fallback, NULL)) {
|
} else if (is_p2sh(fallback, fallback_len, NULL)) {
|
||||||
json_add_string(response, "type", "P2SH");
|
json_add_string(response, "type", "P2SH");
|
||||||
} else if (is_p2wpkh(fallback, NULL)) {
|
} else if (is_p2wpkh(fallback, fallback_len, NULL)) {
|
||||||
json_add_string(response, "type", "P2WPKH");
|
json_add_string(response, "type", "P2WPKH");
|
||||||
} else if (is_p2wsh(fallback, NULL)) {
|
} else if (is_p2wsh(fallback, fallback_len, NULL)) {
|
||||||
json_add_string(response, "type", "P2WSH");
|
json_add_string(response, "type", "P2WSH");
|
||||||
} else if (is_p2tr(fallback, NULL)) {
|
} else if (is_p2tr(fallback, fallback_len, NULL)) {
|
||||||
json_add_string(response, "type", "P2TR");
|
json_add_string(response, "type", "P2TR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,9 +50,12 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
|
|||||||
/* One output is to us. */
|
/* One output is to us. */
|
||||||
bitcoin_tx_add_output(tx, script, NULL, to_us);
|
bitcoin_tx_add_output(tx, script, NULL, to_us);
|
||||||
assert((local_wallet_index == NULL) == (local_wallet_ext_key == NULL));
|
assert((local_wallet_index == NULL) == (local_wallet_ext_key == NULL));
|
||||||
if (local_wallet_index)
|
if (local_wallet_index) {
|
||||||
|
size_t script_len = tal_bytelen(script);
|
||||||
psbt_add_keypath_to_last_output(
|
psbt_add_keypath_to_last_output(
|
||||||
tx, *local_wallet_index, local_wallet_ext_key, is_p2tr(script, NULL));
|
tx, *local_wallet_index, local_wallet_ext_key,
|
||||||
|
is_p2tr(script, script_len, NULL));
|
||||||
|
}
|
||||||
num_outputs++;
|
num_outputs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,13 +80,15 @@ static bool is_segwit_output(const tal_t *ctx,
|
|||||||
struct wally_tx_output *output,
|
struct wally_tx_output *output,
|
||||||
const u8 *redeemscript)
|
const u8 *redeemscript)
|
||||||
{
|
{
|
||||||
const u8 *maybe_witness;
|
const u8 *maybe_witness = redeemscript;
|
||||||
if (tal_bytelen(redeemscript) > 0)
|
size_t script_len = tal_bytelen(maybe_witness);
|
||||||
maybe_witness = redeemscript;
|
|
||||||
else
|
|
||||||
maybe_witness = cln_wally_tx_output_get_script(ctx, output);
|
|
||||||
|
|
||||||
return is_known_segwit_scripttype(maybe_witness);
|
if (!script_len) {
|
||||||
|
maybe_witness = output->script;
|
||||||
|
script_len = output->script_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_known_segwit_scripttype(maybe_witness, script_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return first non-handled message or NULL if connection is aborted */
|
/* Return first non-handled message or NULL if connection is aborted */
|
||||||
@ -627,7 +629,7 @@ char *process_interactivetx_updates(const tal_t *ctx,
|
|||||||
* The receiving node: ...
|
* The receiving node: ...
|
||||||
* - MAY fail the negotiation if `script`
|
* - MAY fail the negotiation if `script`
|
||||||
* is non-standard */
|
* is non-standard */
|
||||||
if (!is_known_scripttype(scriptpubkey))
|
if (!is_known_scripttype(scriptpubkey, tal_bytelen(scriptpubkey)))
|
||||||
return tal_fmt(ctx, "Script is not standard");
|
return tal_fmt(ctx, "Script is not standard");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -382,6 +382,7 @@ bool psbt_has_required_fields(struct wally_psbt *psbt)
|
|||||||
u64 serial_id;
|
u64 serial_id;
|
||||||
for (size_t i = 0; i < psbt->num_inputs; i++) {
|
for (size_t i = 0; i < psbt->num_inputs; i++) {
|
||||||
const struct wally_map_item *redeem_script;
|
const struct wally_map_item *redeem_script;
|
||||||
|
const struct wally_tx_output *txout;
|
||||||
struct wally_psbt_input *input = &psbt->inputs[i];
|
struct wally_psbt_input *input = &psbt->inputs[i];
|
||||||
|
|
||||||
if (!psbt_get_serial_id(&input->unknowns, &serial_id))
|
if (!psbt_get_serial_id(&input->unknowns, &serial_id))
|
||||||
@ -391,13 +392,14 @@ bool psbt_has_required_fields(struct wally_psbt *psbt)
|
|||||||
if (!input->utxo)
|
if (!input->utxo)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* If is P2SH, redeemscript must be present */
|
assert(input->index < input->utxo->num_outputs);
|
||||||
assert(psbt->inputs[i].index < input->utxo->num_outputs);
|
txout = &input->utxo->outputs[input->index];
|
||||||
const u8 *outscript =
|
if (!is_p2sh(txout->script, txout->script_len, NULL))
|
||||||
cln_wally_tx_output_get_script(tmpctx,
|
continue;
|
||||||
&input->utxo->outputs[psbt->inputs[i].index]);
|
/* P2SH: redeemscript must be present */
|
||||||
redeem_script = wally_map_get_integer(&psbt->inputs[i].psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04);
|
const u32 key = 0x04; /* PSBT_IN_REDEEM_SCRIPT */
|
||||||
if (is_p2sh(outscript, NULL) && (!redeem_script || redeem_script->value_len == 0))
|
redeem_script = wally_map_get_integer(&input->psbt_fields, key);
|
||||||
|
if (!redeem_script || !redeem_script->value_len)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
* push of 2 to 40 bytes
|
* push of 2 to 40 bytes
|
||||||
* (witness program versions 1 through 16)
|
* (witness program versions 1 through 16)
|
||||||
*/
|
*/
|
||||||
static bool is_valid_witnessprog(const u8 *scriptpubkey)
|
static bool is_valid_witnessprog(const u8 *scriptpubkey, size_t scriptpubkey_len)
|
||||||
{
|
{
|
||||||
size_t pushlen;
|
size_t pushlen;
|
||||||
|
|
||||||
if (tal_bytelen(scriptpubkey) < 2)
|
if (scriptpubkey_len < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (scriptpubkey[0]) {
|
switch (scriptpubkey[0]) {
|
||||||
@ -39,7 +39,7 @@ static bool is_valid_witnessprog(const u8 *scriptpubkey)
|
|||||||
|
|
||||||
pushlen = scriptpubkey[1];
|
pushlen = scriptpubkey[1];
|
||||||
/* Must be all of the rest of scriptpubkey */
|
/* Must be all of the rest of scriptpubkey */
|
||||||
if (2 + pushlen != tal_bytelen(scriptpubkey)) {
|
if (2 + pushlen != scriptpubkey_len) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,13 +50,14 @@ bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey,
|
|||||||
bool anysegwit,
|
bool anysegwit,
|
||||||
bool allow_oldstyle)
|
bool allow_oldstyle)
|
||||||
{
|
{
|
||||||
|
const size_t script_len = tal_bytelen(scriptpubkey);
|
||||||
if (allow_oldstyle) {
|
if (allow_oldstyle) {
|
||||||
if (is_p2pkh(scriptpubkey, NULL)
|
if (is_p2pkh(scriptpubkey, script_len, NULL)
|
||||||
|| is_p2sh(scriptpubkey, NULL))
|
|| is_p2sh(scriptpubkey, script_len, NULL))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_p2wpkh(scriptpubkey, NULL)
|
return is_p2wpkh(scriptpubkey, script_len, NULL)
|
||||||
|| is_p2wsh(scriptpubkey, NULL)
|
|| is_p2wsh(scriptpubkey, script_len, NULL)
|
||||||
|| (anysegwit && is_valid_witnessprog(scriptpubkey));
|
|| (anysegwit && is_valid_witnessprog(scriptpubkey, script_len));
|
||||||
}
|
}
|
||||||
|
@ -123,23 +123,25 @@ int main(int argc, char *argv[])
|
|||||||
struct bitcoin_address pkh;
|
struct bitcoin_address pkh;
|
||||||
struct ripemd160 sh;
|
struct ripemd160 sh;
|
||||||
struct sha256 wsh;
|
struct sha256 wsh;
|
||||||
|
const u8 *fallback = b11->fallbacks[i];
|
||||||
|
const size_t fallback_len = tal_bytelen(fallback);
|
||||||
|
|
||||||
printf("fallback: %s\n", tal_hex(ctx, b11->fallbacks[i]));
|
printf("fallback: %s\n", tal_hex(ctx, fallback));
|
||||||
if (is_p2pkh(b11->fallbacks[i], &pkh)) {
|
if (is_p2pkh(fallback, fallback_len, &pkh)) {
|
||||||
printf("fallback-P2PKH: %s\n",
|
printf("fallback-P2PKH: %s\n",
|
||||||
bitcoin_to_base58(ctx, b11->chain,
|
bitcoin_to_base58(ctx, b11->chain,
|
||||||
&pkh));
|
&pkh));
|
||||||
} else if (is_p2sh(b11->fallbacks[i], &sh)) {
|
} else if (is_p2sh(fallback, fallback_len, &sh)) {
|
||||||
printf("fallback-P2SH: %s\n",
|
printf("fallback-P2SH: %s\n",
|
||||||
p2sh_to_base58(ctx,
|
p2sh_to_base58(ctx,
|
||||||
b11->chain,
|
b11->chain,
|
||||||
&sh));
|
&sh));
|
||||||
} else if (is_p2wpkh(b11->fallbacks[i], &pkh)) {
|
} else if (is_p2wpkh(fallback, fallback_len, &pkh)) {
|
||||||
char out[73 + strlen(b11->chain->onchain_hrp)];
|
char out[73 + strlen(b11->chain->onchain_hrp)];
|
||||||
if (segwit_addr_encode(out, b11->chain->onchain_hrp, 0,
|
if (segwit_addr_encode(out, b11->chain->onchain_hrp, 0,
|
||||||
(const u8 *)&pkh, sizeof(pkh)))
|
(const u8 *)&pkh, sizeof(pkh)))
|
||||||
printf("fallback-P2WPKH: %s\n", out);
|
printf("fallback-P2WPKH: %s\n", out);
|
||||||
} else if (is_p2wsh(b11->fallbacks[i], &wsh)) {
|
} else if (is_p2wsh(fallback, fallback_len, &wsh)) {
|
||||||
char out[73 + strlen(b11->chain->onchain_hrp)];
|
char out[73 + strlen(b11->chain->onchain_hrp)];
|
||||||
if (segwit_addr_encode(out, b11->chain->onchain_hrp, 0,
|
if (segwit_addr_encode(out, b11->chain->onchain_hrp, 0,
|
||||||
(const u8 *)&wsh, sizeof(wsh)))
|
(const u8 *)&wsh, sizeof(wsh)))
|
||||||
|
@ -547,7 +547,9 @@ static void sign_our_inputs(struct utxo **utxos, struct wally_psbt *psbt)
|
|||||||
* requires the HSM to find the pubkey, and we
|
* requires the HSM to find the pubkey, and we
|
||||||
* skip doing that until now as a bit of a reduction
|
* skip doing that until now as a bit of a reduction
|
||||||
* of complexity in the calling code */
|
* of complexity in the calling code */
|
||||||
psbt_input_add_pubkey(psbt, j, &pubkey, utxo->scriptPubkey && is_p2tr(utxo->scriptPubkey, NULL));
|
const size_t script_len = tal_bytelen(utxo->scriptPubkey);
|
||||||
|
psbt_input_add_pubkey(psbt, j, &pubkey,
|
||||||
|
is_p2tr(utxo->scriptPubkey, script_len, NULL));
|
||||||
|
|
||||||
/* It's actually a P2WSH in this case. */
|
/* It's actually a P2WSH in this case. */
|
||||||
if (utxo->close_info && utxo->close_info->option_anchors) {
|
if (utxo->close_info && utxo->close_info->option_anchors) {
|
||||||
|
@ -756,19 +756,22 @@ static void process_getfilteredblock_step1(struct bitcoind *bitcoind,
|
|||||||
for (size_t i = 0; i < tal_count(block->tx); i++) {
|
for (size_t i = 0; i < tal_count(block->tx); i++) {
|
||||||
tx = block->tx[i];
|
tx = block->tx[i];
|
||||||
for (size_t j = 0; j < tx->wtx->num_outputs; j++) {
|
for (size_t j = 0; j < tx->wtx->num_outputs; j++) {
|
||||||
const u8 *script = bitcoin_tx_output_get_script(NULL, tx, j);
|
const struct wally_tx_output *output;
|
||||||
struct amount_asset amount = bitcoin_tx_output_get_amount(tx, j);
|
output = &tx->wtx->outputs[j];
|
||||||
if (amount_asset_is_main(&amount) && is_p2wsh(script, NULL)) {
|
|
||||||
|
if (!is_p2wsh(output->script, output->script_len, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct amount_asset amount = wally_tx_output_get_amount(output);
|
||||||
|
if (amount_asset_is_main(&amount)) {
|
||||||
/* This is an interesting output, remember it. */
|
/* This is an interesting output, remember it. */
|
||||||
o = tal(call->outpoints, struct filteredblock_outpoint);
|
o = tal(call->outpoints, struct filteredblock_outpoint);
|
||||||
bitcoin_txid(tx, &o->outpoint.txid);
|
bitcoin_txid(tx, &o->outpoint.txid);
|
||||||
o->outpoint.n = j;
|
o->outpoint.n = j;
|
||||||
o->amount = amount_asset_to_sat(&amount);
|
o->amount = amount_asset_to_sat(&amount);
|
||||||
o->txindex = i;
|
o->txindex = i;
|
||||||
o->scriptPubKey = tal_steal(o, script);
|
o->scriptPubKey = tal_dup_arr(o, u8, output->script, output->script_len, 0);
|
||||||
tal_arr_expand(&call->outpoints, o);
|
tal_arr_expand(&call->outpoints, o);
|
||||||
} else {
|
|
||||||
tal_free(script);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -956,22 +956,21 @@ static void topo_add_utxos(struct chain_topology *topo, struct block *b)
|
|||||||
for (size_t i = 0; i < num_txs; i++) {
|
for (size_t i = 0; i < num_txs; i++) {
|
||||||
const struct bitcoin_tx *tx = b->full_txs[i];
|
const struct bitcoin_tx *tx = b->full_txs[i];
|
||||||
for (size_t n = 0; n < tx->wtx->num_outputs; n++) {
|
for (size_t n = 0; n < tx->wtx->num_outputs; n++) {
|
||||||
if (tx->wtx->outputs[n].features & skip_features)
|
const struct wally_tx_output *output;
|
||||||
|
output = &tx->wtx->outputs[n];
|
||||||
|
if (output->features & skip_features)
|
||||||
continue;
|
continue;
|
||||||
if (tx->wtx->outputs[n].script_len != BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)
|
if (!is_p2wsh(output->script, output->script_len, NULL))
|
||||||
continue; /* Cannot possibly be a p2wsh utxo */
|
continue; /* We only care about p2wsh utxos */
|
||||||
|
|
||||||
struct amount_asset amt = bitcoin_tx_output_get_amount(tx, n);
|
struct amount_asset amt = bitcoin_tx_output_get_amount(tx, n);
|
||||||
if (!amount_asset_is_main(&amt))
|
if (!amount_asset_is_main(&amt))
|
||||||
continue; /* Ignore non-policy asset outputs */
|
continue; /* Ignore non-policy asset outputs */
|
||||||
|
|
||||||
const u8 *script = bitcoin_tx_output_get_script(tmpctx, tx, n);
|
|
||||||
if (!is_p2wsh(script, NULL))
|
|
||||||
continue; /* We only care about p2wsh utxos */
|
|
||||||
|
|
||||||
struct bitcoin_outpoint outpoint = { b->txids[i], n };
|
struct bitcoin_outpoint outpoint = { b->txids[i], n };
|
||||||
wallet_utxoset_add(topo->ld->wallet, &outpoint,
|
wallet_utxoset_add(topo->ld->wallet, &outpoint,
|
||||||
b->height, i, script,
|
b->height, i,
|
||||||
|
output->script, output->script_len,
|
||||||
amount_asset_to_sat(&amt));
|
amount_asset_to_sat(&amt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2050,10 +2050,9 @@ static const size_t *match_htlc_output(const tal_t *ctx,
|
|||||||
u8 **htlc_scripts)
|
u8 **htlc_scripts)
|
||||||
{
|
{
|
||||||
size_t *matches = tal_arr(ctx, size_t, 0);
|
size_t *matches = tal_arr(ctx, size_t, 0);
|
||||||
const u8 *script = tal_dup_arr(tmpctx, u8, out->script, out->script_len,
|
|
||||||
0);
|
|
||||||
/* Must be a p2wsh output */
|
/* Must be a p2wsh output */
|
||||||
if (!is_p2wsh(script, NULL))
|
if (!is_p2wsh(out->script, out->script_len, NULL))
|
||||||
return matches;
|
return matches;
|
||||||
|
|
||||||
for (size_t i = 0; i < tal_count(htlc_scripts); i++) {
|
for (size_t i = 0; i < tal_count(htlc_scripts); i++) {
|
||||||
@ -2062,7 +2061,7 @@ static const size_t *match_htlc_output(const tal_t *ctx,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
sha256(&sha, htlc_scripts[i], tal_count(htlc_scripts[i]));
|
sha256(&sha, htlc_scripts[i], tal_count(htlc_scripts[i]));
|
||||||
if (memeq(script + 2, tal_count(script) - 2, &sha, sizeof(sha)))
|
if (memeq(out->script + 2, out->script_len - 2, &sha, sizeof(sha)))
|
||||||
tal_arr_expand(&matches, i);
|
tal_arr_expand(&matches, i);
|
||||||
}
|
}
|
||||||
return matches;
|
return matches;
|
||||||
|
@ -993,8 +993,7 @@ static char *check_balances(const tal_t *ctx,
|
|||||||
|
|
||||||
static bool is_segwit_output(struct wally_tx_output *output)
|
static bool is_segwit_output(struct wally_tx_output *output)
|
||||||
{
|
{
|
||||||
const u8 *script = cln_wally_tx_output_get_script(tmpctx, output);
|
return is_known_segwit_scripttype(output->script, output->script_len);
|
||||||
return is_known_segwit_scripttype(script);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_remote_upfront_shutdown(struct state *state,
|
static void set_remote_upfront_shutdown(struct state *state,
|
||||||
@ -1973,7 +1972,7 @@ static bool run_tx_interactive(struct state *state,
|
|||||||
* The receiving node: ...
|
* The receiving node: ...
|
||||||
* - MAY fail the negotiation if `script`
|
* - MAY fail the negotiation if `script`
|
||||||
* is non-standard */
|
* is non-standard */
|
||||||
if (!is_known_scripttype(scriptpubkey)) {
|
if (!is_known_scripttype(scriptpubkey, tal_bytelen(scriptpubkey))) {
|
||||||
open_abort(state, "Script is not standard");
|
open_abort(state, "Script is not standard");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -799,14 +799,15 @@ bool wallet_can_spend(struct wallet *w, const u8 *script,
|
|||||||
{
|
{
|
||||||
struct ext_key ext;
|
struct ext_key ext;
|
||||||
u64 bip32_max_index = db_get_intvar(w->db, "bip32_max_index", 0);
|
u64 bip32_max_index = db_get_intvar(w->db, "bip32_max_index", 0);
|
||||||
|
size_t script_len = tal_bytelen(script);
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
/* If not one of these, can't be for us. */
|
/* If not one of these, can't be for us. */
|
||||||
if (is_p2sh(script, NULL))
|
if (is_p2sh(script, script_len, NULL))
|
||||||
*output_is_p2sh = true;
|
*output_is_p2sh = true;
|
||||||
else if (is_p2wpkh(script, NULL))
|
else if (is_p2wpkh(script, script_len, NULL))
|
||||||
*output_is_p2sh = false;
|
*output_is_p2sh = false;
|
||||||
else if (is_p2tr(script, NULL))
|
else if (is_p2tr(script, script_len, NULL))
|
||||||
*output_is_p2sh = false;
|
*output_is_p2sh = false;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -4353,8 +4354,8 @@ bool wallet_outpoint_spend(struct wallet *w, const tal_t *ctx, const u32 blockhe
|
|||||||
|
|
||||||
void wallet_utxoset_add(struct wallet *w,
|
void wallet_utxoset_add(struct wallet *w,
|
||||||
const struct bitcoin_outpoint *outpoint,
|
const struct bitcoin_outpoint *outpoint,
|
||||||
const u32 blockheight,
|
const u32 blockheight, const u32 txindex,
|
||||||
const u32 txindex, const u8 *scriptpubkey,
|
const u8 *scriptpubkey, size_t scriptpubkey_len,
|
||||||
struct amount_sat sat)
|
struct amount_sat sat)
|
||||||
{
|
{
|
||||||
struct db_stmt *stmt;
|
struct db_stmt *stmt;
|
||||||
@ -4373,7 +4374,7 @@ void wallet_utxoset_add(struct wallet *w,
|
|||||||
db_bind_int(stmt, blockheight);
|
db_bind_int(stmt, blockheight);
|
||||||
db_bind_null(stmt);
|
db_bind_null(stmt);
|
||||||
db_bind_int(stmt, txindex);
|
db_bind_int(stmt, txindex);
|
||||||
db_bind_talarr(stmt, scriptpubkey);
|
db_bind_blob(stmt, scriptpubkey, scriptpubkey_len);
|
||||||
db_bind_amount_sat(stmt, &sat);
|
db_bind_amount_sat(stmt, &sat);
|
||||||
db_exec_prepared_v2(take(stmt));
|
db_exec_prepared_v2(take(stmt));
|
||||||
|
|
||||||
|
@ -1146,8 +1146,8 @@ struct outpoint *wallet_outpoint_for_scid(struct wallet *w, tal_t *ctx,
|
|||||||
|
|
||||||
void wallet_utxoset_add(struct wallet *w,
|
void wallet_utxoset_add(struct wallet *w,
|
||||||
const struct bitcoin_outpoint *outpoint,
|
const struct bitcoin_outpoint *outpoint,
|
||||||
const u32 blockheight,
|
const u32 blockheight, const u32 txindex,
|
||||||
const u32 txindex, const u8 *scriptpubkey,
|
const u8 *scriptpubkey, size_t scriptpubkey_len,
|
||||||
struct amount_sat sat);
|
struct amount_sat sat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -660,14 +660,13 @@ static void match_psbt_outputs_to_wallet(struct wally_psbt *psbt,
|
|||||||
{
|
{
|
||||||
tal_wally_start();
|
tal_wally_start();
|
||||||
for (size_t outndx = 0; outndx < psbt->num_outputs; ++outndx) {
|
for (size_t outndx = 0; outndx < psbt->num_outputs; ++outndx) {
|
||||||
|
struct ext_key ext;
|
||||||
|
const u8 *script = psbt->outputs[outndx].script;
|
||||||
|
const size_t script_len = psbt->outputs[outndx].script_len;
|
||||||
u32 index;
|
u32 index;
|
||||||
bool is_p2sh;
|
bool is_p2sh;
|
||||||
const u8 *script;
|
|
||||||
struct ext_key ext;
|
|
||||||
|
|
||||||
script = wally_psbt_output_get_script(tmpctx,
|
if (!script_len)
|
||||||
&psbt->outputs[outndx]);
|
|
||||||
if (!script)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!wallet_can_spend(w, script, &index, &is_p2sh))
|
if (!wallet_can_spend(w, script, &index, &is_p2sh))
|
||||||
@ -678,7 +677,8 @@ static void match_psbt_outputs_to_wallet(struct wally_psbt *psbt,
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
psbt_output_set_keypath(index, &ext, is_p2tr(script, NULL),
|
psbt_output_set_keypath(index, &ext,
|
||||||
|
is_p2tr(script, script_len, NULL),
|
||||||
&psbt->outputs[outndx]);
|
&psbt->outputs[outndx]);
|
||||||
}
|
}
|
||||||
tal_wally_end(psbt);
|
tal_wally_end(psbt);
|
||||||
|
Loading…
Reference in New Issue
Block a user