Skip to content

Commit cb7caa3

Browse files
instagibbsrustyrussell
authored andcommitted
Re-enable PSBT tests for Liquid except test_sign_and_send_psbt
1 parent 908f834 commit cb7caa3

File tree

6 files changed

+150
-42
lines changed

6 files changed

+150
-42
lines changed

.github/scripts/install-bitcoind.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ set -e
55
DIRNAME="bitcoin-${BITCOIN_VERSION}"
66
EDIRNAME="elements-${ELEMENTS_VERSION}"
77
FILENAME="${DIRNAME}-x86_64-linux-gnu.tar.gz"
8-
EFILENAME="${EDIRNAME}-x86_64-linux-gnu.tar.bz2"
8+
EFILENAME="${EDIRNAME}-x86_64-linux-gnu.tar.gz"
99

1010
cd /tmp/
1111
wget "https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/${FILENAME}"
12-
wget -q "https://storage.googleapis.com/c-lightning-tests/${EFILENAME}"
12+
wget "https://github.com/ElementsProject/elements/releases/download/elements-${ELEMENTS_VERSION}/${EFILENAME}"
1313
tar -xf "${FILENAME}"
14-
tar -xaf "${EFILENAME}"
14+
tar -xf "${EFILENAME}"
1515
sudo mv "${DIRNAME}"/bin/* "/usr/local/bin"
1616
sudo mv "${EDIRNAME}"/bin/* "/usr/local/bin"
1717

.github/scripts/setup.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -e
33
export DEBIAN_FRONTEND=noninteractive
44
export BITCOIN_VERSION=24.0.1
5-
export ELEMENTS_VERSION=0.18.1.8
5+
export ELEMENTS_VERSION=22.0.2
66
export RUST_VERSION=stable
77

88
sudo useradd -ms /bin/bash tester
@@ -57,16 +57,16 @@ sudo chmod 0440 /etc/sudoers.d/tester
5757
(
5858
cd /tmp/ || exit 1
5959
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz
60-
wget -q https://storage.googleapis.com/c-lightning-tests/elements-$ELEMENTS_VERSION-x86_64-linux-gnu.tar.bz2
61-
tar -xf bitcoin-$BITCOIN_VERSION-x86_64-linux-gnu.tar.gz
62-
tar -xjf elements-$ELEMENTS_VERSION-x86_64-linux-gnu.tar.bz2
63-
sudo mv bitcoin-$BITCOIN_VERSION/bin/* /usr/local/bin
64-
sudo mv elements-$ELEMENTS_VERSION/bin/* /usr/local/bin
60+
wget https://github.com/ElementsProject/elements/releases/download/elements-${ELEMENTS_VERSION}/elements-${ELEMENTS_VERSION}-x86_64-linux-gnu.tar.gz
61+
tar -xf bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz
62+
tar -xf elements-${ELEMENTS_VERSION}-x86_64-linux-gnu.tar.gz
63+
sudo mv bitcoin-${BITCOIN_VERSION}/bin/* /usr/local/bin
64+
sudo mv elements-${ELEMENTS_VERSION}/bin/* /usr/local/bin
6565
rm -rf \
66-
bitcoin-$BITCOIN_VERSION-x86_64-linux-gnu.tar.gz \
67-
bitcoin-$BITCOIN_VERSION \
68-
elements-$ELEMENTS_VERSION-x86_64-linux-gnu.tar.bz2 \
69-
elements-$ELEMENTS_VERSION
66+
bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz \
67+
bitcoin-${BITCOIN_VERSION} \
68+
elements-${ELEMENTS_VERSION}-x86_64-linux-gnu.tar.gz \
69+
elements-${ELEMENTS_VERSION}
7070
)
7171

7272
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ jobs:
170170
env:
171171
COMPAT: 1
172172
BITCOIN_VERSION: 24.0.1
173-
ELEMENTS_VERSION: 0.18.1.8
173+
ELEMENTS_VERSION: 22.0.2
174174
RUST_PROFILE: release # Has to match the one in the compile step
175175
needs:
176176
- compile
@@ -277,7 +277,7 @@ jobs:
277277
env:
278278
COMPAT: 1
279279
BITCOIN_VERSION: 24.0.1
280-
ELEMENTS_VERSION: 0.18.1.8
280+
ELEMENTS_VERSION: 22.0.2
281281
RUST_PROFILE: release # Has to match the one in the compile step
282282
VALGRIND: 1
283283
CFG: gcc-dev1-exp1

contrib/pyln-testing/pyln/testing/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None):
547547
'-nowallet',
548548
'-validatepegin=0',
549549
'-con_blocksubsidy=5000000000',
550+
'-acceptnonstdtxn=1', # FIXME Issues such as dust limit interacting with anchors
550551
]
551552
conf_file = os.path.join(bitcoin_dir, 'elements.conf')
552553
config['rpcport'] = self.rpcport

tests/test_misc.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ def test_htlc_in_timeout(node_factory, bitcoind, executor):
436436
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
437437

438438

439-
@unittest.skipIf(not TEST_NETWORK == 'regtest', 'must be on bitcoin network')
439+
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', 'must be on bitcoin network')
440440
@pytest.mark.developer("needs DEVELOPER=1")
441441
def test_bech32_funding(node_factory, chainparams):
442442
# Don't get any funds from previous runs.
@@ -461,7 +461,6 @@ def is_p2wpkh(output):
461461
assert only_one(fundingtx['vin'])['txid'] == res['wallettxid']
462462

463463

464-
@unittest.skipIf(not TEST_NETWORK == 'regtest', 'no support for PSETv0')
465464
def test_withdraw_misc(node_factory, bitcoind, chainparams):
466465
def dont_spend_outputs(n, txid):
467466
"""Reserve both outputs (we assume there are two!) in case any our ours, so we don't spend change: wrecks accounting checks"""

tests/test_wallet.py

Lines changed: 133 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,6 @@ def test_txprepare(node_factory, bitcoind, chainparams):
441441
assert decode['vout'][changenum]['scriptPubKey']['type'] == 'witness_v0_keyhash'
442442

443443

444-
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
445444
def test_reserveinputs(node_factory, bitcoind, chainparams):
446445
amount = 1000000
447446
total_outs = 12
@@ -495,12 +494,14 @@ def test_reserveinputs(node_factory, bitcoind, chainparams):
495494
assert not any('reserved_to_block' in o for o in l1.rpc.listfunds()['outputs'])
496495

497496

498-
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
499497
def test_fundpsbt(node_factory, bitcoind, chainparams):
500498
amount = 1000000
501499
total_outs = 4
502500
l1 = node_factory.get_node()
503501

502+
# CLN returns PSBTv0 and PSETv2, for now
503+
is_psbt_v2 = chainparams['elements']
504+
504505
outputs = []
505506
# Add a medley of funds to withdraw later
506507
for i in range(total_outs):
@@ -515,22 +516,35 @@ def test_fundpsbt(node_factory, bitcoind, chainparams):
515516

516517
# Should get one input, plus some excess
517518
funding = l1.rpc.fundpsbt(amount // 2, feerate, 0, reserve=0)
519+
518520
psbt = bitcoind.rpc.decodepsbt(funding['psbt'])
519521
# We can fuzz this up to 99 blocks back.
520-
assert psbt['tx']['locktime'] > bitcoind.rpc.getblockcount() - 100
521-
assert psbt['tx']['locktime'] <= bitcoind.rpc.getblockcount()
522-
assert len(psbt['tx']['vin']) == 1
523522
assert funding['excess_msat'] > Millisatoshi(0)
524523
assert funding['excess_msat'] < Millisatoshi(amount // 2 * 1000)
525524
assert funding['feerate_per_kw'] == 7500
526525
assert 'estimated_final_weight' in funding
527526
assert 'reservations' not in funding
528527

528+
if is_psbt_v2:
529+
assert psbt['fallback_locktime'] > bitcoind.rpc.getblockcount() - 100
530+
assert psbt['fallback_locktime'] <= bitcoind.rpc.getblockcount()
531+
assert psbt['input_count'] == 1
532+
else:
533+
assert psbt['tx']['locktime'] > bitcoind.rpc.getblockcount() - 100
534+
assert psbt['tx']['locktime'] <= bitcoind.rpc.getblockcount()
535+
assert len(psbt['tx']['vin']) == 1
536+
529537
# This should add 99 to the weight, but otherwise be identical (might choose different inputs though!) except for locktime.
530538
funding2 = l1.rpc.fundpsbt(amount // 2, feerate, 99, reserve=0, locktime=bitcoind.rpc.getblockcount() + 1)
531539
psbt2 = bitcoind.rpc.decodepsbt(funding2['psbt'])
532-
assert psbt2['tx']['locktime'] == bitcoind.rpc.getblockcount() + 1
533-
assert len(psbt2['tx']['vin']) == 1
540+
541+
if is_psbt_v2:
542+
assert psbt2['fallback_locktime'] == bitcoind.rpc.getblockcount() + 1
543+
assert psbt2['input_count'] == 1
544+
else:
545+
assert psbt2['tx']['locktime'] == bitcoind.rpc.getblockcount() + 1
546+
assert len(psbt2['tx']['vin']) == 1
547+
534548
assert funding2['excess_msat'] < funding['excess_msat']
535549
assert funding2['feerate_per_kw'] == 7500
536550
# Naively you'd expect this to be +99, but it might have selected a non-p2sh output...
@@ -548,7 +562,12 @@ def test_fundpsbt(node_factory, bitcoind, chainparams):
548562
assert funding3['excess_msat'] == Millisatoshi(0)
549563
# Should have the excess msat as the output value (minus fee for change)
550564
psbt = bitcoind.rpc.decodepsbt(funding3['psbt'])
551-
change = Millisatoshi("{}btc".format(psbt['tx']['vout'][funding3['change_outnum']]['value']))
565+
566+
if is_psbt_v2:
567+
change = Millisatoshi("{}btc".format(psbt["outputs"][funding3['change_outnum']]["amount"]))
568+
else:
569+
change = Millisatoshi("{}btc".format(psbt['tx']['vout'][funding3['change_outnum']]['value']))
570+
552571
# The weight should be greater (now includes change output)
553572
change_weight = funding3['estimated_final_weight'] - funding['estimated_final_weight']
554573
assert change_weight > 0
@@ -558,7 +577,10 @@ def test_fundpsbt(node_factory, bitcoind, chainparams):
558577

559578
# Should get two inputs.
560579
psbt = bitcoind.rpc.decodepsbt(l1.rpc.fundpsbt(amount, feerate, 0, reserve=0)['psbt'])
561-
assert len(psbt['tx']['vin']) == 2
580+
if is_psbt_v2:
581+
assert psbt['input_count'] == 2
582+
else:
583+
assert len(psbt['tx']['vin']) == 2
562584

563585
# Should not use reserved outputs.
564586
psbt = bitcoind.rpc.createpsbt([{'txid': out[0], 'vout': out[1]} for out in outputs], [])
@@ -579,11 +601,13 @@ def test_fundpsbt(node_factory, bitcoind, chainparams):
579601
l1.rpc.fundpsbt(amount // 2, feerate, 0)
580602

581603

582-
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
583604
def test_utxopsbt(node_factory, bitcoind, chainparams):
584605
amount = 1000000
585606
l1 = node_factory.get_node()
586607

608+
# CLN returns PSBTv0 and PSETv2, for now
609+
is_psbt_v2 = chainparams['elements']
610+
587611
outputs = []
588612
# Add a funds to withdraw later
589613
for _ in range(2):
@@ -603,27 +627,40 @@ def test_utxopsbt(node_factory, bitcoind, chainparams):
603627
reserve=0)
604628
psbt = bitcoind.rpc.decodepsbt(funding['psbt'])
605629
# We can fuzz this up to 99 blocks back.
606-
assert psbt['tx']['locktime'] > bitcoind.rpc.getblockcount() - 100
607-
assert psbt['tx']['locktime'] <= bitcoind.rpc.getblockcount()
608-
assert len(psbt['tx']['vin']) == 1
609630
assert funding['excess_msat'] > Millisatoshi(0)
610631
assert funding['excess_msat'] < Millisatoshi(amount // 2 * 1000)
611632
assert funding['feerate_per_kw'] == 7500
612633
assert 'estimated_final_weight' in funding
613634
assert 'reservations' not in funding
614635

636+
if is_psbt_v2:
637+
assert psbt['fallback_locktime'] > bitcoind.rpc.getblockcount() - 100
638+
assert psbt['fallback_locktime'] <= bitcoind.rpc.getblockcount()
639+
assert psbt['input_count'] == 1
640+
else:
641+
assert psbt['tx']['locktime'] > bitcoind.rpc.getblockcount() - 100
642+
assert psbt['tx']['locktime'] <= bitcoind.rpc.getblockcount()
643+
assert len(psbt['tx']['vin']) == 1
644+
615645
# This should add 99 to the weight, but otherwise be identical except for locktime.
616646
start_weight = 99
617647
funding2 = l1.rpc.utxopsbt(amount // 2, feerate, start_weight,
618648
['{}:{}'.format(outputs[0][0], outputs[0][1])],
619649
reserve=0, locktime=bitcoind.rpc.getblockcount() + 1)
620650
psbt2 = bitcoind.rpc.decodepsbt(funding2['psbt'])
621-
assert psbt2['tx']['locktime'] == bitcoind.rpc.getblockcount() + 1
622-
assert psbt2['tx']['vin'] == psbt['tx']['vin']
651+
652+
if is_psbt_v2:
653+
assert psbt2['fallback_locktime'] == bitcoind.rpc.getblockcount() + 1
654+
assert psbt2['inputs'] == psbt['inputs']
655+
else:
656+
assert psbt2['tx']['locktime'] == bitcoind.rpc.getblockcount() + 1
657+
assert psbt2['tx']['vin'] == psbt['tx']['vin']
658+
623659
if chainparams['elements']:
660+
assert is_psbt_v2
624661
# elements includes the fee as an output
625662
addl_fee = Millisatoshi((fee_val * start_weight + 999) // 1000 * 1000)
626-
assert psbt2['tx']['vout'][0]['value'] == psbt['tx']['vout'][0]['value'] + addl_fee.to_btc()
663+
assert psbt2['outputs'][0]['amount'] == psbt['outputs'][0]['amount'] + addl_fee.to_btc()
627664
else:
628665
assert psbt2['tx']['vout'] == psbt['tx']['vout']
629666
assert funding2['excess_msat'] < funding['excess_msat']
@@ -649,7 +686,11 @@ def test_utxopsbt(node_factory, bitcoind, chainparams):
649686
assert funding3['excess_msat'] == Millisatoshi(0)
650687
# Should have the excess msat as the output value (minus fee for change)
651688
psbt = bitcoind.rpc.decodepsbt(funding3['psbt'])
652-
change = Millisatoshi("{}btc".format(psbt['tx']['vout'][funding3['change_outnum']]['value']))
689+
if is_psbt_v2:
690+
change = Millisatoshi("{}btc".format(psbt['outputs'][funding3['change_outnum']]['amount']))
691+
else:
692+
change = Millisatoshi("{}btc".format(psbt['tx']['vout'][funding3['change_outnum']]['value']))
693+
653694
# The weight should be greater (now includes change output)
654695
change_weight = funding3['estimated_final_weight'] - funding['estimated_final_weight']
655696
assert change_weight > 0
@@ -670,7 +711,10 @@ def test_utxopsbt(node_factory, bitcoind, chainparams):
670711
['{}:{}'.format(outputs[0][0], outputs[0][1]),
671712
'{}:{}'.format(outputs[1][0], outputs[1][1])])
672713
psbt = bitcoind.rpc.decodepsbt(funding['psbt'])
673-
assert len(psbt['tx']['vin']) == 2
714+
if is_psbt_v2:
715+
assert psbt['input_count'] == 2
716+
else:
717+
assert len(psbt['tx']['vin']) == 2
674718
assert len(funding['reservations']) == 2
675719
assert funding['reservations'][0]['txid'] == outputs[0][0]
676720
assert funding['reservations'][0]['vout'] == outputs[0][1]
@@ -694,7 +738,6 @@ def test_utxopsbt(node_factory, bitcoind, chainparams):
694738
reservedok=True)
695739

696740

697-
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
698741
def test_sign_external_psbt(node_factory, bitcoind, chainparams):
699742
"""
700743
A PSBT w/ one of our inputs should be signable (we can fill
@@ -723,11 +766,64 @@ def test_sign_external_psbt(node_factory, bitcoind, chainparams):
723766
l1.rpc.signpsbt(psbt)
724767

725768

726-
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
769+
def test_psbt_version(node_factory, bitcoind, chainparams):
770+
771+
sats_amount = 10**8
772+
773+
# CLN returns PSBTv0 and PSETv2, for now
774+
is_elements = chainparams['elements']
775+
776+
l1 = node_factory.get_node()
777+
bitcoind.rpc.sendtoaddress(l1.rpc.newaddr()['bech32'],
778+
sats_amount / 100000000)
779+
780+
bitcoind.generate_block(1)
781+
wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 1)
782+
783+
funding = l1.rpc.fundpsbt(satoshi=int(sats_amount / 2),
784+
feerate=7500,
785+
startweight=42)['psbt']
786+
787+
# Short elements test
788+
if is_elements:
789+
# Only v2 is allowed, and is a no-op
790+
for i in [0, 1, 3, 4, 5]:
791+
with pytest.raises(RpcError, match=r"Could not set PSBT version"):
792+
l1.rpc.setpsbtversion(funding, i)
793+
assert funding == l1.rpc.setpsbtversion(funding, 2)['psbt']
794+
# And elementsd can understand it
795+
bitcoind.rpc.decodepsbt(funding)
796+
return
797+
798+
# Non-elements test
799+
v2_funding = l1.rpc.setpsbtversion(funding, 2)['psbt']
800+
801+
# Bitcoind cannot understand PSBTv2 yet
802+
with pytest.raises(JSONRPCError, match=r"TX decode failed Unsupported version number"):
803+
bitcoind.rpc.decodepsbt(v2_funding)
804+
805+
# But it round-trips fine enough
806+
v0_funding = l1.rpc.setpsbtversion(v2_funding, 0)['psbt']
807+
808+
# CLN returns v0 for now
809+
assert funding == v0_funding
810+
811+
# And we reject non-0/2 args
812+
for i in [1, 3, 4, 5]:
813+
with pytest.raises(RpcError, match=r"Could not set PSBT version"):
814+
l1.rpc.setpsbtversion(v2_funding, i)
815+
816+
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', 'Core/Elements need joinpsbt support for v2')
727817
def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
728818
"""
729819
Tests for the sign + send psbt RPCs
730820
"""
821+
# CLN returns PSBTv0 and PSETv2, for now
822+
is_psbt_v2 = chainparams['elements']
823+
824+
# Once support for v2 joinpsbt is added, below test should work verbatim
825+
assert not is_psbt_v2
826+
731827
amount = 1000000
732828
total_outs = 12
733829
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
@@ -750,16 +846,24 @@ def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
750846
startweight=42)
751847
assert len([x for x in l1.rpc.listfunds()['outputs'] if x['reserved']]) == 4
752848
psbt = bitcoind.rpc.decodepsbt(funding['psbt'])
753-
saved_input = psbt['tx']['vin'][0]
849+
if is_psbt_v2:
850+
saved_input = psbt['inputs'][0]
851+
else:
852+
saved_input = psbt['tx']['vin'][0]
754853

755854
# Go ahead and unreserve the UTXOs, we'll use a smaller
756855
# set of them to create a second PSBT that we'll attempt to sign
757856
# and broadcast (to disastrous results)
758857
l1.rpc.unreserveinputs(funding['psbt'])
759858

760859
# Re-reserve one of the utxos we just unreserved
761-
psbt = bitcoind.rpc.createpsbt([{'txid': saved_input['txid'],
762-
'vout': saved_input['vout']}], [])
860+
if is_psbt_v2:
861+
psbt = bitcoind.rpc.createpsbt([{'txid': saved_input['previous_txid'],
862+
'vout': saved_input['previous_vout']}], [])
863+
else:
864+
psbt = bitcoind.rpc.createpsbt([{'txid': saved_input['txid'],
865+
'vout': saved_input['vout']}], [])
866+
763867
l1.rpc.reserveinputs(psbt)
764868

765869
# We require the utxos be reserved before signing them
@@ -823,8 +927,12 @@ def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
823927
l1_funding = l1.rpc.fundpsbt(satoshi=out_total,
824928
feerate=7500,
825929
startweight=42)
826-
l1_num_inputs = len(bitcoind.rpc.decodepsbt(l1_funding['psbt'])['tx']['vin'])
827-
l2_num_inputs = len(bitcoind.rpc.decodepsbt(l2_funding['psbt'])['tx']['vin'])
930+
if is_psbt_v2:
931+
l1_num_inputs = bitcoind.rpc.decodepsbt(l1_funding['psbt'])["input_count"]
932+
l2_num_inputs = bitcoind.rpc.decodepsbt(l2_funding['psbt'])["input_count"]
933+
else:
934+
l1_num_inputs = len(bitcoind.rpc.decodepsbt(l1_funding['psbt'])['tx']['vin'])
935+
l2_num_inputs = len(bitcoind.rpc.decodepsbt(l2_funding['psbt'])['tx']['vin'])
828936

829937
# Join and add an output (reorders!)
830938
out_2_ms = Millisatoshi(l1_funding['excess_msat'])

0 commit comments

Comments
 (0)