Browse Source

implement bip39 seed to wallet

fix auto-upgrade wallet
patch-4
Sander van Grieken 3 years ago
parent
commit
e329c54162
  1. 4
      electrum/gui/qml/components/OpenWallet.qml
  2. 30
      electrum/gui/qml/components/Wallets.qml
  3. 44
      electrum/gui/qml/components/wizard/WCBIP39Refine.qml
  4. 4
      electrum/gui/qml/qebitcoin.py
  5. 5
      electrum/gui/qml/qewallet.py
  6. 50
      electrum/gui/qml/qewalletdb.py

4
electrum/gui/qml/components/OpenWallet.qml

@ -95,10 +95,6 @@ Pane {
Daemon.availableWallets.reload()
app.stack.pop()
}
onRequiresUpgradeChanged: {
if (requiresUpgrade)
wallet_db.doUpgrade()
}
onReadyChanged: {
if (ready) {
Daemon.load_wallet(Daemon.path, password.text)

30
electrum/gui/qml/components/Wallets.qml

@ -1,6 +1,7 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import org.electrum 1.0
@ -25,25 +26,25 @@ Pane {
columns: 4
Label { text: 'Wallet'; Layout.columnSpan: 2 }
Label { text: Daemon.walletName; Layout.columnSpan: 2 }
Label { text: Daemon.walletName; Layout.columnSpan: 2; color: Material.accentColor }
Label { text: 'derivation path (BIP32)'; visible: Daemon.currentWallet.isDeterministic; Layout.columnSpan: 2 }
Label { text: Daemon.currentWallet.derivationPath; visible: Daemon.currentWallet.isDeterministic; color: Material.accentColor; Layout.columnSpan: 2 }
Label { text: 'txinType' }
Label { text: Daemon.currentWallet.txinType }
Label { text: Daemon.currentWallet.txinType; color: Material.accentColor }
Label { text: 'is deterministic' }
Label { text: Daemon.currentWallet.isDeterministic }
Label { text: Daemon.currentWallet.isDeterministic; color: Material.accentColor }
Label { text: 'is watch only' }
Label { text: Daemon.currentWallet.isWatchOnly }
Label { text: Daemon.currentWallet.isWatchOnly; color: Material.accentColor }
Label { text: 'is Encrypted' }
Label { text: Daemon.currentWallet.isEncrypted }
Label { text: Daemon.currentWallet.isEncrypted; color: Material.accentColor }
Label { text: 'is Hardware' }
Label { text: Daemon.currentWallet.isHardware }
Label { text: 'derivation path (BIP32)'; visible: Daemon.currentWallet.isDeterministic }
Label { text: Daemon.currentWallet.derivationPath; visible: Daemon.currentWallet.isDeterministic }
Label { text: Daemon.currentWallet.isHardware; color: Material.accentColor }
}
}
// }
@ -75,16 +76,19 @@ Pane {
}
RowLayout {
x: 10
spacing: 10
width: parent.width - 20
width: parent.width
Image {
source: "../../kivy/theming/light/wallet.png"
id: walleticon
source: "../../icons/wallet.png"
fillMode: Image.PreserveAspectFit
Layout.preferredWidth: 32
Layout.preferredHeight: 32
}
Label {
font.pointSize: 11
font.pixelSize: 18
text: model.name
Layout.fillWidth: true
}

44
electrum/gui/qml/components/wizard/WCBIP39Refine.qml

@ -10,24 +10,36 @@ WizardComponent {
valid: false
onAccept: {
wizard_data['script_type'] = scripttypegroup.checkedButton.scripttype
wizard_data['derivation_path'] = derivationpathtext.text
}
function setDerivationPath() {
var addrtype = {
function getScriptTypePurposeDict() {
return {
'p2pkh': 44,
'p2wpkh-p2sh': 49,
'p2wpkh': 84
}
var nChain = Network.isTestNet ? 1 : 0
}
function validate() {
valid = false
if (!scripttypegroup.checkedButton.scripttype in getScriptTypePurposeDict())
return
if (!bitcoin.verify_derivation_path(derivationpathtext.text))
return
valid = true
}
function setDerivationPath() {
var p = getScriptTypePurposeDict()
derivationpathtext.text =
"m/" + addrtype[addresstypegroup.checkedButton.addresstype] + "'/"
"m/" + p[scripttypegroup.checkedButton.scripttype] + "'/"
+ (Network.isTestNet ? 1 : 0) + "'/0'"
}
ButtonGroup {
id: addresstypegroup
id: scripttypegroup
onCheckedButtonChanged: {
console.log('button changed: ' + checkedButton.addresstype)
setDerivationPath()
}
}
@ -50,18 +62,18 @@ WizardComponent {
}
Label { text: qsTr('Choose the type of addresses in your wallet.') }
RadioButton {
ButtonGroup.group: addresstypegroup
property string addresstype: 'p2pkh'
ButtonGroup.group: scripttypegroup
property string scripttype: 'p2pkh'
text: qsTr('legacy (p2pkh)')
}
RadioButton {
ButtonGroup.group: addresstypegroup
property string addresstype: 'p2wpkh-p2sh'
ButtonGroup.group: scripttypegroup
property string scripttype: 'p2wpkh-p2sh'
text: qsTr('wrapped segwit (p2wpkh-p2sh)')
}
RadioButton {
ButtonGroup.group: addresstypegroup
property string addresstype: 'p2wpkh'
ButtonGroup.group: scripttypegroup
property string scripttype: 'p2wpkh'
checked: true
text: qsTr('native segwit (p2wpkh)')
}
@ -73,8 +85,14 @@ WizardComponent {
id: derivationpathtext
Layout.fillWidth: true
placeholderText: qsTr('Derivation path')
onTextChanged: validate()
}
}
}
Bitcoin {
id: bitcoin
}
}

4
electrum/gui/qml/qebitcoin.py

@ -4,6 +4,7 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger
from electrum.keystore import bip39_is_checksum_valid
from electrum.bip32 import is_bip32_derivation
from electrum.slip39 import decode_mnemonic, Slip39Error
from electrum import mnemonic
@ -107,3 +108,6 @@ class QEBitcoin(QObject):
self._logger.debug('seed verified: ' + str(seed_valid))
@pyqtSlot(str, result=bool)
def verify_derivation_path(self, path):
return is_bip32_derivation(path)

5
electrum/gui/qml/qewallet.py

@ -175,7 +175,10 @@ class QEWallet(QObject):
@pyqtProperty('QString', notify=dataChanged)
def derivationPath(self):
return self.wallet.get_address_path_str(self.wallet.dummy_address())
keystores = self.wallet.get_keystores()
if len(keystores) > 1:
self._logger.debug('multiple keystores not supported yet')
return keystores[0].get_derivation_prefix()
balanceChanged = pyqtSignal()

50
electrum/gui/qml/qewalletdb.py

@ -5,6 +5,7 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import Logger, get_logger
from electrum.storage import WalletStorage, StorageEncryptionVersion
from electrum.wallet_db import WalletDB
from electrum.bip32 import normalize_bip32_derivation
from electrum.util import InvalidPassword
from electrum import keystore
@ -28,8 +29,6 @@ class QEWalletDB(QObject):
passwordChanged = pyqtSignal()
invalidPasswordChanged = pyqtSignal()
requiresSplitChanged = pyqtSignal()
requiresUpgradeChanged = pyqtSignal()
upgradingChanged = pyqtSignal()
splitFinished = pyqtSignal()
readyChanged = pyqtSignal()
createError = pyqtSignal([str], arguments=["error"])
@ -41,8 +40,6 @@ class QEWalletDB(QObject):
self._needsHWDevice = False
self._password = ''
self._requiresSplit = False
self._requiresUpgrade = False
self._upgrading = False
self._invalidPassword = False
self._storage = None
@ -115,14 +112,6 @@ class QEWalletDB(QObject):
def requiresSplit(self):
return self._requiresSplit
@pyqtProperty(bool, notify=requiresUpgradeChanged)
def requiresUpgrade(self):
return self._requiresUpgrade
@pyqtProperty(bool, notify=upgradingChanged)
def upgrading(self):
return self._upgrading
@pyqtProperty(bool, notify=invalidPasswordChanged)
def invalidPassword(self):
return self._invalidPassword
@ -142,23 +131,6 @@ class QEWalletDB(QObject):
self.splitFinished.emit()
@pyqtSlot()
def doUpgrade(self):
self._logger.warning('doUpgrade')
if not self._requiresUpgrade:
return
self._logger.warning('upgrading')
self._upgrading = True
self.upgradingChanged.emit()
self._db.upgrade()
self._db.write(self._storage)
self._upgrading = False
self.upgradingChanged.emit()
def load_storage(self):
self._storage = WalletStorage(self._path)
if not self._storage.file_exists():
@ -188,15 +160,15 @@ class QEWalletDB(QObject):
self._requiresSplit = True
self.requiresSplitChanged.emit()
return
if self._db.requires_upgrade():
self._logger.warning('requires upgrade')
self._requiresUpgrade = True
self.requiresUpgradeChanged.emit()
return
if self._db.get_action():
self._logger.warning('action pending. QML version doesn\'t support continuation of wizard')
return
if self._db.requires_upgrade():
self._logger.warning('wallet requires upgrade, upgrading')
self._db.upgrade()
self._db.write(self._storage)
self._ready = True
self.readyChanged.emit()
@ -212,7 +184,15 @@ class QEWalletDB(QObject):
raise Exception('file already exists at path')
storage = WalletStorage(path)
k = keystore.from_seed(data['seed'], data['seed_extra_words'], data['wallet_type'] == 'multisig')
if data['seed_type'] in ['old', 'standard', 'segwit']: #2fa, 2fa-segwit
self._logger.debug('creating keystore from electrum seed')
k = keystore.from_seed(data['seed'], data['seed_extra_words'], data['wallet_type'] == 'multisig')
elif data['seed_type'] == 'bip39':
self._logger.debug('creating keystore from bip39 seed')
root_seed = keystore.bip39_to_seed(data['seed'], data['seed_extra_words'])
derivation = normalize_bip32_derivation(data['derivation_path'])
script = data['script_type'] if data['script_type'] != 'p2pkh' else 'standard'
k = keystore.from_bip43_rootseed(root_seed, derivation, xtype=script)
if data['encrypt']:
storage.set_password(data['password'], enc_version=StorageEncryptionVersion.USER_PASSWORD)

Loading…
Cancel
Save