diff --git a/bitcoin/tx.c b/bitcoin/tx.c index a12b442cf6f8..aa3b117ae737 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -935,8 +935,9 @@ size_t bitcoin_tx_input_witness_weight(enum utxotype utxotype) * to `1` and witness: * Otherwise, this output is a simple P2WPKH to `remotepubkey`. */ - /* In practice, these predate anchors, so: */ - return 1 + 1 + bitcoin_tx_input_sig_weight(); + /* Only the anchors form is P2WSH, so the witness is the sig + * and that script: 37 bytes, or up to 39 with a lease's csv. */ + return bitcoin_tx_input_sig_weight() + 1 + 39; case UTXO_P2TR: /* Unified Schnorr signatures include an explicit sighash byte. */ return 1 + 64 + !is_elements(chainparams); diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 6d1bc722fffb..1add2d856706 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -2948,3 +2948,29 @@ def mock_fail_sendrawtx(r): bitcoind.generate_block(1) sync_blockheight(bitcoind, [l1]) assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=0')[0]['c'] == 0 + + +@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd anchors not supported') +def test_withdraw_anchor_to_remote_min_feerate(node_factory, bitcoind): + """The to_remote output of an anchor channel's unilateral close is spent + at the minimum feerate: its weight estimate covers the witness script.""" + l1, l2 = node_factory.line_graph(2) + l1.pay(l2, 200000000) + l1.rpc.dev_fail(l2.info['id']) + l1.wait_for_channel_onchain(l2.info['id']) + bitcoind.generate_block(1, wait_for_mempool=1) + sync_blockheight(bitcoind, [l2]) + + wait_for(lambda: [o for o in l2.rpc.listfunds()['outputs'] + if o['scriptpubkey'].startswith('0020')] != []) + utxo = only_one([o for o in l2.rpc.listfunds()['outputs'] + if o['scriptpubkey'].startswith('0020')]) + # Its csv lock is one block. + bitcoind.generate_block(1) + sync_blockheight(bitcoind, [l2]) + + out = l2.rpc.withdraw(bitcoind.rpc.getnewaddress(), 'all', '253perkw', + utxos=['{}:{}'.format(utxo['txid'], utxo['output'])]) + tx = bitcoind.rpc.getrawtransaction(out['txid'], True) + fee = bitcoind.rpc.getmempoolentry(out['txid'])['fees']['base'] + assert fee * 10**8 * 1000 / tx['weight'] >= 250