diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index f473e6843f1c..7e8c7c12ff1f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -300,6 +300,7 @@ static struct bitcoin_tx *sign_and_send_last(const tal_t *ctx, tx = sign_last_tx(ctx, channel, last_tx, last_sig); bitcoin_txid(tx, &txid); wallet_transaction_add(ld->wallet, tx->wtx, 0, 0); + wallet_extract_owned_outputs(ld->wallet, tx->wtx, false, NULL, NULL); /* Remember anchor information for commit_tx_boost */ adet = create_anchor_details(NULL, channel, tx); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 989270b84852..0981757b3d27 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -964,6 +964,12 @@ void wallet_channeltxs_add(struct wallet *w UNNEEDED, struct channel *chan UNNEE /* Generated stub for wallet_delete_peer_if_unused */ void wallet_delete_peer_if_unused(struct wallet *w UNNEEDED, u64 peer_dbid UNNEEDED) { fprintf(stderr, "wallet_delete_peer_if_unused called!\n"); abort(); } +/* Generated stub for wallet_extract_owned_outputs */ +int wallet_extract_owned_outputs(struct wallet *w UNNEEDED, const struct wally_tx *tx UNNEEDED, + bool is_coinbase UNNEEDED, + const u32 *blockheight UNNEEDED, + struct amount_sat *total UNNEEDED) +{ fprintf(stderr, "wallet_extract_owned_outputs called!\n"); abort(); } /* Generated stub for wallet_htlcs_load_in_for_channel */ bool wallet_htlcs_load_in_for_channel(struct wallet *wallet UNNEEDED, struct channel *chan UNNEEDED, diff --git a/tests/test_closing.py b/tests/test_closing.py index c96ae9f2b0f6..bda0b01add8a 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -3853,7 +3853,7 @@ def test_closing_tx_valid(node_factory, bitcoind): assert bitcoind.rpc.getrawtransaction(close['txid']) == close['tx'] bitcoind.generate_block(1) # Change output and the closed channel output. - wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 2) + wait_for(lambda: [o['status'] for o in l1.rpc.listfunds()['outputs']] == ['confirmed'] * 2) # Now, unilateral close. l1.rpc.connect(l2.info['id'], 'localhost', l2.port) @@ -3878,3 +3878,33 @@ def test_closing_minfee(node_factory, bitcoind): txid = l1.rpc.close(l2.info['id'])['txid'] bitcoind.generate_block(1, wait_for_mempool=txid) + + +def test_closing_cpfp(node_factory, bitcoind): + l1, l2 = node_factory.line_graph(2) + + # We want to ignore l1's change output + change = only_one(l1.rpc.listfunds()['outputs']) + + # Make sure both sides have some output + l1.rpc.pay(l2.rpc.invoice(10000000, 'test', 'test')['bolt11']) + + # Mutual close + close_txid = l1.rpc.close(l2.info['id'])['txid'] + + l1out = only_one([o for o in l1.rpc.listfunds()['outputs'] if o != change]) + assert l1out['txid'] == close_txid + l1.rpc.withdraw(l1.rpc.newaddr()['bech32'], 'all', '20000perkb', minconf=0, utxos=["{}:{}".format(l1out['txid'], l1out['output'])]) + + # l2 should be able to do this too! + l2out = only_one(l2.rpc.listfunds()['outputs']) + assert l2out['txid'] == close_txid + l2.rpc.withdraw(l2.rpc.newaddr()['bech32'], 'all', '20000perkb', minconf=0, utxos=["{}:{}".format(l2out['txid'], l2out['output'])]) + + # There should be *three* transactions in mempool now! + bitcoind.generate_block(1, wait_for_mempool=3) + + # They should now see a single additional output each + sync_blockheight(bitcoind, [l1, l2]) + assert len(l1.rpc.listfunds()['outputs']) == 2 + assert len(l2.rpc.listfunds()['outputs']) == 1 diff --git a/wallet/wallet.c b/wallet/wallet.c index 301efe5f4703..f2ee951d9cb4 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -140,7 +140,8 @@ struct wallet *wallet_new(struct lightningd *ld, struct timers *timers) * * This can fail if we've already seen UTXO. */ -static bool wallet_add_utxo(struct wallet *w, struct utxo *utxo, +static bool wallet_add_utxo(struct wallet *w, + const struct utxo *utxo, enum wallet_output_type type) { struct db_stmt *stmt; @@ -2573,7 +2574,8 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct wally_tx *wtx, { int num_utxos = 0; - *total = AMOUNT_SAT(0); + if (total) + *total = AMOUNT_SAT(0); for (size_t output = 0; output < wtx->num_outputs; output++) { struct utxo *utxo; u32 index; @@ -2646,7 +2648,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct wally_tx *wtx, outpointfilter_add(w->owned_outpoints, &utxo->outpoint); - if (!amount_sat_add(total, *total, utxo->amount)) + if (total && !amount_sat_add(total, *total, utxo->amount)) fatal("Cannot add utxo output %zu/%zu %s + %s", output, wtx->num_outputs, type_to_string(tmpctx, struct amount_sat, total), diff --git a/wallet/wallet.h b/wallet/wallet.h index 189673694f97..1676c70fff54 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -569,6 +569,7 @@ bool wallet_has_funds(struct wallet *wallet, const struct utxo **excludes, u32 current_blockheight, struct amount_sat sats); + /** * wallet_add_onchaind_utxo - Add a UTXO with spending info from onchaind. *