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:
Jon Griffiths 2024-02-22 10:03:07 +13:00 committed by Rusty Russell
parent 5dee5ce178
commit aa23c2a2b2
20 changed files with 128 additions and 115 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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);
} }
} }

View File

@ -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");
} }

View File

@ -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++;
} }

View File

@ -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");
/* /*

View File

@ -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;
} }

View File

@ -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));
} }

View File

@ -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)))

View File

@ -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) {

View File

@ -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);
} }
} }
} }

View File

@ -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));
} }
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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));

View File

@ -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);
/** /**

View File

@ -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);