add close_channel method to peer
This commit is contained in:
@@ -42,7 +42,6 @@ class ChannelsList(MyTreeWidget):
|
|||||||
def create_menu(self, position):
|
def create_menu(self, position):
|
||||||
menu = QMenu()
|
menu = QMenu()
|
||||||
channel_id = self.currentItem().data(0, QtCore.Qt.UserRole)
|
channel_id = self.currentItem().data(0, QtCore.Qt.UserRole)
|
||||||
print('ID', bh2u(channel_id))
|
|
||||||
def close():
|
def close():
|
||||||
netw = self.parent.network
|
netw = self.parent.network
|
||||||
coro = self.parent.wallet.lnworker.close_channel(channel_id)
|
coro = self.parent.wallet.lnworker.close_channel(channel_id)
|
||||||
@@ -50,7 +49,15 @@ class ChannelsList(MyTreeWidget):
|
|||||||
_txid = netw.run_from_another_thread(coro)
|
_txid = netw.run_from_another_thread(coro)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.main_window.show_error('Force-close failed:\n{}'.format(repr(e)))
|
self.main_window.show_error('Force-close failed:\n{}'.format(repr(e)))
|
||||||
menu.addAction(_("Force-close channel"), close)
|
def force_close():
|
||||||
|
netw = self.parent.network
|
||||||
|
coro = self.parent.wallet.lnworker.force_close_channel(channel_id)
|
||||||
|
try:
|
||||||
|
_txid = netw.run_from_another_thread(coro)
|
||||||
|
except Exception as e:
|
||||||
|
self.main_window.show_error('Force-close failed:\n{}'.format(repr(e)))
|
||||||
|
menu.addAction(_("Close channel"), close)
|
||||||
|
menu.addAction(_("Force-close channel"), force_close)
|
||||||
menu.exec_(self.viewport().mapToGlobal(position))
|
menu.exec_(self.viewport().mapToGlobal(position))
|
||||||
|
|
||||||
@QtCore.pyqtSlot(Channel)
|
@QtCore.pyqtSlot(Channel)
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ class Peer(PrintError):
|
|||||||
self.lnwatcher = lnworker.network.lnwatcher
|
self.lnwatcher = lnworker.network.lnwatcher
|
||||||
self.channel_db = lnworker.network.channel_db
|
self.channel_db = lnworker.network.channel_db
|
||||||
self.ping_time = 0
|
self.ping_time = 0
|
||||||
|
self.shutdown_received = defaultdict(asyncio.Future)
|
||||||
self.channel_accepted = defaultdict(asyncio.Queue)
|
self.channel_accepted = defaultdict(asyncio.Queue)
|
||||||
self.channel_reestablished = defaultdict(asyncio.Future)
|
self.channel_reestablished = defaultdict(asyncio.Future)
|
||||||
self.funding_signed = defaultdict(asyncio.Queue)
|
self.funding_signed = defaultdict(asyncio.Queue)
|
||||||
@@ -1122,14 +1123,37 @@ class Peer(PrintError):
|
|||||||
if chan_id not in self.closing_signed: raise Exception("Got unknown closing_signed")
|
if chan_id not in self.closing_signed: raise Exception("Got unknown closing_signed")
|
||||||
self.closing_signed[chan_id].put_nowait(payload)
|
self.closing_signed[chan_id].put_nowait(payload)
|
||||||
|
|
||||||
|
@log_exceptions
|
||||||
|
async def close_channel(self, chan_id):
|
||||||
|
chan = self.channels[chan_id]
|
||||||
|
self.shutdown_received[chan_id] = asyncio.Future()
|
||||||
|
self.send_shutdown(chan)
|
||||||
|
payload = await self.shutdown_received[chan_id]
|
||||||
|
await self._shutdown(chan, payload)
|
||||||
|
self.network.trigger_callback('ln_message', self.lnworker, 'Channel closed')
|
||||||
|
|
||||||
@log_exceptions
|
@log_exceptions
|
||||||
async def on_shutdown(self, payload):
|
async def on_shutdown(self, payload):
|
||||||
# length of scripts allowed in BOLT-02
|
# length of scripts allowed in BOLT-02
|
||||||
if int.from_bytes(payload['len'], 'big') not in (3+20+2, 2+20+1, 2+20, 2+32):
|
if int.from_bytes(payload['len'], 'big') not in (3+20+2, 2+20+1, 2+20, 2+32):
|
||||||
raise Exception('scriptpubkey length in received shutdown message invalid: ' + str(payload['len']))
|
raise Exception('scriptpubkey length in received shutdown message invalid: ' + str(payload['len']))
|
||||||
chan = self.channels[payload['channel_id']]
|
chan_id = payload['channel_id']
|
||||||
|
if chan_id in self.shutdown_received:
|
||||||
|
self.shutdown_received[chan_id].set_result(payload)
|
||||||
|
self.print_error('Channel closed by us')
|
||||||
|
else:
|
||||||
|
chan = self.channels[chan_id]
|
||||||
|
self.send_shutdown(chan)
|
||||||
|
await self._shutdown(chan, payload)
|
||||||
|
self.print_error('Channel closed by remote peer')
|
||||||
|
|
||||||
|
def send_shutdown(self, chan):
|
||||||
scriptpubkey = bfh(bitcoin.address_to_script(chan.sweep_address))
|
scriptpubkey = bfh(bitcoin.address_to_script(chan.sweep_address))
|
||||||
self.send_message('shutdown', channel_id=chan.channel_id, len=len(scriptpubkey), scriptpubkey=scriptpubkey)
|
self.send_message('shutdown', channel_id=chan.channel_id, len=len(scriptpubkey), scriptpubkey=scriptpubkey)
|
||||||
|
|
||||||
|
@log_exceptions
|
||||||
|
async def _shutdown(self, chan, payload):
|
||||||
|
scriptpubkey = bfh(bitcoin.address_to_script(chan.sweep_address))
|
||||||
signature, fee = chan.make_closing_tx(scriptpubkey, payload['scriptpubkey'])
|
signature, fee = chan.make_closing_tx(scriptpubkey, payload['scriptpubkey'])
|
||||||
self.send_message('closing_signed', channel_id=chan.channel_id, fee_satoshis=fee, signature=signature)
|
self.send_message('closing_signed', channel_id=chan.channel_id, fee_satoshis=fee, signature=signature)
|
||||||
while chan.get_state() != 'CLOSED':
|
while chan.get_state() != 'CLOSED':
|
||||||
@@ -1141,4 +1165,3 @@ class Peer(PrintError):
|
|||||||
fee = int.from_bytes(closing_signed['fee_satoshis'], 'big')
|
fee = int.from_bytes(closing_signed['fee_satoshis'], 'big')
|
||||||
signature, _ = chan.make_closing_tx(scriptpubkey, payload['scriptpubkey'], fee_sat=fee)
|
signature, _ = chan.make_closing_tx(scriptpubkey, payload['scriptpubkey'], fee_sat=fee)
|
||||||
self.send_message('closing_signed', channel_id=chan.channel_id, fee_satoshis=fee, signature=signature)
|
self.send_message('closing_signed', channel_id=chan.channel_id, fee_satoshis=fee, signature=signature)
|
||||||
self.print_error('REMOTE PEER CLOSED CHANNEL')
|
|
||||||
|
|||||||
@@ -419,6 +419,11 @@ class LNWorker(PrintError):
|
|||||||
}
|
}
|
||||||
|
|
||||||
async def close_channel(self, chan_id):
|
async def close_channel(self, chan_id):
|
||||||
|
chan = self.channels[chan_id]
|
||||||
|
peer = self.peers[chan.node_id]
|
||||||
|
await peer.close_channel(chan_id)
|
||||||
|
|
||||||
|
async def force_close_channel(self, chan_id):
|
||||||
chan = self.channels[chan_id]
|
chan = self.channels[chan_id]
|
||||||
# local_commitment always gives back the next expected local_commitment,
|
# local_commitment always gives back the next expected local_commitment,
|
||||||
# but in this case, we want the current one. So substract one ctn number
|
# but in this case, we want the current one. So substract one ctn number
|
||||||
@@ -432,7 +437,9 @@ class LNWorker(PrintError):
|
|||||||
none_idx = tx._inputs[0]["signatures"].index(None)
|
none_idx = tx._inputs[0]["signatures"].index(None)
|
||||||
tx.add_signature_to_txin(0, none_idx, bh2u(remote_sig))
|
tx.add_signature_to_txin(0, none_idx, bh2u(remote_sig))
|
||||||
assert tx.is_complete()
|
assert tx.is_complete()
|
||||||
return await self.network.broadcast_transaction(tx)
|
txid = await self.network.broadcast_transaction(tx)
|
||||||
|
self.network.trigger_callback('ln_message', self, 'Channel closed' + '\n' + txid)
|
||||||
|
return txid
|
||||||
|
|
||||||
def _get_next_peers_to_try(self) -> Sequence[LNPeerAddr]:
|
def _get_next_peers_to_try(self) -> Sequence[LNPeerAddr]:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
|||||||
Reference in New Issue
Block a user