electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit a07a3f748e34abc5384b237d8cf2369ae35c36a7
parent 4e8c6160904237214565e2e907f8a5b39fdcee2a
Author: ThomasV <thomasv@electrum.org>
Date:   Tue,  7 Jun 2016 09:57:24 +0200

Qt GUI: let users type tx output in script language

Diffstat:
Mgui/kivy/main_window.py | 3++-
Mgui/qt/main_window.py | 14++++++++------
Mgui/qt/paytoedit.py | 37+++++++++++++++++++++++++++----------
Mlib/commands.py | 2+-
Mlib/wallet.py | 3++-
Mplugins/trustedcoin/trustedcoin.py | 3++-
6 files changed, 42 insertions(+), 20 deletions(-)

diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py @@ -8,6 +8,7 @@ from decimal import Decimal import threading import electrum +from electrum.bitcoin import TYPE_ADDRESS from electrum import WalletStorage, Wallet from electrum_gui.kivy.i18n import _ from electrum.contacts import Contacts @@ -563,7 +564,7 @@ class ElectrumWindow(App): def get_max_amount(self): inputs = self.wallet.get_spendable_coins(None) addr = str(self.send_screen.screen.address) or self.wallet.dummy_address() - amount, fee = self.wallet.get_max_amount(self.electrum_config, inputs, addr, None) + amount, fee = self.wallet.get_max_amount(self.electrum_config, inputs, (TYPE_ADDRESS, addr), None) return format_satoshis_plain(amount, self.decimal_point()) def format_amount(self, x, is_diff=False, whitespaces=False): diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -1022,8 +1022,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): inputs = self.get_coins() sendable = sum(map(lambda x:x['value'], inputs)) fee = self.fee_e.get_amount() if self.fee_e.isModified() else None - addr = self.get_payto_or_dummy() - amount, fee = self.wallet.get_max_amount(self.config, inputs, addr, fee) + r = self.get_payto_or_dummy() + amount, fee = self.wallet.get_max_amount(self.config, inputs, r, fee) if not self.fee_e.isModified(): self.fee_e.setAmount(fee) self.amount_e.setAmount(amount) @@ -1032,12 +1032,14 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): self.amount_e.textEdited.emit("") self.is_max = True - def update_fee(self): self.require_fee_update = True def get_payto_or_dummy(self): - return self.payto_e.payto_address if self.payto_e.payto_address else self.wallet.dummy_address() + r = self.payto_e.get_recipient() + if r: + return r + return (TYPE_ADDRESS, self.wallet.dummy_address()) def do_update_fee(self): '''Recalculate the fee. If the fee was manually input, retain it, but @@ -1054,8 +1056,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): fee = self.fee_e.get_amount() if freeze_fee else None outputs = self.payto_e.get_outputs() if not outputs: - addr = self.get_payto_or_dummy() - outputs = [(TYPE_ADDRESS, addr, amount)] + _type, addr = self.get_payto_or_dummy() + outputs = [(_type, addr, amount)] try: tx = self.wallet.make_unsigned_transaction(self.get_coins(), outputs, self.config, fee) self.not_enough_funds = False diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py @@ -80,15 +80,28 @@ class PayToEdit(ScanQRTextEdit): def parse_address_and_amount(self, line): x, y = line.split(',') - n = re.match('^SCRIPT\s+([0-9a-fA-F]+)$', x.strip()) - if n: - script = str(n.group(1)).decode('hex') - amount = self.parse_amount(y) - return bitcoin.TYPE_SCRIPT, script, amount - else: + out_type, out = self.parse_output(x) + amount = self.parse_amount(y) + return out_type, out, amount + + def parse_output(self, x): + try: address = self.parse_address(x) - amount = self.parse_amount(y) - return bitcoin.TYPE_ADDRESS, address, amount + return bitcoin.TYPE_ADDRESS, address + except: + script = self.parse_script(x) + return bitcoin.TYPE_SCRIPT, script + + def parse_script(self, x): + from electrum.transaction import opcodes, push_script + script = '' + for word in x.split(): + if word[0:3] == 'OP_': + assert word in opcodes.lookup + script += chr(opcodes.lookup[word]) + else: + script += push_script(word).decode('hex') + return script def parse_amount(self, x): p = pow(10, self.amount_edit.decimal_point()) @@ -116,7 +129,7 @@ class PayToEdit(ScanQRTextEdit): self.scan_f(data) return try: - self.payto_address = self.parse_address(data) + self.payto_address = self.parse_output(data) except: pass if self.payto_address: @@ -150,13 +163,17 @@ class PayToEdit(ScanQRTextEdit): def get_errors(self): return self.errors + def get_recipient(self): + return self.payto_address + def get_outputs(self): if self.payto_address: try: amount = self.amount_edit.get_amount() except: amount = None - self.outputs = [(bitcoin.TYPE_ADDRESS, self.payto_address, amount)] + _type, addr = self.payto_address + self.outputs = [(_type, addr, amount)] return self.outputs[:] diff --git a/lib/commands.py b/lib/commands.py @@ -418,7 +418,7 @@ class Commands: if amount == '!': assert len(outputs) == 1 inputs = self.wallet.get_spendable_coins(domain) - amount, fee = self.wallet.get_max_amount(self.config, inputs, address, fee) + amount, fee = self.wallet.get_max_amount(self.config, inputs, (TYPE_ADDRESS, address), fee) else: amount = int(COIN*Decimal(amount)) final_outputs.append((TYPE_ADDRESS, address, amount)) diff --git a/lib/wallet.py b/lib/wallet.py @@ -681,7 +681,8 @@ class Abstract_Wallet(PrintError): if fee is None: for i in inputs: self.add_input_info(i) - outputs = [(TYPE_ADDRESS, recipient, sendable)] + _type, addr = recipient + outputs = [(_type, addr, sendable)] dummy_tx = Transaction.from_io(inputs, outputs) fee = self.estimate_fee(config, dummy_tx.estimated_size()) amount = max(0, sendable - fee) diff --git a/plugins/trustedcoin/trustedcoin.py b/plugins/trustedcoin/trustedcoin.py @@ -220,7 +220,8 @@ class Wallet_2fa(Multisig_Wallet): if xf and sendable >= xf: billing_address = self.billing_info['billing_address'] sendable -= xf - outputs = [(TYPE_ADDRESS, recipient, sendable), + _type, addr = recipient + outputs = [(_type, addr, sendable), (TYPE_ADDRESS, billing_address, xf)] else: outputs = [(TYPE_ADDRESS, recipient, sendable)]