2
2
import http .client
3
3
import json
4
4
import logging
5
- import os
6
5
import ssl
7
6
from abc import ABC , abstractmethod
8
7
from time import sleep
9
- from typing import Optional
10
8
11
- from kubernetes import client , config
12
- from kubernetes .stream import stream
9
+ import requests
13
10
14
11
# hard-coded deterministic lnd credentials
15
12
ADMIN_MACAROON_HEX = "0201036c6e6402f801030a1062beabbf2a614b112128afa0c0b4fdd61201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620b17be53e367290871681055d0de15587f6d1cd47d1248fe2662ae27f62cfbdc6"
19
16
INSECURE_CONTEXT .verify_mode = ssl .CERT_NONE
20
17
21
18
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
-
52
19
# https://github.com/lightningcn/lightning-rfc/blob/master/07-routing-gossip.md#the-channel_update-message
53
20
# We use the field names as written in the BOLT as our canonical, internal field names.
54
21
# In LND, Policy objects returned by DescribeGraph have completely different labels
@@ -113,19 +80,16 @@ def to_lnd_chanpolicy(self, capacity):
113
80
114
81
class LNNode (ABC ):
115
82
@abstractmethod
116
- def __init__ (self , pod_name ):
83
+ def __init__ (self , pod_name , ip_address ):
117
84
self .name = pod_name
85
+ self .ip_address = ip_address
118
86
self .log = logging .getLogger (pod_name )
119
87
handler = logging .StreamHandler ()
120
- formatter = logging .Formatter (f' %(name)-8s - %(levelname)s: %(message)s' )
88
+ formatter = logging .Formatter (" %(name)-8s - %(levelname)s: %(message)s" )
121
89
handler .setFormatter (formatter )
122
90
self .log .addHandler (handler )
123
91
self .log .setLevel (logging .INFO )
124
92
125
- @staticmethod
126
- def param_dict_to_list (params : dict ) -> list [str ]:
127
- return [f"{ k } ={ v } " for k , v in params .items ()]
128
-
129
93
@staticmethod
130
94
def hex_to_b64 (hex ):
131
95
return base64 .b64encode (bytes .fromhex (hex )).decode ()
@@ -167,23 +131,20 @@ def update(self, txid_hex: str, policy: dict, capacity: int) -> dict:
167
131
168
132
169
133
class 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
175
137
self .headers = {}
176
138
self .impl = "cln"
139
+ self .reset_connection ()
177
140
178
141
def reset_connection (self ):
179
142
self .conn = http .client .HTTPSConnection (
180
143
host = self .name , port = 3010 , timeout = 5 , context = INSECURE_CONTEXT
181
144
)
182
145
183
146
def setRune (self , rune ):
184
- self .headers = {
185
- "Rune" : rune
186
- }
147
+ self .headers = {"Rune" : rune }
187
148
188
149
def get (self , uri ):
189
150
attempt = 0
@@ -204,7 +165,9 @@ def get(self, uri):
204
165
return None
205
166
sleep (1 )
206
167
207
- def post (self , uri , data = {}):
168
+ def post (self , uri , data = None ):
169
+ if not data :
170
+ data = {}
208
171
body = json .dumps (data )
209
172
post_header = self .headers
210
173
post_header ["Content-Length" ] = str (len (body ))
@@ -239,37 +202,15 @@ def post(self, uri, data={}):
239
202
return None
240
203
sleep (1 )
241
204
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
-
265
205
def createrune (self , max_tries = 2 ):
266
206
attempt = 0
267
207
while attempt < max_tries :
268
208
attempt += 1
269
- response = self . rpc ( "createrune" )
209
+ response = requests . get ( f"http:// { self . ip_address } :8080/rune.json" , timeout = 5 ). text
270
210
if not response :
271
211
sleep (2 )
272
212
continue
213
+ self .log .debug (response )
273
214
res = json .loads (response )
274
215
self .setRune (res ["rune" ])
275
216
return
@@ -367,14 +308,16 @@ def channel(self, pk, capacity, push_amt, fee_rate, max_tries=5) -> dict:
367
308
return None
368
309
369
310
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
+ )
371
314
if response :
372
315
res = json .loads (response )
373
316
return res ["bolt11" ]
374
317
return None
375
318
376
319
def payinvoice (self , payment_request ) -> str :
377
- response = self .rpc ( " pay" , {"bolt11" : payment_request })
320
+ response = self .post ( "/v1/ pay" , {"bolt11" : payment_request })
378
321
if response :
379
322
res = json .loads (response )
380
323
if "code" in res :
@@ -413,8 +356,8 @@ def update(self, txid_hex: str, policy: dict, capacity: int, max_tries=2) -> dic
413
356
414
357
415
358
class 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 )
418
361
self .conn = http .client .HTTPSConnection (
419
362
host = pod_name , port = 8080 , timeout = 5 , context = INSECURE_CONTEXT
420
363
)
0 commit comments