(node_factory, bitcoind, executor)
| 1424 | @unittest.skipIf(SLOW_MACHINE and not VALGRIND, "Way too taxing on CI machines") |
| 1425 | @pytest.mark.openchannel('v1') |
| 1426 | def test_funding_cancel_race(node_factory, bitcoind, executor): |
| 1427 | l1 = node_factory.get_node() |
| 1428 | |
| 1429 | # make sure we can generate PSBTs. |
| 1430 | addr = l1.rpc.newaddr()['bech32'] |
| 1431 | bitcoind.rpc.sendtoaddress(addr, 200000 / 10**8) |
| 1432 | bitcoind.generate_block(1) |
| 1433 | wait_for(lambda: len(l1.rpc.listfunds()["outputs"]) != 0) |
| 1434 | |
| 1435 | if node_factory.valgrind: |
| 1436 | num = 5 |
| 1437 | else: |
| 1438 | num = 100 |
| 1439 | |
| 1440 | # Allow the other nodes to log unexpected WIRE_FUNDING_CREATED messages |
| 1441 | nodes = node_factory.get_nodes(num, opts={'allow_broken_log': True}) |
| 1442 | |
| 1443 | num_complete = 0 |
| 1444 | num_cancel = 0 |
| 1445 | |
| 1446 | for count, n in enumerate(nodes): |
| 1447 | l1.rpc.connect(n.info['id'], 'localhost', n.port) |
| 1448 | start = l1.rpc.fundchannel_start(n.info['id'], "100000sat") |
| 1449 | |
| 1450 | prep = l1.rpc.txprepare([{start['funding_address']: "100000sat"}]) |
| 1451 | |
| 1452 | # Submit two of each at once. |
| 1453 | completes = [] |
| 1454 | cancels = [] |
| 1455 | |
| 1456 | # Switch order around. |
| 1457 | for i in range(4): |
| 1458 | if (i + count) % 2 == 0: |
| 1459 | completes.append(executor.submit(l1.rpc.fundchannel_complete, n.info['id'], prep['psbt'])) |
| 1460 | else: |
| 1461 | cancels.append(executor.submit(l1.rpc.fundchannel_cancel, n.info['id'])) |
| 1462 | |
| 1463 | # Only up to one should succeed. |
| 1464 | success = False |
| 1465 | for c in completes: |
| 1466 | try: |
| 1467 | c.result(TIMEOUT) |
| 1468 | num_complete += 1 |
| 1469 | assert not success |
| 1470 | success = True |
| 1471 | except RpcError: |
| 1472 | pass |
| 1473 | |
| 1474 | # At least one of these must succeed, regardless of whether |
| 1475 | # the completes succeeded or not. |
| 1476 | cancelled = False |
| 1477 | for c in cancels: |
| 1478 | try: |
| 1479 | c.result(TIMEOUT) |
| 1480 | cancelled = True |
| 1481 | except RpcError: |
| 1482 | pass |
| 1483 | # cancel always succeeds, as per Sequential Consistency. |
nothing calls this directly
no test coverage detected