From 8f8571c1e02bb23e384b8ff3b92a5a7a10b2125e Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Wed, 16 Mar 2022 12:33:07 -0700 Subject: [PATCH 01/14] fixup: Rename formal parameter name to avoid C++ reserved word. --- common/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils.h b/common/utils.h index 982492245d0f..3b37661a153d 100644 --- a/common/utils.h +++ b/common/utils.h @@ -136,7 +136,7 @@ extern const tal_t *wally_tal_ctx; /* Like mkstemp but resolves template relative to $TMPDIR (or /tmp if unset). * Returns created temporary path name at *created if successful. */ -int tmpdir_mkstemp(const tal_t *ctx, const char *template TAKES, char **created); +int tmpdir_mkstemp(const tal_t *ctx, const char *tmplt TAKES, char **created); /** * tal_strlowering - return the same string by in lower case. From 58a84ffadee281d2c6286898376ecc7ed2a16c24 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Tue, 14 Feb 2023 14:53:35 -0800 Subject: [PATCH 02/14] ci: add curl to setup.sh --- .github/scripts/setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/scripts/setup.sh b/.github/scripts/setup.sh index 59a092051897..dc57215668aa 100755 --- a/.github/scripts/setup.sh +++ b/.github/scripts/setup.sh @@ -15,6 +15,7 @@ sudo apt-get -qq install --no-install-recommends --allow-unauthenticated -yy \ build-essential \ clang \ cppcheck \ + curl \ docbook-xml \ eatmydata \ gcc-aarch64-linux-gnu \ From 0341470fdf5d66798cd509354819c26bce525e28 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Tue, 9 May 2023 14:57:57 -0700 Subject: [PATCH 03/14] gitignore VLS proxy daemons --- lightningd/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lightningd/.gitignore b/lightningd/.gitignore index 4ba7a1a9cec2..576e635ee243 100644 --- a/lightningd/.gitignore +++ b/lightningd/.gitignore @@ -8,3 +8,5 @@ lightning_hsmd lightning_onchaind lightning_openingd lightning_websocketd +remote_hsmd_serial +remote_hsmd_socket From 152510f24755445a4f59e1c747f3a48aa9399615 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Thu, 16 Nov 2023 06:41:09 -0800 Subject: [PATCH 04/14] tests: add PYTEST_MOREOPTS so users can extend the options --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fd2b38e41546..7ce942db0cbb 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ COMPAT_CFLAGS=-DCOMPAT_V052=1 -DCOMPAT_V060=1 -DCOMPAT_V061=1 -DCOMPAT_V062=1 -D endif # (method=thread to support xdist) -PYTEST_OPTS := -v -p no:logging $(PYTEST_OPTS) +PYTEST_OPTS := -v -p no:logging $(PYTEST_OPTS) $(PYTEST_MOREOPTS) MY_CHECK_PYTHONPATH=$${PYTHONPATH}$${PYTHONPATH:+:}$(shell pwd)/contrib/pyln-client:$(shell pwd)/contrib/pyln-testing:$(shell pwd)/contrib/pyln-proto/:$(shell pwd)/external/lnprototest:$(shell pwd)/contrib/pyln-spec/bolt1:$(shell pwd)/contrib/pyln-spec/bolt2:$(shell pwd)/contrib/pyln-spec/bolt4:$(shell pwd)/contrib/pyln-spec/bolt7 # Collect generated python files to be excluded from lint checks PYTHON_GENERATED= \ From 454fff273256f378271bee3d97164044e3e64e64 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Tue, 21 Nov 2023 11:14:00 -0800 Subject: [PATCH 05/14] tests: add TEST_KEEPDIR to prevent cleanup of successful tests --- contrib/pyln-testing/pyln/testing/fixtures.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/pyln-testing/pyln/testing/fixtures.py b/contrib/pyln-testing/pyln/testing/fixtures.py index 4bfce3578d1d..f4761b6be4fc 100644 --- a/contrib/pyln-testing/pyln/testing/fixtures.py +++ b/contrib/pyln-testing/pyln/testing/fixtures.py @@ -31,6 +31,9 @@ def test_base_dir(): yield directory + if bool(int(os.getenv('TEST_KEEPDIR', '0'))): + return + # Now check if any test directory is left because the corresponding test # failed. If there are no such tests we can clean up the root test # directory. @@ -92,7 +95,7 @@ def directory(request, test_base_dir, test_name): outcome = 'passed' if rep_call is None else rep_call.outcome failed = not outcome or request.node.has_errors or outcome != 'passed' - if not failed: + if not failed and not bool(int(os.getenv('TEST_KEEPDIR', '0'))): try: shutil.rmtree(directory) except OSError: From c11214616cc27d15bc5021d4b04f29f814ff3b04 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Tue, 21 Nov 2023 11:14:46 -0800 Subject: [PATCH 06/14] tests: add VLS to CLN integration suite --- contrib/pyln-testing/pyln/testing/utils.py | 137 ++++++++++++++++++++- 1 file changed, 132 insertions(+), 5 deletions(-) diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 7f39637d2c76..6884fd05084c 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -78,6 +78,7 @@ def env(name, default=None): SLOW_MACHINE = env("SLOW_MACHINE", "0") == "1" DEPRECATED_APIS = env("DEPRECATED_APIS", "0") == "1" TIMEOUT = int(env("TIMEOUT", 180 if SLOW_MACHINE else 60)) +SUBDAEMON = env("SUBDAEMON", "") EXPERIMENTAL_DUAL_FUND = env("EXPERIMENTAL_DUAL_FUND", "0") == "1" EXPERIMENTAL_SPLICING = env("EXPERIMENTAL_SPLICING", "0") == "1" @@ -578,6 +579,43 @@ def getnewaddress(self): return info['unconfidential'] +class ValidatingLightningSignerD(TailableProc): + def __init__(self, vlsd_dir, vlsd_port, node_id, network): + TailableProc.__init__(self, vlsd_dir, verbose=True) + self.executable = env("REMOTE_SIGNER_CMD", 'vlsd2') + os.environ['ALLOWLIST'] = env( + 'REMOTE_SIGNER_ALLOWLIST', + 'contrib/remote_hsmd/TESTING_ALLOWLIST') + self.opts = [ + '--network={}'.format(network), + '--datadir={}'.format(vlsd_dir), + '--connect=http://localhost:{}'.format(vlsd_port), + '--integration-test', + ] + self.prefix = 'vlsd2-%d' % (node_id) + self.vlsd_port = vlsd_port + + @property + def cmd_line(self): + return [self.executable] + self.opts + + def start(self, stdin=None, stdout_redir=True, stderr_redir=True, + wait_for_initialized=True): + TailableProc.start(self, stdin, stdout_redir, stderr_redir) + # We need to always wait for initialization + self.wait_for_log("vlsd2 git_desc") + logging.info("vlsd2 started") + + def stop(self, timeout=10): + logging.info("stopping vlsd2") + rc = TailableProc.stop(self, timeout) + logging.info("vlsd2 stopped") + self.logs_catchup() + return rc + + def __del__(self): + self.logs_catchup() + class LightningD(TailableProc): def __init__( self, @@ -594,6 +632,12 @@ def __init__( self.lightning_dir = lightning_dir self.port = port self.cmd_prefix = [] + self.lightning_dir = lightning_dir + self.use_vlsd = False + self.vlsd_dir = os.path.join(lightning_dir, "vlsd") + self.vlsd_port = None + self.vlsd = None + self.node_id = node_id self.rpcproxy = bitcoindproxy self.env['CLN_PLUGIN_LOG'] = "cln_plugin=trace,cln_rpc=trace,cln_grpc=trace,debug" @@ -616,12 +660,38 @@ def __init__( if grpc_port is not None: opts['grpc-port'] = grpc_port + if SUBDAEMON: + assert node_id > 0 + subdaemons = SUBDAEMON.split(',') + # VLS_SERIAL_SELECT "swaps" the selected item with the first item + select = env("VLS_SERIAL_SELECT", '1') + if node_id == int(select): + ndx = 1 + elif node_id == 1: + ndx = int(select) + else: + ndx = node_id + if ndx > len(subdaemons): + # use the last element if not as many specifiers as nodes + opts['subdaemon'] = subdaemons[-1] + else: + # use the matching specifier + opts['subdaemon'] = subdaemons[ndx - 1] + + print(f"starting node {node_id} with subdaemon {opts['subdaemon']}") + if SUBDAEMON == 'hsmd:remote_hsmd_socket': + self.use_vlsd = True + for k, v in opts.items(): self.opts[k] = v if not os.path.exists(os.path.join(lightning_dir, TEST_NETWORK)): os.makedirs(os.path.join(lightning_dir, TEST_NETWORK)) + if self.use_vlsd: + if not os.path.exists(self.vlsd_dir): + os.makedirs(self.vlsd_dir) + # Last 32-bytes of final part of dir -> seed. seed = (bytes(re.search('([^/]+)/*$', lightning_dir).group(1), encoding='utf-8') + bytes(32))[:32] if not random_hsm: @@ -637,6 +707,10 @@ def __init__( self.early_opts = ['--developer'] def cleanup(self): + if self.use_vlsd: + # Make sure the remotesigner is shutdown + self.vlsd.stop() + # To force blackhole to exit, disconnect file must be truncated! if 'dev-disconnect' in self.opts: with open(self.opts['dev-disconnect'], "w") as f: @@ -657,12 +731,65 @@ def cmd_line(self): return self.cmd_prefix + [self.executable] + self.early_opts + opts + def __del__(self): + if self.vlsd_port is not None: + drop_unused_port(self.vlsd_port) + def start(self, stdin=None, wait_for_initialized=True, stderr_redir=False): - self.opts['bitcoin-rpcport'] = self.rpcproxy.rpcport - TailableProc.start(self, stdin, stdout_redir=False, stderr_redir=stderr_redir) - if wait_for_initialized: - self.wait_for_log("Server started with public key") - logging.info("LightningD started") + try: + self.env['VLS_LSS'] = f"http://localhost:{self.lssd_port}" + self.env['RUST_LOG'] = 'debug' + # Some of the remote hsmd proxies need a bitcoind RPC connection + self.env['BITCOIND_RPC_URL'] = 'http://{}:{}@localhost:{}'.format( + BITCOIND_CONFIG['rpcuser'], + BITCOIND_CONFIG['rpcpassword'], + BITCOIND_CONFIG['rpcport']) + + # The remote hsmd proxies need to know which network we are using + if 'network' in self.opts: + self.env['VLS_NETWORK'] = self.opts['network'] + + self.opts['bitcoin-rpcport'] = self.rpcproxy.rpcport + + if self.use_vlsd: + self.vlsd_port = reserve_unused_port() + # We can't do this in the constructor because we need a new port on each restart. + self.env['VLS_PORT'] = str(self.vlsd_port) + # Kill any previous vlsd (we may have been restarted) + if self.vlsd is not None: + logging.info("killing prior vlsd") + self.vlsd.kill() + + TailableProc.start(self, stdin, stdout_redir=False, stderr_redir=stderr_redir) + + if self.use_vlsd: + # Start the remote signer first + self.vlsd = ValidatingLightningSignerD( + self.vlsd_dir, self.vlsd_port, self.node_id, self.opts['network']) + self.vlsd.start( + stdin, stdout_redir=True, stderr_redir=True, + wait_for_initialized=wait_for_initialized) + + if wait_for_initialized: + self.wait_for_log("Server started with public key") + logging.info("LightningD started") + except Exception: + if self.use_vlsd: + # LightningD didn't start, stop the remotesigner + self.vlsd.stop() + raise + + def stop(self, timeout=10): + if self.use_vlsd: + # Stop the remote signer first + self.vlsd.stop(timeout) + return TailableProc.stop(self, timeout) + + def kill(self): + if self.use_vlsd: + # Kill the remote signer first + self.vlsd.kill() + TailableProc.kill(self) def wait(self, timeout=TIMEOUT): """Wait for the daemon to stop for up to timeout seconds From 014092d8cd736d8c9471547e1b4a618570458f67 Mon Sep 17 00:00:00 2001 From: Devrandom Date: Tue, 4 Oct 2022 10:24:05 +0200 Subject: [PATCH 07/14] tests: integrate lssd --- contrib/pyln-testing/pyln/testing/fixtures.py | 24 ++++++++- contrib/pyln-testing/pyln/testing/utils.py | 50 +++++++++++++++++-- tests/fixtures.py | 2 +- tests/test_misc.py | 4 +- 4 files changed, 72 insertions(+), 8 deletions(-) diff --git a/contrib/pyln-testing/pyln/testing/fixtures.py b/contrib/pyln-testing/pyln/testing/fixtures.py index f4761b6be4fc..17a7ec27a69e 100644 --- a/contrib/pyln-testing/pyln/testing/fixtures.py +++ b/contrib/pyln-testing/pyln/testing/fixtures.py @@ -1,6 +1,6 @@ from concurrent import futures from pyln.testing.db import SqliteDbProvider, PostgresDbProvider -from pyln.testing.utils import NodeFactory, BitcoinD, ElementsD, env, LightningNode, TEST_DEBUG +from pyln.testing.utils import NodeFactory, BitcoinD, ElementsD, env, LightningNode, TEST_DEBUG, LssD from pyln.client import Millisatoshi from typing import Dict @@ -167,6 +167,25 @@ def bitcoind(directory, teardown_checks): bitcoind.proc.wait() +@pytest.fixture +def lssd(directory, teardown_checks): + lssd = LssD(directory) + + try: + lssd.start() + except Exception: + lssd.stop() + raise + + yield lssd + + try: + lssd.stop() + except Exception: + lssd.proc.kill() + lssd.proc.wait() + + class TeardownErrors(object): def __init__(self): self.errors = [] @@ -449,11 +468,12 @@ def jsonschemas(): @pytest.fixture -def node_factory(request, directory, test_name, bitcoind, executor, db_provider, teardown_checks, node_cls, jsonschemas): +def node_factory(request, directory, test_name, bitcoind, lssd, executor, db_provider, teardown_checks, node_cls, jsonschemas): nf = NodeFactory( request, test_name, bitcoind, + lssd, executor, directory=directory, db_provider=db_provider, diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 6884fd05084c..d2b904994f49 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -384,6 +384,45 @@ def f(*args): return f +class LssD(TailableProc): + def __init__(self, directory, rpcport=None): + lss_dir = os.path.join(directory, 'lss') + TailableProc.__init__(self, lss_dir, verbose=False) + + if rpcport is None: + self.reserved_rpcport = reserve_unused_port() + rpcport = self.reserved_rpcport + else: + self.reserved_rpcport = None + + self.rpcport = rpcport + self.prefix = 'lss' + + if not os.path.exists(lss_dir): + os.makedirs(lss_dir) + + self.cmd_line = [ + 'lssd', + '--datadir={}'.format(lss_dir), + '--port={}'.format(rpcport), + ] + + def __del__(self): + if self.reserved_rpcport is not None: + drop_unused_port(self.reserved_rpcport) + + def start(self): + self.env['RUST_LOG'] = 'debug' + TailableProc.start(self) + self.wait_for_log("ready on", timeout=TIMEOUT) + + logging.info("LssD started") + + def stop(self): + logging.info("Stopping LssD") + return TailableProc.stop(self) + + class BitcoinD(TailableProc): def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): @@ -621,6 +660,7 @@ def __init__( self, lightning_dir, bitcoindproxy, + lssd_port, port=9735, random_hsm=False, node_id=0, @@ -641,6 +681,7 @@ def __init__( self.rpcproxy = bitcoindproxy self.env['CLN_PLUGIN_LOG'] = "cln_plugin=trace,cln_rpc=trace,cln_grpc=trace,debug" + self.lssd_port = lssd_port self.opts = LIGHTNINGD_CONFIG.copy() opts = { @@ -872,7 +913,7 @@ def call(self, method, payload=None, cmdprefix=None, filter=None): class LightningNode(object): - def __init__(self, node_id, lightning_dir, bitcoind, executor, valgrind, may_fail=False, + def __init__(self, node_id, lightning_dir, bitcoind, lssd, executor, valgrind, may_fail=False, may_reconnect=False, allow_broken_log=False, allow_warning=False, @@ -882,6 +923,7 @@ def __init__(self, node_id, lightning_dir, bitcoind, executor, valgrind, may_fai valgrind_plugins=True, **kwargs): self.bitcoin = bitcoind + self.lssd = lssd self.executor = executor self.may_fail = may_fail self.may_reconnect = may_reconnect @@ -901,6 +943,7 @@ def __init__(self, node_id, lightning_dir, bitcoind, executor, valgrind, may_fai self.daemon = LightningD( lightning_dir, bitcoindproxy=bitcoind.get_proxy(), + lssd_port=lssd.rpcport, port=port, random_hsm=random_hsm, node_id=node_id, grpc_port=self.grpc_port, ) @@ -1605,7 +1648,7 @@ def flock(directory: Path): class NodeFactory(object): """A factory to setup and start `lightningd` daemons. """ - def __init__(self, request, testname, bitcoind, executor, directory, + def __init__(self, request, testname, bitcoind, lssd, executor, directory, db_provider, node_cls, jsonschemas): if request.node.get_closest_marker("slow_test") and SLOW_MACHINE: self.valgrind = False @@ -1617,6 +1660,7 @@ def __init__(self, request, testname, bitcoind, executor, directory, self.reserved_ports = [] self.executor = executor self.bitcoind = bitcoind + self.lssd = lssd self.directory = directory self.lock = threading.Lock() self.db_provider = db_provider @@ -1702,7 +1746,7 @@ def get_node(self, node_id=None, options=None, dbfile=None, db = self.db_provider.get_db(os.path.join(lightning_dir, TEST_NETWORK), self.testname, node_id) db.provider = self.db_provider node = self.node_cls( - node_id, lightning_dir, self.bitcoind, self.executor, self.valgrind, db=db, + node_id, lightning_dir, self.bitcoind, self.lssd, self.executor, self.valgrind, db=db, port=port, options=options, may_fail=may_fail or expect_fail, jsonschemas=self.jsonschemas, **kwargs diff --git a/tests/fixtures.py b/tests/fixtures.py index ea23f10ad0a9..d9a6874080f6 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1,5 +1,5 @@ from utils import TEST_NETWORK, VALGRIND # noqa: F401,F403 -from pyln.testing.fixtures import directory, test_base_dir, test_name, chainparams, node_factory, bitcoind, teardown_checks, db_provider, executor, setup_logging, jsonschemas # noqa: F401,F403 +from pyln.testing.fixtures import directory, test_base_dir, test_name, chainparams, node_factory, bitcoind, lssd, teardown_checks, db_provider, executor, setup_logging, jsonschemas # noqa: F401,F403 from pyln.testing import utils from utils import COMPAT from pathlib import Path diff --git a/tests/test_misc.py b/tests/test_misc.py index 9bea5e75e3fd..af2ada244301 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2549,13 +2549,13 @@ def test_unicode_rpc(node_factory, executor, bitcoind): @unittest.skipIf(VALGRIND, "Testing pyln doesn't exercise anything interesting in the c code.") -def test_unix_socket_path_length(node_factory, bitcoind, directory, executor, db_provider, test_base_dir): +def test_unix_socket_path_length(node_factory, bitcoind, lssd, directory, executor, db_provider, test_base_dir): lightning_dir = os.path.join(directory, "anode" + "far" * 30 + "away") os.makedirs(lightning_dir) db = db_provider.get_db(lightning_dir, "test_unix_socket_path_length", 1) db.provider = db_provider - l1 = LightningNode(1, lightning_dir, bitcoind, executor, VALGRIND, db=db, port=reserve()) + l1 = LightningNode(1, lightning_dir, bitcoind, lssd, executor, VALGRIND, db=db, port=reserve()) # `LightningNode.start()` internally calls `LightningRpc.getinfo()` which # exercises the socket logic, and raises an issue if it fails. From 1568ec6163d272864a51119e0c7ebd5c58fc5693 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Wed, 7 Jun 2023 14:16:26 -0700 Subject: [PATCH 08/14] tests: add call to preapproveinvoice in pay to inform signer --- contrib/pyln-testing/pyln/testing/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index d2b904994f49..5fca522c2829 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -1392,6 +1392,9 @@ def pay(self, dst, amt, label=None, route=False): 'channel': scid } + # let the signer know this payment is coming + self.rpc.preapproveinvoice(bolt11=inv['bolt11']) + # sendpay is async now self.rpc.sendpay([routestep], rhash, payment_secret=psecret, bolt11=inv['bolt11']) # wait for sendpay to comply From 2908cdba6099212105410969bf36f9530a42ed7e Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Thu, 8 Jun 2023 09:31:06 -0700 Subject: [PATCH 09/14] tests: add explicit preapprove{invoice,keysend} calls before sendpay --- tests/test_closing.py | 11 +++++++++++ tests/test_connection.py | 7 +++++++ tests/test_pay.py | 26 ++++++++++++++++++++++++++ tests/test_plugin.py | 12 ++++++++++++ tests/test_renepay.py | 2 ++ 5 files changed, 58 insertions(+) diff --git a/tests/test_closing.py b/tests/test_closing.py index 28e40fac0944..affb4e3a2f0b 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -1811,6 +1811,7 @@ def test_onchaind_replay(node_factory, bitcoind): 'delay': 101, 'channel': first_scid(l1, l2) } + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([routestep], rhash, payment_secret=inv['payment_secret']) l1.daemon.wait_for_log('sendrawtx exit 0') bitcoind.generate_block(1, wait_for_mempool=1) @@ -1954,6 +1955,7 @@ def test_onchain_timeout(node_factory, bitcoind, executor, chainparams, anchors) 'channel': first_scid(l1, l2) } + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([routestep], rhash, payment_secret=inv['payment_secret'], groupid=1) with pytest.raises(RpcError): l1.rpc.waitsendpay(rhash) @@ -2088,6 +2090,7 @@ def test_onchain_middleman_simple(node_factory, bitcoind, chainparams, anchors): q = queue.Queue() + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming def try_pay(): try: l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) @@ -2227,6 +2230,7 @@ def test_onchain_middleman_their_unilateral_in(node_factory, bitcoind, chainpara q = queue.Queue() + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming def try_pay(): try: l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) @@ -2339,6 +2343,8 @@ def try_pay(): try: # rhash is fake (so is payment_secret) rhash = 'B1' * 32 + # let the signer know this payment is coming + l1.rpc.preapprovekeysend(l2.info['id'], rhash, 10**8) l1.rpc.sendpay(route, rhash, payment_secret=rhash) q.put(None) except Exception as err: @@ -2479,6 +2485,7 @@ def test_onchain_feechange(node_factory, bitcoind, executor): 'channel': first_scid(l1, l2) } + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming executor.submit(l1.rpc.sendpay, [routestep], rhash, payment_secret=inv['payment_secret']) # l2 will drop to chain. @@ -2559,6 +2566,7 @@ def test_onchain_all_dust(node_factory, bitcoind, executor): 'channel': first_scid(l1, l2) } + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming executor.submit(l1.rpc.sendpay, [routestep], rhash, payment_secret=inv['payment_secret']) # l2 will drop to chain. @@ -3740,6 +3748,7 @@ def test_closing_anchorspend_htlc_tx_rbf(node_factory, bitcoind): 'delay': 12, 'channel': first_scid(l1, l2) } + l1.rpc.preapprovekeysend(routestep['id'], rhash, routestep['amount_msat']) l1.rpc.sendpay([routestep], rhash, payment_secret=inv['payment_secret']) l2.daemon.wait_for_log('dev_disconnect') l2.stop() @@ -3807,6 +3816,7 @@ def test_htlc_no_force_close(node_factory, bitcoind, anchors): 'id': l3.info['id'], 'delay': 10, 'channel': first_scid(l2, l3)}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret']) l3.daemon.wait_for_log('dev_disconnect') @@ -3928,6 +3938,7 @@ def test_peer_anchor_push(node_factory, bitcoind, executor, chainparams): amt = 100_000_000 sticky_inv = l3.rpc.invoice(amt, 'sticky', 'sticky') route = l1.rpc.getroute(l3.info['id'], amt, 1)['route'] + l1.rpc.preapproveinvoice(bolt11=sticky_inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, sticky_inv['payment_hash'], payment_secret=sticky_inv['payment_secret']) l3.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC') diff --git a/tests/test_connection.py b/tests/test_connection.py index 570faaa54bbc..45ca4da66283 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -844,6 +844,7 @@ def test_reconnect_sender_add1(node_factory): l1.daemon.wait_for_log('Already have funding locked in') # This will send commit, so will reconnect as required. + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) @@ -874,6 +875,7 @@ def test_reconnect_sender_add(node_factory): route = [{'amount_msat': amt, 'id': l2.info['id'], 'delay': 5, 'channel': first_scid(l1, l2)}] # This will send commit, so will reconnect as required. + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) # Should have printed this for every reconnect. for i in range(0, len(disconnects)): @@ -905,6 +907,7 @@ def test_reconnect_receiver_add(node_factory): assert only_one(l2.rpc.listinvoices('testpayment2')['invoices'])['status'] == 'unpaid' route = [{'amount_msat': amt, 'id': l2.info['id'], 'delay': 5, 'channel': first_scid(l1, l2)}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) for i in range(len(disconnects)): l1.daemon.wait_for_log('Already have funding locked in') @@ -934,6 +937,7 @@ def test_reconnect_receiver_fulfill(node_factory): assert only_one(l2.rpc.listinvoices('testpayment2')['invoices'])['status'] == 'unpaid' route = [{'amount_msat': amt, 'id': l2.info['id'], 'delay': 5, 'channel': first_scid(l1, l2)}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) for i in range(len(disconnects)): l1.daemon.wait_for_log('Already have funding locked in') @@ -4165,6 +4169,7 @@ def test_multichan(node_factory, executor, bitcoind): before = l2.rpc.listpeerchannels(l3.info['id'])['channels'] inv1 = l3.rpc.invoice(100000000, "invoice", "invoice") + l1.rpc.preapproveinvoice(bolt11=inv1['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv1['payment_hash'], payment_secret=inv1['payment_secret']) l1.rpc.waitsendpay(inv1['payment_hash']) @@ -4192,6 +4197,7 @@ def test_multichan(node_factory, executor, bitcoind): before = l2.rpc.listpeerchannels(l3.info['id'])['channels'] route[1]['channel'] = scid23b inv2 = l3.rpc.invoice(100000000, "invoice2", "invoice2") + l1.rpc.preapproveinvoice(bolt11=inv2['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv2['payment_hash'], payment_secret=inv2['payment_secret']) l1.rpc.waitsendpay(inv2['payment_hash']) # Wait until HTLCs fully settled @@ -4236,6 +4242,7 @@ def test_multichan(node_factory, executor, bitcoind): # We can actually pay by *closed* scid (at least until it's completely forgotten) route[1]['channel'] = scid23a inv3 = l3.rpc.invoice(100000000, "invoice3", "invoice3") + l1.rpc.preapproveinvoice(bolt11=inv3['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv3['payment_hash'], payment_secret=inv3['payment_secret']) l1.rpc.waitsendpay(inv3['payment_hash']) diff --git a/tests/test_pay.py b/tests/test_pay.py index 919ac39c5836..2c59737c4ec2 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -574,6 +574,7 @@ def invoice_unpaid(dst, label): with pytest.raises(RpcError): rs = copy.deepcopy(routestep) rs['amount_msat'] = rs['amount_msat'] - 1 + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([rs], rhash, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(rhash) assert invoice_unpaid(l2, 'testpayment2') @@ -582,6 +583,7 @@ def invoice_unpaid(dst, label): with pytest.raises(RpcError): rs = copy.deepcopy(routestep) rs['amount_msat'] = rs['amount_msat'] * 2 + 1 + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([rs], rhash, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(rhash) assert invoice_unpaid(l2, 'testpayment2') @@ -590,6 +592,7 @@ def invoice_unpaid(dst, label): with pytest.raises(RpcError): rs = copy.deepcopy(routestep) rs['delay'] = rs['delay'] - 2 + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([rs], rhash, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(rhash) assert invoice_unpaid(l2, 'testpayment2') @@ -599,17 +602,20 @@ def invoice_unpaid(dst, label): with pytest.raises(RpcError): rs = copy.deepcopy(routestep) rs['id'] = '00000000000000000000000000000000' + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([rs], rhash, payment_secret=inv['payment_secret']) assert invoice_unpaid(l2, 'testpayment2') l1.rpc.check_request_schemas = True # Bad payment_secret + l1.rpc.preapprovekeysend(l2.info['id'], rhash, routestep['amount_msat']) l1.rpc.sendpay([routestep], rhash, payment_secret="00" * 32) with pytest.raises(RpcError): l1.rpc.waitsendpay(rhash) assert invoice_unpaid(l2, 'testpayment2') # Missing payment_secret + l1.rpc.preapprovekeysend(l2.info['id'], rhash, routestep['amount_msat']) l1.rpc.sendpay([routestep], rhash) with pytest.raises(RpcError): l1.rpc.waitsendpay(rhash) @@ -625,6 +631,7 @@ def invoice_unpaid(dst, label): # This works. before = int(time.time()) + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming details = l1.rpc.sendpay([routestep], rhash, payment_secret=inv['payment_secret']) after = int(time.time()) preimage = l1.rpc.waitsendpay(rhash)['payment_preimage'] @@ -667,6 +674,7 @@ def check_balances(): rhash = inv['payment_hash'] assert only_one(l2.rpc.listinvoices('testpayment3')['invoices'])['status'] == 'unpaid' routestep = {'amount_msat': amt * 2, 'id': l2.info['id'], 'delay': 5, 'channel': first_scid(l1, l2)} + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([routestep], rhash, payment_secret=inv['payment_secret']) preimage3 = l1.rpc.waitsendpay(rhash)['payment_preimage'] assert only_one(l2.rpc.listinvoices('testpayment3')['invoices'])['status'] == 'paid' @@ -702,6 +710,7 @@ def test_repay(node_factory): 'delay': 5, 'channel': first_scid(l1, l2) } + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([routestep], inv['payment_hash'], payment_secret=inv['payment_secret']) l1.daemon.wait_for_log("Sending 200000000msat over 1 hops to deliver 200000000msat") l1.rpc.waitsendpay(inv['payment_hash'])['payment_preimage'] @@ -730,6 +739,7 @@ def test_wait_sendpay(node_factory, executor): 'delay': 5, 'channel': first_scid(l1, l2) } + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay([routestep], inv['payment_hash'], payment_secret=inv['payment_secret']) assert wait_created.result(TIMEOUT) == {'subsystem': 'sendpays', 'created': 1, @@ -1157,6 +1167,7 @@ def test_forward(node_factory, bitcoind): # Unknown other peer route = copy.deepcopy(baseroute) route[1]['id'] = '031a8dc444e41bb989653a4501e11175a488a57439b0c4947704fd6e3de5dca607' + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, rhash, payment_secret=inv['payment_secret']) with pytest.raises(RpcError): l1.rpc.waitsendpay(rhash) @@ -1559,6 +1570,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor): l2.rpc.close(c23, 1) + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming with pytest.raises(RpcError): l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash) @@ -1584,6 +1596,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor): 'delay': 6, 'channel': c24}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming with pytest.raises(RpcError): l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash) @@ -1610,6 +1623,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor): 'delay': 6, 'channel': c25}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming with pytest.raises(RpcError): l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash) @@ -1633,6 +1647,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor): # Replace id with a different pubkey, so onion encoded badly at l2 hop. route[1]['id'] = mangled_nodeid + l6.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming with pytest.raises(RpcError): l6.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret']) l6.rpc.waitsendpay(payment_hash) @@ -1660,6 +1675,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor): 'delay': 5, 'channel': c24}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming executor.submit(l1.rpc.sendpay, route, payment_hash, payment_secret=inv['payment_secret']) l4.daemon.wait_for_log('permfail') @@ -1715,6 +1731,7 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind): # L2 tries to pay r = l2.rpc.getroute(l4.info['id'], 10**8, 1)["route"] + l2.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l2.rpc.sendpay(r, h, payment_secret=inv['payment_secret']) # Now increment CLTV @@ -1723,6 +1740,7 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind): # L1 tries to pay r = l1.rpc.getroute(l4.info['id'], 10**8, 1)["route"] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(r, h, payment_secret=inv['payment_secret']) # Now increment CLTV @@ -1731,6 +1749,7 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind): # L3 tries to pay r = l3.rpc.getroute(l4.info['id'], 10**8, 1)["route"] + l3.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l3.rpc.sendpay(r, h, payment_secret=inv['payment_secret']) # Give them time to go through. @@ -1796,6 +1815,7 @@ def exhaust_channel(opener, peer, scid, already_spent=0): 'delay': 10, 'channel': scid } + opener.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming opener.rpc.sendpay([routestep], inv['payment_hash'], payment_secret=inv['payment_secret']) opener.rpc.waitsendpay(inv['payment_hash']) @@ -2513,6 +2533,7 @@ def test_channel_spendable(node_factory, bitcoind): # Exact amount should succeed. route = l1.rpc.getroute(l2.info['id'], amount, riskfactor=1, fuzzpercent=0)['route'] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret']) # Amount should drop to 0 once HTLC is sent; we have time, thanks to @@ -2538,6 +2559,7 @@ def test_channel_spendable(node_factory, bitcoind): # Exact amount should succeed. route = l2.rpc.getroute(l1.info['id'], amount, riskfactor=1, fuzzpercent=0)['route'] + l2.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l2.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret']) # Amount should drop to 0 once HTLC is sent; we have time, thanks to @@ -2697,6 +2719,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams): route = l1.rpc.getroute(l2.info['id'], non_dust_htlc_val_sat * 1000, 1)['route'] for i in range(0, 3): inv = l2.rpc.invoice((non_dust_htlc_val_sat * 1000), str(i + 100), str(i + 100)) + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret']) l2.daemon.wait_for_log(r'their htlc .* dev_ignore_htlcs') res = only_one(l1.rpc.listsendpays(payment_hash=inv['payment_hash'])['payments']) @@ -2706,6 +2729,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams): route = l1.rpc.getroute(l2.info['id'], htlc_val_msat, 1)['route'] for i in range(0, num_dusty_htlcs): inv = l2.rpc.invoice(htlc_val_msat, str(i), str(i)) + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret']) l2.daemon.wait_for_log(r'their htlc .* dev_ignore_htlcs') res = only_one(l1.rpc.listsendpays(payment_hash=inv['payment_hash'])['payments']) @@ -2713,6 +2737,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams): # one more should tip it over, and return a payment failure inv = l2.rpc.invoice(htlc_val_msat, str(num_dusty_htlcs), str(num_dusty_htlcs)) + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret']) l1.daemon.wait_for_log('CHANNEL_ERR_DUST_FAILURE') wait_for(lambda: only_one(l1.rpc.listsendpays(payment_hash=inv['payment_hash'])['payments'])['status'] == 'failed') @@ -2720,6 +2745,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams): # but we can still add a non dust htlc route = l1.rpc.getroute(l2.info['id'], non_dust_htlc_val_sat * 1000, 1)['route'] inv = l2.rpc.invoice((10000 * 1000), str(120), str(120)) + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret']) l2.daemon.wait_for_log(r'their htlc .* dev_ignore_htlcs') res = only_one(l1.rpc.listsendpays(payment_hash=inv['payment_hash'])['payments']) diff --git a/tests/test_plugin.py b/tests/test_plugin.py index e86bc18df052..1cbbcfad8e63 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1341,12 +1341,14 @@ def test_forward_event_notification(node_factory, bitcoind, executor): route = l1.rpc.getroute(l3.info['id'], amount, 1)['route'] # status: offered -> settled + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash13, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash13) # status: offered -> failed route = l1.rpc.getroute(l4.info['id'], amount, 1)['route'] payment_hash14 = "f" * 64 + l1.rpc.preapprovekeysend(l4.info['id'], payment_hash14, amount) with pytest.raises(RpcError): l1.rpc.sendpay(route, payment_hash14, payment_secret="f" * 64) l1.rpc.waitsendpay(payment_hash14) @@ -1366,6 +1368,7 @@ def test_forward_event_notification(node_factory, bitcoind, executor): 'delay': 5, 'channel': c25}] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming executor.submit(l1.rpc.sendpay, route, payment_hash15, payment_secret=inv['payment_secret']) l5.daemon.wait_for_log('permfail') @@ -1452,11 +1455,13 @@ def test_sendpay_notifications(node_factory, bitcoind): payment_hash2 = inv2['payment_hash'] route = l1.rpc.getroute(l3.info['id'], amount, 1)['route'] + l1.rpc.preapproveinvoice(bolt11=inv1['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash1, payment_secret=inv1['payment_secret']) response1 = l1.rpc.waitsendpay(payment_hash1) l2.rpc.close(chanid23, 1) + l1.rpc.preapproveinvoice(bolt11=inv2['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash2, payment_secret=inv2['payment_secret']) with pytest.raises(RpcError) as err: l1.rpc.waitsendpay(payment_hash2) @@ -1483,11 +1488,13 @@ def test_sendpay_notifications_nowaiter(node_factory): payment_hash2 = inv2['payment_hash'] route = l1.rpc.getroute(l3.info['id'], amount, 1)['route'] + l1.rpc.preapproveinvoice(bolt11=inv1['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash1, payment_secret=inv1['payment_secret']) l1.daemon.wait_for_log(r'Received a sendpay_success') l2.rpc.close(chanid23, 1) + l1.rpc.preapproveinvoice(bolt11=inv2['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash2, payment_secret=inv2['payment_secret']) l1.daemon.wait_for_log(r'Received a sendpay_failure') @@ -2087,12 +2094,14 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): route = l1.rpc.getroute(l3.info['id'], amount, 1)['route'] # status: offered -> settled + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash13, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash13) # status: offered -> failed route = l1.rpc.getroute(l3.info['id'], amount, 1)['route'] payment_hash13 = "f" * 64 + l1.rpc.preapprovekeysend(l3.info['id'], payment_hash13, amount) with pytest.raises(RpcError): l1.rpc.sendpay(route, payment_hash13, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash13) @@ -2101,6 +2110,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): inv = l1.rpc.invoice(amount // 2, "first", "desc") payment_hash31 = inv['payment_hash'] route = l3.rpc.getroute(l1.info['id'], amount // 2, 1)['route'] + l3.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l3.rpc.sendpay(route, payment_hash31, payment_secret=inv['payment_secret']) l3.rpc.waitsendpay(payment_hash31) @@ -2108,6 +2118,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): inv = l2.rpc.invoice(amount, "first", "desc") payment_hash12 = inv['payment_hash'] route = l1.rpc.getroute(l2.info['id'], amount, 1)['route'] + l1.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l1.rpc.sendpay(route, payment_hash12, payment_secret=inv['payment_secret']) l1.rpc.waitsendpay(payment_hash12) @@ -2117,6 +2128,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): # Make sure previous completely settled wait_for(lambda: only_one(l2.rpc.listpeerchannels(l1.info['id'])['channels'])['htlcs'] == []) route = l2.rpc.getroute(l1.info['id'], amount // 2, 1)['route'] + l2.rpc.preapproveinvoice(bolt11=inv['bolt11']) # let the signer know this payment is coming l2.rpc.sendpay(route, payment_hash21, payment_secret=inv['payment_secret']) l2.rpc.waitsendpay(payment_hash21) diff --git a/tests/test_renepay.py b/tests/test_renepay.py index f2b8f76f8ce2..86c2b814ef4f 100644 --- a/tests/test_renepay.py +++ b/tests/test_renepay.py @@ -72,6 +72,8 @@ def test_mpp(node_factory): send_amount = Millisatoshi('1200000sat') inv = l6.rpc.invoice(send_amount, 'test_renepay', 'description')['bolt11'] + # FIXME - This shouldn't be necessary, renepay should automatically generate ... vls-hsmd:#6 + l1.rpc.preapproveinvoice(bolt11=inv) # let the signer know this payment is coming details = l1.rpc.call('renepay', {'invstring': inv}) assert details['status'] == 'complete' assert details['amount_msat'] == send_amount From c6f5f749c5515fa664931bdca126ae079601c545 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Thu, 16 Nov 2023 04:25:21 -0800 Subject: [PATCH 10/14] tests: disable flaky on test_splice, incompatible w/ pytest-timeout --- tests/test_splicing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_splicing.py b/tests/test_splicing.py index 78e480571ac8..aa9bb217859f 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -12,7 +12,8 @@ @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') -@flaky +# incompatible w/ pytest-timeout +# @flaky def test_splice(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=True, opts={'experimental-splicing': None}) From 099385600dd6ea47ed91980f58baf04e3ee1e862 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Sun, 19 Nov 2023 21:01:26 -0800 Subject: [PATCH 11/14] tests: skip splicing / dual-funding tests when VLS_SKIP_SPLICE_TESTS --- tests/test_connection.py | 6 +++++- tests/test_opening.py | 14 ++++++++++++++ tests/test_splicing.py | 6 ++++++ tests/test_splicing_disconnect.py | 2 ++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/test_connection.py b/tests/test_connection.py index 45ca4da66283..a7e55c9ed68d 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -584,6 +584,7 @@ def test_disconnect_fundee(node_factory): assert len(l2.rpc.listpeers()) == 1 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_disconnect_fundee_v2(node_factory): @@ -660,6 +661,7 @@ def test_disconnect_half_signed_v2(node_factory): assert len(l1.rpc.listpeerchannels(l2.info['id'])['channels']) == 1 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') def test_reconnect_signed(node_factory): @@ -1212,7 +1214,8 @@ def test_v2_open(node_factory, bitcoind, chainparams): result = l1.rpc.waitsendpay(p['payment_hash']) assert(result['status'] == 'complete') - +# policy failed: policy-onchain-no-channel-push validate_onchain_tx: channel push not allowed: dual-funding not supported yet +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') def test_funding_push(node_factory, bitcoind, chainparams): """ Try to push peer some sats """ @@ -1836,6 +1839,7 @@ def test_multifunding_v1_v2_mixed(node_factory, bitcoind): l1.rpc.pay(inv) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_multifunding_v2_exclusive(node_factory, bitcoind): diff --git a/tests/test_opening.py b/tests/test_opening.py index 25ff00fd1eb7..ab1b47a694b0 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -172,6 +172,7 @@ def test_v2_open_sigs_reconnect_2(node_factory, bitcoind): l2.daemon.wait_for_log(r'to CHANNELD_NORMAL') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_v2_open_sigs_reconnect_1(node_factory, bitcoind): @@ -334,6 +335,7 @@ def test_v2_open_sigs_restart_while_dead(node_factory, bitcoind): l1.daemon.wait_for_log(r'to CHANNELD_NORMAL') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_v2_rbf_single(node_factory, bitcoind, chainparams): @@ -515,6 +517,7 @@ def test_v2_rbf_abort_retry(node_factory, bitcoind, chainparams): assert not l2.daemon.is_in_log('WIRE_CHANNEL_REESTABLISH') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_v2_rbf_abort_channel_opens(node_factory, bitcoind, chainparams): @@ -670,6 +673,7 @@ def test_v2_rbf_liquidity_ad(node_factory, bitcoind, chainparams): l1.daemon.wait_for_log('State changed from CLOSINGD_SIGEXCHANGE to CLOSINGD_COMPLETE') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_v2_rbf_multi(node_factory, bitcoind, chainparams): @@ -860,6 +864,7 @@ def test_rbf_reconnect_ack(node_factory, bitcoind, chainparams): l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_reconnect_tx_construct(node_factory, bitcoind, chainparams): @@ -981,6 +986,7 @@ def test_rbf_reconnect_tx_construct(node_factory, bitcoind, chainparams): l2.daemon.wait_for_log(r'to CHANNELD_NORMAL') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_reconnect_tx_sigs(node_factory, bitcoind, chainparams): @@ -1062,6 +1068,7 @@ def test_rbf_reconnect_tx_sigs(node_factory, bitcoind, chainparams): assert l1_funding_txid == l2_funding_txid +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_to_chain_before_commit(node_factory, bitcoind, chainparams): @@ -1163,6 +1170,7 @@ def test_rbf_no_overlap(node_factory, bitcoind, chainparams): l1.rpc.openchannel_update(chan_id, bump['psbt']) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_fails_to_broadcast(node_factory, bitcoind, chainparams): @@ -1244,6 +1252,7 @@ def run_retry(): assert last_txs['tx'] +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_broadcast_close_inflights(node_factory, bitcoind, chainparams): @@ -1319,6 +1328,7 @@ def run_retry(): assert inflights[1]['scratch_txid'] not in bitcoind.rpc.getrawmempool() +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_rbf_non_last_mined(node_factory, bitcoind, chainparams): @@ -1419,6 +1429,7 @@ def censoring_sendrawtx(r): l1.daemon.wait_for_log(r'to ONCHAIN') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_funder_options(node_factory, bitcoind): @@ -1485,6 +1496,8 @@ def test_funder_options(node_factory, bitcoind): assert chan_info['funding']['local_funds_msat'] == Millisatoshi('1000000000msat') +# policy-onchain-no-fund-inbound validate_onchain_tx: can't sign for inbound channel: dual-funding not supported yet +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') def test_funder_contribution_limits(node_factory, bitcoind): opts = {'experimental-dual-fund': None, @@ -2325,6 +2338,7 @@ def _no_utxo_response(r): wait_for(lambda: l2.rpc.listpeerchannels()['channels'] == []) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v2') def test_openchannel_no_unconfirmed_inputs_accepter(node_factory, bitcoind): """ If the accepter flags 'require-confirmed-inputs' for an open, diff --git a/tests/test_splicing.py b/tests/test_splicing.py index aa9bb217859f..6c09bf7ba0ea 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -9,6 +9,7 @@ ) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @@ -48,6 +49,7 @@ def test_splice(node_factory, bitcoind): assert l1.db_query("SELECT count(*) as c FROM channeltxs;")[0]['c'] == 0 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @@ -106,6 +108,7 @@ def test_splice_gossip(node_factory, bitcoind): assert not l2.daemon.is_in_log("invalid local_channel_announcement") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @@ -141,6 +144,7 @@ def test_splice_listnodes(node_factory, bitcoind): assert len(l2.rpc.listnodes()['nodes']) == 2 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @@ -177,6 +181,7 @@ def test_splice_out(node_factory, bitcoind): assert l1.db_query("SELECT count(*) as c FROM channeltxs;")[0]['c'] == 0 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @@ -288,6 +293,7 @@ def test_commit_crash_splice(node_factory, bitcoind): assert l1.db_query("SELECT count(*) as c FROM channeltxs;")[0]['c'] == 0 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') diff --git a/tests/test_splicing_disconnect.py b/tests/test_splicing_disconnect.py index 093afe296fec..b2249acd99f2 100644 --- a/tests/test_splicing_disconnect.py +++ b/tests/test_splicing_disconnect.py @@ -8,6 +8,7 @@ ) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @@ -63,6 +64,7 @@ def test_splice_disconnect_sig(node_factory, bitcoind): assert l1.db_query("SELECT count(*) as c FROM channeltxs;")[0]['c'] == 0 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') From 646eff82a4e021718f8f010fe1baefb5b133582d Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Mon, 20 Nov 2023 14:52:02 -0800 Subject: [PATCH 12/14] tests: skip test_reckless.py::test_disable_enable, unexplained --- tests/test_reckless.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_reckless.py b/tests/test_reckless.py index ac4f0db19ee5..e3e1307f732c 100644 --- a/tests/test_reckless.py +++ b/tests/test_reckless.py @@ -6,7 +6,7 @@ import os import shutil import time - +import unittest @pytest.fixture(autouse=True) def canned_github_server(directory): @@ -175,6 +175,7 @@ def test_local_dir_install(node_factory): assert os.path.exists(plugin_path) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "fails unexpectedly in CI") def test_disable_enable(node_factory): """test search, git clone, and installation to folder.""" n = get_reckless_node(node_factory) From 6f397d8db666e8d89b13563d7505ad2c5040af03 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Tue, 21 Nov 2023 10:09:44 -0800 Subject: [PATCH 13/14] tests: skip tests incompatible with VLS --- tests/test_bookkeeper.py | 3 +++ tests/test_closing.py | 14 ++++++++++++++ tests/test_connection.py | 10 ++++++++++ tests/test_db.py | 6 ++++++ tests/test_gossip.py | 1 + tests/test_invoices.py | 1 + tests/test_misc.py | 6 ++++++ tests/test_opening.py | 13 +++++++++++++ tests/test_pay.py | 13 +++++++++++++ tests/test_plugin.py | 5 +++++ tests/test_renepay.py | 3 +++ tests/test_wallet.py | 5 +++++ 12 files changed, 80 insertions(+) diff --git a/tests/test_bookkeeper.py b/tests/test_bookkeeper.py index 9614942e863d..db281e481d1a 100644 --- a/tests/test_bookkeeper.py +++ b/tests/test_bookkeeper.py @@ -332,6 +332,7 @@ def test_bookkeeping_rbf_withdraw(node_factory, bitcoind): assert len(fees) == 1 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "hsmd_sign_option_will_fund_offer not supported") @pytest.mark.openchannel('v2') @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "turns off bookkeeper at start") @unittest.skipIf(TEST_NETWORK != 'regtest', "network fees hardcoded") @@ -408,6 +409,7 @@ def _check_events(node, channel_id, exp_events): @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "turns off bookkeeper at start") @unittest.skipIf(TEST_NETWORK != 'regtest', "network fees hardcoded") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "remote_hsmd doesn't allow push of non-trivial amount") @pytest.mark.openchannel('v1', 'Uses push-msat') def test_bookkeeping_missed_chans_pushed(node_factory, bitcoind): """ @@ -599,6 +601,7 @@ def test_bookkeeping_onchaind_txs(node_factory, bitcoind): assert outs == only_one(wallet_bal['balances'])['balance_msat'] +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "invoice from offer: Invalid bech32: invalid checksum") def test_bookkeeping_descriptions(node_factory, bitcoind, chainparams): """ When an 'invoice' type event comes through, we look up the description details diff --git a/tests/test_closing.py b/tests/test_closing.py index affb4e3a2f0b..85aae5153f64 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -482,6 +482,7 @@ def test_closing_negotiation_step_700sat(node_factory, bitcoind, chainparams): closing_negotiation_step(node_factory, bitcoind, chainparams, opts) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "dev_sign_last_tx causes subsequent validate_holder_commitment_tx failure") @pytest.mark.parametrize("anchors", [False, True]) def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams, anchors): """Test penalty transaction with an incoming HTLC""" @@ -614,6 +615,7 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams, anchors): check_utxos_channel(l2, [channel_id], expected_2, tags) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "dev_sign_last_tx causes subsequent validate_holder_commitment_tx failure") @pytest.mark.parametrize("anchors", [False, True]) def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams, anchors): """Test penalty transaction with an outgoing HTLC""" @@ -750,6 +752,7 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams, anchors) @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') @pytest.mark.slow_test def test_channel_lease_falls_behind(node_factory, bitcoind): @@ -791,6 +794,7 @@ def test_channel_lease_falls_behind(node_factory, bitcoind): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') @pytest.mark.slow_test def test_channel_lease_post_expiry(node_factory, bitcoind, chainparams): @@ -892,6 +896,7 @@ def test_channel_lease_post_expiry(node_factory, bitcoind, chainparams): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') @pytest.mark.slow_test def test_channel_lease_unilat_closes(node_factory, bitcoind): @@ -1004,6 +1009,7 @@ def test_channel_lease_unilat_closes(node_factory, bitcoind): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Makes use of the sqlite3 db") def test_channel_lease_lessor_cheat(node_factory, bitcoind, chainparams): @@ -1080,6 +1086,7 @@ def test_channel_lease_lessor_cheat(node_factory, bitcoind, chainparams): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Makes use of the sqlite3 db") def test_channel_lease_lessee_cheat(node_factory, bitcoind, chainparams): @@ -1155,6 +1162,7 @@ def test_channel_lease_lessee_cheat(node_factory, bitcoind, chainparams): 'Unknown spend of OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by']) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_payments: unbalanced payments on channel") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Makes use of the sqlite3 db") @pytest.mark.slow_test @pytest.mark.parametrize("anchors", [False, True]) @@ -1339,6 +1347,7 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors): check_balance_snaps(l2, expected_bals_2) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_payments: unbalanced payments on channel") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Makes use of the sqlite3 db") @pytest.mark.slow_test @pytest.mark.parametrize("anchors", [False, True]) @@ -1568,6 +1577,7 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams, anchors): assert acc['resolved_at_block'] > 0 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "exceeds max fee policy") @pytest.mark.parametrize("anchors", [False, True]) def test_penalty_rbf_normal(node_factory, bitcoind, executor, chainparams, anchors): ''' @@ -2859,6 +2869,7 @@ def route_to_l1(src): @pytest.mark.slow_test +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "frequently flakes") def test_onchain_multihtlc_our_unilateral(node_factory, bitcoind): """Node pushes a channel onchain with multiple HTLCs with same payment_hash """ h, l1, l2, l3, l4, l5, l6, l7 = setup_multihtlc_test(node_factory, bitcoind) @@ -2914,6 +2925,7 @@ def test_onchain_multihtlc_our_unilateral(node_factory, bitcoind): @pytest.mark.slow_test +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "frequently flakes") def test_onchain_multihtlc_their_unilateral(node_factory, bitcoind): """Node pushes a channel onchain with multiple HTLCs with same payment_hash """ h, l1, l2, l3, l4, l5, l6, l7 = setup_multihtlc_test(node_factory, bitcoind) @@ -3077,6 +3089,7 @@ def test_permfail_htlc_out(node_factory, bitcoind, executor): wait_for(lambda: l2.rpc.listpeers()['peers'] == []) +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "policy: can't withdraw to non-wallet address") # FIXME - should work with auto-approve def test_permfail(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2) @@ -3176,6 +3189,7 @@ def test_shutdown(node_factory): l1.rpc.stop() +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_setup_channel: holder_shutdown_script is not in wallet or allowlist") def test_option_upfront_shutdown_script(node_factory, bitcoind, executor, chainparams): l1 = node_factory.get_node(start=False, allow_warning=True) # Insist on upfront script we're not going to match. diff --git a/tests/test_connection.py b/tests/test_connection.py index a7e55c9ed68d..77085ee4b6d5 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1214,6 +1214,7 @@ def test_v2_open(node_factory, bitcoind, chainparams): result = l1.rpc.waitsendpay(p['payment_hash']) assert(result['status'] == 'complete') + # policy failed: policy-onchain-no-channel-push validate_onchain_tx: channel push not allowed: dual-funding not supported yet @unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @pytest.mark.openchannel('v1') @@ -1643,6 +1644,7 @@ def test_funding_v2_cancel_race(node_factory, bitcoind, executor): executor.map(lambda n: n.stop(), node_factory.nodes) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_setup_channel: holder_shutdown_script is not in wallet or allowlist") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', "External wallet support doesn't work with elements yet.") @@ -1793,6 +1795,7 @@ def test_funding_external_wallet(node_factory, bitcoind): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v1') # We manually turn on dual-funding for select nodes +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "commit c0cc285a causes: channel stub can only return point for commitment number zero") def test_multifunding_v1_v2_mixed(node_factory, bitcoind): ''' Simple test for multifundchannel, using v1 + v2 @@ -2055,6 +2058,7 @@ def test_multifunding_wumbo(node_factory): l1.rpc.multifundchannel(destinations) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "flakes too frequently w/ VLS") @unittest.skipIf(TEST_NETWORK == 'liquid-regtest', "Fees on elements are different") @pytest.mark.openchannel('v1') # v2 the weight calculation is off by 3 @pytest.mark.parametrize("anchors", [False, True]) @@ -2448,6 +2452,7 @@ def test_update_fee(node_factory, bitcoind): l2.daemon.wait_for_log('onchaind complete, forgetting peer') +@pytest.mark.developer def test_fee_limits(node_factory, bitcoind): l1, l2, l3, l4 = node_factory.get_nodes(4, opts=[{'dev-max-fee-multiplier': 5, 'may_reconnect': True, 'allow_warning': True}, @@ -3581,6 +3586,8 @@ def test_channel_features(node_factory, bitcoind, anchors): assert only_one(l2.rpc.listpeerchannels()['channels'])['features'] == chan['features'] +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_setup_channel: unsafe commitment type: Legacy") +@pytest.mark.developer("need dev-force-features") def test_nonstatic_channel(node_factory, bitcoind): """Smoke test for a channel without option_static_remotekey""" l1, l2 = node_factory.line_graph(2, @@ -3696,6 +3703,7 @@ def test_openchannel_init_alternate(node_factory, executor): print("nothing to do") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_setup_channel: unsafe commitment type: Legacy") def test_upgrade_statickey(node_factory, executor): """l1 doesn't have option_static_remotekey, l2 offers it.""" l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, @@ -3726,6 +3734,7 @@ def test_upgrade_statickey(node_factory, executor): l2.daemon.wait_for_log(r"They sent desired_channel_type \[12\]") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_setup_channel: unsafe commitment type: Legacy") def test_upgrade_statickey_onchaind(node_factory, executor, bitcoind): """We test penalty before/after, and unilateral before/after""" l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, @@ -3860,6 +3869,7 @@ def test_upgrade_statickey_onchaind(node_factory, executor, bitcoind): wait_for(lambda: len(l2.rpc.listpeerchannels()['channels']) == 0) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_setup_channel: unsafe commitment type: Legacy") def test_upgrade_statickey_fail(node_factory, executor, bitcoind): """We reconnect at all points during retransmit, and we won't upgrade.""" l1_disconnects = ['-WIRE_COMMITMENT_SIGNED', diff --git a/tests/test_db.py b/tests/test_db.py index 82b3e3b5c930..aa881cd18a6e 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -136,6 +136,7 @@ def test_max_channel_id(node_factory, bitcoind): @unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot") @unittest.skipIf(TEST_NETWORK != 'regtest', "The network must match the DB snapshot") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't like channel_nonce changing") def test_scid_upgrade(node_factory, bitcoind): bitcoind.generate_block(1) @@ -167,6 +168,7 @@ def test_scid_upgrade(node_factory, bitcoind): @unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot") @unittest.skipIf(TEST_NETWORK != 'regtest', "The network must match the DB snapshot") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't like channel_nonce changing") def test_last_tx_inflight_psbt_upgrade(node_factory, bitcoind): bitcoind.generate_block(12) @@ -185,6 +187,7 @@ def test_last_tx_inflight_psbt_upgrade(node_factory, bitcoind): @unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot") @unittest.skipIf(TEST_NETWORK != 'regtest', "The network must match the DB snapshot") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't like channel_nonce changing") def test_last_tx_psbt_upgrade(node_factory, bitcoind): bitcoind.generate_block(12) @@ -219,6 +222,7 @@ def test_last_tx_psbt_upgrade(node_factory, bitcoind): @pytest.mark.slow_test @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot") @unittest.skipIf(TEST_NETWORK != 'regtest', "The network must match the DB snapshot") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support backfill yet") def test_backfill_scriptpubkeys(node_factory, bitcoind): bitcoind.generate_block(214) @@ -352,6 +356,7 @@ def get_dsn(self): os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "This test is based on a sqlite3 snapshot" ) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support DB migration") def test_local_basepoints_cache(bitcoind, node_factory): """XXX started caching the local basepoints as well as the remote ones. @@ -440,6 +445,7 @@ def test_sqlite3_builtin_backup(bitcoind, node_factory): @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Don't know how to swap dbs in Postgres") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "vlsd chokes on allowlist when started on wrong network") def test_db_sanity_checks(bitcoind, node_factory): l1, l2 = node_factory.get_nodes(2, opts=[{'allow_broken_log': True, 'may_fail': True}, {}]) diff --git a/tests/test_gossip.py b/tests/test_gossip.py index cf8815cc00a8..8714c8e50731 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -182,6 +182,7 @@ def test_announce_dns_suppressed(node_factory, bitcoind): assert addresses[0]['port'] == 1236 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "trouble with IPv6 in VLS CI runner") def test_announce_and_connect_via_dns(node_factory, bitcoind): """ Test that DNS annoucements propagate and can be used when connecting. diff --git a/tests/test_invoices.py b/tests/test_invoices.py index 5d72725eea34..0bc09a95b19e 100644 --- a/tests/test_invoices.py +++ b/tests/test_invoices.py @@ -130,6 +130,7 @@ def test_invoice_weirdstring(node_factory): l1.rpc.delinvoice(weird_label, "unpaid") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "sign_invoice: already have a different invoice for same secret") def test_invoice_preimage(node_factory): """Test explicit invoice 'preimage'. """ diff --git a/tests/test_misc.py b/tests/test_misc.py index af2ada244301..d6f5734bc358 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1145,6 +1145,7 @@ def test_cli_commando(node_factory): assert only_one(j['invoices'])['label'] == 'l"[]{}' +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd integration test job control fails here") def test_daemon_option(node_factory): """ Make sure --daemon at least vaguely works! @@ -2173,6 +2174,7 @@ def test_bitcoind_feerate_floor(node_factory, bitcoind, anchors): @unittest.skipIf(TEST_NETWORK != 'regtest', "Addresses are network specific") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support forced secrets") def test_dev_force_bip32_seed(node_factory): l1 = node_factory.get_node(options={'dev-force-bip32-seed': '0000000000000000000000000000000000000000000000000000000000000001'}) # First is m/0/0/1 .. @@ -2511,6 +2513,7 @@ def test_regtest_upgrade(node_factory): @unittest.skipIf(VALGRIND, "valgrind files can't be written since we rmdir") @unittest.skipIf(TEST_NETWORK != "regtest", "needs bitcoin mainnet") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't create hsm_secret file") def test_new_node_is_mainnet(node_factory): """Test that an empty directory causes us to be on mainnet""" l1 = node_factory.get_node(start=False, may_fail=True) @@ -2674,6 +2677,7 @@ def test_sendcustommsg(node_factory): ]) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support dev-force-privkey") def test_makesecret(node_factory): """ Test makesecret command. @@ -2711,6 +2715,7 @@ def test_staticbackup(node_factory): and l1.rpc.staticbackup()["scb"][0][16: 16 + 64] == _["channel_id"]) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd says no such channel") def test_recoverchannel(node_factory): """ Test recoverchannel @@ -3744,6 +3749,7 @@ def test_setconfig(node_factory, bitcoind): assert len(lines) == 3 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support this command") @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "deletes database, which is assumed sqlite3") def test_recover_command(node_factory, bitcoind): l1, l2 = node_factory.get_nodes(2) diff --git a/tests/test_opening.py b/tests/test_opening.py index ab1b47a694b0..858365025b24 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -7,6 +7,7 @@ from pathlib import Path from pprint import pprint +import os import pytest import re import unittest @@ -18,6 +19,7 @@ def find_next_feerate(node, peer): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_queryrates(node_factory, bitcoind): @@ -57,6 +59,7 @@ def test_queryrates(node_factory, bitcoind): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v1') # Mixed v1 + v2, v2 manually turned on +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "commit c0cc285a causes: channel stub can only return point for commitment number zero") def test_multifunding_v2_best_effort(node_factory, bitcoind): ''' Check that best_effort flag works. @@ -436,6 +439,7 @@ def test_v2_rbf_single(node_factory, bitcoind, chainparams): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_v2_rbf_abort_retry(node_factory, bitcoind, chainparams): l1, l2 = node_factory.get_nodes(2, opts={'allow_warning': True}) @@ -577,6 +581,7 @@ def test_v2_rbf_abort_channel_opens(node_factory, bitcoind, chainparams): l1.daemon.wait_for_log(' to CHANNELD_NORMAL') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "handle_sign_option_will_fund_offer unimplemented") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_v2_rbf_liquidity_ad(node_factory, bitcoind, chainparams): @@ -1499,6 +1504,7 @@ def test_funder_options(node_factory, bitcoind): # policy-onchain-no-fund-inbound validate_onchain_tx: can't sign for inbound channel: dual-funding not supported yet @unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "dual-funding not supported yet") # FIXME - should work with VLS_PERMISSIVE def test_funder_contribution_limits(node_factory, bitcoind): opts = {'experimental-dual-fund': None, 'feerates': (5000, 5000, 5000, 5000)} @@ -1560,6 +1566,7 @@ def test_funder_contribution_limits(node_factory, bitcoind): assert l3.daemon.is_in_log(r'calling `signpsbt` .* 6 inputs') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_inflight_dbload(node_factory, bitcoind): """Bad db field access breaks Postgresql on startup with opening leases""" @@ -1638,6 +1645,7 @@ def test_zeroconf_mindepth(bitcoind, node_factory): wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['state'] == "CHANNELD_NORMAL") +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "tried commitment when funding is not buried ") def test_zeroconf_open(bitcoind, node_factory): """Let's open a zeroconf channel @@ -1702,6 +1710,7 @@ def test_zeroconf_open(bitcoind, node_factory): l2.rpc.pay(inv) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "missing WIRE_HSMD_CUPDATE_SIG_REQ log messages") def test_zeroconf_public(bitcoind, node_factory, chainparams): """Test that we transition correctly from zeroconf to public @@ -1805,6 +1814,7 @@ def test_zeroconf_public(bitcoind, node_factory, chainparams): wait_for(lambda: only_one([x for x in n.rpc.bkpr_listbalances()['accounts'] if x['account'] == channel_id])['account_resolved']) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "tried commitment when funding is not buried ") def test_zeroconf_forward(node_factory, bitcoind): """Ensure that we can use zeroconf channels in forwards. @@ -1869,6 +1879,7 @@ def test_buy_liquidity_ad_no_v2(node_factory, bitcoind): compact_lease='029a002d000000004b2003e8') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_v2_replay_bookkeeping(node_factory, bitcoind): """ Test that your bookkeeping for a liquidity ad is good @@ -1933,6 +1944,7 @@ def test_v2_replay_bookkeeping(node_factory, bitcoind): l1.rpc.bkpr_listbalances() +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_buy_liquidity_ad_check_bookkeeping(node_factory, bitcoind): """ Test that your bookkeeping for a liquidity ad is good.""" @@ -2053,6 +2065,7 @@ def test_scid_alias_private(node_factory, bitcoind): l1.rpc.waitsendpay(inv['payment_hash']) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "tried commitment when funding is not buried ") def test_zeroconf_multichan_forward(node_factory): """The freedom to choose the forward channel bytes us when it is 0conf diff --git a/tests/test_pay.py b/tests/test_pay.py index 2c59737c4ec2..bb9ea2b38f70 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -552,6 +552,7 @@ def test_pay_maxfee_shadow(node_factory): assert pay_status["amount_msat"] == Millisatoshi(amount) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "fails multiple policy checks") def test_sendpay(node_factory): l1, l2 = node_factory.line_graph(2, fundamount=10**6) @@ -2513,6 +2514,7 @@ def test_setchannel_startup_opts(node_factory, bitcoind): assert result[1]['htlc_maximum_msat'] == Millisatoshi(5) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "invoice with any amount") def test_channel_spendable(node_factory, bitcoind): """Test that spendable_msat is accurate""" sats = 10**6 @@ -2569,6 +2571,7 @@ def test_channel_spendable(node_factory, bitcoind): l2.rpc.waitsendpay(payment_hash, TIMEOUT) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "invoice with any amount") def test_channel_receivable(node_factory, bitcoind): """Test that receivable_msat is accurate""" sats = 10**6 @@ -2624,6 +2627,7 @@ def test_channel_receivable(node_factory, bitcoind): l2.rpc.waitsendpay(payment_hash, TIMEOUT) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "invoice with any amount") def test_channel_spendable_large(node_factory, bitcoind): """Test that spendable_msat is accurate for large channels""" # This is almost the max allowable spend. @@ -2766,6 +2770,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams): l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret']) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "feerate above maximum (escalates)") def test_htlc_too_dusty_incoming(node_factory, bitcoind): """ Try to hit the 'too much dust' limit, should fail the HTLC """ feerate = 30000 @@ -2828,6 +2833,7 @@ def test_error_returns_blockheight(node_factory, bitcoind): == '400f{:016x}{:08x}'.format(100, bitcoind.rpc.getblockcount())) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "inv_nosecret: The invoice is missing the mandatory payment secret") @unittest.skipIf(TEST_NETWORK != 'regtest', "Invoice is network specific") def test_pay_no_secret(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, wait_for_announce=True) @@ -4205,6 +4211,7 @@ def test_mpp_interference_2(node_factory, bitcoind, executor): @pytest.mark.slow_test +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "remote_hsmd doesn't allow push of greater than 20k sat") def test_mpp_overload_payee(node_factory, bitcoind): """ We had a bug where if the payer is unusually well-connected compared @@ -4439,6 +4446,7 @@ def test_offer(node_factory, bitcoind): assert 'recurrence: every 600 seconds paywindow -10 to +600 (pay proportional)\n' in output +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "Invalid bech32: invalid checksum") def test_offer_deprecated_api(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, opts={'experimental-offers': None, 'allow-deprecated-apis': True}) @@ -4464,6 +4472,7 @@ def test_fetchinvoice_3hop(node_factory, bitcoind): l1.rpc.call('fetchinvoice', {'offer': offer1['bolt12']}) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "invoice not bolt12: InvalidSemantics(UnsupportedCurrency) and not bolt11: Bech32Error(InvalidChecksum)") def test_fetchinvoice(node_factory, bitcoind): # We remove the conversion plugin on l3, causing it to get upset. l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, @@ -4589,6 +4598,7 @@ def test_fetchinvoice(node_factory, bitcoind): l1.rpc.call('fetchinvoice', {'offer': offer1['bolt12'], 'timeout': 10}) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "invoice not bolt12: Decode(UnknownRequiredFeature) and not bolt11: Bech32Error(InvalidChecksum)") def test_fetchinvoice_recurrence(node_factory, bitcoind): """Test for our recurrence extension""" l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, @@ -4683,6 +4693,7 @@ def test_fetchinvoice_recurrence(node_factory, bitcoind): 'recurrence_label': 'test paywindow'}) +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "invoice from offer: Invalid bech32: invalid checksum") def test_fetchinvoice_autoconnect(node_factory, bitcoind): """We should autoconnect if we need to, to route.""" @@ -4759,6 +4770,7 @@ def test_dev_rawrequest(node_factory): assert 'invoice' in ret +#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sendinvoice: bolt12: Invalid bech32: invalid checksum") def test_sendinvoice(node_factory, bitcoind): l2opts = {'experimental-offers': None} l1, l2 = node_factory.line_graph(2, wait_for_announce=True, @@ -5196,6 +5208,7 @@ def test_payerkey(node_factory): assert n.rpc.decode(b12)['invreq_payer_id'] == k +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "tried commitment when funding is not buried ") def test_pay_multichannel_use_zeroconf(bitcoind, node_factory): """Check that we use the zeroconf direct channel to pay when we need to""" # 0. Setup normal channel, 200k sats. diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 1cbbcfad8e63..6fb03dd576ea 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -705,6 +705,7 @@ def test_openchannel_hook(node_factory, bitcoind): l1.rpc.fundchannel(l2.info['id'], 100001) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "this test frequently hangs w/ VLSD") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') def test_openchannel_hook_error_handling(node_factory, bitcoind): @@ -1785,6 +1786,7 @@ def test_bitcoin_backend(node_factory, bitcoind): " bitcoind") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "channel too big, then feerate above maximum") def test_bitcoin_bad_estimatefee(node_factory, bitcoind): """ This tests that we don't crash if bitcoind backend gives bad estimatefees. @@ -1955,6 +1957,7 @@ def test_replacement_payload(node_factory): assert l2.daemon.wait_for_log("Attempt to pay.*with wrong secret") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "dev_sign_last_tx causes subsequent validate_holder_commitment_tx failure") def test_watchtower(node_factory, bitcoind, directory, chainparams): """Test watchtower hook. @@ -2173,6 +2176,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): check_coin_moves(l2, chanid_3, l2_l3_mvts, chainparams) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "trouble managing remotesigner when node killed this way") def test_important_plugin(node_factory): # Cache it here. pluginsdir = os.path.join(os.path.dirname(__file__), "plugins") @@ -3403,6 +3407,7 @@ def test_block_added_notifications(node_factory, bitcoind): assert len(ret) == 3 and ret[1] == next_l2_base + 1 and ret[2] == next_l2_base + 2 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "timeout waiting for hold_invoice plugin") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') def test_sql(node_factory, bitcoind): opts = {'experimental-offers': None, diff --git a/tests/test_renepay.py b/tests/test_renepay.py index 86c2b814ef4f..af4565ccbc55 100644 --- a/tests/test_renepay.py +++ b/tests/test_renepay.py @@ -6,6 +6,7 @@ import time import json import subprocess +import unittest def test_simple(node_factory): @@ -217,6 +218,7 @@ def test_amounts(node_factory): assert invoice['amount_received_msat'] >= Millisatoshi(123456) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "invoice with any amount") def test_limits(node_factory): ''' Topology: @@ -315,6 +317,7 @@ def start_channels(connections): wait_for(lambda: 'alias' in only_one(n.rpc.listnodes(n2.info['id'])['nodes'])) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "invoice with any amount") def test_hardmpp(node_factory): ''' Topology: diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 40d078cd338d..9c563d9b2cd3 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -782,6 +782,7 @@ def test_utxopsbt(node_factory, bitcoind, chainparams): reservedok=True) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "non-beneficial value considered as fees is above maximum feerate") def test_sign_external_psbt(node_factory, bitcoind, chainparams): """ A PSBT w/ one of our inputs should be signable (we can fill @@ -858,6 +859,7 @@ def test_psbt_version(node_factory, bitcoind, chainparams): l1.rpc.setpsbtversion(v2_funding, i) +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "validate_payments: unbalanced payments on channel") @unittest.skipIf(TEST_NETWORK == 'liquid-regtest', 'Core/Elements need joinpsbt support for v2') def test_sign_and_send_psbt(node_factory, bitcoind, chainparams): """ @@ -1117,6 +1119,7 @@ def write_all(fd, bytestr): @unittest.skipIf(VALGRIND, "It does not play well with prompt and key derivation.") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support hsm_secret file") def test_hsm_secret_encryption(node_factory): l1 = node_factory.get_node(may_fail=True) # May fail when started without key password = "reckful&é🍕\n" @@ -1180,6 +1183,7 @@ def __init__(self, directory, *args): @unittest.skipIf(VALGRIND, "It does not play well with prompt and key derivation.") +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support hsm_secret file") def test_hsmtool_secret_decryption(node_factory): l1 = node_factory.get_node() password = "reckless123#{ù}\n" @@ -1316,6 +1320,7 @@ def test_hsmtool_dump_descriptors(node_factory, bitcoind): assert res["total_amount"] == Decimal('0.00001000') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "remote_hsmd doesn't support generatehsm") def test_hsmtool_generatehsm(node_factory): l1 = node_factory.get_node(start=False) hsm_path = os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, From 80833a37a35a340af9af78f4714606b15e3b0300 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Tue, 21 Nov 2023 12:54:27 -0800 Subject: [PATCH 14/14] tests: reevaluate: reenabled tests which pass --- tests/test_bookkeeper.py | 1 - tests/test_closing.py | 1 - tests/test_connection.py | 1 - tests/test_opening.py | 3 --- tests/test_pay.py | 3 --- 5 files changed, 9 deletions(-) diff --git a/tests/test_bookkeeper.py b/tests/test_bookkeeper.py index db281e481d1a..5b02ef7a32f9 100644 --- a/tests/test_bookkeeper.py +++ b/tests/test_bookkeeper.py @@ -601,7 +601,6 @@ def test_bookkeeping_onchaind_txs(node_factory, bitcoind): assert outs == only_one(wallet_bal['balances'])['balance_msat'] -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "invoice from offer: Invalid bech32: invalid checksum") def test_bookkeeping_descriptions(node_factory, bitcoind, chainparams): """ When an 'invoice' type event comes through, we look up the description details diff --git a/tests/test_closing.py b/tests/test_closing.py index 85aae5153f64..70c9af54ffc6 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -3089,7 +3089,6 @@ def test_permfail_htlc_out(node_factory, bitcoind, executor): wait_for(lambda: l2.rpc.listpeers()['peers'] == []) -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "policy: can't withdraw to non-wallet address") # FIXME - should work with auto-approve def test_permfail(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2) diff --git a/tests/test_connection.py b/tests/test_connection.py index 77085ee4b6d5..0171419f17c2 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1795,7 +1795,6 @@ def test_funding_external_wallet(node_factory, bitcoind): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v1') # We manually turn on dual-funding for select nodes -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "commit c0cc285a causes: channel stub can only return point for commitment number zero") def test_multifunding_v1_v2_mixed(node_factory, bitcoind): ''' Simple test for multifundchannel, using v1 + v2 diff --git a/tests/test_opening.py b/tests/test_opening.py index 858365025b24..b734bd65aadb 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -59,7 +59,6 @@ def test_queryrates(node_factory, bitcoind): @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v1') # Mixed v1 + v2, v2 manually turned on -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "commit c0cc285a causes: channel stub can only return point for commitment number zero") def test_multifunding_v2_best_effort(node_factory, bitcoind): ''' Check that best_effort flag works. @@ -1504,7 +1503,6 @@ def test_funder_options(node_factory, bitcoind): # policy-onchain-no-fund-inbound validate_onchain_tx: can't sign for inbound channel: dual-funding not supported yet @unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_SKIP_SPLICE_TESTS') == '1', "test expected to fail before VLS dual-funding / splicing support") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "dual-funding not supported yet") # FIXME - should work with VLS_PERMISSIVE def test_funder_contribution_limits(node_factory, bitcoind): opts = {'experimental-dual-fund': None, 'feerates': (5000, 5000, 5000, 5000)} @@ -1645,7 +1643,6 @@ def test_zeroconf_mindepth(bitcoind, node_factory): wait_for(lambda: only_one(l2.rpc.listpeerchannels()['channels'])['state'] == "CHANNELD_NORMAL") -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('VLS_PERMISSIVE') != '1', "tried commitment when funding is not buried ") def test_zeroconf_open(bitcoind, node_factory): """Let's open a zeroconf channel diff --git a/tests/test_pay.py b/tests/test_pay.py index bb9ea2b38f70..a3c2d70e4c6a 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -4446,7 +4446,6 @@ def test_offer(node_factory, bitcoind): assert 'recurrence: every 600 seconds paywindow -10 to +600 (pay proportional)\n' in output -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "Invalid bech32: invalid checksum") def test_offer_deprecated_api(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, opts={'experimental-offers': None, 'allow-deprecated-apis': True}) @@ -4693,7 +4692,6 @@ def test_fetchinvoice_recurrence(node_factory, bitcoind): 'recurrence_label': 'test paywindow'}) -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "invoice from offer: Invalid bech32: invalid checksum") def test_fetchinvoice_autoconnect(node_factory, bitcoind): """We should autoconnect if we need to, to route.""" @@ -4770,7 +4768,6 @@ def test_dev_rawrequest(node_factory): assert 'invoice' in ret -#@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sendinvoice: bolt12: Invalid bech32: invalid checksum") def test_sendinvoice(node_factory, bitcoind): l2opts = {'experimental-offers': None} l1, l2 = node_factory.line_graph(2, wait_for_announce=True,