diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py index cc45c5826..9a8464c98 100644 --- a/electrum/address_synchronizer.py +++ b/electrum/address_synchronizer.py @@ -243,7 +243,14 @@ class AddressSynchronizer(Logger, EventListener): return conflicting_txns def get_transaction(self, txid: str) -> Transaction: - return self.db.get_transaction(txid) + tx = self.db.get_transaction(txid) + # add verified tx info + tx.deserialize() + for txin in tx._inputs: + tx_height, tx_pos = self.get_txpos(txin.prevout.txid.hex()) + txin.block_height = tx_height + txin.block_txpos = tx_pos + return tx def add_transaction(self, tx: Transaction, *, allow_unrelated=False, is_new=True) -> bool: """ @@ -768,9 +775,10 @@ class AddressSynchronizer(Logger, EventListener): received = {} sent = {} for tx_hash, height in h: + hh, pos = self.get_txpos(tx_hash) d = self.db.get_txo_addr(tx_hash, address) for n, (v, is_cb) in d.items(): - received[tx_hash + ':%d'%n] = (height, v, is_cb) + received[tx_hash + ':%d'%n] = (height, pos, v, is_cb) for tx_hash, height in h: l = self.db.get_txi_addr(tx_hash, address) for txi, v in l: @@ -778,17 +786,18 @@ class AddressSynchronizer(Logger, EventListener): return received, sent def get_addr_outputs(self, address: str) -> Dict[TxOutpoint, PartialTxInput]: - coins, spent = self.get_addr_io(address) + received, sent = self.get_addr_io(address) out = {} - for prevout_str, v in coins.items(): - tx_height, value, is_cb = v + for prevout_str, v in received.items(): + tx_height, tx_pos, value, is_cb = v prevout = TxOutpoint.from_str(prevout_str) utxo = PartialTxInput(prevout=prevout, is_coinbase_output=is_cb) utxo._trusted_address = address utxo._trusted_value_sats = value utxo.block_height = tx_height - if prevout_str in spent: - txid, height = spent[prevout_str] + utxo.block_txpos = tx_pos + if prevout_str in sent: + txid, height = sent[prevout_str] utxo.spent_txid = txid utxo.spent_height = height else: @@ -807,7 +816,7 @@ class AddressSynchronizer(Logger, EventListener): # return the total amount ever received by an address def get_addr_received(self, address): received, sent = self.get_addr_io(address) - return sum([v for height, v, is_cb in received.values()]) + return sum([value for height, pos, value, is_cb in received.values()]) @with_local_height_cached def get_balance(self, domain, *, excluded_addresses: Set[str] = None, diff --git a/electrum/gui/qt/transaction_dialog.py b/electrum/gui/qt/transaction_dialog.py index 0007b2212..0916af943 100644 --- a/electrum/gui/qt/transaction_dialog.py +++ b/electrum/gui/qt/transaction_dialog.py @@ -45,8 +45,9 @@ from electrum.bitcoin import base_encode, NLOCKTIME_BLOCKHEIGHT_MAX from electrum.i18n import _ from electrum.plugin import run_hook from electrum import simple_config -from electrum.transaction import SerializationError, Transaction, PartialTransaction, PartialTxInput +from electrum.transaction import SerializationError, Transaction, PartialTransaction, PartialTxInput, TxOutpoint from electrum.logging import get_logger +from electrum.util import ShortID from .util import (MessageBoxMixin, read_QIcon, Buttons, icon_path, MONOSPACE_FONT, ColorScheme, ButtonsLineEdit, ShowQRLineEdit, text_dialog, @@ -593,8 +594,17 @@ class BaseTxDialog(QDialog, MessageBoxMixin): return self.txo_color_2fa.text_char_format return ext - def format_amount(amt): - return self.main_window.format_amount(amt, whitespaces=True) + def insert_tx_io(cursor, is_coinbase, short_id, address, value): + if is_coinbase: + cursor.insertText('coinbase') + else: + address_str = address or '
' + value_str = self.main_window.format_amount(value, whitespaces=True) + cursor.insertText("%-15s\t"%str(short_id), ext) + cursor.insertText("%-62s"%address_str, text_format(address)) + cursor.insertText('\t', ext) + cursor.insertText(value_str, ext) + cursor.insertBlock() i_text = self.inputs_textedit i_text.clear() @@ -602,34 +612,26 @@ class BaseTxDialog(QDialog, MessageBoxMixin): i_text.setReadOnly(True) cursor = i_text.textCursor() for txin in self.tx.inputs(): - if txin.is_coinbase_input(): - cursor.insertText('coinbase') - else: - prevout_hash = txin.prevout.txid.hex() - prevout_n = txin.prevout.out_idx - cursor.insertText(prevout_hash + ":%-4d " % prevout_n, ext) - addr = self.wallet.adb.get_txin_address(txin) - if addr is None: - addr = '' - cursor.insertText(addr, text_format(addr)) - txin_value = self.wallet.adb.get_txin_value(txin) - if txin_value is not None: - cursor.insertText(format_amount(txin_value), ext) - cursor.insertBlock() + addr = self.wallet.adb.get_txin_address(txin) + txin_value = self.wallet.adb.get_txin_value(txin) + insert_tx_io(cursor, txin.is_coinbase_output(), txin.short_id, addr, txin_value) self.outputs_header.setText(_("Outputs") + ' (%d)'%len(self.tx.outputs())) o_text = self.outputs_textedit o_text.clear() o_text.setFont(QFont(MONOSPACE_FONT)) o_text.setReadOnly(True) + tx_height, tx_pos = self.wallet.adb.get_txpos(self.tx.txid()) + tx_hash = bytes.fromhex(self.tx.txid()) cursor = o_text.textCursor() - for o in self.tx.outputs(): - addr, v = o.get_ui_address_str(), o.value - cursor.insertText(addr, text_format(addr)) - if v is not None: - cursor.insertText('\t', ext) - cursor.insertText(format_amount(v), ext) - cursor.insertBlock() + for index, o in enumerate(self.tx.outputs()): + if tx_pos is not None and tx_pos >= 0: + short_id = ShortID.from_components(tx_height, tx_pos, index) + else: + short_id = TxOutpoint(tx_hash, index).short_name() + + addr, value = o.get_ui_address_str(), o.value + insert_tx_io(cursor, False, short_id, addr, value) self.txo_color_recv.legend_label.setVisible(tf_used_recv) self.txo_color_change.legend_label.setVisible(tf_used_change) diff --git a/electrum/gui/qt/utxo_list.py b/electrum/gui/qt/utxo_list.py index 727e38d46..3c1d067e7 100644 --- a/electrum/gui/qt/utxo_list.py +++ b/electrum/gui/qt/utxo_list.py @@ -46,14 +46,12 @@ class UTXOList(MyTreeView): ADDRESS = 1 LABEL = 2 AMOUNT = 3 - HEIGHT = 4 headers = { + Columns.OUTPOINT: _('Output point'), Columns.ADDRESS: _('Address'), Columns.LABEL: _('Label'), Columns.AMOUNT: _('Amount'), - Columns.HEIGHT: _('Height'), - Columns.OUTPOINT: _('Output point'), } filter_columns = [Columns.ADDRESS, Columns.LABEL, Columns.OUTPOINT] stretch_column = Columns.LABEL @@ -86,10 +84,8 @@ class UTXOList(MyTreeView): name = utxo.prevout.to_str() self._utxo_dict[name] = utxo address = utxo.address - height = utxo.block_height - name_short = utxo.prevout.txid.hex()[:16] + '...' + ":%d" % utxo.prevout.out_idx amount = self.parent.format_amount(utxo.value_sats(), whitespaces=True) - labels = [name_short, address, '', amount, '%d'%height] + labels = [str(utxo.short_id), address, '', amount] utxo_item = [QStandardItem(x) for x in labels] self.set_editability(utxo_item) utxo_item[self.Columns.OUTPOINT].setData(name, self.ROLE_CLIPBOARD_DATA) diff --git a/electrum/lnutil.py b/electrum/lnutil.py index 2b1f3a7ce..90c079aa9 100644 --- a/electrum/lnutil.py +++ b/electrum/lnutil.py @@ -13,6 +13,9 @@ from aiorpcx import NetAddress from .util import bfh, bh2u, inv_dict, UserFacingException from .util import list_enabled_bits +from .util import ShortID as ShortChannelID +from .util import format_short_id as format_short_channel_id + from .crypto import sha256 from .transaction import (Transaction, PartialTransaction, PartialTxInput, TxOutpoint, PartialTxOutput, opcodes, TxOutput) @@ -1487,63 +1490,7 @@ NUM_MAX_HOPS_IN_PAYMENT_PATH = 20 NUM_MAX_EDGES_IN_PAYMENT_PATH = NUM_MAX_HOPS_IN_PAYMENT_PATH -class ShortChannelID(bytes): - - def __repr__(self): - return f"