From 4f252a438c499aad930636d0efa9e30fd11f3f4f Mon Sep 17 00:00:00 2001 From: Sander van Grieken Date: Mon, 15 May 2023 14:45:21 +0200 Subject: [PATCH] qml: validate duplicate master key in WCBIP39Refine for BIP39 cosigner seeds (fixes #8432) --- .../qml/components/wizard/WCBIP39Refine.qml | 21 +++++++++++++++++++ .../gui/qml/components/wizard/WCHaveSeed.qml | 21 ++++++++++++------- electrum/gui/qml/qewizard.py | 2 +- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/electrum/gui/qml/components/wizard/WCBIP39Refine.qml b/electrum/gui/qml/components/wizard/WCBIP39Refine.qml index 20d7c4b14..647c23c33 100644 --- a/electrum/gui/qml/components/wizard/WCBIP39Refine.qml +++ b/electrum/gui/qml/components/wizard/WCBIP39Refine.qml @@ -43,11 +43,24 @@ WizardComponent { function validate() { valid = false + validationtext.text = '' + var p = isMultisig ? getMultisigScriptTypePurposeDict() : getScriptTypePurposeDict() if (!scripttypegroup.checkedButton.scripttype in p) return if (!bitcoin.verifyDerivationPath(derivationpathtext.text)) return + + if (isMultisig && cosigner) { + apply() + if (wiz.hasDuplicateMasterKeys(wizard_data)) { + validationtext.text = qsTr('Error: duplicate master public key') + return + } else if (wiz.hasHeterogeneousMasterKeys(wizard_data)) { + validationtext.text = qsTr('Error: master public key types do not match') + return + } + } valid = true } @@ -148,6 +161,13 @@ WizardComponent { onTextChanged: validate() } + InfoTextArea { + id: validationtext + Layout.fillWidth: true + visible: text + iconStyle: InfoTextArea.IconStyle.Error + } + Pane { Layout.alignment: Qt.AlignHCenter Layout.topMargin: constants.paddingLarge @@ -199,6 +219,7 @@ WizardComponent { participants = wizard_data['multisig_participants'] if ('multisig_current_cosigner' in wizard_data) cosigner = wizard_data['multisig_current_cosigner'] + validate() } } } diff --git a/electrum/gui/qml/components/wizard/WCHaveSeed.qml b/electrum/gui/qml/components/wizard/WCHaveSeed.qml index 29229641e..c8fa5c797 100644 --- a/electrum/gui/qml/components/wizard/WCHaveSeed.qml +++ b/electrum/gui/qml/components/wizard/WCHaveSeed.qml @@ -64,13 +64,18 @@ WizardComponent { valid = validSeed return } else { - apply() - if (wiz.hasDuplicateMasterKeys(wizard_data)) { - validationtext.text = qsTr('Error: duplicate master public key') - return - } else if (wiz.hasHeterogeneousMasterKeys(wizard_data)) { - validationtext.text = qsTr('Error: master public key types do not match') - return + // bip39 validate after derivation path is known + if (seed_variant_cb.currentValue == 'electrum') { + apply() + if (wiz.hasDuplicateMasterKeys(wizard_data)) { + validationtext.text = qsTr('Error: duplicate master public key') + return + } else if (wiz.hasHeterogeneousMasterKeys(wizard_data)) { + validationtext.text = qsTr('Error: master public key types do not match') + return + } else { + valid = true + } } else { valid = true } @@ -165,6 +170,7 @@ WizardComponent { InfoTextArea { id: infotext + visible: !cosigner Layout.fillWidth: true Layout.columnSpan: 2 Layout.bottomMargin: constants.paddingLarge @@ -214,7 +220,6 @@ WizardComponent { Bitcoin { id: bitcoin onSeedTypeChanged: seedtext.indicatorText = bitcoin.seedType - onValidationMessageChanged: validationtext.text = validationMessage } function startValidationTimer() { diff --git a/electrum/gui/qml/qewizard.py b/electrum/gui/qml/qewizard.py index 43d0108ce..55486e644 100644 --- a/electrum/gui/qml/qewizard.py +++ b/electrum/gui/qml/qewizard.py @@ -60,7 +60,6 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): 'bip39_refine': { 'gui': 'WCBIP39Refine' }, 'have_master_key': { 'gui': 'WCHaveMasterKey' }, 'multisig': { 'gui': 'WCMultisig' }, - # 'multisig_show_masterpubkey': { 'gui': 'WCShowMasterPubkey' }, 'multisig_cosigner_keystore': { 'gui': 'WCCosignerKeystore' }, 'multisig_cosigner_key': { 'gui': 'WCHaveMasterKey' }, 'multisig_cosigner_seed': { 'gui': 'WCHaveSeed' }, @@ -117,6 +116,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): self._logger.error(f"createStorage errored: {e!r}") self.createError.emit(str(e)) + class QEServerConnectWizard(ServerConnectWizard, QEAbstractWizard): def __init__(self, daemon, parent = None):