Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPFP for mutual close #6734

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lightningd/peer_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions lightningd/test/run-invoice-select-inchan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
32 changes: 31 additions & 1 deletion tests/test_closing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
8 changes: 5 additions & 3 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Loading