Skip to content

Commit d0be63f

Browse files
committed
tests: add VLS to CLN integration suite
1 parent 17be74f commit d0be63f

File tree

1 file changed

+132
-5
lines changed
  • contrib/pyln-testing/pyln/testing

1 file changed

+132
-5
lines changed

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

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def env(name, default=None):
7878
SLOW_MACHINE = env("SLOW_MACHINE", "0") == "1"
7979
DEPRECATED_APIS = env("DEPRECATED_APIS", "0") == "1"
8080
TIMEOUT = int(env("TIMEOUT", 180 if SLOW_MACHINE else 60))
81+
SUBDAEMON = env("SUBDAEMON", "")
8182
EXPERIMENTAL_DUAL_FUND = env("EXPERIMENTAL_DUAL_FUND", "0") == "1"
8283
EXPERIMENTAL_SPLICING = env("EXPERIMENTAL_SPLICING", "0") == "1"
8384

@@ -578,6 +579,43 @@ def getnewaddress(self):
578579
return info['unconfidential']
579580

580581

582+
class ValidatingLightningSignerD(TailableProc):
583+
def __init__(self, vlsd_dir, vlsd_port, node_id, network):
584+
TailableProc.__init__(self, vlsd_dir, verbose=True)
585+
self.executable = env("REMOTE_SIGNER_CMD", 'vlsd2')
586+
os.environ['ALLOWLIST'] = env(
587+
'REMOTE_SIGNER_ALLOWLIST',
588+
'contrib/remote_hsmd/TESTING_ALLOWLIST')
589+
self.opts = [
590+
'--network={}'.format(network),
591+
'--datadir={}'.format(vlsd_dir),
592+
'--connect=http://localhost:{}'.format(vlsd_port),
593+
'--integration-test',
594+
]
595+
self.prefix = 'vlsd2-%d' % (node_id)
596+
self.vlsd_port = vlsd_port
597+
598+
@property
599+
def cmd_line(self):
600+
return [self.executable] + self.opts
601+
602+
def start(self, stdin=None, stdout_redir=True, stderr_redir=True,
603+
wait_for_initialized=True):
604+
TailableProc.start(self, stdin, stdout_redir, stderr_redir)
605+
# We need to always wait for initialization
606+
self.wait_for_log("vlsd2 git_desc")
607+
logging.info("vlsd2 started")
608+
609+
def stop(self, timeout=10):
610+
logging.info("stopping vlsd2")
611+
rc = TailableProc.stop(self, timeout)
612+
logging.info("vlsd2 stopped")
613+
self.logs_catchup()
614+
return rc
615+
616+
def __del__(self):
617+
self.logs_catchup()
618+
581619
class LightningD(TailableProc):
582620
def __init__(
583621
self,
@@ -594,6 +632,12 @@ def __init__(
594632
self.lightning_dir = lightning_dir
595633
self.port = port
596634
self.cmd_prefix = []
635+
self.lightning_dir = lightning_dir
636+
self.use_vlsd = False
637+
self.vlsd_dir = os.path.join(lightning_dir, "vlsd")
638+
self.vlsd_port = None
639+
self.vlsd = None
640+
self.node_id = node_id
597641

598642
self.rpcproxy = bitcoindproxy
599643
self.env['CLN_PLUGIN_LOG'] = "cln_plugin=trace,cln_rpc=trace,cln_grpc=trace,debug"
@@ -616,12 +660,38 @@ def __init__(
616660
if grpc_port is not None:
617661
opts['grpc-port'] = grpc_port
618662

663+
if SUBDAEMON:
664+
assert node_id > 0
665+
subdaemons = SUBDAEMON.split(',')
666+
# VLS_SERIAL_SELECT "swaps" the selected item with the first item
667+
select = env("VLS_SERIAL_SELECT", '1')
668+
if node_id == int(select):
669+
ndx = 1
670+
elif node_id == 1:
671+
ndx = int(select)
672+
else:
673+
ndx = node_id
674+
if ndx > len(subdaemons):
675+
# use the last element if not as many specifiers as nodes
676+
opts['subdaemon'] = subdaemons[-1]
677+
else:
678+
# use the matching specifier
679+
opts['subdaemon'] = subdaemons[ndx - 1]
680+
681+
print(f"starting node {node_id} with subdaemon {opts['subdaemon']}")
682+
if SUBDAEMON == 'hsmd:remote_hsmd_socket':
683+
self.use_vlsd = True
684+
619685
for k, v in opts.items():
620686
self.opts[k] = v
621687

622688
if not os.path.exists(os.path.join(lightning_dir, TEST_NETWORK)):
623689
os.makedirs(os.path.join(lightning_dir, TEST_NETWORK))
624690

691+
if self.use_vlsd:
692+
if not os.path.exists(self.vlsd_dir):
693+
os.makedirs(self.vlsd_dir)
694+
625695
# Last 32-bytes of final part of dir -> seed.
626696
seed = (bytes(re.search('([^/]+)/*$', lightning_dir).group(1), encoding='utf-8') + bytes(32))[:32]
627697
if not random_hsm:
@@ -637,6 +707,10 @@ def __init__(
637707
self.early_opts = ['--developer']
638708

639709
def cleanup(self):
710+
if self.use_vlsd:
711+
# Make sure the remotesigner is shutdown
712+
self.vlsd.stop()
713+
640714
# To force blackhole to exit, disconnect file must be truncated!
641715
if 'dev-disconnect' in self.opts:
642716
with open(self.opts['dev-disconnect'], "w") as f:
@@ -657,12 +731,65 @@ def cmd_line(self):
657731

658732
return self.cmd_prefix + [self.executable] + self.early_opts + opts
659733

734+
def __del__(self):
735+
if self.vlsd_port is not None:
736+
drop_unused_port(self.vlsd_port)
737+
660738
def start(self, stdin=None, wait_for_initialized=True, stderr_redir=False):
661-
self.opts['bitcoin-rpcport'] = self.rpcproxy.rpcport
662-
TailableProc.start(self, stdin, stdout_redir=False, stderr_redir=stderr_redir)
663-
if wait_for_initialized:
664-
self.wait_for_log("Server started with public key")
665-
logging.info("LightningD started")
739+
try:
740+
self.env['VLS_LSS'] = f"http://localhost:{self.lssd_port}"
741+
self.env['RUST_LOG'] = 'debug'
742+
# Some of the remote hsmd proxies need a bitcoind RPC connection
743+
self.env['BITCOIND_RPC_URL'] = 'http://{}:{}@localhost:{}'.format(
744+
BITCOIND_CONFIG['rpcuser'],
745+
BITCOIND_CONFIG['rpcpassword'],
746+
BITCOIND_CONFIG['rpcport'])
747+
748+
# The remote hsmd proxies need to know which network we are using
749+
if 'network' in self.opts:
750+
self.env['VLS_NETWORK'] = self.opts['network']
751+
752+
self.opts['bitcoin-rpcport'] = self.rpcproxy.rpcport
753+
754+
if self.use_vlsd:
755+
self.vlsd_port = reserve_unused_port()
756+
# We can't do this in the constructor because we need a new port on each restart.
757+
self.env['VLS_PORT'] = str(self.vlsd_port)
758+
# Kill any previous vlsd (we may have been restarted)
759+
if self.vlsd is not None:
760+
logging.info("killing prior vlsd")
761+
self.vlsd.kill()
762+
763+
TailableProc.start(self, stdin, stdout_redir=False, stderr_redir=stderr_redir)
764+
765+
if self.use_vlsd:
766+
# Start the remote signer first
767+
self.vlsd = ValidatingLightningSignerD(
768+
self.vlsd_dir, self.vlsd_port, self.node_id, self.opts['network'])
769+
self.vlsd.start(
770+
stdin, stdout_redir=True, stderr_redir=True,
771+
wait_for_initialized=wait_for_initialized)
772+
773+
if wait_for_initialized:
774+
self.wait_for_log("Server started with public key")
775+
logging.info("LightningD started")
776+
except Exception:
777+
if self.use_vlsd:
778+
# LightningD didn't start, stop the remotesigner
779+
self.vlsd.stop()
780+
raise
781+
782+
def stop(self, timeout=10):
783+
if self.use_vlsd:
784+
# Stop the remote signer first
785+
self.vlsd.stop(timeout)
786+
return TailableProc.stop(self, timeout)
787+
788+
def kill(self):
789+
if self.use_vlsd:
790+
# Kill the remote signer first
791+
self.vlsd.kill()
792+
TailableProc.kill(self)
666793

667794
def wait(self, timeout=TIMEOUT):
668795
"""Wait for the daemon to stop for up to timeout seconds

0 commit comments

Comments
 (0)