mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-19 13:18:26 +02:00
Add c-lightning support
This commit is contained in:
parent
80155f1fb7
commit
a3408e687c
11 changed files with 317 additions and 6 deletions
22
clightning-config.ini
Normal file
22
clightning-config.ini
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[node]
|
||||
network=testnet
|
||||
|
||||
[clightning]
|
||||
enabled=true
|
||||
|
||||
|
||||
[bitcoin]
|
||||
rpc_host=localhost
|
||||
rpc_port=18332
|
||||
rpc_user=devuser
|
||||
rpc_pass=devpass
|
||||
zeromq_hashblock_port=28334
|
||||
|
||||
[tor]
|
||||
proxy_ip=localhost
|
||||
proxy_port=9150
|
||||
|
||||
[webadmin]
|
||||
enabled=true
|
||||
username=devuser
|
||||
password=devpass
|
||||
25
docker/config-clightning.ini
Normal file
25
docker/config-clightning.ini
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
[node]
|
||||
network=testnet
|
||||
|
||||
[lnd]
|
||||
external_host=clightning_server
|
||||
port=19735
|
||||
|
||||
[clightning]
|
||||
enabled=true
|
||||
|
||||
[bitcoin]
|
||||
rpc_host=bitcoin-core
|
||||
rpc_port=18332
|
||||
rpc_user=devuser
|
||||
rpc_pass=devpass
|
||||
zeromq_hashblock_port=28334
|
||||
|
||||
[tor]
|
||||
proxy_ip=tor-node
|
||||
proxy_port=9050
|
||||
|
||||
[webadmin]
|
||||
enabled=true
|
||||
username=devuser
|
||||
password=devpass
|
||||
|
|
@ -19,6 +19,16 @@ services:
|
|||
environment:
|
||||
- NETWORK=mainnet
|
||||
|
||||
clightning_client:
|
||||
command:
|
||||
- --bitcoin-rpcconnect=bitcoin-core
|
||||
- --bitcoin-rpcuser=devuser
|
||||
- --bitcoin-rpcpassword=devpass
|
||||
- --network=mainnet
|
||||
- --plugin-dir=/usr/libexec/c-lightning/plugins
|
||||
- --alias=myitestnode
|
||||
- --log-level=debug
|
||||
|
||||
# squeaknode:
|
||||
# environment:
|
||||
# - NETWORK=mainnet
|
||||
|
|
|
|||
|
|
@ -15,6 +15,32 @@ services:
|
|||
-zmqpubhashblock=tcp://0.0.0.0:28334
|
||||
-zmqpubhashtx=tcp://0.0.0.0:28334
|
||||
|
||||
clightning_client:
|
||||
command:
|
||||
- --bitcoin-rpcconnect=bitcoin-core
|
||||
- --bitcoin-rpcuser=devuser
|
||||
- --bitcoin-rpcpassword=devpass
|
||||
- --network=testnet
|
||||
- --plugin-dir=/usr/libexec/c-lightning/plugins
|
||||
- --alias=myclientningclient
|
||||
- --log-level=debug
|
||||
- --rpc-file=/root/.lightning/lightning-rpc
|
||||
- --rpc-file-mode=0777
|
||||
- --proxy=tor-node:9050
|
||||
|
||||
clightning_server:
|
||||
command:
|
||||
- --bitcoin-rpcconnect=bitcoin-core
|
||||
- --bitcoin-rpcuser=devuser
|
||||
- --bitcoin-rpcpassword=devpass
|
||||
- --network=testnet
|
||||
- --plugin-dir=/usr/libexec/c-lightning/plugins
|
||||
- --alias=myclientningserver
|
||||
- --log-level=debug
|
||||
- --rpc-file=/root/.lightning/lightning-rpc
|
||||
- --rpc-file-mode=0777
|
||||
- --proxy=tor-node:9050
|
||||
|
||||
# squeaknode:
|
||||
# environment:
|
||||
# - NETWORK=testnet
|
||||
|
|
|
|||
|
|
@ -57,6 +57,45 @@ services:
|
|||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
entrypoint: ["./start-lnd.sh"]
|
||||
|
||||
clightning_client:
|
||||
image: elementsproject/lightningd:v0.11.0.1
|
||||
container_name: clightning_client
|
||||
expose:
|
||||
- "9735"
|
||||
- "19735"
|
||||
- "9835"
|
||||
- "10009"
|
||||
ports:
|
||||
- 10010:10009
|
||||
- 9835:9835
|
||||
volumes:
|
||||
- ~/.lightning:/root/.lightning
|
||||
- tor-dir:/var/lib/tor
|
||||
links:
|
||||
- "bitcoin-core:bitcoin-core"
|
||||
depends_on:
|
||||
- "tor-node"
|
||||
sysctls:
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
|
||||
clightning_server:
|
||||
image: elementsproject/lightningd:v0.11.0.1
|
||||
container_name: clightning_server
|
||||
expose:
|
||||
- "9735"
|
||||
- "19735"
|
||||
- "9835"
|
||||
- "10009"
|
||||
volumes:
|
||||
- clightning_server_dir:/root/.lightning
|
||||
- tor-dir:/var/lib/tor
|
||||
links:
|
||||
- "bitcoin-core:bitcoin-core"
|
||||
depends_on:
|
||||
- "tor-node"
|
||||
sysctls:
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
|
||||
tor-node:
|
||||
image: osminogin/tor-simple
|
||||
container_name: tor-node
|
||||
|
|
@ -89,10 +128,36 @@ services:
|
|||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
entrypoint: ["./entrypoint.sh"]
|
||||
|
||||
squeaknode_clightning:
|
||||
image: squeaknode
|
||||
container_name: squeaknode_clightning
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: Dockerfile
|
||||
depends_on:
|
||||
- "lnd_server"
|
||||
volumes:
|
||||
- clightning_server_dir:/root/.lightning
|
||||
- squeaknode_clightning_dir:/root/.sqk
|
||||
- ./config-clightning.ini:/config.ini
|
||||
ports:
|
||||
- 18558:18555
|
||||
- 12996:12994
|
||||
links:
|
||||
- "bitcoin-core:bitcoin-core"
|
||||
- "lnd_server:lnd"
|
||||
sysctls:
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
entrypoint: ["./entrypoint.sh"]
|
||||
|
||||
volumes:
|
||||
lnd_server_dir:
|
||||
driver: local
|
||||
clightning_server_dir:
|
||||
driver: local
|
||||
squeaknode_dir:
|
||||
driver: local
|
||||
squeaknode_clightning_dir:
|
||||
driver: local
|
||||
tor-dir:
|
||||
driver: local
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
alembic==1.7.1
|
||||
docutils==0.17.1
|
||||
Flask==2.0.1
|
||||
flask-cors==3.0.10
|
||||
flask-login==0.5.0
|
||||
|
|
@ -7,6 +8,7 @@ googleapis-common-protos==1.53.0
|
|||
importlib_resources==1.4.0
|
||||
mypy-protobuf==2.9
|
||||
protobuf==3.17.3
|
||||
pyln-client==0.10.1
|
||||
PySocks==1.7.1
|
||||
python-bitcoinlib==0.11.0
|
||||
pyzmq==22.3.0
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ BITCOIN_RPC_PORT = {
|
|||
}
|
||||
DEFAULT_LND_PORT = 9735
|
||||
DEFAULT_LND_RPC_PORT = 10009
|
||||
DEFAULT_CLIGHTNING_DIR = ".lightning"
|
||||
DEFAULT_CLIGHTNING_RPC_FILE = str(
|
||||
Path.home() / DEFAULT_CLIGHTNING_DIR / 'lightning-rpc')
|
||||
DEFAULT_SQK_DIR = ".sqk"
|
||||
DEFAULT_SQK_DIR_PATH = str(Path.home() / DEFAULT_SQK_DIR)
|
||||
DEFAULT_LND_HOST = "localhost"
|
||||
|
|
@ -92,6 +95,13 @@ class LndConfig(Config):
|
|||
macaroon_path = key(cast=str, required=False, default="")
|
||||
|
||||
|
||||
@section('clightning')
|
||||
class CLightningConfig(Config):
|
||||
enabled = key(cast=bool, required=False, default=False)
|
||||
rpc_file = key(cast=str, required=False,
|
||||
default=DEFAULT_CLIGHTNING_RPC_FILE)
|
||||
|
||||
|
||||
@section('tor')
|
||||
class TorConfig(Config):
|
||||
proxy_ip = key(cast=str, required=False, default="")
|
||||
|
|
@ -173,6 +183,7 @@ class TwitterConfig(Config):
|
|||
class SqueaknodeConfig(Config):
|
||||
bitcoin = group_key(BitcoinConfig)
|
||||
lnd = group_key(LndConfig)
|
||||
clightning = group_key(CLightningConfig)
|
||||
tor = group_key(TorConfig)
|
||||
server = group_key(ServerConfig)
|
||||
rpc = group_key(RpcConfig)
|
||||
|
|
|
|||
133
squeaknode/lightning/clightning_lightning_client.py
Normal file
133
squeaknode/lightning/clightning_lightning_client.py
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2020 Jonathan Zernik
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
import logging
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from pyln.client import LightningRpc
|
||||
|
||||
from squeaknode.core.exception import InvoiceSubscriptionError
|
||||
from squeaknode.lightning.info import Info
|
||||
from squeaknode.lightning.invoice import Invoice
|
||||
from squeaknode.lightning.invoice_stream import InvoiceStream
|
||||
from squeaknode.lightning.lightning_client import LightningClient
|
||||
from squeaknode.lightning.pay_req import PayReq
|
||||
from squeaknode.lightning.payment import Payment
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CLightningClient(LightningClient):
|
||||
"""Access a c-lightning instance using the Python API."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
rpc_path: str,
|
||||
) -> None:
|
||||
self.rpc_path = rpc_path
|
||||
|
||||
def init(self):
|
||||
# Create an instance of the LightningRpc object using the Core Lightning daemon on your computer.
|
||||
logger.info('initializing clightning client: {}'.format(self.rpc_path))
|
||||
self.lrpc = LightningRpc(self.rpc_path)
|
||||
|
||||
def pay_invoice(self, payment_request: str) -> Payment:
|
||||
payment = self.lrpc.pay(payment_request)
|
||||
if payment['status'] == 'complete':
|
||||
return Payment(
|
||||
payment_preimage=bytes.fromhex(payment['payment_preimage']),
|
||||
payment_error='',
|
||||
)
|
||||
else:
|
||||
return Payment(
|
||||
payment_preimage=b'',
|
||||
payment_error='Payment failed.',
|
||||
)
|
||||
|
||||
def get_info(self) -> Info:
|
||||
info = self.lrpc.getinfo()
|
||||
pubkey = info['id']
|
||||
binding = info.get('binding')
|
||||
uris = []
|
||||
if binding:
|
||||
for b in binding:
|
||||
address = b['address']
|
||||
if ':' not in address: # TODO: Change type of uri to LightningAddress.
|
||||
port = b['port']
|
||||
uri = f"{pubkey}@{address}:{port}"
|
||||
uris.append(uri)
|
||||
return Info(
|
||||
uris=uris,
|
||||
)
|
||||
|
||||
def decode_pay_req(self, payment_request: str) -> PayReq:
|
||||
pay_req = self.lrpc.decodepay(payment_request)
|
||||
return PayReq(
|
||||
payment_hash=bytes.fromhex(pay_req['payment_hash']),
|
||||
payment_point=b'', # TODO: Use real payment point.
|
||||
num_msat=pay_req['amount_msat'].millisatoshis,
|
||||
destination=pay_req['payee'],
|
||||
timestamp=int(pay_req['created_at']),
|
||||
expiry=int(pay_req['expiry']),
|
||||
)
|
||||
|
||||
def create_invoice(self, preimage: bytes, amount_msat: int) -> Invoice:
|
||||
created_invoice = self.lrpc.invoice(
|
||||
amount_msat,
|
||||
label=str(uuid.uuid4()),
|
||||
description="Squeaknode invoice",
|
||||
preimage=preimage.hex(),
|
||||
)
|
||||
creation_time = int(time.time())
|
||||
expiry = int(created_invoice['expires_at']) - creation_time
|
||||
return Invoice(
|
||||
r_hash=bytes.fromhex(created_invoice['payment_hash']),
|
||||
payment_request=created_invoice['bolt11'],
|
||||
value_msat=amount_msat,
|
||||
settled=False,
|
||||
settle_index=0,
|
||||
creation_date=creation_time,
|
||||
expiry=expiry,
|
||||
)
|
||||
|
||||
def subscribe_invoices(self, settle_index: int) -> InvoiceStream:
|
||||
# subscribe_invoices_request = lnd_pb2.InvoiceSubscription(
|
||||
# settle_index=settle_index,
|
||||
# )
|
||||
# subscribe_result = self.stub.SubscribeInvoices(
|
||||
# subscribe_invoices_request,
|
||||
# )
|
||||
# return InvoiceStream(
|
||||
# cancel=subscribe_result.cancel,
|
||||
# result_stream=iter(subscribe_result),
|
||||
# )
|
||||
def cancel_fn():
|
||||
return None
|
||||
|
||||
def get_invoice_stream():
|
||||
raise InvoiceSubscriptionError()
|
||||
|
||||
return InvoiceStream(
|
||||
cancel=cancel_fn,
|
||||
result_stream=get_invoice_stream(),
|
||||
)
|
||||
|
|
@ -34,6 +34,13 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class LightningClient(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def init(self):
|
||||
"""Initialize the lightning client.
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_info(self) -> Info:
|
||||
"""Get info about the lightning node.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ from squeaknode.core.squeak_core import SqueakCore
|
|||
from squeaknode.db.db_engine import get_connection_string
|
||||
from squeaknode.db.db_engine import get_engine
|
||||
from squeaknode.db.squeak_db import SqueakDb
|
||||
from squeaknode.lightning.clightning_lightning_client import CLightningClient
|
||||
from squeaknode.lightning.lnd_lightning_client import LNDLightningClient
|
||||
from squeaknode.node.node_settings import NodeSettings
|
||||
from squeaknode.node.payment_processor import PaymentProcessor
|
||||
|
|
@ -48,6 +49,7 @@ from squeaknode.server.app import SqueakPeerWebServer
|
|||
from squeaknode.server.squeak_peer_server_handler import SqueakPeerServerHandler
|
||||
from squeaknode.twitter.twitter_forwarder import TwitterForwarder
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
@ -118,12 +120,17 @@ class SqueakNode:
|
|||
self.node_settings = NodeSettings(self.squeak_db)
|
||||
|
||||
def create_lightning_client(self):
|
||||
self.lightning_client = LNDLightningClient(
|
||||
self.config.lnd.host,
|
||||
self.config.lnd.rpc_port,
|
||||
self.config.lnd.tls_cert_path,
|
||||
self.config.lnd.macaroon_path,
|
||||
)
|
||||
if self.config.clightning.enabled:
|
||||
self.lightning_client = CLightningClient(
|
||||
self.config.clightning.rpc_file,
|
||||
)
|
||||
else:
|
||||
self.lightning_client = LNDLightningClient(
|
||||
self.config.lnd.host,
|
||||
self.config.lnd.rpc_port,
|
||||
self.config.lnd.tls_cert_path,
|
||||
self.config.lnd.macaroon_path,
|
||||
)
|
||||
|
||||
def create_bitcoin_client(self):
|
||||
self.bitcoin_client = BitcoinCoreClient(
|
||||
|
|
|
|||
|
|
@ -189,6 +189,9 @@ class MockLightningClient(LightningClient):
|
|||
self.payment = payment
|
||||
self.invoice_stream = invoice_stream
|
||||
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
def get_info(self):
|
||||
return self.info
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue