5
5
from subprocess import run
6
6
from time import sleep
7
7
8
- from warnet .k8s import get_pods_with_label , wait_for_pod
8
+ from warnet .k8s import download , get_pods_with_label , wait_for_pod
9
9
from warnet .plugin import _get_plugin_directory as get_plugin_directory
10
10
from warnet .process import run_command
11
11
from warnet .status import _get_tank_status as network_status
21
21
lightning_selector = "mission=lightning"
22
22
23
23
24
- # @post_deploy
25
- def deploy_helm ():
26
- print ("SimLN Plugin ⚡" )
27
- plugin_dir = get_plugin_directory ()
28
- print (f"DIR: { plugin_dir } " )
29
- command = f"helm upgrade --install simln { plugin_dir } /simln/charts/simln"
30
- helm_result = run_command (command )
31
- print (helm_result )
32
-
33
-
34
24
def run_simln ():
25
+ """Run a SimLN Plugin demo"""
35
26
init_network ()
36
27
fund_wallets ()
37
28
wait_for_everyone_to_have_a_host ()
@@ -41,43 +32,46 @@ def run_simln():
41
32
log .info (warnet ("bitcoin rpc tank-0000 -generate 7" ))
42
33
wait_for_gossip_sync (2 )
43
34
log .info ("done waiting" )
44
- pod_name = prepare_and_launch_activity ()
35
+ pod_name = _prepare_and_launch_activity ()
45
36
log .info (pod_name )
46
37
wait_for_pod (pod_name , 60 )
47
38
48
39
49
- def prepare_and_launch_activity () -> str :
50
- pods = get_pods_with_label (lightning_selector )
51
- pod_a = pods [1 ].metadata .name
52
- pod_b = pods [2 ].metadata .name
53
- log .info (f"pod_a: { pod_a } " )
54
- log .info (f"pod_b: { pod_b } " )
55
- sample_activity = [
56
- {"source" : pod_a , "destination" : pod_b , "interval_secs" : 1 , "amount_msat" : 2000 }
57
- ]
40
+ def _prepare_and_launch_activity () -> str :
41
+ sample_activity = get_example_activity ()
58
42
log .info (f"Activity: { sample_activity } " )
59
43
pod_name = launch_activity (sample_activity )
60
44
log .info ("Sent command. Done." )
61
45
return pod_name
62
46
63
47
48
+ def get_example_activity () -> list [dict ]:
49
+ """Get an activity representing node 2 sending msat to node 3"""
50
+ pods = get_pods_with_label (lightning_selector )
51
+ pod_a = pods [1 ].metadata .name
52
+ pod_b = pods [2 ].metadata .name
53
+ return [{"source" : pod_a , "destination" : pod_b , "interval_secs" : 1 , "amount_msat" : 2000 }]
54
+
55
+
64
56
def launch_activity (activity : list [dict ]) -> str :
57
+ """Launch a SimLN chart which includes the `activity`"""
65
58
random_digits = "" .join (random .choices ("0123456789" , k = 10 ))
66
59
plugin_dir = get_plugin_directory ()
67
- generate_nodes_file (activity , plugin_dir / Path ("simln/charts/simln/files/sim.json" ))
60
+ _generate_nodes_file (activity , plugin_dir / Path ("simln/charts/simln/files/sim.json" ))
68
61
command = f"helm upgrade --install simln-{ random_digits } { plugin_dir } /simln/charts/simln"
69
62
log .info (f"generate activity: { command } " )
70
63
run_command (command )
71
64
return f"simln-simln-{ random_digits } "
72
65
73
66
74
67
def init_network ():
68
+ """Mine regtest coins and wait for ln nodes to come online."""
75
69
log .info ("Initializing network" )
76
70
wait_for_all_tanks_status (target = "running" )
77
71
78
72
warnet ("bitcoin rpc tank-0000 createwallet miner" )
79
73
warnet ("bitcoin rpc tank-0000 -generate 110" )
80
- wait_for_predicate (lambda : int (warnet ("bitcoin rpc tank-0000 getblockcount" )) > 100 )
74
+ _wait_for_predicate (lambda : int (warnet ("bitcoin rpc tank-0000 getblockcount" )) > 100 )
81
75
82
76
def wait_for_all_ln_rpc ():
83
77
lns = get_pods_with_label (lightning_selector )
@@ -90,10 +84,11 @@ def wait_for_all_ln_rpc():
90
84
return False
91
85
return True
92
86
93
- wait_for_predicate (wait_for_all_ln_rpc )
87
+ _wait_for_predicate (wait_for_all_ln_rpc )
94
88
95
89
96
90
def fund_wallets ():
91
+ """Fund each ln node with 10 regtest coins."""
97
92
log .info ("Funding wallets" )
98
93
outputs = ""
99
94
lns = get_pods_with_label (lightning_selector )
@@ -108,6 +103,7 @@ def fund_wallets():
108
103
109
104
110
105
def everyone_has_a_host () -> bool :
106
+ """Find out if each ln node has a host."""
111
107
pods = get_pods_with_label (lightning_selector )
112
108
host_havers = 0
113
109
for pod in pods :
@@ -119,10 +115,10 @@ def everyone_has_a_host() -> bool:
119
115
120
116
121
117
def wait_for_everyone_to_have_a_host ():
122
- wait_for_predicate (everyone_has_a_host )
118
+ _wait_for_predicate (everyone_has_a_host )
123
119
124
120
125
- def wait_for_predicate (predicate , timeout = 5 * 60 , interval = 5 ):
121
+ def _wait_for_predicate (predicate , timeout = 5 * 60 , interval = 5 ):
126
122
log .info (
127
123
f"Waiting for predicate ({ predicate .__name__ } ) with timeout { timeout } s and interval { interval } s"
128
124
)
@@ -142,9 +138,7 @@ def wait_for_predicate(predicate, timeout=5 * 60, interval=5):
142
138
143
139
144
140
def wait_for_all_tanks_status (target : str = "running" , timeout : int = 20 * 60 , interval : int = 5 ):
145
- """Poll the warnet server for container status
146
- Block until all tanks are running
147
- """
141
+ """Poll the warnet server for container status. Block until all tanks are running"""
148
142
149
143
def check_status ():
150
144
tanks = network_status ()
@@ -159,10 +153,11 @@ def check_status():
159
153
log .info (f"Waiting for all tanks to reach '{ target } ': { stats } " )
160
154
return target in stats and stats [target ] == stats ["total" ]
161
155
162
- wait_for_predicate (check_status , timeout , interval )
156
+ _wait_for_predicate (check_status , timeout , interval )
163
157
164
158
165
- def wait_for_gossip_sync (expected : int ):
159
+ def wait_for_gossip_sync (expected : int = 2 ):
160
+ """Wait for any of the ln nodes to have an `expected` number of edges."""
166
161
log .info (f"Waiting for sync (expecting { expected } )..." )
167
162
current = 0
168
163
while current < expected :
@@ -178,6 +173,7 @@ def wait_for_gossip_sync(expected: int):
178
173
179
174
180
175
def warnet (cmd : str = "--help" ):
176
+ """Pass a `cmd` to Warnet."""
181
177
log .info (f"Executing warnet command: { cmd } " )
182
178
command = ["warnet" ] + cmd .split ()
183
179
proc = run (command , capture_output = True )
@@ -186,7 +182,7 @@ def warnet(cmd: str = "--help"):
186
182
return proc .stdout .decode ()
187
183
188
184
189
- def generate_nodes_file (activity : dict , output_file : Path = Path ("nodes.json" )):
185
+ def _generate_nodes_file (activity : list [ dict ] , output_file : Path = Path ("nodes.json" )):
190
186
nodes = []
191
187
192
188
for i in get_pods_with_label (lightning_selector ):
@@ -206,8 +202,10 @@ def generate_nodes_file(activity: dict, output_file: Path = Path("nodes.json")):
206
202
207
203
208
204
def manual_open_channels ():
205
+ """Manually open channels between ln nodes 1, 2, and 3"""
206
+
209
207
def wait_for_two_txs ():
210
- wait_for_predicate (
208
+ _wait_for_predicate (
211
209
lambda : json .loads (warnet ("bitcoin rpc tank-0000 getmempoolinfo" ))["size" ] == 2
212
210
)
213
211
@@ -241,3 +239,13 @@ def wait_for_two_txs():
241
239
wait_for_two_txs ()
242
240
243
241
warnet ("bitcoin rpc tank-0000 -generate 10" )
242
+
243
+
244
+ def list_simln_podnames () -> list [str ]:
245
+ """Get a list of simln pod names"""
246
+ return [pod .metadata .name for pod in get_pods_with_label ("mission=simln" )]
247
+
248
+
249
+ def download_results (pod_name : str ):
250
+ """Download SimLN results to the current directory"""
251
+ download (pod_name , source_path = Path ("/working/results" ))
0 commit comments