Skip to content

Commit 28192e3

Browse files
committed
common/utxo: use a real type for the UTXO, not a boolean.
To actually evaluate spend cost, we need to know whether it's taproot or not. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 260149c commit 28192e3

File tree

8 files changed

+78
-21
lines changed

8 files changed

+78
-21
lines changed

common/utxo.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void towire_utxo(u8 **pptr, const struct utxo *utxo)
1010
towire_bitcoin_outpoint(pptr, &utxo->outpoint);
1111
towire_amount_sat(pptr, utxo->amount);
1212
towire_u32(pptr, utxo->keyindex);
13-
towire_bool(pptr, utxo->is_p2sh);
13+
towire_u32(pptr, utxo->utxotype);
1414

1515
towire_u16(pptr, tal_count(utxo->scriptPubkey));
1616
towire_u8_array(pptr, utxo->scriptPubkey, tal_count(utxo->scriptPubkey));
@@ -36,7 +36,7 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max)
3636
fromwire_bitcoin_outpoint(ptr, max, &utxo->outpoint);
3737
utxo->amount = fromwire_amount_sat(ptr, max);
3838
utxo->keyindex = fromwire_u32(ptr, max);
39-
utxo->is_p2sh = fromwire_bool(ptr, max);
39+
utxo->utxotype = fromwire_u32(ptr, max);
4040

4141
utxo->scriptPubkey = fromwire_tal_arrn(utxo, ptr, max, fromwire_u16(ptr, max));
4242

@@ -68,10 +68,10 @@ size_t utxo_spend_weight(const struct utxo *utxo, size_t min_witness_weight)
6868
/* If the min is less than what we'd use for a 'normal' tx,
6969
* we return the value with the greater added/calculated */
7070
if (wit_weight < min_witness_weight)
71-
return bitcoin_tx_input_weight(utxo->is_p2sh,
71+
return bitcoin_tx_input_weight(utxo->utxotype == UTXO_P2SH_P2WPKH,
7272
min_witness_weight);
7373

74-
return bitcoin_tx_input_weight(utxo->is_p2sh, wit_weight);
74+
return bitcoin_tx_input_weight(utxo->utxotype == UTXO_P2SH_P2WPKH, wit_weight);
7575
}
7676

7777
u32 utxo_is_immature(const struct utxo *utxo, u32 blockheight)
@@ -91,3 +91,18 @@ u32 utxo_is_immature(const struct utxo *utxo, u32 blockheight)
9191
return 0;
9292
}
9393
}
94+
95+
const char *utxotype_to_str(enum utxotype utxotype)
96+
{
97+
switch (utxotype) {
98+
case UTXO_P2SH_P2WPKH:
99+
return "p2sh_p2wpkh";
100+
case UTXO_P2WPKH:
101+
return "p2wpkh";
102+
case UTXO_P2WSH_FROM_CLOSE:
103+
return "p2wsh_from_close";
104+
case UTXO_P2TR:
105+
return "p2tr";
106+
}
107+
abort();
108+
}

common/utxo.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,24 @@ enum output_status {
3131
OUTPUT_STATE_ANY = 255
3232
};
3333

34+
enum utxotype {
35+
/* Obsolete: we used to have P2SH-wrapped outputs (removed in 24.02, though can still have old UTXOs) */
36+
UTXO_P2SH_P2WPKH = 1,
37+
/* "bech32" addresses */
38+
UTXO_P2WPKH = 2,
39+
/* Used for closing addresses: implies ->close_info is non-NULL */
40+
UTXO_P2WSH_FROM_CLOSE = 3,
41+
/* "p2tr" addresses. */
42+
UTXO_P2TR = 4,
43+
};
44+
45+
const char *utxotype_to_str(enum utxotype utxotype);
46+
3447
struct utxo {
3548
struct bitcoin_outpoint outpoint;
3649
struct amount_sat amount;
3750
u32 keyindex;
38-
bool is_p2sh;
51+
enum utxotype utxotype;
3952
enum output_status status;
4053

4154
/* Optional unilateral close information, NULL if this is just

devtools/mkfunding.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static struct bitcoin_tx *tx_spending_utxo(const tal_t *ctx,
4242
struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams, 1, num_output,
4343
nlocktime);
4444

45-
assert(!utxo->is_p2sh);
45+
assert(utxo->utxotype != UTXO_P2SH_P2WPKH);
4646
bitcoin_tx_add_input(tx, &utxo->outpoint,
4747
nsequence, NULL, utxo->amount,
4848
utxo->scriptPubkey, NULL);
@@ -95,7 +95,7 @@ int main(int argc, char *argv[])
9595
if (argc != 1 + 7)
9696
errx(1, "Usage: mkfunding <input-txid> <input-txout> <input-amount> <feerate-per-kw> <input-privkey> <local-funding-privkey> <remote-funding-privkey>");
9797

98-
input.is_p2sh = false;
98+
input.utxotype = UTXO_P2WPKH;
9999
input.close_info = NULL;
100100

101101
argnum = 1;

tests/test_closing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ def test_closing_simple(node_factory, bitcoind, chainparams):
7575
]
7676
bitcoind.generate_block(1)
7777

78-
l1.daemon.wait_for_log(r'Owning output.* \(SEGWIT\).* txid %s.* CONFIRMED' % closetxid)
79-
l2.daemon.wait_for_log(r'Owning output.* \(SEGWIT\).* txid %s.* CONFIRMED' % closetxid)
78+
l1.daemon.wait_for_log(r'Owning output.* \(p2tr\).* txid %s.* CONFIRMED' % closetxid)
79+
l2.daemon.wait_for_log(r'Owning output.* \(p2tr\).* txid %s.* CONFIRMED' % closetxid)
8080

8181
# Make sure both nodes have grabbed their close tx funds
8282
assert closetxid in set([o['txid'] for o in l1.rpc.listfunds()['outputs']])
@@ -334,11 +334,11 @@ def test_closing_specified_destination(node_factory, bitcoind, chainparams):
334334

335335
# l1 can't spent the output to addr.
336336
for txid in closetxs.values():
337-
assert not l1.daemon.is_in_log(r'Owning output.* \(SEGWIT\).* txid {}.* CONFIRMED'.format(txid))
337+
assert not l1.daemon.is_in_log(r'Owning output.* \(p2tr\).* txid {}.* CONFIRMED'.format(txid))
338338

339339
# Check the txid has at least 1 confirmation
340340
for n, txid in closetxs.items():
341-
n.daemon.wait_for_log(r'Owning output.* \(SEGWIT\).* txid {}.* CONFIRMED'.format(txid))
341+
n.daemon.wait_for_log(r'Owning output.* \(p2tr\).* txid {}.* CONFIRMED'.format(txid))
342342

343343
for n in [l2, l3, l4]:
344344
# Make sure both nodes have grabbed their close tx funds

tests/test_misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ def test_htlc_sig_persistence(node_factory, bitcoind, executor):
399399
bitcoind.generate_block(5)
400400
bitcoind.generate_block(1, wait_for_mempool=txid)
401401
l1.daemon.wait_for_logs([
402-
r'Owning output . (\d+)sat .SEGWIT. txid',
402+
rf'Owning output . (\d+)sat \(p2tr\) txid {txid} CONFIRMED',
403403
])
404404

405405
# We should now have 1) the unilateral to us, and b) the HTLC respend to us

wallet/reservation.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ struct wally_psbt *psbt_using_utxos(const tal_t *ctx,
277277
u32 this_nsequence;
278278
struct bitcoin_tx *tx;
279279

280-
if (utxos[i]->is_p2sh) {
280+
if (utxos[i]->utxotype == UTXO_P2SH_P2WPKH) {
281281
bip32_pubkey(wallet->ld, &key, utxos[i]->keyindex);
282282
scriptSig = bitcoin_scriptsig_p2sh_p2wpkh(tmpctx, &key);
283283
redeemscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &key);

wallet/wallet.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt)
337337
db_col_txid(stmt, "prev_out_tx", &utxo->outpoint.txid);
338338
utxo->outpoint.n = db_col_int(stmt, "prev_out_index");
339339
utxo->amount = db_col_amount_sat(stmt, "value");
340-
utxo->is_p2sh = db_col_int(stmt, "type") == p2sh_wpkh;
341340
utxo->status = db_col_int(stmt, "status");
342341
utxo->keyindex = db_col_int(stmt, "keyindex");
343342

@@ -363,6 +362,19 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt)
363362
}
364363

365364
utxo->scriptPubkey = db_col_arr(utxo, stmt, "scriptpubkey", u8);
365+
/* FIXME: add p2tr to type? */
366+
if (db_col_int(stmt, "type") == p2sh_wpkh)
367+
utxo->utxotype = UTXO_P2SH_P2WPKH;
368+
else if (is_p2wpkh(utxo->scriptPubkey, tal_bytelen(utxo->scriptPubkey), NULL))
369+
utxo->utxotype = UTXO_P2WPKH;
370+
else if (is_p2tr(utxo->scriptPubkey, tal_bytelen(utxo->scriptPubkey), NULL))
371+
utxo->utxotype = UTXO_P2TR;
372+
else if (is_p2wsh(utxo->scriptPubkey, tal_bytelen(utxo->scriptPubkey), NULL)) {
373+
if (!utxo->close_info)
374+
fatal("Unspendable scriptPubkey without close_info %s", tal_hex(tmpctx, utxo->scriptPubkey));
375+
utxo->utxotype = UTXO_P2WSH_FROM_CLOSE;
376+
} else
377+
fatal("Unknown utxo type %s", tal_hex(tmpctx, utxo->scriptPubkey));
366378

367379
utxo->blockheight = NULL;
368380
utxo->spendheight = NULL;
@@ -775,7 +787,7 @@ struct utxo *wallet_find_utxo(const tal_t *ctx, struct wallet *w,
775787
while (!utxo && db_step(stmt)) {
776788
utxo = wallet_stmt2output(ctx, stmt);
777789
if (excluded(excludes, utxo)
778-
|| (nonwrapped && utxo->is_p2sh)
790+
|| (nonwrapped && utxo->utxotype == UTXO_P2SH_P2WPKH)
779791
|| !deep_enough(maxheight, utxo, current_blockheight))
780792
utxo = tal_free(utxo);
781793

@@ -2928,7 +2940,24 @@ static void got_utxo(struct wallet *w,
29282940
struct amount_asset asset = wally_tx_output_get_amount(txout);
29292941

29302942
utxo->keyindex = keyindex;
2931-
utxo->is_p2sh = (addrtype == ADDR_P2SH_SEGWIT);
2943+
/* This switch() pattern catches anyone adding new cases, plus
2944+
* runtime errors */
2945+
switch (addrtype) {
2946+
case ADDR_P2SH_SEGWIT:
2947+
utxo->utxotype = UTXO_P2SH_P2WPKH;
2948+
goto type_ok;
2949+
case ADDR_BECH32:
2950+
utxo->utxotype = UTXO_P2WPKH;
2951+
goto type_ok;
2952+
case ADDR_P2TR:
2953+
utxo->utxotype = UTXO_P2TR;
2954+
goto type_ok;
2955+
case ADDR_ALL:
2956+
break;
2957+
}
2958+
abort();
2959+
2960+
type_ok:
29322961
utxo->amount = amount_asset_to_sat(&asset);
29332962
utxo->status = OUTPUT_STATE_AVAILABLE;
29342963
wally_txid(wtx, &utxo->outpoint.txid);
@@ -2942,7 +2971,7 @@ static void got_utxo(struct wallet *w,
29422971
log_debug(w->log, "Owning output %zu %s (%s) txid %s%s%s",
29432972
outnum,
29442973
fmt_amount_sat(tmpctx, utxo->amount),
2945-
utxo->is_p2sh ? "P2SH" : "SEGWIT",
2974+
utxotype_to_str(utxo->utxotype),
29462975
fmt_bitcoin_txid(tmpctx, &utxo->outpoint.txid),
29472976
blockheight ? " CONFIRMED" : "",
29482977
is_coinbase ? " COINBASE" : "");
@@ -2958,7 +2987,7 @@ static void got_utxo(struct wallet *w,
29582987
notify_chain_mvt(w->ld, mvt);
29592988
}
29602989

2961-
if (!wallet_add_utxo(w, utxo, utxo->is_p2sh ? p2sh_wpkh : our_change)) {
2990+
if (!wallet_add_utxo(w, utxo, utxo->utxotype == UTXO_P2SH_P2WPKH ? p2sh_wpkh : our_change)) {
29622991
/* In case we already know the output, make
29632992
* sure we actually track its
29642993
* blockheight. This can happen when we grab
@@ -2970,7 +2999,7 @@ static void got_utxo(struct wallet *w,
29702999
}
29713000

29723001
/* This is an unconfirmed change output, we should track it */
2973-
if (!utxo->is_p2sh && !blockheight)
3002+
if (utxo->utxotype != UTXO_P2SH_P2WPKH && !blockheight)
29743003
txfilter_add_scriptpubkey(w->ld->owned_txfilter, txout->script);
29753004

29763005
outpointfilter_add(w->owned_outpoints, &utxo->outpoint);

wallet/walletrpc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ static void json_add_utxo(struct json_stream *response,
349349
json_add_num(response, "output", utxo->outpoint.n);
350350
json_add_amount_sat_msat(response, "amount_msat", utxo->amount);
351351

352-
if (utxo->is_p2sh) {
352+
if (utxo->utxotype == UTXO_P2SH_P2WPKH) {
353353
struct pubkey key;
354354
bip32_pubkey(wallet->ld, &key, utxo->keyindex);
355355

@@ -693,7 +693,7 @@ static struct command_result *match_psbt_inputs_to_utxos(struct command *cmd,
693693
if (!psbt->inputs[i].utxo && !psbt->inputs[i].witness_utxo) {
694694
u8 *scriptPubKey;
695695

696-
if (utxo->is_p2sh) {
696+
if (utxo->utxotype == UTXO_P2SH_P2WPKH) {
697697
struct pubkey key;
698698
u8 *redeemscript;
699699
int wally_err;

0 commit comments

Comments
 (0)