submarine_swaps: small clean-up
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import attr
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional, Dict
|
||||
|
||||
import attr
|
||||
|
||||
from .crypto import sha256, hash_160
|
||||
from .ecc import ECPrivkey
|
||||
@@ -64,20 +65,28 @@ WITNESS_TEMPLATE_REVERSE_SWAP = [
|
||||
class SwapData(StoredObject):
|
||||
is_reverse = attr.ib(type=bool)
|
||||
locktime = attr.ib(type=int)
|
||||
onchain_amount = attr.ib(type=int)
|
||||
lightning_amount = attr.ib(type=int)
|
||||
onchain_amount = attr.ib(type=int) # in sats
|
||||
lightning_amount = attr.ib(type=int) # in sats
|
||||
redeem_script = attr.ib(type=bytes, converter=hex_to_bytes)
|
||||
preimage = attr.ib(type=bytes, converter=hex_to_bytes)
|
||||
prepay_hash = attr.ib(type=bytes, converter=hex_to_bytes)
|
||||
prepay_hash = attr.ib(type=Optional[bytes], converter=hex_to_bytes)
|
||||
privkey = attr.ib(type=bytes, converter=hex_to_bytes)
|
||||
lockup_address = attr.ib(type=str)
|
||||
funding_txid = attr.ib(type=str)
|
||||
spending_txid = attr.ib(type=str)
|
||||
funding_txid = attr.ib(type=Optional[str])
|
||||
spending_txid = attr.ib(type=Optional[str])
|
||||
is_redeemed = attr.ib(type=bool)
|
||||
|
||||
|
||||
def create_claim_tx(txin, witness_script, preimage, privkey:bytes, address, amount_sat, locktime):
|
||||
pubkey = ECPrivkey(privkey).get_public_key_bytes(compressed=True)
|
||||
def create_claim_tx(
|
||||
*,
|
||||
txin: PartialTxInput,
|
||||
witness_script: bytes,
|
||||
preimage: bytes,
|
||||
privkey: bytes,
|
||||
address: str,
|
||||
amount_sat: int,
|
||||
locktime: int,
|
||||
) -> PartialTransaction:
|
||||
if is_segwit_address(txin.address):
|
||||
txin.script_type = 'p2wsh'
|
||||
txin.script_sig = b''
|
||||
@@ -86,7 +95,7 @@ def create_claim_tx(txin, witness_script, preimage, privkey:bytes, address, amou
|
||||
txin.redeem_script = bytes.fromhex(p2wsh_nested_script(witness_script.hex()))
|
||||
txin.script_sig = bytes.fromhex(push_script(txin.redeem_script.hex()))
|
||||
txin.witness_script = witness_script
|
||||
txout = PartialTxOutput(scriptpubkey=bytes.fromhex(address_to_script(address)), value=amount_sat)
|
||||
txout = PartialTxOutput.from_address_and_value(address, amount_sat)
|
||||
tx = PartialTransaction.from_io([txin], [txout], version=2, locktime=(None if preimage else locktime))
|
||||
#tx.set_rbf(True)
|
||||
sig = bytes.fromhex(tx.sign_txin(0, privkey))
|
||||
@@ -97,7 +106,7 @@ def create_claim_tx(txin, witness_script, preimage, privkey:bytes, address, amou
|
||||
|
||||
class SwapManager(Logger):
|
||||
|
||||
def __init__(self, wallet: 'Abstract_Wallet', network:'Network'):
|
||||
def __init__(self, wallet: 'Abstract_Wallet', network: 'Network'):
|
||||
Logger.__init__(self)
|
||||
self.normal_fee = 0
|
||||
self.lockup_fee = 0
|
||||
@@ -108,8 +117,8 @@ class SwapManager(Logger):
|
||||
self.wallet = wallet
|
||||
self.lnworker = wallet.lnworker
|
||||
self.lnwatcher = self.wallet.lnworker.lnwatcher
|
||||
self.swaps = self.wallet.db.get_dict('submarine_swaps')
|
||||
self.prepayments = {} # fee_preimage -> preimage
|
||||
self.swaps = self.wallet.db.get_dict('submarine_swaps') # type: Dict[str, SwapData]
|
||||
self.prepayments = {} # type: Dict[bytes, bytes] # fee_preimage -> preimage
|
||||
for k, swap in self.swaps.items():
|
||||
if swap.is_reverse and swap.prepay_hash is not None:
|
||||
self.prepayments[swap.prepay_hash] = bytes.fromhex(k)
|
||||
@@ -118,7 +127,7 @@ class SwapManager(Logger):
|
||||
self.add_lnwatcher_callback(swap)
|
||||
|
||||
@log_exceptions
|
||||
async def _claim_swap(self, swap):
|
||||
async def _claim_swap(self, swap: SwapData) -> None:
|
||||
if not self.lnwatcher.is_up_to_date():
|
||||
return
|
||||
current_height = self.network.get_local_height()
|
||||
@@ -128,7 +137,7 @@ class SwapManager(Logger):
|
||||
return
|
||||
txos = self.lnwatcher.get_addr_outputs(swap.lockup_address)
|
||||
for txin in txos.values():
|
||||
if swap.is_reverse and txin._trusted_value_sats < swap.onchain_amount:
|
||||
if swap.is_reverse and txin.value_sats() < swap.onchain_amount:
|
||||
self.logger.info('amount too low, we should not reveal the preimage')
|
||||
continue
|
||||
spent_height = txin.spent_height
|
||||
@@ -138,35 +147,43 @@ class SwapManager(Logger):
|
||||
self.lnwatcher.remove_callback(swap.lockup_address)
|
||||
swap.is_redeemed = True
|
||||
continue
|
||||
amount_sat = txin._trusted_value_sats - self.get_claim_fee()
|
||||
amount_sat = txin.value_sats() - self.get_claim_fee()
|
||||
if amount_sat < dust_threshold():
|
||||
self.logger.info('utxo value below dust threshold')
|
||||
continue
|
||||
address = self.wallet.get_receiving_address()
|
||||
preimage = swap.preimage if swap.is_reverse else 0
|
||||
tx = create_claim_tx(txin, swap.redeem_script, preimage, swap.privkey, address, amount_sat, swap.locktime)
|
||||
tx = create_claim_tx(txin=txin,
|
||||
witness_script=swap.redeem_script,
|
||||
preimage=preimage,
|
||||
privkey=swap.privkey,
|
||||
address=address,
|
||||
amount_sat=amount_sat,
|
||||
locktime=swap.locktime)
|
||||
await self.network.broadcast_transaction(tx)
|
||||
# save txid
|
||||
if swap.is_reverse:
|
||||
swap.spending_txid = tx.txid()
|
||||
else:
|
||||
self.wallet.setlabel(tx.txid(), 'Swap refund')
|
||||
self.wallet.set_label(tx.txid(), 'Swap refund')
|
||||
|
||||
def get_claim_fee(self):
|
||||
return self.lnwatcher.config.estimate_fee(136, allow_fallback_to_static_rates=True)
|
||||
|
||||
def get_swap(self, payment_hash):
|
||||
def get_swap(self, payment_hash: bytes) -> Optional[SwapData]:
|
||||
# for history
|
||||
swap = self.swaps.get(payment_hash.hex())
|
||||
if swap:
|
||||
return swap
|
||||
|
||||
def add_lnwatcher_callback(self, swap):
|
||||
def add_lnwatcher_callback(self, swap: SwapData) -> None:
|
||||
callback = lambda: self._claim_swap(swap)
|
||||
self.lnwatcher.add_callback(swap.lockup_address, callback)
|
||||
|
||||
@log_exceptions
|
||||
async def normal_swap(self, lightning_amount, expected_onchain_amount, password, *, tx=None):
|
||||
async def normal_swap(self, lightning_amount: int, expected_onchain_amount: int,
|
||||
password, *, tx: PartialTransaction = None) -> str:
|
||||
"""send on-chain BTC, receive on Lightning"""
|
||||
privkey = os.urandom(32)
|
||||
pubkey = ECPrivkey(privkey).get_public_key_bytes(compressed=True)
|
||||
key = await self.lnworker._add_request_coro(lightning_amount, 'swap', expiry=3600*24)
|
||||
@@ -237,7 +254,8 @@ class SwapManager(Logger):
|
||||
return tx.txid()
|
||||
|
||||
@log_exceptions
|
||||
async def reverse_swap(self, amount_sat, expected_amount):
|
||||
async def reverse_swap(self, amount_sat: int, expected_amount: int) -> bool:
|
||||
"""send on Lightning, receive on-chain"""
|
||||
privkey = os.urandom(32)
|
||||
pubkey = ECPrivkey(privkey).get_public_key_bytes(compressed=True)
|
||||
preimage = os.urandom(32)
|
||||
@@ -315,7 +333,7 @@ class SwapManager(Logger):
|
||||
return success
|
||||
|
||||
@log_exceptions
|
||||
async def get_pairs(self):
|
||||
async def get_pairs(self) -> None:
|
||||
response = await self.network._send_http_on_proxy(
|
||||
'get',
|
||||
API_URL + '/getpairs',
|
||||
@@ -329,7 +347,7 @@ class SwapManager(Logger):
|
||||
self.min_amount = limits['minimal']
|
||||
self.max_amount = limits['maximal']
|
||||
|
||||
def get_recv_amount(self, send_amount, is_reverse):
|
||||
def get_recv_amount(self, send_amount: Optional[int], is_reverse: bool) -> Optional[int]:
|
||||
if send_amount is None:
|
||||
return
|
||||
if send_amount < self.min_amount or send_amount > self.max_amount:
|
||||
@@ -346,7 +364,7 @@ class SwapManager(Logger):
|
||||
return
|
||||
return x
|
||||
|
||||
def get_send_amount(self, recv_amount, is_reverse):
|
||||
def get_send_amount(self, recv_amount: Optional[int], is_reverse: bool) -> Optional[int]:
|
||||
if not recv_amount:
|
||||
return
|
||||
x = recv_amount
|
||||
|
||||
Reference in New Issue
Block a user