From d26d3abf5db068da211f60d4fcd8a0c791102760 Mon Sep 17 00:00:00 2001 From: molecular Date: Sat, 16 Aug 2014 15:40:21 +0200 Subject: [PATCH 01/14] fix (or at least work around) #788 --- lib/plugins.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/plugins.py b/lib/plugins.py index feea2fcf..46c1c396 100644 --- a/lib/plugins.py +++ b/lib/plugins.py @@ -50,6 +50,7 @@ def run_hook(name, *args): except Exception: print_error("Plugin error") traceback.print_exc(file=sys.stdout) + r = False if r: results.append(r) From dc40a4fefac1df3306b1b1526a64ca5041a0be64 Mon Sep 17 00:00:00 2001 From: Max Kaye Date: Sun, 17 Aug 2014 21:41:42 +1000 Subject: [PATCH 02/14] Add Trezor plugin settings - can now view ID and set device label --- plugins/trezor.py | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/plugins/trezor.py b/plugins/trezor.py index fe792823..e58f64b4 100644 --- a/plugins/trezor.py +++ b/plugins/trezor.py @@ -1,4 +1,4 @@ -from PyQt4.Qt import QMessageBox, QDialog, QVBoxLayout, QLabel, QThread, SIGNAL +from PyQt4.Qt import QMessageBox, QDialog, QVBoxLayout, QLabel, QThread, SIGNAL, QGridLayout, QInputDialog, QPushButton import PyQt4.QtCore as QtCore from binascii import unhexlify from struct import pack @@ -7,7 +7,7 @@ from time import sleep from base64 import b64encode, b64decode from electrum_gui.qt.password_dialog import make_password_dialog, run_password_dialog -from electrum_gui.qt.util import ok_cancel_buttons +from electrum_gui.qt.util import ok_cancel_buttons, EnterButton from electrum.account import BIP32_Account from electrum.bitcoin import EncodeBase58Check, public_key_to_bc_address from electrum.i18n import _ @@ -39,6 +39,7 @@ class Plugin(BasePlugin): def __init__(self, gui, name): BasePlugin.__init__(self, gui, name) self._is_available = self._init() + self._requires_settings = True self.wallet = None def _init(self): @@ -47,6 +48,9 @@ class Plugin(BasePlugin): def is_available(self): return self._is_available + def requires_settings(self): + return self._requires_settings + def set_enabled(self, enabled): self.wallet.storage.put('use_' + self.name, enabled) @@ -79,6 +83,41 @@ class Plugin(BasePlugin): except Exception as e: tx.error = str(e) + def settings_widget(self, window): + return EnterButton(_('Settings'), self.settings_dialog) + + def settings_dialog(self): + get_label = lambda: self.wallet.get_client().features.label + update_label = lambda: current_label_label.setText("Label: %s" % get_label()) + + d = QDialog() + layout = QGridLayout(d) + layout.addWidget(QLabel("Trezor Options"),0,0) + layout.addWidget(QLabel("ID:"),1,0) + layout.addWidget(QLabel(" %s" % self.wallet.get_client().get_device_id()),1,1) + + def modify_label(): + response = QInputDialog().getText(None, "Set New Trezor Label", "New Trezor Label: (upon submission confirm on Trezor)") + if not response[1]: + return + new_label = str(response[0]) + twd.start("Please confirm label change on Trezor") + status = self.wallet.get_client().apply_settings(label=new_label) + twd.stop() + update_label() + + current_label_label = QLabel() + update_label() + change_label_button = QPushButton("Modify") + change_label_button.clicked.connect(modify_label) + layout.addWidget(current_label_label,3,0) + layout.addWidget(change_label_button,3,1) + + if d.exec_(): + return True + else: + return False + class TrezorWallet(NewWallet): From 95413cd1a9a457bdf35de6d07d4b9dc65ad3e0e2 Mon Sep 17 00:00:00 2001 From: Janne Pulkkinen Date: Tue, 19 Aug 2014 20:57:37 +0300 Subject: [PATCH 03/14] Confirmation count included in API command history --- lib/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/commands.py b/lib/commands.py index 4f9df0fc..fc6dc855 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -320,7 +320,7 @@ class Commands: label, is_default_label = self.wallet.get_label(tx_hash) - out.append({'txid':tx_hash, 'date':"%16s"%time_str, 'label':label, 'value':format_satoshis(value)}) + out.append({'txid':tx_hash, 'date':"%16s"%time_str, 'label':label, 'value':format_satoshis(value), 'confirmations':conf}) return out def setlabel(self, key, label): From 23c826863ea2f76247a26809d3e8cb9e3ca520fb Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 25 Aug 2014 11:52:47 +0200 Subject: [PATCH 04/14] cosigner plugin update --- plugins/cosigner_pool.py | 99 +++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/plugins/cosigner_pool.py b/plugins/cosigner_pool.py index a8e09764..4b8a5ff7 100644 --- a/plugins/cosigner_pool.py +++ b/plugins/cosigner_pool.py @@ -45,42 +45,36 @@ class Listener(threading.Thread): threading.Thread.__init__(self) self.daemon = True self.parent = parent - self.key = None + self.keyname = None + self.keyhash = None self.is_running = False self.message = None - self.delete = False - - def set_key(self, key): - self.key = key + + def set_key(self, keyname, keyhash): + self.keyname = keyname + self.keyhash = keyhash def clear(self): - self.delete = True + server.delete(self.keyhash) + self.message = None + def run(self): self.is_running = True while self.is_running: - - if not self.key: + if not self.keyhash: time.sleep(2) continue - if not self.message: try: - self.message = server.get(self.key) + self.message = server.get(self.keyhash) except Exception as e: util.print_error("cannot contact cosigner pool") time.sleep(30) continue - if self.message: self.parent.win.emit(SIGNAL("cosigner:receive")) - else: - if self.delete: - # save it to disk - server.delete(self.key) - self.message = None - self.delete = False - + # poll every 30 seconds time.sleep(30) @@ -109,21 +103,23 @@ class Plugin(BasePlugin): self.load_wallet(self.win.wallet) return True + def is_available(self): + if self.wallet is None: + return True + return self.wallet.wallet_type in ['2of2', '2of3'] + def load_wallet(self, wallet): self.wallet = wallet mpk = self.wallet.get_master_public_keys() - - self.cold = mpk.get('x2') - if self.cold: - self.cold_K = bitcoin.deserialize_xkey(self.cold)[-1].encode('hex') - self.cold_hash = bitcoin.Hash(self.cold_K).encode('hex') - - self.hot = mpk.get('x1') - if self.hot: - self.hot_K = bitcoin.deserialize_xkey(self.hot)[-1].encode('hex') - self.hot_hash = bitcoin.Hash(self.hot_K).encode('hex') - self.listener.set_key(self.hot_hash) - + self.cosigner_list = [] + for key, xpub in mpk.items(): + keyname = key + '/' # fixme + K = bitcoin.deserialize_xkey(xpub)[-1].encode('hex') + _hash = bitcoin.Hash(K).encode('hex') + if self.wallet.master_private_keys.get(keyname): + self.listener.set_key(keyname, _hash) + else: + self.cosigner_list.append((xpub, K, _hash)) def transaction_dialog(self, d): self.send_button = b = QPushButton(_("Send to cosigner")) @@ -131,18 +127,18 @@ class Plugin(BasePlugin): d.buttons.insertWidget(2, b) self.transaction_dialog_update(d) - def transaction_dialog_update(self, d): if d.tx.is_complete(): self.send_button.hide() return - if self.cosigner_can_sign(d.tx): - self.send_button.show() + for xpub, K, _hash in self.cosigner_list: + if self.cosigner_can_sign(d.tx, xpub): + self.send_button.show() + break else: self.send_button.hide() - - def cosigner_can_sign(self, tx): + def cosigner_can_sign(self, tx, cosigner_xpub): from electrum.transaction import x_to_xpub xpub_set = set([]) for txin in tx.inputs: @@ -151,24 +147,21 @@ class Plugin(BasePlugin): if xpub: xpub_set.add(xpub) - return self.cold in xpub_set - + return cosigner_xpub in xpub_set def do_send(self, tx): - if not self.cosigner_can_sign(tx): - return - - message = bitcoin.encrypt_message(tx.raw, self.cold_K) - - try: - server.put(self.cold_hash, message) - self.win.show_message("Your transaction was sent to the cosigning pool.\nOpen your cosigner wallet to retrieve it.") - except Exception as e: - self.win.show_message(str(e)) - + for xpub, K, _hash in self.cosigner_list: + if not self.cosigner_can_sign(tx, xpub): + continue + message = bitcoin.encrypt_message(tx.raw, K) + try: + server.put(_hash, message) + except Exception as e: + self.win.show_message(str(e)) + return + self.win.show_message("Your transaction was sent to the cosigning pool.\nOpen your cosigner wallet to retrieve it.") def on_receive(self): - if self.wallet.use_encryption: password = self.win.password_dialog('An encrypted transaction was retrieved from cosigning pool.\nPlease enter your password to decrypt it.') if not password: @@ -177,11 +170,12 @@ class Plugin(BasePlugin): password = None message = self.listener.message - xpriv = self.wallet.get_master_private_key('x1/', password) - if not xpriv: + key = self.listener.keyname + xprv = self.wallet.get_master_private_key(key, password) + if not xprv: return try: - k = bitcoin.deserialize_xkey(xpriv)[-1].encode('hex') + k = bitcoin.deserialize_xkey(xprv)[-1].encode('hex') EC = bitcoin.EC_KEY(k.decode('hex')) message = EC.decrypt_message(message) except Exception as e: @@ -190,7 +184,6 @@ class Plugin(BasePlugin): return self.listener.clear() - tx = transaction.Transaction.deserialize(message) self.win.show_transaction(tx) From 9f8e537a7e49df8c1e41ff7262de3c7391e74b0e Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 25 Aug 2014 14:16:31 +0200 Subject: [PATCH 05/14] fix broken test --- lib/tests/test_wallet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tests/test_wallet.py b/lib/tests/test_wallet.py index 49d22caf..8f8ea3f8 100644 --- a/lib/tests/test_wallet.py +++ b/lib/tests/test_wallet.py @@ -131,7 +131,8 @@ class TestNewWallet(WalletTestCase): # in setUp() new_dir = tempfile.mkdtemp() config = FakeConfig(new_dir) - wallet = NewWallet(config) + storage = WalletStorage(config) + wallet = NewWallet(storage) self.assertTrue(wallet.is_watching_only()) shutil.rmtree(new_dir) # Don't leave useless stuff in /tmp From 03f4b4c9330e2c973b336bde1ca93534d8d9cc8c Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 25 Aug 2014 15:11:52 +0200 Subject: [PATCH 06/14] fix broken test --- lib/tests/test_wallet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tests/test_wallet.py b/lib/tests/test_wallet.py index 8f8ea3f8..3c12be8d 100644 --- a/lib/tests/test_wallet.py +++ b/lib/tests/test_wallet.py @@ -3,6 +3,7 @@ import tempfile import sys import unittest import os +import json from StringIO import StringIO from lib.wallet import WalletStorage, NewWallet @@ -97,7 +98,7 @@ class TestWalletStorage(WalletTestCase): contents = "" with open(path, "r") as f: contents = f.read() - self.assertEqual(repr(some_dict), contents) + self.assertEqual(some_dict, json.loads(contents)) class TestNewWallet(WalletTestCase): From ef74ae57ff488c784e3890429ea8e8335b5b8569 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 25 Aug 2014 15:32:21 +0200 Subject: [PATCH 07/14] fix tests --- lib/bitcoin.py | 3 +-- lib/tests/test_bitcoin.py | 2 +- lib/wallet.py | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/bitcoin.py b/lib/bitcoin.py index 39b33996..002dcdc2 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -706,10 +706,9 @@ def xpub_from_xprv(xprv, testnet=False): return EncodeBase58Check(xpub) -def bip32_root(mnemonic_seed, testnet=False): +def bip32_root(seed, testnet=False): import hmac header_pub, header_priv = _get_headers(testnet) - seed = mnemonic_to_seed(mnemonic_seed,'') I = hmac.new("Bitcoin seed", seed, hashlib.sha512).digest() master_k = I[0:32] master_c = I[32:] diff --git a/lib/tests/test_bitcoin.py b/lib/tests/test_bitcoin.py index e2227170..c61df592 100644 --- a/lib/tests/test_bitcoin.py +++ b/lib/tests/test_bitcoin.py @@ -68,7 +68,7 @@ class Test_bitcoin(unittest.TestCase): assert xprv == "tprv8jTo9vZtZTSiTo6BBDjeQDgLEaipWPsrhYsQpZYoqqJNPKbCyDewkHJZhkoSHiWYCUf1Gm4TFzQxcG4D6s1J9Hsn4whDK7QYyHHokJeUuac" def _do_test_bip32(self, seed, sequence, testnet): - xprv, xpub = bip32_root(seed, testnet) + xprv, xpub = bip32_root(seed.decode('hex'), testnet) assert sequence[0:2] == "m/" path = 'm' sequence = sequence[2:] diff --git a/lib/wallet.py b/lib/wallet.py index 09830457..fc4d6d10 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -1385,7 +1385,7 @@ class BIP39_Wallet(BIP32_Wallet): def create_master_keys(self, password): seed = self.get_seed(password) - xprv, xpub = bip32_root(seed) + xprv, xpub = bip32_root(mnemonic_to_seed(seed,'')) xprv, xpub = bip32_private_derivation(xprv, "m/", self.root_derivation) self.add_master_public_key(self.root_name, xpub) self.add_master_private_key(self.root_name, xprv, password) @@ -1459,7 +1459,7 @@ class Wallet_2of2(BIP39_Wallet): def add_cosigner_seed(self, seed, name, password): # we don't store the seed, only the master xpriv - xprv, xpub = bip32_root(seed) + xprv, xpub = bip32_root(mnemonic_to_seed(seed,'')) xprv, xpub = bip32_private_derivation(xprv, "m/", self.root_derivation) self.add_master_public_key(name, xpub) self.add_master_private_key(name, xprv, password) From c2d175cb60db02cb31e9f92a56a96ffb3fd807d9 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 25 Aug 2014 15:55:06 +0200 Subject: [PATCH 08/14] remove broken tests --- lib/tests/test_wallet.py | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/lib/tests/test_wallet.py b/lib/tests/test_wallet.py index 3c12be8d..e537c9a0 100644 --- a/lib/tests/test_wallet.py +++ b/lib/tests/test_wallet.py @@ -103,15 +103,10 @@ class TestWalletStorage(WalletTestCase): class TestNewWallet(WalletTestCase): - seed_text = "The seed will sprout and grow up tall." + seed_text = "travel nowhere air position hill peace suffer parent beautiful rise blood power home crumble teach" password = "secret" - master_xpub = "xpub661MyMwAqRbcGEop5Rnp68oX1ikeFNVMtx1utwXZGRKMmeXVxwBM5UzkwU9nGB1EofZekLDRfi1w5F9P7Vac3PEuWdWHr2gHLW8vp5YyKJ1" - master_xpriv = "xprv9s21ZrQH143K3kjLyQFoizrnTgv9qumWXj6K6Z7wi5nNtrCMRPs6XggH6Bbgz9CUgPJnZnV74yUdRSr8qWVELr9QQTgU5aNL33ViMyD9nhs" - first_account_name = "account1" - first_account_first_address = "1Jv9pLCJ4Sqr7aDYLGX5QhET4ps5qRcB9V" - first_account_second_address = "14n9EsZsgTTc4eC4TxeP1ccP8bXgwxPMmL" import_private_key = "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW" import_key_address = "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma" @@ -144,22 +139,6 @@ class TestNewWallet(WalletTestCase): self.assertEqual(self.wallet.get_seed(self.password), self.seed_text) self.assertEqual(0, len(self.wallet.addresses())) - def test_add_account(self): - self.wallet.create_account(self.first_account_name, self.password) - self.assertEqual(1, len(self.wallet.addresses())) - self.assertIn(self.first_account_first_address, - self.wallet.addresses()) - - def test_add_account_add_address(self): - self.wallet.create_account(self.first_account_name, self.password) - self.wallet.synchronizer = FakeSynchronizer() - - self.wallet.create_new_address() - self.assertEqual(2, len(self.wallet.addresses())) - self.assertIn(self.first_account_first_address, - self.wallet.addresses()) - self.assertIn(self.first_account_second_address, - self.wallet.addresses()) def test_key_import(self): # Wallets have no imported keys by default. From 5f10b498118d03be7df3df73e7e0afcd62c0f511 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 25 Aug 2014 15:58:06 +0200 Subject: [PATCH 09/14] fix load_wallet of cosigner --- plugins/cosigner_pool.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/cosigner_pool.py b/plugins/cosigner_pool.py index 4b8a5ff7..69f1b0a4 100644 --- a/plugins/cosigner_pool.py +++ b/plugins/cosigner_pool.py @@ -110,6 +110,8 @@ class Plugin(BasePlugin): def load_wallet(self, wallet): self.wallet = wallet + if not self.is_available(): + return mpk = self.wallet.get_master_public_keys() self.cosigner_list = [] for key, xpub in mpk.items(): From b58aae699ebea742fdac29dd5196945c0a3bd5e1 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 26 Aug 2014 12:38:05 +0200 Subject: [PATCH 10/14] fix address_id --- plugins/trezor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/trezor.py b/plugins/trezor.py index cf4dc5f1..08efde44 100644 --- a/plugins/trezor.py +++ b/plugins/trezor.py @@ -177,7 +177,7 @@ class TrezorWallet(NewWallet): def address_id(self, address): account_id, (change, address_index) = self.get_address_index(address) - return "%s/%d/%d" % (account_id, change, address_index) + return "44'/0'/%s'/%d/%d" % (account_id, change, address_index) def create_main_account(self, password): self.create_account('Main account', None) #name, empty password @@ -221,6 +221,8 @@ class TrezorWallet(NewWallet): return str(decrypted_msg) def sign_message(self, address, message, password): + if not self.check_proper_device(): + give_error('Wrong device or password') try: address_path = self.address_id(address) address_n = self.get_client().expand_path(address_path) From 58c6518b30189ca7579cee951800071951d4928c Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 26 Aug 2014 12:55:53 +0200 Subject: [PATCH 11/14] print more tracebacks --- gui/qt/main_window.py | 2 ++ plugins/trezor.py | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index 57fb1283..a3795997 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -1988,6 +1988,7 @@ class ElectrumWindow(QMainWindow): decrypted = self.wallet.decrypt_message(str(pubkey_e.text()), str(encrypted_e.toPlainText()), password) message_e.setText(decrypted) except Exception as e: + traceback.print_exc(file=sys.stdout) self.show_message(str(e)) @@ -1998,6 +1999,7 @@ class ElectrumWindow(QMainWindow): encrypted = bitcoin.encrypt_message(message, str(pubkey_e.text())) encrypted_e.setText(encrypted) except Exception as e: + traceback.print_exc(file=sys.stdout) self.show_message(str(e)) diff --git a/plugins/trezor.py b/plugins/trezor.py index 08efde44..12e8c8e5 100644 --- a/plugins/trezor.py +++ b/plugins/trezor.py @@ -206,12 +206,9 @@ class TrezorWallet(NewWallet): pass def decrypt_message(self, pubkey, message, password): - try: - address = public_key_to_bc_address(pubkey.decode('hex')) - address_path = self.address_id(address) - address_n = self.get_client().expand_path(address_path) - except Exception, e: - raise e + address = public_key_to_bc_address(pubkey.decode('hex')) + address_path = self.address_id(address) + address_n = self.get_client().expand_path(address_path) try: decrypted_msg = self.get_client().decrypt_message(address_n, b64decode(message)) except Exception, e: From 744eee68586bcfe7608448f5fdf3482438219d07 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 26 Aug 2014 16:23:24 +0200 Subject: [PATCH 12/14] wizard integration --- gui/qt/installwizard.py | 46 ++++++++++++----------------------------- gui/qt/util.py | 8 +++---- lib/wallet.py | 6 ++++++ 3 files changed, 23 insertions(+), 37 deletions(-) diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py index 039000a1..b5e3e497 100644 --- a/gui/qt/installwizard.py +++ b/gui/qt/installwizard.py @@ -33,6 +33,7 @@ class InstallWizard(QDialog): self.network = network self.storage = storage self.setMinimumSize(575, 400) + self.setMaximumSize(575, 400) self.setWindowTitle('Electrum') self.connect(self, QtCore.SIGNAL('accept'), self.accept) @@ -313,16 +314,19 @@ class InstallWizard(QDialog): return None - def question(self, msg, icon=None): + def question(self, msg, yes_label=_('OK'), no_label=_('Cancel'), icon=None): vbox = QVBoxLayout() self.set_layout(vbox) if icon: logo = QLabel() logo.setPixmap(icon) vbox.addWidget(logo) - vbox.addWidget(QLabel(msg)) + + label = QLabel(msg) + label.setWordWrap(True) + vbox.addWidget(label) vbox.addStretch(1) - vbox.addLayout(ok_cancel_buttons(self, _('OK'))) + vbox.addLayout(ok_cancel_buttons(self, yes_label, no_label)) if not self.exec_(): return None return True @@ -343,29 +347,6 @@ class InstallWizard(QDialog): return run_password_dialog(self, None, self)[2] - def create_cold_seed(self, wallet): - from electrum.bitcoin import mnemonic_to_seed, bip32_root - msg = _('You are about to generate the cold storage seed of your wallet.') + '\n' \ - + _('For safety, you should do this on an offline computer.') - icon = QPixmap( ':icons/cold_seed.png').scaledToWidth(56) - if not self.question(msg, icon): - return - - cold_seed = wallet.make_seed() - if not self.show_seed(cold_seed, 'cold'): - return - if not self.verify_seed(cold_seed, 'cold'): - return - - hex_seed = mnemonic_to_seed(cold_seed,'').encode('hex') - xpriv, xpub = bip32_root(hex_seed) - wallet.add_master_public_key('cold/', xpub) - - msg = _('Your master public key was saved in your wallet file.') + '\n'\ - + _('Your cold seed must be stored on paper; it is not in the wallet file.')+ '\n\n' \ - + _('This program is about to close itself.') + '\n'\ - + _('You will need to reopen your wallet on an online computer, in order to complete the creation of your wallet') - self.show_message(msg) @@ -429,14 +410,13 @@ class InstallWizard(QDialog): return self.waiting_dialog(wallet.synchronize) - elif action == 'create_cold_seed': - self.create_cold_seed(wallet) - return - else: - r = run_hook('install_wizard_action', self, wallet, action) - if not r: - raise BaseException('unknown wizard action', action) + f = run_hook('get_wizard_action', self, wallet, action) + if not f: + raise BaseException('unknown wizard action', action) + r = f(wallet, self) + if not r: + return # next action action = wallet.get_action() diff --git a/gui/qt/util.py b/gui/qt/util.py index c021e8b3..4998498d 100644 --- a/gui/qt/util.py +++ b/gui/qt/util.py @@ -94,10 +94,10 @@ def close_button(dialog, label=_("Close") ): b.setDefault(True) return hbox -def ok_cancel_buttons2(dialog, ok_label=_("OK") ): +def ok_cancel_buttons2(dialog, ok_label=_("OK"), cancel_label=_('Cancel')): hbox = QHBoxLayout() hbox.addStretch(1) - b = QPushButton(_("Cancel")) + b = QPushButton(cancel_label) hbox.addWidget(b) b.clicked.connect(dialog.reject) b = QPushButton(ok_label) @@ -106,8 +106,8 @@ def ok_cancel_buttons2(dialog, ok_label=_("OK") ): b.setDefault(True) return hbox, b -def ok_cancel_buttons(dialog, ok_label=_("OK") ): - hbox, b = ok_cancel_buttons2(dialog, ok_label) +def ok_cancel_buttons(dialog, ok_label=_("OK"), cancel_label=_('Cancel')): + hbox, b = ok_cancel_buttons2(dialog, ok_label, cancel_label) return hbox def line_dialog(parent, title, label, ok_label, default=None): diff --git a/lib/wallet.py b/lib/wallet.py index fc4d6d10..5bb75839 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -1464,6 +1464,12 @@ class Wallet_2of2(BIP39_Wallet): self.add_master_public_key(name, xpub) self.add_master_private_key(name, xprv, password) + def add_cosigner_xpub(self, seed, name): + # store only master xpub + xprv, xpub = bip32_root(mnemonic_to_seed(seed,'')) + xprv, xpub = bip32_private_derivation(xprv, "m/", self.root_derivation) + self.add_master_public_key(name, xpub) + class Wallet_2of3(Wallet_2of2): From b24f67fe9d0eec787b39a951b240ef66a6deae49 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 26 Aug 2014 17:17:17 +0200 Subject: [PATCH 13/14] add trustedcoin icon --- icons.qrc | 1 + icons/trustedcoin.png | Bin 0 -> 3727 bytes 2 files changed, 1 insertion(+) create mode 100644 icons/trustedcoin.png diff --git a/icons.qrc b/icons.qrc index 5dce17bc..97bae3b2 100644 --- a/icons.qrc +++ b/icons.qrc @@ -25,5 +25,6 @@ icons/network.png icons/dark_background.png icons/qrcode.png + icons/trustedcoin.png diff --git a/icons/trustedcoin.png b/icons/trustedcoin.png new file mode 100644 index 0000000000000000000000000000000000000000..2153866a66b0600350f245d89e762a6c4f0de607 GIT binary patch literal 3727 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 Date: Tue, 26 Aug 2014 17:58:17 +0200 Subject: [PATCH 14/14] fix plugin restore: wallet_type --- gui/qt/installwizard.py | 1 + plugins/trezor.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py index b5e3e497..250552ef 100644 --- a/gui/qt/installwizard.py +++ b/gui/qt/installwizard.py @@ -538,6 +538,7 @@ class InstallWizard(QDialog): wallet.create_main_account(password) else: + self.storage.put('wallet_type', t) wallet = run_hook('installwizard_restore', self, self.storage) if not wallet: return diff --git a/plugins/trezor.py b/plugins/trezor.py index 12e8c8e5..79bb85e0 100644 --- a/plugins/trezor.py +++ b/plugins/trezor.py @@ -81,6 +81,8 @@ class Plugin(BasePlugin): wallet_types.append(('trezor', _("Trezor wallet"), TrezorWallet)) def installwizard_restore(self, wizard, storage): + if storage.get('wallet_type') != 'trezor': + return wallet = TrezorWallet(storage) try: wallet.create_main_account(None)