Files
palladum-lightning/hsmd
Rusty Russell 992771bbdf pytest: fix flakes in feerates.
Sometimes we get a shorter signature than expected, and we're supposed
to disable the feerate tests in that case.  But we didn't catch all the
cases where we make signatures.

```
2025-10-13T02:36:24.1901527Z ____________________________ test_peer_anchor_push _____________________________
2025-10-13T02:36:24.1902251Z [gw5] linux -- Python 3.10.18 /home/runner/work/lightning/lightning/.venv/bin/python
2025-10-13T02:36:24.1902731Z 
2025-10-13T02:36:24.1903045Z node_factory = <pyln.testing.utils.NodeFactory object at 0x7f17fdffd6f0>
2025-10-13T02:36:24.1903740Z bitcoind = <pyln.testing.utils.BitcoinD object at 0x7f17fdffe830>
2025-10-13T02:36:24.1904495Z executor = <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f17fdffcbb0>
2025-10-13T02:36:24.1906158Z chainparams = {'bip173_prefix': 'bcrt', 'chain_hash': '06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f', 'elements': False, 'example_addr': 'bcrt1qeyyk6sl5pr49ycpqyckvmttus5ttj25pd0zpvg', ...}
2025-10-13T02:36:24.1907285Z 
2025-10-13T02:36:24.1907600Z     @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd anchors not supportd')
2025-10-13T02:36:24.1908344Z     def test_peer_anchor_push(node_factory, bitcoind, executor, chainparams):
2025-10-13T02:36:24.1909033Z         """Test that we use anchor on peer's commit to CPFP tx"""
2025-10-13T02:36:24.1909853Z         l1, l2, l3 = node_factory.line_graph(3, opts=[{},
2025-10-13T02:36:24.1910334Z                                                       {'min-emergency-msat': 546000,
2025-10-13T02:36:24.1910825Z                                                        'dev-warn-on-overgrind': None,
2025-10-13T02:36:24.1911313Z                                                        'broken_log': 'overgrind: short signature length'},
2025-10-13T02:36:24.1911662Z                                                       {'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC'],
2025-10-13T02:36:24.1911976Z                                                        'dev-warn-on-overgrind': None,
2025-10-13T02:36:24.1912304Z                                                        'broken_log': 'overgrind: short signature length'}],
2025-10-13T02:36:24.1912790Z                                              wait_for_announce=True)
2025-10-13T02:36:24.1913041Z     
2025-10-13T02:36:24.1913305Z         # We splinter l2's funds so it's forced to use more than one UTXO to push.
2025-10-13T02:36:24.1914043Z         fundsats = int(Millisatoshi(only_one(l2.rpc.listfunds()['outputs'])['amount_msat']).to_satoshi())
2025-10-13T02:36:24.1914443Z         OUTPUT_SAT = 10000
2025-10-13T02:36:24.1914647Z         NUM_OUTPUTS = 10
2025-10-13T02:36:24.1914903Z         psbt = l2.rpc.fundpsbt("all", "1000perkw", 1000)['psbt']
2025-10-13T02:36:24.1915520Z         # Pay 5k sats in fees.
2025-10-13T02:36:24.1916329Z         psbt = l2.rpc.addpsbtoutput(fundsats - OUTPUT_SAT * NUM_OUTPUTS - 5000, psbt, destination=l3.rpc.newaddr()['bech32'])['psbt']
2025-10-13T02:36:24.1917156Z         for _ in range(NUM_OUTPUTS):
2025-10-13T02:36:24.1917638Z             psbt = l2.rpc.addpsbtoutput(OUTPUT_SAT, psbt)['psbt']
2025-10-13T02:36:24.1918194Z         l2.rpc.sendpsbt(l2.rpc.signpsbt(psbt)['signed_psbt'])
2025-10-13T02:36:24.1918731Z         bitcoind.generate_block(1, wait_for_mempool=1)
2025-10-13T02:36:24.1919232Z         sync_blockheight(bitcoind, [l1, l2])
2025-10-13T02:36:24.1919634Z     
2025-10-13T02:36:24.1919847Z         # Make sure all amounts are below OUTPUT_SAT sats!
2025-10-13T02:36:24.1920318Z         assert [x for x in l2.rpc.listfunds()['outputs'] if x['amount_msat'] > Millisatoshi(str(OUTPUT_SAT) + "sat")] == []
2025-10-13T02:36:24.1920735Z     
2025-10-13T02:36:24.1920957Z         # Get HTLC stuck, so l2 has reason to push commitment tx.
2025-10-13T02:36:24.1921244Z         amt = 100_000_000
2025-10-13T02:36:24.1921517Z         sticky_inv = l3.rpc.invoice(amt, 'sticky', 'sticky')
2025-10-13T02:36:24.1921842Z         route = l1.rpc.getroute(l3.info['id'], amt, 1)['route']
2025-10-13T02:36:24.1922277Z         l1.rpc.sendpay(route, sticky_inv['payment_hash'], payment_secret=sticky_inv['payment_secret'])
2025-10-13T02:36:24.1922751Z         l3.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
2025-10-13T02:36:24.1923060Z     
2025-10-13T02:36:24.1923241Z         # Make sure HTLC expiry is what we expect!
2025-10-13T02:36:24.1923637Z         l2.daemon.wait_for_log('Adding HTLC 0 amount=100000000msat cltv=119 gave CHANNEL_ERR_ADD_OK')
2025-10-13T02:36:24.1923998Z     
2025-10-13T02:36:24.1924229Z         # l3 drops to chain, but make sure it doesn't CPFP its own anchor.
2025-10-13T02:36:24.1924685Z         wait_for(lambda: only_one(l3.rpc.listpeerchannels(l2.info['id'])['channels'])['htlcs'] != [])
2025-10-13T02:36:24.1925688Z         closetx = l3.rpc.dev_sign_last_tx(l2.info['id'])['tx']
2025-10-13T02:36:24.1926132Z         l3.stop()
2025-10-13T02:36:24.1926337Z         # We don't care about l1 any more, either
2025-10-13T02:36:24.1926579Z         l1.stop()
2025-10-13T02:36:24.1926739Z     
2025-10-13T02:36:24.1926941Z         # We put l3's tx in the mempool, but won't mine it.
2025-10-13T02:36:24.1927316Z         bitcoind.rpc.sendrawtransaction(closetx)
2025-10-13T02:36:24.1927754Z     
2025-10-13T02:36:24.1928139Z         # We aim for feerate ~3750, so this won't mine l3's unilateral close.
2025-10-13T02:36:24.1928991Z         # HTLC's going to time out at block 120 (we give one block grace)
2025-10-13T02:36:24.1929527Z         for block in range(110, 120):
2025-10-13T02:36:24.1929989Z             bitcoind.generate_block(1, needfeerate=5000)
2025-10-13T02:36:24.1930510Z             assert bitcoind.rpc.getblockcount() == block
2025-10-13T02:36:24.1931014Z             sync_blockheight(bitcoind, [l2])
2025-10-13T02:36:24.1931715Z         assert only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['state'] == 'CHANNELD_NORMAL'
2025-10-13T02:36:24.1932368Z     
2025-10-13T02:36:24.1932642Z         # Drops to chain
2025-10-13T02:36:24.1933030Z         bitcoind.generate_block(1, needfeerate=5000)
2025-10-13T02:36:24.1933824Z         wait_for(lambda: only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['state'] == 'AWAITING_UNILATERAL')
2025-10-13T02:36:24.1934522Z     
2025-10-13T02:36:24.1935254Z         # But, l3's tx already there, and identical feerate will not RBF.
2025-10-13T02:36:24.1935839Z         l2.daemon.wait_for_log("rejecting replacement")
2025-10-13T02:36:24.1936357Z         wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 2)
2025-10-13T02:36:24.1936801Z     
2025-10-13T02:36:24.1937127Z         # As blocks pass, we will use anchor to boost l3's tx.
2025-10-13T02:36:24.1937666Z         for block, feerate in zip(range(120, 124), (12000, 13000, 14000, 15000)):
2025-10-13T02:36:24.1938560Z             l2.daemon.wait_for_log(fr"Worth fee [0-9]*sat for remote commit tx to get 100000000msat at block 125 \(\+{125 - block}\) at feerate {feerate}perkw")
2025-10-13T02:36:24.1939369Z             l2.daemon.wait_for_log("sendrawtx exit 0")
2025-10-13T02:36:24.1939902Z             # Check feerate for entire package (commitment tx + anchor) is ~ correct
2025-10-13T02:36:24.1940473Z             details = bitcoind.rpc.getrawmempool(True).values()
2025-10-13T02:36:24.1940920Z             print(f"mempool = {details}")
2025-10-13T02:36:24.1941347Z             total_weight = sum([d['weight'] for d in details])
2025-10-13T02:36:24.1941903Z             total_fees = sum([float(d['fees']['base']) * 100_000_000 for d in details])
2025-10-13T02:36:24.1942467Z             total_feerate_perkw = total_fees / total_weight * 1000
2025-10-13T02:36:24.1942972Z >           check_feerate([l3, l2], total_feerate_perkw, feerate)
2025-10-13T02:36:24.1943279Z 
2025-10-13T02:36:24.1943411Z tests/test_closing.py:4064: 
2025-10-13T02:36:24.1943813Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2025-10-13T02:36:24.1944170Z 
2025-10-13T02:36:24.1944685Z nodes = [<fixtures.LightningNode object at 0x7f17fdf684f0>, <fixtures.LightningNode object at 0x7f17fdf6af50>]
2025-10-13T02:36:24.1945708Z actual_feerate = 13005.66942869603, expected_feerate = 13000
2025-10-13T02:36:24.1946091Z 
2025-10-13T02:36:24.1946247Z     def check_feerate(nodes, actual_feerate, expected_feerate):
2025-10-13T02:36:24.1946558Z         # Feerate can't be lower.
2025-10-13T02:36:24.1946870Z         assert actual_feerate > expected_feerate - 2
2025-10-13T02:36:24.1947365Z         if actual_feerate >= expected_feerate + 2:
2025-10-13T02:36:24.1947830Z             if any([did_short_sig(n) for n in nodes]):
2025-10-13T02:36:24.1948239Z                 return
2025-10-13T02:36:24.1948589Z         # Use assert as it shows the actual values on failure
2025-10-13T02:36:24.1949043Z >       assert actual_feerate < expected_feerate + 2
2025-10-13T02:36:24.1949489Z E       AssertionError
2025-10-13T02:36:24.1949704Z 
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-14 09:48:02 +10:30
..
2025-10-14 09:48:02 +10:30