New flow for submarine swaps:
- client requests payment_hash from the server - client sends an invoice with that hash - client waits to receive HTLCs, then broadcasts funding tx This means that we now use same script for normal and reverse swaps. The new flow is enabled by setting option LIGHTNING_SWAP_HTLC_FIRST in the client. The old protocol is still supported server-side.
This commit is contained in:
@@ -5,11 +5,10 @@ from collections import defaultdict
|
||||
from aiohttp import web
|
||||
from aiorpcx import NetAddress
|
||||
|
||||
|
||||
from electrum.util import log_exceptions, ignore_exceptions
|
||||
from electrum.logging import Logger
|
||||
from electrum.util import EventListener
|
||||
|
||||
from electrum.lnaddr import lndecode
|
||||
|
||||
class SwapServer(Logger, EventListener):
|
||||
"""
|
||||
@@ -24,6 +23,7 @@ class SwapServer(Logger, EventListener):
|
||||
Logger.__init__(self)
|
||||
self.config = config
|
||||
self.wallet = wallet
|
||||
self.sm = self.wallet.lnworker.swap_manager
|
||||
self.addr = NetAddress.from_string(self.config.SWAPSERVER_ADDRESS)
|
||||
self.register_callbacks() # eventlistener
|
||||
|
||||
@@ -36,6 +36,8 @@ class SwapServer(Logger, EventListener):
|
||||
app = web.Application()
|
||||
app.add_routes([web.get('/api/getpairs', self.get_pairs)])
|
||||
app.add_routes([web.post('/api/createswap', self.create_swap)])
|
||||
app.add_routes([web.post('/api/createnormalswap', self.create_normal_swap)])
|
||||
app.add_routes([web.post('/api/addswapinvoice', self.add_swap_invoice)])
|
||||
|
||||
runner = web.AppRunner(app)
|
||||
await runner.setup()
|
||||
@@ -44,7 +46,7 @@ class SwapServer(Logger, EventListener):
|
||||
self.logger.info(f"now running and listening. addr={self.addr}")
|
||||
|
||||
async def get_pairs(self, r):
|
||||
sm = self.wallet.lnworker.swap_manager
|
||||
sm = self.sm
|
||||
sm.init_pairs()
|
||||
pairs = {
|
||||
"info": [],
|
||||
@@ -84,9 +86,36 @@ class SwapServer(Logger, EventListener):
|
||||
}
|
||||
return web.json_response(pairs)
|
||||
|
||||
async def add_swap_invoice(self, r):
|
||||
request = await r.json()
|
||||
invoice = request['invoice']
|
||||
self.sm.add_invoice(invoice, pay_now=True)
|
||||
return web.json_response({})
|
||||
|
||||
async def create_normal_swap(self, r):
|
||||
# normal for client, reverse for server
|
||||
request = await r.json()
|
||||
lightning_amount_sat = request['invoiceAmount']
|
||||
their_pubkey = bytes.fromhex(request['refundPublicKey'])
|
||||
assert len(their_pubkey) == 33
|
||||
swap = self.sm.create_reverse_swap(
|
||||
payment_hash=None,
|
||||
lightning_amount_sat=lightning_amount_sat,
|
||||
their_pubkey=their_pubkey
|
||||
)
|
||||
response = {
|
||||
"id": swap.payment_hash.hex(),
|
||||
'preimageHash': swap.payment_hash.hex(),
|
||||
"acceptZeroConf": False,
|
||||
"expectedAmount": swap.onchain_amount,
|
||||
"timeoutBlockHeight": swap.locktime,
|
||||
"address": swap.lockup_address,
|
||||
"redeemScript": swap.redeem_script.hex(),
|
||||
}
|
||||
return web.json_response(response)
|
||||
|
||||
async def create_swap(self, r):
|
||||
sm = self.wallet.lnworker.swap_manager
|
||||
sm.init_pairs()
|
||||
self.sm.init_pairs()
|
||||
request = await r.json()
|
||||
req_type = request['type']
|
||||
assert request['pairId'] == 'BTC/BTC'
|
||||
@@ -96,7 +125,7 @@ class SwapServer(Logger, EventListener):
|
||||
their_pubkey=bytes.fromhex(request['claimPublicKey'])
|
||||
assert len(payment_hash) == 32
|
||||
assert len(their_pubkey) == 33
|
||||
swap, payment_hash, invoice, prepay_invoice = sm.add_server_swap(
|
||||
swap, invoice, prepay_invoice = self.sm.create_normal_swap(
|
||||
lightning_amount_sat=lightning_amount_sat,
|
||||
payment_hash=payment_hash,
|
||||
their_pubkey=their_pubkey
|
||||
@@ -111,13 +140,19 @@ class SwapServer(Logger, EventListener):
|
||||
"onchainAmount": swap.onchain_amount,
|
||||
}
|
||||
elif req_type == 'submarine':
|
||||
# old protocol
|
||||
their_invoice=request['invoice']
|
||||
their_pubkey=bytes.fromhex(request['refundPublicKey'])
|
||||
assert len(their_pubkey) == 33
|
||||
swap, payment_hash, invoice, prepay_invoice = sm.add_server_swap(
|
||||
invoice=their_invoice,
|
||||
lnaddr = lndecode(their_invoice)
|
||||
payment_hash = lnaddr.paymenthash
|
||||
lightning_amount_sat = int(lnaddr.get_amount_sat()) # should return int
|
||||
swap = self.sm.create_reverse_swap(
|
||||
lightning_amount_sat=lightning_amount_sat,
|
||||
payment_hash=payment_hash,
|
||||
their_pubkey=their_pubkey
|
||||
)
|
||||
self.sm.add_invoice(their_invoice, pay_now=False)
|
||||
response = {
|
||||
"id": payment_hash.hex(),
|
||||
"acceptZeroConf": False,
|
||||
|
||||
@@ -55,7 +55,6 @@ class SwapServerPlugin(BasePlugin):
|
||||
self.server = SwapServer(self.config, wallet)
|
||||
sm = wallet.lnworker.swap_manager
|
||||
for coro in [
|
||||
sm.pay_pending_invoices(), # FIXME this method can raise, which is not properly handled...?
|
||||
self.server.run(),
|
||||
]:
|
||||
asyncio.run_coroutine_threadsafe(daemon.taskgroup.spawn(coro), daemon.asyncio_loop)
|
||||
|
||||
Reference in New Issue
Block a user