Browse Source

save channel timestamps, and show lightning payments in history tab

regtest_lnd
ThomasV 6 years ago
committed by SomberNight
parent
commit
8e748521fd
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 19
      electrum/commands.py
  2. 131
      electrum/gui/qt/history_list.py
  3. 11
      electrum/lnwatcher.py
  4. 68
      electrum/lnworker.py

19
electrum/commands.py

@ -834,24 +834,7 @@ class Commands:
@command('w') @command('w')
def lightning_history(self): def lightning_history(self):
out = [] return self.lnworker.get_history()
for chan_id, htlc, direction, status in self.lnworker.get_payments().values():
payment_hash = bh2u(htlc.payment_hash)
timestamp = self.lnworker.invoices[payment_hash][3] if payment_hash in self.lnworker.invoices else None
item = {
'timestamp':timestamp or 0,
'date':timestamp_to_datetime(timestamp),
'direction': 'sent' if direction == SENT else 'received',
'status':status,
'amout_msat':htlc.amount_msat,
'payment_hash':bh2u(htlc.payment_hash),
'chan_id':bh2u(chan_id),
'htlc_id':htlc.htlc_id,
'cltv_expiry':htlc.cltv_expiry
}
out.append(item)
out.sort(key=operator.itemgetter('timestamp'))
return out
@command('wn') @command('wn')
def closechannel(self, channel_point, force=False): def closechannel(self, channel_point, force=False):

131
electrum/gui/qt/history_list.py

@ -42,7 +42,8 @@ from PyQt5.QtWidgets import (QMenu, QHeaderView, QLabel, QMessageBox,
from electrum.address_synchronizer import TX_HEIGHT_LOCAL from electrum.address_synchronizer import TX_HEIGHT_LOCAL
from electrum.i18n import _ from electrum.i18n import _
from electrum.util import (block_explorer_URL, profiler, TxMinedInfo, from electrum.util import (block_explorer_URL, profiler, TxMinedInfo,
OrderedDictWithIndex, timestamp_to_datetime) OrderedDictWithIndex, timestamp_to_datetime,
Satoshis, format_time)
from electrum.logging import get_logger, Logger from electrum.logging import get_logger, Logger
from .util import (read_QIcon, MONOSPACE_FONT, Buttons, CancelButton, OkButton, from .util import (read_QIcon, MONOSPACE_FONT, Buttons, CancelButton, OkButton,
@ -77,11 +78,11 @@ TX_ICONS = [
] ]
class HistoryColumns(IntEnum): class HistoryColumns(IntEnum):
STATUS_ICON = 0 STATUS = 0
STATUS_TEXT = 1 DESCRIPTION = 1
DESCRIPTION = 2 COIN_VALUE = 2
COIN_VALUE = 3 ONCHAIN_BALANCE = 3
RUNNING_COIN_BALANCE = 4 CHANNELS_BALANCE = 4
FIAT_VALUE = 5 FIAT_VALUE = 5
FIAT_ACQ_PRICE = 6 FIAT_ACQ_PRICE = 6
FIAT_CAP_GAINS = 7 FIAT_CAP_GAINS = 7
@ -134,50 +135,66 @@ class HistoryModel(QAbstractItemModel, Logger):
assert index.isValid() assert index.isValid()
col = index.column() col = index.column()
tx_item = self.transactions.value_from_pos(index.row()) tx_item = self.transactions.value_from_pos(index.row())
tx_hash = tx_item['txid'] is_lightning = tx_item.get('lightning', False)
conf = tx_item['confirmations'] timestamp = tx_item['timestamp']
txpos = tx_item['txpos_in_block'] or 0 if is_lightning:
height = tx_item['height'] status = 0
try: status_str = format_time(int(timestamp))
status, status_str = self.tx_status_cache[tx_hash] else:
except KeyError: tx_hash = tx_item['txid']
tx_mined_info = self.tx_mined_info_from_tx_item(tx_item) conf = tx_item['confirmations']
status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_info) txpos = tx_item['txpos_in_block'] or 0
height = tx_item['height']
try:
status, status_str = self.tx_status_cache[tx_hash]
except KeyError:
tx_mined_info = self.tx_mined_info_from_tx_item(tx_item)
status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_info)
# we sort by timestamp
if conf<=0:
timestamp = time.time()
if role == Qt.UserRole: if role == Qt.UserRole:
# for sorting # for sorting
d = { d = {
HistoryColumns.STATUS_ICON: HistoryColumns.STATUS:
# height breaks ties for unverified txns # height breaks ties for unverified txns
# txpos breaks ties for verified same block txns # txpos breaks ties for verified same block txns
(status, conf, -height, -txpos), (-timestamp, status, conf, -height, -txpos) if not is_lightning else (-timestamp, 0,0,0,0),
HistoryColumns.STATUS_TEXT: status_str, HistoryColumns.DESCRIPTION:
HistoryColumns.DESCRIPTION: tx_item['label'], tx_item['label'] if 'label' in tx_item else None,
HistoryColumns.COIN_VALUE: tx_item['value'].value, HistoryColumns.COIN_VALUE:
HistoryColumns.RUNNING_COIN_BALANCE: tx_item['balance'].value, tx_item['value'].value if 'value' in tx_item else None,
HistoryColumns.ONCHAIN_BALANCE:
tx_item['balance'].value if not is_lightning else None,
HistoryColumns.CHANNELS_BALANCE:
tx_item['balance_msat'] if is_lightning else None,
HistoryColumns.FIAT_VALUE: HistoryColumns.FIAT_VALUE:
tx_item['fiat_value'].value if 'fiat_value' in tx_item else None, tx_item['fiat_value'].value if 'fiat_value' in tx_item else None,
HistoryColumns.FIAT_ACQ_PRICE: HistoryColumns.FIAT_ACQ_PRICE:
tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None, tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None,
HistoryColumns.FIAT_CAP_GAINS: HistoryColumns.FIAT_CAP_GAINS:
tx_item['capital_gain'].value if 'capital_gain' in tx_item else None, tx_item['capital_gain'].value if 'capital_gain' in tx_item else None,
HistoryColumns.TXID: tx_hash, HistoryColumns.TXID: tx_hash if not is_lightning else None,
} }
return QVariant(d[col]) return QVariant(d[col])
if role not in (Qt.DisplayRole, Qt.EditRole): if role not in (Qt.DisplayRole, Qt.EditRole):
if col == HistoryColumns.STATUS_ICON and role == Qt.DecorationRole: if col == HistoryColumns.STATUS and role == Qt.DecorationRole:
return QVariant(read_QIcon(TX_ICONS[status])) icon = "lightning" if is_lightning else TX_ICONS[status]
elif col == HistoryColumns.STATUS_ICON and role == Qt.ToolTipRole: return QVariant(read_QIcon(icon))
return QVariant(str(conf) + _(" confirmation" + ("s" if conf != 1 else ""))) elif col == HistoryColumns.STATUS and role == Qt.ToolTipRole:
msg = 'lightning transaction' if is_lightning else str(conf) + _(" confirmation" + ("s" if conf != 1 else ""))
return QVariant(msg)
elif col > HistoryColumns.DESCRIPTION and role == Qt.TextAlignmentRole: elif col > HistoryColumns.DESCRIPTION and role == Qt.TextAlignmentRole:
return QVariant(Qt.AlignRight | Qt.AlignVCenter) return QVariant(Qt.AlignRight | Qt.AlignVCenter)
elif col != HistoryColumns.STATUS_TEXT and role == Qt.FontRole: elif col != HistoryColumns.STATUS and role == Qt.FontRole:
monospace_font = QFont(MONOSPACE_FONT) monospace_font = QFont(MONOSPACE_FONT)
return QVariant(monospace_font) return QVariant(monospace_font)
elif col == HistoryColumns.DESCRIPTION and role == Qt.DecorationRole \ elif col == HistoryColumns.DESCRIPTION and role == Qt.DecorationRole and not is_lightning\
and self.parent.wallet.invoices.paid.get(tx_hash): and self.parent.wallet.invoices.paid.get(tx_hash):
return QVariant(read_QIcon("seal")) return QVariant(read_QIcon("seal"))
elif col in (HistoryColumns.DESCRIPTION, HistoryColumns.COIN_VALUE) \ elif col in (HistoryColumns.DESCRIPTION, HistoryColumns.COIN_VALUE) \
and role == Qt.ForegroundRole and tx_item['value'].value < 0: and role == Qt.ForegroundRole and not is_lightning and tx_item['value'].value < 0:
red_brush = QBrush(QColor("#BC1E1E")) red_brush = QBrush(QColor("#BC1E1E"))
return QVariant(red_brush) return QVariant(red_brush)
elif col == HistoryColumns.FIAT_VALUE and role == Qt.ForegroundRole \ elif col == HistoryColumns.FIAT_VALUE and role == Qt.ForegroundRole \
@ -185,18 +202,22 @@ class HistoryModel(QAbstractItemModel, Logger):
blue_brush = QBrush(QColor("#1E1EFF")) blue_brush = QBrush(QColor("#1E1EFF"))
return QVariant(blue_brush) return QVariant(blue_brush)
return QVariant() return QVariant()
if col == HistoryColumns.STATUS_TEXT: if col == HistoryColumns.STATUS:
return QVariant(status_str) return QVariant(status_str)
elif col == HistoryColumns.DESCRIPTION: elif col == HistoryColumns.DESCRIPTION and 'label' in tx_item:
return QVariant(tx_item['label']) return QVariant(tx_item['label'])
elif col == HistoryColumns.COIN_VALUE: elif col == HistoryColumns.COIN_VALUE and 'value' in tx_item:
value = tx_item['value'].value value = tx_item['value'].value
v_str = self.parent.format_amount(value, is_diff=True, whitespaces=True) v_str = self.parent.format_amount(value, is_diff=True, whitespaces=True)
return QVariant(v_str) return QVariant(v_str)
elif col == HistoryColumns.RUNNING_COIN_BALANCE: elif col == HistoryColumns.ONCHAIN_BALANCE and not is_lightning:
balance = tx_item['balance'].value balance = tx_item['balance'].value
balance_str = self.parent.format_amount(balance, whitespaces=True) balance_str = self.parent.format_amount(balance, whitespaces=True)
return QVariant(balance_str) return QVariant(balance_str)
elif col == HistoryColumns.CHANNELS_BALANCE and is_lightning:
balance = tx_item['balance_msat']//1000
balance_str = self.parent.format_amount(balance, whitespaces=True)
return QVariant(balance_str)
elif col == HistoryColumns.FIAT_VALUE and 'fiat_value' in tx_item: elif col == HistoryColumns.FIAT_VALUE and 'fiat_value' in tx_item:
value_str = self.parent.fx.format_fiat(tx_item['fiat_value'].value) value_str = self.parent.fx.format_fiat(tx_item['fiat_value'].value)
return QVariant(value_str) return QVariant(value_str)
@ -240,18 +261,24 @@ class HistoryModel(QAbstractItemModel, Logger):
fx = self.parent.fx fx = self.parent.fx
if fx: fx.history_used_spot = False if fx: fx.history_used_spot = False
r = self.parent.wallet.get_full_history(domain=self.get_domain(), from_timestamp=None, to_timestamp=None, fx=fx) r = self.parent.wallet.get_full_history(domain=self.get_domain(), from_timestamp=None, to_timestamp=None, fx=fx)
lightning_history = self.parent.wallet.lnworker.get_history()
self.set_visibility_of_columns() self.set_visibility_of_columns()
if r['transactions'] == list(self.transactions.values()): #if r['transactions'] == list(self.transactions.values()):
return # return
old_length = len(self.transactions) old_length = len(self.transactions)
if old_length != 0: if old_length != 0:
self.beginRemoveRows(QModelIndex(), 0, old_length) self.beginRemoveRows(QModelIndex(), 0, old_length)
self.transactions.clear() self.transactions.clear()
self.endRemoveRows() self.endRemoveRows()
self.beginInsertRows(QModelIndex(), 0, len(r['transactions'])-1) self.beginInsertRows(QModelIndex(), 0, len(r['transactions'])+len(lightning_history)-1)
for tx_item in r['transactions']: for tx_item in r['transactions']:
txid = tx_item['txid'] txid = tx_item['txid']
self.transactions[txid] = tx_item self.transactions[txid] = tx_item
for tx_item in lightning_history:
tx_item['lightning'] = True
tx_item['value'] = Satoshis(tx_item['amount_msat']/1000 * (-1 if tx_item['direction'] =='sent' else 1))
key = tx_item['payment_hash'] if 'payment_hash' in tx_item else tx_item['type'] + tx_item['channel_id']
self.transactions[key] = tx_item
self.endInsertRows() self.endInsertRows()
if selected_row: if selected_row:
self.view.selectionModel().select(self.createIndex(selected_row, 0), QItemSelectionModel.Rows | QItemSelectionModel.SelectCurrent) self.view.selectionModel().select(self.createIndex(selected_row, 0), QItemSelectionModel.Rows | QItemSelectionModel.SelectCurrent)
@ -269,8 +296,9 @@ class HistoryModel(QAbstractItemModel, Logger):
# update tx_status_cache # update tx_status_cache
self.tx_status_cache.clear() self.tx_status_cache.clear()
for txid, tx_item in self.transactions.items(): for txid, tx_item in self.transactions.items():
tx_mined_info = self.tx_mined_info_from_tx_item(tx_item) if not tx_item.get('lightning', False):
self.tx_status_cache[txid] = self.parent.wallet.get_tx_status(txid, tx_mined_info) tx_mined_info = self.tx_mined_info_from_tx_item(tx_item)
self.tx_status_cache[txid] = self.parent.wallet.get_tx_status(txid, tx_mined_info)
def set_visibility_of_columns(self): def set_visibility_of_columns(self):
def set_visible(col: int, b: bool): def set_visible(col: int, b: bool):
@ -312,6 +340,8 @@ class HistoryModel(QAbstractItemModel, Logger):
def on_fee_histogram(self): def on_fee_histogram(self):
for tx_hash, tx_item in list(self.transactions.items()): for tx_hash, tx_item in list(self.transactions.items()):
if tx_item.get('lightning'):
continue
tx_mined_info = self.tx_mined_info_from_tx_item(tx_item) tx_mined_info = self.tx_mined_info_from_tx_item(tx_item)
if tx_mined_info.conf > 0: if tx_mined_info.conf > 0:
# note: we could actually break here if we wanted to rely on the order of txns in self.transactions # note: we could actually break here if we wanted to rely on the order of txns in self.transactions
@ -331,11 +361,11 @@ class HistoryModel(QAbstractItemModel, Logger):
fiat_acq_title = '%s '%fx.ccy + _('Acquisition price') fiat_acq_title = '%s '%fx.ccy + _('Acquisition price')
fiat_cg_title = '%s '%fx.ccy + _('Capital Gains') fiat_cg_title = '%s '%fx.ccy + _('Capital Gains')
return { return {
HistoryColumns.STATUS_ICON: '', HistoryColumns.STATUS: _('Date'),
HistoryColumns.STATUS_TEXT: _('Date'),
HistoryColumns.DESCRIPTION: _('Description'), HistoryColumns.DESCRIPTION: _('Description'),
HistoryColumns.COIN_VALUE: _('Amount'), HistoryColumns.COIN_VALUE: _('Amount'),
HistoryColumns.RUNNING_COIN_BALANCE: _('Balance'), HistoryColumns.ONCHAIN_BALANCE: _('Balance'),
HistoryColumns.CHANNELS_BALANCE: u'\U0001f5f2 ' + _('Channels balance'),
HistoryColumns.FIAT_VALUE: fiat_title, HistoryColumns.FIAT_VALUE: fiat_title,
HistoryColumns.FIAT_ACQ_PRICE: fiat_acq_title, HistoryColumns.FIAT_ACQ_PRICE: fiat_acq_title,
HistoryColumns.FIAT_CAP_GAINS: fiat_cg_title, HistoryColumns.FIAT_CAP_GAINS: fiat_cg_title,
@ -356,7 +386,7 @@ class HistoryModel(QAbstractItemModel, Logger):
return tx_mined_info return tx_mined_info
class HistoryList(MyTreeView, AcceptFileDragDrop): class HistoryList(MyTreeView, AcceptFileDragDrop):
filter_columns = [HistoryColumns.STATUS_TEXT, filter_columns = [HistoryColumns.STATUS,
HistoryColumns.DESCRIPTION, HistoryColumns.DESCRIPTION,
HistoryColumns.COIN_VALUE, HistoryColumns.COIN_VALUE,
HistoryColumns.TXID] HistoryColumns.TXID]
@ -390,7 +420,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
self.years = [] self.years = []
self.create_toolbar_buttons() self.create_toolbar_buttons()
self.wallet = self.parent.wallet # type: Abstract_Wallet self.wallet = self.parent.wallet # type: Abstract_Wallet
self.sortByColumn(HistoryColumns.STATUS_ICON, Qt.AscendingOrder) self.sortByColumn(HistoryColumns.STATUS, Qt.AscendingOrder)
self.editable_columns |= {HistoryColumns.FIAT_VALUE} self.editable_columns |= {HistoryColumns.FIAT_VALUE}
self.header().setStretchLastSection(False) self.header().setStretchLastSection(False)
@ -565,12 +595,10 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
return return
tx_item = self.hm.transactions.value_from_pos(idx.row()) tx_item = self.hm.transactions.value_from_pos(idx.row())
column = idx.column() column = idx.column()
if column == HistoryColumns.STATUS_ICON: column_title = self.hm.headerData(column, Qt.Horizontal, Qt.DisplayRole)
column_title = _('Transaction ID') column_data = self.hm.data(idx, Qt.DisplayRole).value()
column_data = tx_item['txid'] if tx_item.get('lightning'):
else: return
column_title = self.hm.headerData(column, Qt.Horizontal, Qt.DisplayRole)
column_data = self.hm.data(idx, Qt.DisplayRole).value()
tx_hash = tx_item['txid'] tx_hash = tx_item['txid']
tx = self.wallet.db.get_transaction(tx_hash) tx = self.wallet.db.get_transaction(tx_hash)
if not tx: if not tx:
@ -583,12 +611,13 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
menu = QMenu() menu = QMenu()
if height == TX_HEIGHT_LOCAL: if height == TX_HEIGHT_LOCAL:
menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash))
menu.addAction(_("Copy Transaction ID"), lambda: self.parent.app.clipboard().setText(tx_hash))
amount_columns = [HistoryColumns.COIN_VALUE, HistoryColumns.RUNNING_COIN_BALANCE, HistoryColumns.FIAT_VALUE, HistoryColumns.FIAT_ACQ_PRICE, HistoryColumns.FIAT_CAP_GAINS] amount_columns = [HistoryColumns.COIN_VALUE, HistoryColumns.ONCHAIN_BALANCE, HistoryColumns.CHANNELS_BALANCE,
HistoryColumns.FIAT_VALUE, HistoryColumns.FIAT_ACQ_PRICE, HistoryColumns.FIAT_CAP_GAINS]
if column in amount_columns: if column in amount_columns:
column_data = column_data.strip() column_data = column_data.strip()
menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data))
for c in self.editable_columns: for c in self.editable_columns:
if self.isColumnHidden(c): continue if self.isColumnHidden(c): continue
label = self.hm.headerData(c, Qt.Horizontal, Qt.DisplayRole) label = self.hm.headerData(c, Qt.Horizontal, Qt.DisplayRole)

11
electrum/lnwatcher.py

@ -140,11 +140,14 @@ class LNWatcher(AddressSynchronizer):
async def check_onchain_situation(self, address, funding_outpoint): async def check_onchain_situation(self, address, funding_outpoint):
keep_watching, spenders = self.inspect_tx_candidate(funding_outpoint, 0) keep_watching, spenders = self.inspect_tx_candidate(funding_outpoint, 0)
txid = spenders.get(funding_outpoint) funding_txid = funding_outpoint.split(':')[0]
if txid is None: funding_height = self.get_tx_height(funding_txid)
self.network.trigger_callback('channel_open', funding_outpoint) closing_txid = spenders.get(funding_outpoint)
if closing_txid is None:
self.network.trigger_callback('channel_open', funding_outpoint, funding_txid, funding_height)
else: else:
self.network.trigger_callback('channel_closed', funding_outpoint, txid, spenders) closing_height = self.get_tx_height(closing_txid)
self.network.trigger_callback('channel_closed', funding_outpoint, spenders, funding_txid, funding_height, closing_txid, closing_height)
await self.do_breach_remedy(funding_outpoint, spenders) await self.do_breach_remedy(funding_outpoint, spenders)
if not keep_watching: if not keep_watching:
self.unwatch_channel(address, funding_outpoint) self.unwatch_channel(address, funding_outpoint)

68
electrum/lnworker.py

@ -11,6 +11,7 @@ from typing import Optional, Sequence, Tuple, List, Dict, TYPE_CHECKING
import threading import threading
import socket import socket
import json import json
import operator
from datetime import datetime, timezone from datetime import datetime, timezone
from functools import partial from functools import partial
@ -26,6 +27,7 @@ from .transaction import Transaction
from .crypto import sha256 from .crypto import sha256
from .bip32 import bip32_root from .bip32 import bip32_root
from .util import bh2u, bfh, PrintError, InvoiceError, resolve_dns_srv, is_ip_address, log_exceptions from .util import bh2u, bfh, PrintError, InvoiceError, resolve_dns_srv, is_ip_address, log_exceptions
from .util import timestamp_to_datetime
from .lntransport import LNResponderTransport from .lntransport import LNResponderTransport
from .lnbase import Peer from .lnbase import Peer
from .lnaddr import lnencode, LnAddr, lndecode from .lnaddr import lnencode, LnAddr, lndecode
@ -81,6 +83,8 @@ class LNWorker(PrintError):
self.channels[c.channel_id] = c self.channels[c.channel_id] = c
c.set_remote_commitment() c.set_remote_commitment()
c.set_local_commitment(c.current_commitment(LOCAL)) c.set_local_commitment(c.current_commitment(LOCAL))
# timestamps of opening and closing transactions
self.channel_timestamps = self.wallet.storage.get('lightning_channel_timestamps', {})
def start_network(self, network: 'Network'): def start_network(self, network: 'Network'):
self.network = network self.network = network
@ -150,6 +154,56 @@ class LNWorker(PrintError):
out.update(chan.get_payments()) out.update(chan.get_payments())
return out return out
def get_history(self):
out = []
for chan_id, htlc, direction, status in self.get_payments().values():
key = bh2u(htlc.payment_hash)
timestamp = self.invoices[key][3] if key in self.invoices else None
item = {
'type':'payment',
'timestamp':timestamp or 0,
'date':timestamp_to_datetime(timestamp),
'direction': 'sent' if direction == SENT else 'received',
'status':status,
'amount_msat':htlc.amount_msat,
'payment_hash':bh2u(htlc.payment_hash),
'channel_id':bh2u(chan_id),
'htlc_id':htlc.htlc_id,
'cltv_expiry':htlc.cltv_expiry,
}
out.append(item)
# add funding events
for chan in self.channels.values():
funding_txid, funding_height, funding_timestamp, closing_txid, closing_height, closing_timestamp = self.channel_timestamps.get(bh2u(chan.channel_id))
item = {
'channel_id': bh2u(chan.channel_id),
'type': 'channel_opening',
'label': _('Channel opening'),
'txid': funding_txid,
'amount_msat': chan.balance(LOCAL, ctn=0),
'direction': 'received',
'timestamp': funding_timestamp,
}
out.append(item)
if not chan.is_closed():
continue
item = {
'channel_id': bh2u(chan.channel_id),
'txid':closing_txid,
'label': _('Channel closure'),
'type': 'channel_closure',
'amount_msat': chan.balance(LOCAL),
'direction': 'sent',
'timestamp': closing_timestamp,
}
out.append(item)
out.sort(key=operator.itemgetter('timestamp'))
balance_msat = 0
for item in out:
balance_msat += item['amount_msat'] * (1 if item['direction']=='received' else -1)
item['balance_msat'] = balance_msat
return out
def _read_ln_keystore(self) -> BIP32_KeyStore: def _read_ln_keystore(self) -> BIP32_KeyStore:
xprv = self.wallet.storage.get('lightning_privkey2') xprv = self.wallet.storage.get('lightning_privkey2')
if xprv is None: if xprv is None:
@ -240,21 +294,25 @@ class LNWorker(PrintError):
if chan.funding_outpoint.to_str() == txo: if chan.funding_outpoint.to_str() == txo:
return chan return chan
def on_channel_open(self, event, funding_outpoint): def on_channel_open(self, event, funding_outpoint, funding_txid, funding_height):
chan = self.channel_by_txo(funding_outpoint) chan = self.channel_by_txo(funding_outpoint)
if not chan: if not chan:
return return
self.print_error('on_channel_open', funding_outpoint) self.print_error('on_channel_open', funding_outpoint)
self.channel_timestamps[bh2u(chan.channel_id)] = funding_txid, funding_height.height, funding_height.timestamp, None, None, None
self.wallet.storage.put('lightning_channel_timestamps', self.channel_timestamps)
chan.set_funding_txo_spentness(False) chan.set_funding_txo_spentness(False)
# send event to GUI # send event to GUI
self.network.trigger_callback('channel', chan) self.network.trigger_callback('channel', chan)
@log_exceptions @log_exceptions
async def on_channel_closed(self, event, funding_outpoint, txid, spenders): async def on_channel_closed(self, event, funding_outpoint, spenders, funding_txid, funding_height, closing_txid, closing_height):
chan = self.channel_by_txo(funding_outpoint) chan = self.channel_by_txo(funding_outpoint)
if not chan: if not chan:
return return
self.print_error('on_channel_closed', funding_outpoint) self.print_error('on_channel_closed', funding_outpoint)
self.channel_timestamps[bh2u(chan.channel_id)] = funding_txid, funding_height.height, funding_height.timestamp, closing_txid, closing_height.height, closing_height.timestamp
self.wallet.storage.put('lightning_channel_timestamps', self.channel_timestamps)
chan.set_funding_txo_spentness(True) chan.set_funding_txo_spentness(True)
if chan.get_state() != 'FORCE_CLOSING': if chan.get_state() != 'FORCE_CLOSING':
chan.set_state("CLOSED") chan.set_state("CLOSED")
@ -263,14 +321,14 @@ class LNWorker(PrintError):
# remove from channel_db # remove from channel_db
self.channel_db.remove_channel(chan.short_channel_id) self.channel_db.remove_channel(chan.short_channel_id)
# detect who closed # detect who closed
if txid == chan.local_commitment.txid(): if closing_txid == chan.local_commitment.txid():
self.print_error('we force closed', funding_outpoint) self.print_error('we force closed', funding_outpoint)
encumbered_sweeptxs = chan.local_sweeptxs encumbered_sweeptxs = chan.local_sweeptxs
elif txid == chan.remote_commitment.txid(): elif closing_txid == chan.remote_commitment.txid():
self.print_error('they force closed', funding_outpoint) self.print_error('they force closed', funding_outpoint)
encumbered_sweeptxs = chan.remote_sweeptxs encumbered_sweeptxs = chan.remote_sweeptxs
else: else:
self.print_error('not sure who closed', funding_outpoint, txid) self.print_error('not sure who closed', funding_outpoint, closing_txid)
return return
# sweep # sweep
for prevout, spender in spenders.items(): for prevout, spender in spenders.items():

Loading…
Cancel
Save