Skip to content

Commit da1c130

Browse files
committed
tests: update upfront close to use the dual-funded pathway
Not sure what the best way to gate/split tests is.
1 parent d882da3 commit da1c130

File tree

3 files changed

+47
-38
lines changed

3 files changed

+47
-38
lines changed

tests/plugins/accepter_close_to.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,38 @@
1414
plugin = Plugin()
1515

1616

17+
def extract_opening_amount(openchannel):
18+
key = 'opener_satoshis' if 'version' in openchannel and openchannel['version'] == 2 else 'funding_satoshis'
19+
return Millisatoshi(openchannel[key])
20+
21+
1722
@plugin.hook('openchannel')
1823
def on_openchannel(openchannel, plugin, **kwargs):
24+
ret = {'result': 'continue'}
25+
amt_msat = extract_opening_amount(openchannel)
26+
amt = amt_msat.to_satoshi()
27+
28+
if openchannel['version'] == 2:
29+
# We match their funds. Always.
30+
ret['funding_sats'] = amt_msat.to_satoshi_str()
31+
1932
# - a multiple of 11: we send back a valid address (regtest)
20-
if Millisatoshi(openchannel['funding_satoshis']).to_satoshi() % 11 == 0:
21-
return {'result': 'continue', 'close_to': 'bcrt1q7gtnxmlaly9vklvmfj06amfdef3rtnrdazdsvw'}
33+
if amt % 11 == 0:
34+
ret['close_to'] = 'bcrt1q7gtnxmlaly9vklvmfj06amfdef3rtnrdazdsvw'
35+
return ret
2236

2337
# - a multiple of 7: we send back an empty address
24-
if Millisatoshi(openchannel['funding_satoshis']).to_satoshi() % 7 == 0:
25-
return {'result': 'continue', 'close_to': ''}
38+
if amt % 7 == 0:
39+
ret['close_to'] = ''
40+
return ret
2641

2742
# - a multiple of 5: we send back an address for the wrong chain (mainnet)
28-
if Millisatoshi(openchannel['funding_satoshis']).to_satoshi() % 5 == 0:
29-
return {'result': 'continue', 'close_to': 'bc1qlq8srqnz64wgklmqvurv7qnr4rvtq2u96hhfg2'}
43+
if amt % 5 == 0:
44+
ret['close_to'] = 'bc1qlq8srqnz64wgklmqvurv7qnr4rvtq2u96hhfg2'
45+
return ret
3046

3147
# - otherwise: we don't include the close_to
32-
return {'result': 'continue'}
48+
return ret
3349

3450

3551
plugin.run()

tests/plugins/funder.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515

1616
@plugin.hook("openchannel")
1717
def on_openchannel(openchannel, plugin, **kwargs):
18-
if openchannel['version'] == "1":
18+
if openchannel['version'] == 1:
1919
raise ValueError("Not to be used with v1")
2020

2121
their_funds = Millisatoshi(openchannel['opener_satoshis'])
2222
# We send back our maximum available funds
2323
if their_funds.to_satoshi() % 2 == 1:
2424
our_funds = Millisatoshi(openchannel['available_funds'])
25-
return {'result': 'continue', 'funding_sats': our_funds}
25+
return {'result': 'continue', 'funding_sats': our_funds.to_satoshi_str()}
2626
else:
27-
return {'result': 'continue', 'funding_sats': their_funds}
27+
return {'result': 'continue', 'funding_sats': their_funds.to_satoshi_str()}
2828

2929

3030
plugin.run()

tests/test_connection.py

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from fixtures import TEST_NETWORK
55
from flaky import flaky # noqa: F401
66
from lightning import RpcError
7-
from utils import DEVELOPER, only_one, wait_for, sync_blockheight, VALGRIND, TIMEOUT, SLOW_MACHINE, COMPAT, expected_features
7+
from utils import DEVELOPER, only_one, wait_for, sync_blockheight, VALGRIND, TIMEOUT, SLOW_MACHINE, COMPAT, expected_features, EXPERIMENTAL_FEATURES
88
from bitcoin.core import CMutableTransaction, CMutableTxOut
99

1010
import binascii
@@ -1110,12 +1110,16 @@ def test_funding_cancel_race(node_factory, bitcoind, executor):
11101110

11111111

11121112
@unittest.skipIf(TEST_NETWORK != 'regtest', "External wallet support doesn't work with elements yet.")
1113+
@unittest.skipIf(not EXPERIMENTAL_FEATURES, "Dual funding needs experimental")
11131114
def test_funding_close_upfront(node_factory, bitcoind):
11141115
l1 = node_factory.get_node()
11151116

11161117
opts = {'plugin': os.path.join(os.getcwd(), 'tests/plugins/accepter_close_to.py')}
11171118
l2 = node_factory.get_node(options=opts)
11181119

1120+
l1.fundwallet(100000000)
1121+
l2.fundwallet(100000000)
1122+
11191123
# The 'accepter_close_to' plugin uses the channel funding amount to determine
11201124
# whether or not to include a 'close_to' address
11211125
amt_normal = 100007 # continues without returning a close_to
@@ -1128,44 +1132,31 @@ def _fundchannel(l1, l2, amount, close_to):
11281132
assert(l1.rpc.listpeers()['peers'][0]['id'] == l2.info['id'])
11291133

11301134
resp = l1.rpc.fundchannel_start(l2.info['id'], amount, close_to=close_to)
1131-
address = resp['funding_address']
1135+
funding_addr = resp['funding_address']
11321136

11331137
if close_to:
11341138
assert resp['close_to']
11351139
else:
11361140
assert 'close_to' not in resp
11371141

1138-
peer = l1.rpc.listpeers()['peers'][0]
1139-
# Peer should still be connected and in state waiting for funding_txid
1140-
assert peer['id'] == l2.info['id']
1141-
r = re.compile('Funding channel start: awaiting funding_txid with output to .*')
1142-
assert any(r.match(line) for line in peer['channels'][0]['status'])
1143-
assert 'OPENINGD' in peer['channels'][0]['state']
1144-
1145-
# 'Externally' fund the address from fundchannel_start
1146-
addr_scriptpubkey = bitcoind.rpc.getaddressinfo(address)['scriptPubKey']
1147-
txout = CMutableTxOut(amount, bytearray.fromhex(addr_scriptpubkey))
1148-
unfunded_tx = CMutableTransaction([], [txout])
1149-
hextx = binascii.hexlify(unfunded_tx.serialize()).decode('utf8')
1150-
1151-
funded_tx_obj = bitcoind.rpc.fundrawtransaction(hextx)
1152-
raw_funded_tx = funded_tx_obj['hex']
1153-
txid = bitcoind.rpc.decoderawtransaction(raw_funded_tx)['txid']
1154-
txout = 1 if funded_tx_obj['changepos'] == 0 else 0
1142+
prep = l1.rpc.txprepare([{funding_addr: amount}], zero_out_change=True)
1143+
decode = bitcoind.rpc.decoderawtransaction(prep['unsigned_tx'])
1144+
assert decode['txid'] == prep['txid']
11551145

1156-
assert l1.rpc.fundchannel_complete(l2.info['id'], txid, txout)['commitments_secured']
1157-
1158-
# Broadcast the transaction manually and confirm that channel locks in
1159-
signed_tx = bitcoind.rpc.signrawtransactionwithwallet(raw_funded_tx)['hex']
1160-
assert txid == bitcoind.rpc.decoderawtransaction(signed_tx)['txid']
1146+
# One output will be correct.
1147+
if decode['vout'][0]['value'] == Decimal(str(amount / 10 ** 8)):
1148+
txout = 0
1149+
elif decode['vout'][1]['value'] == Decimal(str(amount / 10 ** 8)):
1150+
txout = 1
1151+
else:
1152+
assert False
11611153

1162-
bitcoind.rpc.sendrawtransaction(signed_tx)
1154+
txid = l1.rpc.fundchannel_complete(l2.info['id'], prep['txid'], txout)['txid']
1155+
l1.rpc.txsend(txid)
11631156
bitcoind.generate_block(1)
11641157

11651158
for node in [l1, l2]:
11661159
node.daemon.wait_for_log(r'State changed from CHANNELD_AWAITING_LOCKIN to CHANNELD_NORMAL')
1167-
channel = node.rpc.listpeers()['peers'][0]['channels'][-1]
1168-
assert amount * 1000 == channel['msatoshi_total']
11691160

11701161
# check that normal peer close works
11711162
_fundchannel(l1, l2, amt_normal, None)
@@ -1184,9 +1175,11 @@ def _fundchannel(l1, l2, amount, close_to):
11841175
addr = bitcoind.rpc.getnewaddress()
11851176
_fundchannel(l1, l2, amt_normal, addr)
11861177
assert addr == only_one(l1.rpc.listpeers()['peers'])['channels'][2]['close_to_addr']
1178+
l2_close_to_addr = l2.rpc.listpeers()['peers'][0]['channels'][-1]['close_to_addr']
11871179
resp = l1.rpc.close(l2.info['id'], destination=addr)
11881180
assert resp['type'] == 'mutual'
1189-
assert only_one(only_one(bitcoind.rpc.decoderawtransaction(resp['tx'])['vout'])['scriptPubKey']['addresses']) == addr
1181+
for vout in bitcoind.rpc.decoderawtransaction(resp['tx'])['vout']:
1182+
assert only_one(vout['scriptPubKey']['addresses']) in [addr, l2_close_to_addr]
11901183

11911184
# check that remote peer closing works as expected (and that remote's close_to works)
11921185
_fundchannel(l1, l2, amt_addr, addr)

0 commit comments

Comments
 (0)