22import http .client
33import json
44import logging
5- import os
65import ssl
76from abc import ABC , abstractmethod
87from time import sleep
9- from typing import Optional
108
11- from kubernetes import client , config
12- from kubernetes .stream import stream
9+ import requests
1310
1411# hard-coded deterministic lnd credentials
1512ADMIN_MACAROON_HEX = "0201036c6e6402f801030a1062beabbf2a614b112128afa0c0b4fdd61201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620b17be53e367290871681055d0de15587f6d1cd47d1248fe2662ae27f62cfbdc6"
1916INSECURE_CONTEXT .verify_mode = ssl .CERT_NONE
2017
2118
22- # execute kubernetes command
23- def run_command (name , command : list [str ], namespace : Optional [str ] = "default" ) -> str :
24- if os .getenv ("KUBERNETES_SERVICE_HOST" ) and os .getenv ("KUBERNETES_SERVICE_PORT" ):
25- config .load_incluster_config ()
26- else :
27- config .load_kube_config ()
28- sclient = client .CoreV1Api ()
29- resp = stream (
30- sclient .connect_get_namespaced_pod_exec ,
31- name ,
32- namespace ,
33- command = command ,
34- stderr = True ,
35- stdin = False ,
36- stdout = True ,
37- tty = False ,
38- _request_timeout = 20 ,
39- _preload_content = False ,
40- )
41- result = ""
42- while resp .is_open ():
43- resp .update (timeout = 5 )
44- if resp .peek_stdout ():
45- result += resp .read_stdout ()
46- if resp .peek_stderr ():
47- raise Exception (resp .read_stderr ())
48- resp .close ()
49- return result
50-
51-
5219# https://github.com/lightningcn/lightning-rfc/blob/master/07-routing-gossip.md#the-channel_update-message
5320# We use the field names as written in the BOLT as our canonical, internal field names.
5421# In LND, Policy objects returned by DescribeGraph have completely different labels
@@ -113,19 +80,16 @@ def to_lnd_chanpolicy(self, capacity):
11380
11481class LNNode (ABC ):
11582 @abstractmethod
116- def __init__ (self , pod_name ):
83+ def __init__ (self , pod_name , ip_address ):
11784 self .name = pod_name
85+ self .ip_address = ip_address
11886 self .log = logging .getLogger (pod_name )
11987 handler = logging .StreamHandler ()
120- formatter = logging .Formatter (f' %(name)-8s - %(levelname)s: %(message)s' )
88+ formatter = logging .Formatter (" %(name)-8s - %(levelname)s: %(message)s" )
12189 handler .setFormatter (formatter )
12290 self .log .addHandler (handler )
12391 self .log .setLevel (logging .INFO )
12492
125- @staticmethod
126- def param_dict_to_list (params : dict ) -> list [str ]:
127- return [f"{ k } ={ v } " for k , v in params .items ()]
128-
12993 @staticmethod
13094 def hex_to_b64 (hex ):
13195 return base64 .b64encode (bytes .fromhex (hex )).decode ()
@@ -167,23 +131,20 @@ def update(self, txid_hex: str, policy: dict, capacity: int) -> dict:
167131
168132
169133class CLN (LNNode ):
170- def __init__ (self , pod_name ):
171- super ().__init__ (pod_name )
172- self .conn = http .client .HTTPSConnection (
173- host = pod_name , port = 8080 , timeout = 5 , context = INSECURE_CONTEXT
174- )
134+ def __init__ (self , pod_name , ip_address ):
135+ super ().__init__ (pod_name , ip_address )
136+ self .conn = None
175137 self .headers = {}
176138 self .impl = "cln"
139+ self .reset_connection ()
177140
178141 def reset_connection (self ):
179142 self .conn = http .client .HTTPSConnection (
180143 host = self .name , port = 3010 , timeout = 5 , context = INSECURE_CONTEXT
181144 )
182145
183146 def setRune (self , rune ):
184- self .headers = {
185- "Rune" : rune
186- }
147+ self .headers = {"Rune" : rune }
187148
188149 def get (self , uri ):
189150 attempt = 0
@@ -204,7 +165,9 @@ def get(self, uri):
204165 return None
205166 sleep (1 )
206167
207- def post (self , uri , data = {}):
168+ def post (self , uri , data = None ):
169+ if not data :
170+ data = {}
208171 body = json .dumps (data )
209172 post_header = self .headers
210173 post_header ["Content-Length" ] = str (len (body ))
@@ -239,37 +202,15 @@ def post(self, uri, data={}):
239202 return None
240203 sleep (1 )
241204
242- def rpc (
243- self ,
244- method : str ,
245- params : list [str ] = None ,
246- namespace : Optional [str ] = "default" ,
247- max_tries = 5 ,
248- ):
249- cmd = ["lightning-cli" , method ]
250- if params :
251- cmd .extend (params )
252- attempt = 0
253- while attempt < max_tries :
254- attempt += 1
255- try :
256- response = run_command (self .name , cmd , namespace )
257- if not response :
258- continue
259- return response
260- except Exception as e :
261- self .log .error (f"CLN rpc error: { e } , wait and retry..." )
262- sleep (2 )
263- return None
264-
265205 def createrune (self , max_tries = 2 ):
266206 attempt = 0
267207 while attempt < max_tries :
268208 attempt += 1
269- response = self . rpc ( "createrune" )
209+ response = requests . get ( f"http:// { self . ip_address } :8080/rune.json" , timeout = 5 ). text
270210 if not response :
271211 sleep (2 )
272212 continue
213+ self .log .debug (response )
273214 res = json .loads (response )
274215 self .setRune (res ["rune" ])
275216 return
@@ -367,14 +308,16 @@ def channel(self, pk, capacity, push_amt, fee_rate, max_tries=5) -> dict:
367308 return None
368309
369310 def createinvoice (self , sats , label , description = "new invoice" ) -> str :
370- response = self .post ("invoice" , {"amount_msat" : sats * 1000 , "label" : label , "description" : description })
311+ response = self .post (
312+ "invoice" , {"amount_msat" : sats * 1000 , "label" : label , "description" : description }
313+ )
371314 if response :
372315 res = json .loads (response )
373316 return res ["bolt11" ]
374317 return None
375318
376319 def payinvoice (self , payment_request ) -> str :
377- response = self .rpc ( " pay" , {"bolt11" : payment_request })
320+ response = self .post ( "/v1/ pay" , {"bolt11" : payment_request })
378321 if response :
379322 res = json .loads (response )
380323 if "code" in res :
@@ -413,8 +356,8 @@ def update(self, txid_hex: str, policy: dict, capacity: int, max_tries=2) -> dic
413356
414357
415358class LND (LNNode ):
416- def __init__ (self , pod_name ):
417- super ().__init__ (pod_name )
359+ def __init__ (self , pod_name , ip_address ):
360+ super ().__init__ (pod_name , ip_address )
418361 self .conn = http .client .HTTPSConnection (
419362 host = pod_name , port = 8080 , timeout = 5 , context = INSECURE_CONTEXT
420363 )
0 commit comments