From 68938d9eb9e33c952587742d7bf854b7fce7ad41 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Thu, 18 Dec 2025 18:49:06 +0100 Subject: [PATCH 01/15] tests: Fix test_peer_anchor_push error due to variable signature length (Fixes #8493) Changelog-None --- tests/utils.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/utils.py b/tests/utils.py index 9fc902aac23b..2129c3827e47 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -675,15 +675,17 @@ def serialize_payload_final_tlv(amount_msat, delay, total_msat, blockheight, pay # create 71-byte sigs always! def did_short_sig(node): # This can take a moment to appear in the log! - time.sleep(1) + time.sleep(2) return node.daemon.is_in_log('overgrind: short signature length') def check_feerate(nodes, actual_feerate, expected_feerate): # Feerate can't be lower. - assert actual_feerate > expected_feerate - 2 - if actual_feerate >= expected_feerate + 2: + + tolerance = 10 + assert actual_feerate > expected_feerate - tolerance + if actual_feerate >= expected_feerate + tolerance: if any([did_short_sig(n) for n in nodes]): return # Use assert as it shows the actual values on failure - assert actual_feerate < expected_feerate + 2 + assert actual_feerate < expected_feerate + tolerance From d2ed6cc3d3ba7481dae500c40bf4489fd700c674 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 19 Dec 2025 14:29:28 +0100 Subject: [PATCH 02/15] tests: fixed feerate tolerance and signature detection(Fixes #8493) Changelog-None --- tests/utils.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/utils.py b/tests/utils.py index 2129c3827e47..1b115f554d78 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,6 +4,7 @@ from pyln.client import Millisatoshi from pyln.testing.utils import EXPERIMENTAL_DUAL_FUND, EXPERIMENTAL_SPLICING from pyln.proto.onion import TlvPayload +import pytest import struct import subprocess import tempfile @@ -674,18 +675,16 @@ def serialize_payload_final_tlv(amount_msat, delay, total_msat, blockheight, pay # I wish we could force libwally to use different entropy and thus force it to # create 71-byte sigs always! def did_short_sig(node): - # This can take a moment to appear in the log! - time.sleep(2) - return node.daemon.is_in_log('overgrind: short signature length') + try: + wait_for(lambda: node.daemon.is_in_log('overgrind: short signature length'), timeout=5) + return True + except (TimeoutError, ValueError): + return False def check_feerate(nodes, actual_feerate, expected_feerate): - # Feerate can't be lower. - - tolerance = 10 - assert actual_feerate > expected_feerate - tolerance - if actual_feerate >= expected_feerate + tolerance: + assert actual_feerate >= expected_feerate - 10 + if actual_feerate >= expected_feerate + 10: if any([did_short_sig(n) for n in nodes]): return - # Use assert as it shows the actual values on failure - assert actual_feerate < expected_feerate + tolerance + assert actual_feerate == pytest.approx(expected_feerate, rel=0.001, abs=10) From d7822ae3a7e42938afc9b58a09caad8e6afd4109 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Tue, 23 Dec 2025 14:10:58 +0100 Subject: [PATCH 03/15] fix: use 330 sat dust limit for P2TR/P2WPKH change outputs Fixes #8395 Changelog-Fixed: Transactions now correctly create change outputs between 330-546 sat for P2TR/P2WPKH instead of absorbing them as fees --- bitcoin/tx.c | 8 +++++- tests/test_p2tr_change_dust.py | 52 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/test_p2tr_change_dust.py diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 4c1a63de6c0a..876f82237bc2 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -983,12 +983,18 @@ struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw, size_t total_weight) { struct amount_sat fee = change_fee(feerate_perkw, total_weight); + struct amount_sat dust_limit; if (!amount_sat_sub(&excess, excess, fee)) return AMOUNT_SAT(0); + if (chainparams->is_elements) + dust_limit = AMOUNT_SAT(330); /* P2WPKH */ + else + dust_limit = AMOUNT_SAT(330); /* P2TR */ + /* Must be non-dust */ - if (!amount_sat_greater_eq(excess, chainparams->dust_limit)) + if (!amount_sat_greater_eq(excess, dust_limit)) return AMOUNT_SAT(0); return excess; diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py new file mode 100644 index 000000000000..65c55e57494a --- /dev/null +++ b/tests/test_p2tr_change_dust.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""Test P2TR change outputs with dust limit 330 sat (issue #8395).""" +import unittest +from pyln.testing.fixtures import * +from pyln.testing.utils import only_one, TEST_NETWORK, wait_for + + +@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', "P2TR not yet supported on Elements") +def test_p2tr_change_dust_limit(node_factory, bitcoind): + + l1 = node_factory.get_node(feerates=(253, 253, 253, 253)) + + addr = l1.rpc.newaddr('p2tr')['p2tr'] + bitcoind.rpc.sendtoaddress(addr, 1.0) + bitcoind.generate_block(1) + wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 1) + + outputs = l1.rpc.listfunds()['outputs'] + assert len(outputs) == 1 + utxo = outputs[0] + + utxo_amount = int(utxo['amount_msat'] / 1000) + + target_amount = utxo_amount - 450 + + result = l1.rpc.fundpsbt( + satoshi=f"{target_amount}sat", + feerate="253perkw", + startweight=0, + excess_as_change=True + ) + + assert 'change_outnum' in result, "Expected change output to be created" + + psbt = bitcoind.rpc.decodepsbt(result['psbt']) + + change_outnum = result['change_outnum'] + if 'tx' in psbt: + change_output = psbt['tx']['vout'][change_outnum] + change_amount_btc = float(change_output['value']) + else: + change_output = psbt['outputs'][change_outnum] + change_amount_btc = float(change_output['amount']) + + change_amount_sat = int(change_amount_btc * 100_000_000) + + print(f"Change amount: {change_amount_sat} sat") + + assert change_amount_sat >= 330, f"Change {change_amount_sat} sat should be >= 330 sat" + assert change_amount_sat <= 546, f"Change {change_amount_sat} sat should be <= 546 sat (for this test)" + + print(f"SUCCESS: P2TR change output of {change_amount_sat} sat created (between 330 and 546 sat)") From 7406466988b48891fe086dc4d268fbfe135d0fe9 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Tue, 23 Dec 2025 14:22:21 +0100 Subject: [PATCH 04/15] fix: cleaned up code Fixes #8395 Changelog-Fixed: Transactions now correctly create change outputs between 330-546 sat for P2TR/P2WPKH instead of absorbing them as fees --- bitcoin/tx.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 876f82237bc2..7fb5ad778a47 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -983,18 +983,14 @@ struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw, size_t total_weight) { struct amount_sat fee = change_fee(feerate_perkw, total_weight); - struct amount_sat dust_limit; if (!amount_sat_sub(&excess, excess, fee)) return AMOUNT_SAT(0); - if (chainparams->is_elements) - dust_limit = AMOUNT_SAT(330); /* P2WPKH */ - else - dust_limit = AMOUNT_SAT(330); /* P2TR */ - - /* Must be non-dust */ - if (!amount_sat_greater_eq(excess, dust_limit)) + // Change is P2TR (Bitcoin) or P2WPKH (Elements) both have + // dust limit of 330 sat. Legacy types (P2PKH/P2SH) use 546 sat + // but we dont create those as change outputs + if (!amount_sat_greater_eq(excess, AMOUNT_SAT(330))) return AMOUNT_SAT(0); return excess; From 34581e1a2eabbdf04a87ed4e07543795e920302f Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Wed, 7 Jan 2026 23:00:23 +0100 Subject: [PATCH 05/15] fix: simplified did_short_sig(), fixed elements check and now btc uses 330 sat for p2tr change outputs --- bitcoin/tx.c | 12 +++++++----- tests/utils.py | 6 +----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 7fb5ad778a47..e7e84a94848b 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -987,11 +987,13 @@ struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw, if (!amount_sat_sub(&excess, excess, fee)) return AMOUNT_SAT(0); - // Change is P2TR (Bitcoin) or P2WPKH (Elements) both have - // dust limit of 330 sat. Legacy types (P2PKH/P2SH) use 546 sat - // but we dont create those as change outputs - if (!amount_sat_greater_eq(excess, AMOUNT_SAT(330))) - return AMOUNT_SAT(0); + if (chainparams->is_elements) { + if (!amount_sat_greater_eq(excess, AMOUNT_SAT(546))) + return AMOUNT_SAT(0); + } else { + if (!amount_sat_greater_eq(excess, AMOUNT_SAT(330))) + return AMOUNT_SAT(0); + } return excess; } diff --git a/tests/utils.py b/tests/utils.py index 1b115f554d78..d1358c566319 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -675,11 +675,7 @@ def serialize_payload_final_tlv(amount_msat, delay, total_msat, blockheight, pay # I wish we could force libwally to use different entropy and thus force it to # create 71-byte sigs always! def did_short_sig(node): - try: - wait_for(lambda: node.daemon.is_in_log('overgrind: short signature length'), timeout=5) - return True - except (TimeoutError, ValueError): - return False + return node.daemon.is_in_log('overgrind: short signature length') def check_feerate(nodes, actual_feerate, expected_feerate): From 6c8769ee973b3ae4d2f6a6f4dcb747147411a326 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 23 Jan 2026 16:14:31 +0100 Subject: [PATCH 06/15] fix: cleaned all whitespaces Changelog-None --- tests/test_p2tr_change_dust.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py index 65c55e57494a..58ec5fb9789f 100644 --- a/tests/test_p2tr_change_dust.py +++ b/tests/test_p2tr_change_dust.py @@ -41,12 +41,12 @@ def test_p2tr_change_dust_limit(node_factory, bitcoind): else: change_output = psbt['outputs'][change_outnum] change_amount_btc = float(change_output['amount']) - + change_amount_sat = int(change_amount_btc * 100_000_000) - + print(f"Change amount: {change_amount_sat} sat") - + assert change_amount_sat >= 330, f"Change {change_amount_sat} sat should be >= 330 sat" assert change_amount_sat <= 546, f"Change {change_amount_sat} sat should be <= 546 sat (for this test)" - + print(f"SUCCESS: P2TR change output of {change_amount_sat} sat created (between 330 and 546 sat)") From 811f92b2cf3d9abaf017a93ceed16b6709062fae Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 23 Jan 2026 16:28:18 +0100 Subject: [PATCH 07/15] fix: cleaned all whitespaces Changelog-None --- tests/test_p2tr_change_dust.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py index 58ec5fb9789f..0cdd66fc8460 100644 --- a/tests/test_p2tr_change_dust.py +++ b/tests/test_p2tr_change_dust.py @@ -31,14 +31,14 @@ def test_p2tr_change_dust_limit(node_factory, bitcoind): ) assert 'change_outnum' in result, "Expected change output to be created" - + psbt = bitcoind.rpc.decodepsbt(result['psbt']) - + change_outnum = result['change_outnum'] - if 'tx' in psbt: + if 'tx' in psbt: change_output = psbt['tx']['vout'][change_outnum] change_amount_btc = float(change_output['value']) - else: + else: change_output = psbt['outputs'][change_outnum] change_amount_btc = float(change_output['amount']) From 501ee75e06239276a735d4b5423188d26136219e Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 23 Jan 2026 16:33:47 +0100 Subject: [PATCH 08/15] fix: cleaned all whitespaces Changelog-None --- tests/test_p2tr_change_dust.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py index 0cdd66fc8460..4d9bf7daeb4d 100644 --- a/tests/test_p2tr_change_dust.py +++ b/tests/test_p2tr_change_dust.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test P2TR change outputs with dust limit 330 sat (issue #8395).""" import unittest -from pyln.testing.fixtures import * +from pyln.testing.fixtures import * from pyln.testing.utils import only_one, TEST_NETWORK, wait_for @@ -9,27 +9,27 @@ def test_p2tr_change_dust_limit(node_factory, bitcoind): l1 = node_factory.get_node(feerates=(253, 253, 253, 253)) - + addr = l1.rpc.newaddr('p2tr')['p2tr'] bitcoind.rpc.sendtoaddress(addr, 1.0) bitcoind.generate_block(1) wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 1) - + outputs = l1.rpc.listfunds()['outputs'] assert len(outputs) == 1 utxo = outputs[0] utxo_amount = int(utxo['amount_msat'] / 1000) - + target_amount = utxo_amount - 450 - + result = l1.rpc.fundpsbt( satoshi=f"{target_amount}sat", feerate="253perkw", startweight=0, excess_as_change=True ) - + assert 'change_outnum' in result, "Expected change output to be created" psbt = bitcoind.rpc.decodepsbt(result['psbt']) @@ -49,4 +49,4 @@ def test_p2tr_change_dust_limit(node_factory, bitcoind): assert change_amount_sat >= 330, f"Change {change_amount_sat} sat should be >= 330 sat" assert change_amount_sat <= 546, f"Change {change_amount_sat} sat should be <= 546 sat (for this test)" - print(f"SUCCESS: P2TR change output of {change_amount_sat} sat created (between 330 and 546 sat)") + print(f"SUCCESS: P2TR change output of {change_amount_sat} sat created (between 330 and 546 sat)") \ No newline at end of file From ed45ebc4cd976edcea7211990ef8e6418afa0fcd Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 23 Jan 2026 16:39:15 +0100 Subject: [PATCH 09/15] fix: cleaned all whitespaces Changelog-None --- tests/test_p2tr_change_dust.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py index 4d9bf7daeb4d..34b26b6873d8 100644 --- a/tests/test_p2tr_change_dust.py +++ b/tests/test_p2tr_change_dust.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 """Test P2TR change outputs with dust limit 330 sat (issue #8395).""" import unittest -from pyln.testing.fixtures import * -from pyln.testing.utils import only_one, TEST_NETWORK, wait_for + +from pyln.testing.utils import TEST_NETWORK, wait_for @unittest.skipIf(TEST_NETWORK == 'liquid-regtest', "P2TR not yet supported on Elements") @@ -18,10 +18,10 @@ def test_p2tr_change_dust_limit(node_factory, bitcoind): outputs = l1.rpc.listfunds()['outputs'] assert len(outputs) == 1 utxo = outputs[0] - - utxo_amount = int(utxo['amount_msat'] / 1000) - target_amount = utxo_amount - 450 + utxo_amount = int(utxo['amount_msat'] / 1000) + + target_amount = utxo_amount - 450 result = l1.rpc.fundpsbt( satoshi=f"{target_amount}sat", From 838ea395affaffe01379d4c794eda07fbeabb5e4 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 23 Jan 2026 16:45:16 +0100 Subject: [PATCH 10/15] fix: cleaned all whitespaces Changelog-None --- tests/test_p2tr_change_dust.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py index 34b26b6873d8..b130ac6a66ee 100644 --- a/tests/test_p2tr_change_dust.py +++ b/tests/test_p2tr_change_dust.py @@ -49,4 +49,4 @@ def test_p2tr_change_dust_limit(node_factory, bitcoind): assert change_amount_sat >= 330, f"Change {change_amount_sat} sat should be >= 330 sat" assert change_amount_sat <= 546, f"Change {change_amount_sat} sat should be <= 546 sat (for this test)" - print(f"SUCCESS: P2TR change output of {change_amount_sat} sat created (between 330 and 546 sat)") \ No newline at end of file + print(f"SUCCESS: P2TR change output of {change_amount_sat} sat created (between 330 and 546 sat)") From 02519e231347a622c383934a4e51343070aa1ed7 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Fri, 23 Jan 2026 21:56:44 +0100 Subject: [PATCH 11/15] fix: added new imports to correct tests Changelog-None --- tests/test_p2tr_change_dust.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_p2tr_change_dust.py b/tests/test_p2tr_change_dust.py index b130ac6a66ee..bffb04b759e8 100644 --- a/tests/test_p2tr_change_dust.py +++ b/tests/test_p2tr_change_dust.py @@ -2,7 +2,9 @@ """Test P2TR change outputs with dust limit 330 sat (issue #8395).""" import unittest -from pyln.testing.utils import TEST_NETWORK, wait_for +from fixtures import * # noqa: F401,F403 +from fixtures import TEST_NETWORK +from utils import wait_for @unittest.skipIf(TEST_NETWORK == 'liquid-regtest', "P2TR not yet supported on Elements") From 67964a0f578125ba54006f315c0fff924d13cdfe Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Sun, 25 Jan 2026 15:56:31 +0100 Subject: [PATCH 12/15] ci: reduce VALGRIND pytest workers from 3 to 1 to prevent OOM Changelog-None --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 60884992dff4..fa76920fc019 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -525,7 +525,7 @@ jobs: SLOW_MACHINE: 1 TEST_DEBUG: 1 run: | - VALGRIND=1 uv run eatmydata pytest tests/ -n 3 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} + VALGRIND=1 uv run eatmydata pytest tests/ -n 1 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} - name: Upload test results if: always() uses: actions/upload-artifact@v4 From 1b1c5de59b3d5d077d75d5bde7057d2d7d482219 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Sun, 25 Jan 2026 19:53:45 +0100 Subject: [PATCH 13/15] fix: added new rm to clean up broken reps Changelog-None --- .github/scripts/setup.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/scripts/setup.sh b/.github/scripts/setup.sh index 2409cdf0d543..5ef035ce225c 100755 --- a/.github/scripts/setup.sh +++ b/.github/scripts/setup.sh @@ -4,6 +4,10 @@ export DEBIAN_FRONTEND=noninteractive export RUST_VERSION=stable sudo useradd -ms /bin/bash tester + +sudo rm -f /etc/apt/sources.list.d/azure-cli.list || true +sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list || true + sudo apt-get update -qq sudo apt-get -qq install --no-install-recommends --allow-unauthenticated -yy \ From 1216841dbbdd968cc287bd1a725cfe2fefa67159 Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Sun, 25 Jan 2026 22:12:12 +0100 Subject: [PATCH 14/15] added new minor fixes Changelog-None --- tests/plugins/bookkeeper_custom_coins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/bookkeeper_custom_coins.py b/tests/plugins/bookkeeper_custom_coins.py index 9c8f3181cec7..f4ea7c3793a9 100755 --- a/tests/plugins/bookkeeper_custom_coins.py +++ b/tests/plugins/bookkeeper_custom_coins.py @@ -32,8 +32,8 @@ def emit_deposit(plugin, acct, is_withdraw, outpoint, amount, **kwargs): transfer_from = None if is_withdraw: - acct = "external" transfer_from = acct + acct = "external" utxo_deposit = { "account": acct, From f64669d0bc1145a64c293702847af28395a6bbad Mon Sep 17 00:00:00 2001 From: Andezion <245122@edu.p.lodz.pl> Date: Mon, 26 Jan 2026 13:10:31 +0100 Subject: [PATCH 15/15] fix: cleaned up mock on getblockhash Changelog-None --- tests/test_closing.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_closing.py b/tests/test_closing.py index 47cc28d8077c..0b2066a9789e 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -4386,6 +4386,9 @@ def no_new_blocks(req): # Make sure l2 was happy with the reestablish message. assert not l2.daemon.is_in_log('bad reestablish') + # Remove mock so l2 can sync during teardown + l2.daemon.rpcproxy.mock_rpc('getblockhash', None) + @unittest.skipIf(TEST_NETWORK != 'regtest', "elementsd doesn't use p2tr anyway") def test_onchain_close_no_p2tr(node_factory, bitcoind):