From 9354dfc86d12a45fc7d2cd32346425d48325df74 Mon Sep 17 00:00:00 2001 From: Sander van Grieken Date: Mon, 28 Nov 2022 17:42:29 +0100 Subject: [PATCH] qml: skip multisig_show_masterpubkey view and instead present master pub key on every cosigner key/seed import page. --- .../components/wizard/WCCosignerKeystore.qml | 48 +++++++++++++++++ .../qml/components/wizard/WCHaveMasterKey.qml | 46 ++++++++++++++++ .../gui/qml/components/wizard/WCHaveSeed.qml | 52 ++++++++++++++++++- .../components/wizard/WCShowMasterPubkey.qml | 15 +----- electrum/gui/qml/qebitcoin.py | 18 ------- electrum/gui/qml/qewallet.py | 2 - electrum/gui/qml/qewizard.py | 2 +- electrum/wizard.py | 20 +++++-- 8 files changed, 162 insertions(+), 41 deletions(-) diff --git a/electrum/gui/qml/components/wizard/WCCosignerKeystore.qml b/electrum/gui/qml/components/wizard/WCCosignerKeystore.qml index 625f810ab..e16237b2d 100644 --- a/electrum/gui/qml/components/wizard/WCCosignerKeystore.qml +++ b/electrum/gui/qml/components/wizard/WCCosignerKeystore.qml @@ -1,6 +1,7 @@ import QtQuick 2.6 import QtQuick.Layouts 1.0 import QtQuick.Controls 2.1 +import QtQuick.Controls.Material 2.0 import org.electrum 1.0 @@ -13,6 +14,7 @@ WizardComponent { property int cosigner: 0 property int participants: 0 + property string multisigMasterPubkey: wizard_data['multisig_master_pubkey'] function apply() { wizard_data['cosigner_keystore_type'] = keystoregroup.checkedButton.keystoretype @@ -25,6 +27,52 @@ WizardComponent { } ColumnLayout { + width: parent.width + + Label { + visible: cosigner + text: qsTr('Here is your master public key. Please share it with your cosigners') + Layout.fillWidth: true + wrapMode: Text.Wrap + } + + TextHighlightPane { + visible: cosigner + Layout.fillWidth: true + padding: 0 + leftPadding: constants.paddingSmall + + RowLayout { + width: parent.width + Label { + Layout.fillWidth: true + text: multisigMasterPubkey + font.pixelSize: constants.fontSizeMedium + font.family: FixedFont + wrapMode: Text.Wrap + } + ToolButton { + icon.source: '../../../icons/share.png' + icon.color: 'transparent' + onClicked: { + var dialog = app.genericShareDialog.createObject(app, + { title: qsTr('Master public key'), text: multisigMasterPubkey } + ) + dialog.open() + } + } + } + } + + Rectangle { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 1 + Layout.topMargin: constants.paddingLarge + Layout.bottomMargin: constants.paddingLarge + visible: cosigner + color: Material.accentColor + } + Label { text: qsTr('Add cosigner #%1 of %2 to your multi-sig wallet').arg(cosigner).arg(participants) } diff --git a/electrum/gui/qml/components/wizard/WCHaveMasterKey.qml b/electrum/gui/qml/components/wizard/WCHaveMasterKey.qml index bce7b3997..d95615c0b 100644 --- a/electrum/gui/qml/components/wizard/WCHaveMasterKey.qml +++ b/electrum/gui/qml/components/wizard/WCHaveMasterKey.qml @@ -1,6 +1,7 @@ import QtQuick 2.6 import QtQuick.Layouts 1.0 import QtQuick.Controls 2.1 +import QtQuick.Controls.Material 2.0 import org.electrum 1.0 @@ -13,6 +14,7 @@ WizardComponent { property int cosigner: 0 property int participants: 0 + property string multisigMasterPubkey: wizard_data['multisig_master_pubkey'] function apply() { if (cosigner) { @@ -45,6 +47,50 @@ WizardComponent { ColumnLayout { width: parent.width + Label { + visible: cosigner + text: qsTr('Here is your master public key. Please share it with your cosigners') + Layout.fillWidth: true + wrapMode: Text.Wrap + } + + TextHighlightPane { + visible: cosigner + Layout.fillWidth: true + padding: 0 + leftPadding: constants.paddingSmall + + RowLayout { + width: parent.width + Label { + Layout.fillWidth: true + text: multisigMasterPubkey + font.pixelSize: constants.fontSizeMedium + font.family: FixedFont + wrapMode: Text.Wrap + } + ToolButton { + icon.source: '../../../icons/share.png' + icon.color: 'transparent' + onClicked: { + var dialog = app.genericShareDialog.createObject(app, + { title: qsTr('Master public key'), text: multisigMasterPubkey } + ) + dialog.open() + } + } + } + } + + Rectangle { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 1 + Layout.topMargin: constants.paddingLarge + Layout.bottomMargin: constants.paddingLarge + visible: cosigner + color: Material.accentColor + } + Label { text: qsTr('Cosigner #%1 of %2').arg(cosigner).arg(participants) visible: cosigner diff --git a/electrum/gui/qml/components/wizard/WCHaveSeed.qml b/electrum/gui/qml/components/wizard/WCHaveSeed.qml index 753dada8e..1a809c194 100644 --- a/electrum/gui/qml/components/wizard/WCHaveSeed.qml +++ b/electrum/gui/qml/components/wizard/WCHaveSeed.qml @@ -15,6 +15,7 @@ WizardComponent { property bool is2fa: false property int cosigner: 0 property int participants: 0 + property string multisigMasterPubkey: wizard_data['multisig_master_pubkey'] function apply() { if (cosigner) { @@ -85,14 +86,61 @@ WizardComponent { Label { Layout.columnSpan: 2 - text: qsTr('Cosigner #%1 of %2').arg(cosigner).arg(participants) + Layout.fillWidth: true + visible: cosigner + text: qsTr('Here is your master public key. Please share it with your cosigners') + wrapMode: Text.Wrap + } + + TextHighlightPane { + visible: cosigner + Layout.columnSpan: 2 + Layout.fillWidth: true + padding: 0 + leftPadding: constants.paddingSmall + + RowLayout { + width: parent.width + Label { + Layout.fillWidth: true + text: multisigMasterPubkey + font.pixelSize: constants.fontSizeMedium + font.family: FixedFont + wrapMode: Text.Wrap + } + ToolButton { + icon.source: '../../../icons/share.png' + icon.color: 'transparent' + onClicked: { + var dialog = app.genericShareDialog.createObject(app, + { title: qsTr('Master public key'), text: multisigMasterPubkey } + ) + dialog.open() + } + } + } + } + + Rectangle { + Layout.columnSpan: 2 + Layout.preferredWidth: parent.width + Layout.preferredHeight: 1 + Layout.topMargin: constants.paddingLarge + Layout.bottomMargin: constants.paddingLarge + visible: cosigner + color: Material.accentColor + } + + Label { + Layout.columnSpan: 2 visible: cosigner + text: qsTr('Cosigner #%1 of %2').arg(cosigner).arg(participants) } Label { + Layout.fillWidth: true visible: !is2fa text: qsTr('Seed Type') - Layout.fillWidth: true } ComboBox { id: seed_variant_cb diff --git a/electrum/gui/qml/components/wizard/WCShowMasterPubkey.qml b/electrum/gui/qml/components/wizard/WCShowMasterPubkey.qml index 67af8e86d..6dae7ea8a 100644 --- a/electrum/gui/qml/components/wizard/WCShowMasterPubkey.qml +++ b/electrum/gui/qml/components/wizard/WCShowMasterPubkey.qml @@ -9,7 +9,7 @@ import "../controls" WizardComponent { valid: true - property string masterPubkey: '' + property string masterPubkey: wizard_data['multisig_master_pubkey'] ColumnLayout { width: parent.width @@ -48,17 +48,4 @@ WizardComponent { } } - Bitcoin { - id: bitcoin - } - - Component.onCompleted: { - if ('master_key' in wizard_data) { - masterPubkey = bitcoin.getMultisigMasterPubkeyFromKey(wizard_data['master_key']) - } else if (wizard_data['seed_variant'] == 'electrum') { - masterPubkey = bitcoin.getMultisigMasterPubkeyFromSeed(wizard_data['seed_variant'], wizard_data['seed'], wizard_data['seed_extra_words']) - } else { - masterPubkey = bitcoin.getMultisigMasterPubkeyFromSeed(wizard_data['seed_variant'], wizard_data['seed'], wizard_data['seed_extra_words'], wizard_data['derivation_path']) - } - } } diff --git a/electrum/gui/qml/qebitcoin.py b/electrum/gui/qml/qebitcoin.py index 081a4c7a1..efc3684c7 100644 --- a/electrum/gui/qml/qebitcoin.py +++ b/electrum/gui/qml/qebitcoin.py @@ -165,21 +165,3 @@ class QEBitcoin(QObject): @pyqtSlot(str, result=bool) def isPrivateKeyList(self, csv: str): return keystore.is_private_key_list(csv) - - @pyqtSlot(str, result=str) - def getMultisigMasterPubkeyFromKey(self, key): - return keystore.from_master_key(key).get_master_public_key() - - @pyqtSlot(str, str, str, result=str) - @pyqtSlot(str, str, str, str, result=str) - def getMultisigMasterPubkeyFromSeed(self, seed_variant, seed, seed_extra_words, derivation_path = None): - if seed_variant == 'electrum': - k = keystore.from_seed(seed, seed_extra_words, True) - elif seed_variant == 'bip39': - root_seed = keystore.bip39_to_seed(seed, seed_extra_words) - derivation = normalize_bip32_derivation(derivation_path) - k = keystore.from_bip43_rootseed(root_seed, derivation, xtype='p2wsh') - else: - raise Exception(f'Unsupported seed variant {seed_variant}') - - return k.get_master_public_key() diff --git a/electrum/gui/qml/qewallet.py b/electrum/gui/qml/qewallet.py index 3a6303bd7..7d91480c2 100644 --- a/electrum/gui/qml/qewallet.py +++ b/electrum/gui/qml/qewallet.py @@ -510,8 +510,6 @@ class QEWallet(AuthMixin, QObject, QtEventListener): def broadcast(self, tx): assert tx.is_complete() - # network = self.wallet.network # TODO not always defined? - def broadcast_thread(): try: self._logger.info('running broadcast in thread') diff --git a/electrum/gui/qml/qewizard.py b/electrum/gui/qml/qewizard.py index aa863c49c..c827c0da6 100644 --- a/electrum/gui/qml/qewizard.py +++ b/electrum/gui/qml/qewizard.py @@ -60,7 +60,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): 'bip39_refine': { 'gui': 'WCBIP39Refine' }, 'have_master_key': { 'gui': 'WCHaveMasterKey' }, 'multisig': { 'gui': 'WCMultisig' }, - 'multisig_show_masterpubkey': { 'gui': 'WCShowMasterPubkey' }, + # 'multisig_show_masterpubkey': { 'gui': 'WCShowMasterPubkey' }, 'multisig_cosigner_keystore': { 'gui': 'WCCosignerKeystore' }, 'multisig_cosigner_key': { 'gui': 'WCHaveMasterKey' }, 'multisig_cosigner_seed': { 'gui': 'WCHaveSeed' }, diff --git a/electrum/wizard.py b/electrum/wizard.py index f237b9acc..630c3d7d5 100644 --- a/electrum/wizard.py +++ b/electrum/wizard.py @@ -149,26 +149,30 @@ class NewWalletWizard(AbstractWizard): }, 'confirm_seed': { 'next': lambda d: 'wallet_password' if not self.is_multisig(d) else 'multisig_show_masterpubkey', + 'accept': self.maybe_master_pubkey, 'last': lambda v,d: self.is_single_password() and not self.is_multisig(d) }, 'have_seed': { 'next': self.on_have_seed, + 'accept': self.maybe_master_pubkey, 'last': lambda v,d: self.is_single_password() and not self.is_bip39_seed(d) and not self.is_multisig(d) }, 'bip39_refine': { 'next': lambda d: 'wallet_password' if not self.is_multisig(d) else 'multisig_show_masterpubkey', + 'accept': self.maybe_master_pubkey, 'last': lambda v,d: self.is_single_password() and not self.is_multisig(d) }, 'have_master_key': { 'next': lambda d: 'wallet_password' if not self.is_multisig(d) else 'multisig_show_masterpubkey', + 'accept': self.maybe_master_pubkey, 'last': lambda v,d: self.is_single_password() and not self.is_multisig(d) }, 'multisig': { 'next': 'keystore_type' }, - 'multisig_show_masterpubkey': { - 'next': 'multisig_cosigner_keystore' - }, + # 'multisig_show_masterpubkey': { + # 'next': 'multisig_cosigner_keystore' + # }, 'multisig_cosigner_keystore': { # this view should set 'multisig_current_cosigner' 'next': self.on_cosigner_keystore_type }, @@ -229,10 +233,18 @@ class NewWalletWizard(AbstractWizard): if self.is_bip39_seed(wizard_data): return 'bip39_refine' elif self.is_multisig(wizard_data): - return 'multisig_show_masterpubkey' + return 'multisig_cosigner_keystore' else: return 'wallet_password' + def maybe_master_pubkey(self, wizard_data): + self._logger.info('maybe_master_pubkey') + if self.is_bip39_seed(wizard_data) and 'derivation_path' not in wizard_data: + self._logger.info('maybe_master_pubkey2') + return + + wizard_data['multisig_master_pubkey'] = self.keystore_from_data(wizard_data).get_master_public_key() + def on_cosigner_keystore_type(self, wizard_data): t = wizard_data['cosigner_keystore_type'] return {