qml: multisig create_storage
This commit is contained in:
@@ -26,8 +26,10 @@ WizardComponent {
|
|||||||
valid = false
|
valid = false
|
||||||
validationtext.text = ''
|
validationtext.text = ''
|
||||||
|
|
||||||
if (!bitcoin.verifyMasterKey(key.trim(), wizard_data['wallet_type']))
|
if (!bitcoin.verifyMasterKey(key.trim(), wizard_data['wallet_type'])) {
|
||||||
|
validationtext.text = qsTr('Error: invalid master key')
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if (cosigner) {
|
if (cosigner) {
|
||||||
apply()
|
apply()
|
||||||
@@ -57,6 +59,7 @@ WizardComponent {
|
|||||||
id: masterkey_ta
|
id: masterkey_ta
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.minimumHeight: 80
|
Layout.minimumHeight: 80
|
||||||
|
font.family: FixedFont
|
||||||
focus: true
|
focus: true
|
||||||
wrapMode: TextEdit.WrapAnywhere
|
wrapMode: TextEdit.WrapAnywhere
|
||||||
onTextChanged: verifyMasterKey(text)
|
onTextChanged: verifyMasterKey(text)
|
||||||
@@ -67,8 +70,7 @@ WizardComponent {
|
|||||||
icon.height: constants.iconSizeMedium
|
icon.height: constants.iconSizeMedium
|
||||||
icon.width: constants.iconSizeMedium
|
icon.width: constants.iconSizeMedium
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (verifyMasterKey(AppController.clipboardToText()))
|
masterkey_ta.text = AppController.clipboardToText()
|
||||||
masterkey_ta.text = AppController.clipboardToText()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToolButton {
|
ToolButton {
|
||||||
@@ -79,8 +81,7 @@ WizardComponent {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
var scan = qrscan.createObject(root)
|
var scan = qrscan.createObject(root)
|
||||||
scan.onFound.connect(function() {
|
scan.onFound.connect(function() {
|
||||||
if (verifyMasterKey(scan.scanData))
|
masterkey_ta.text = scan.scanData
|
||||||
masterkey_ta.text = scan.scanData
|
|
||||||
scan.destroy()
|
scan.destroy()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,12 @@ WizardComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (wizard_data['seed_variant'] == 'electrum') {
|
if ('master_key' in wizard_data) {
|
||||||
masterPubkey = bitcoin.getMultisigMasterPubkey(wizard_data['seed_variant'], wizard_data['seed'], wizard_data['seed_extra_words'])
|
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 {
|
} else {
|
||||||
masterPubkey = bitcoin.getMultisigMasterPubkey(wizard_data['seed_variant'], wizard_data['seed'], wizard_data['seed_extra_words'], wizard_data['derivation_path'])
|
masterPubkey = bitcoin.getMultisigMasterPubkeyFromSeed(wizard_data['seed_variant'], wizard_data['seed'], wizard_data['seed_extra_words'], wizard_data['derivation_path'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ class QEBitcoin(QObject):
|
|||||||
if t1 not in ['standard', 'p2wsh', 'p2wsh-p2sh']:
|
if t1 not in ['standard', 'p2wsh', 'p2wsh-p2sh']:
|
||||||
self.validationMessage = '%s: %s' % (_('Wrong key type'), t1)
|
self.validationMessage = '%s: %s' % (_('Wrong key type'), t1)
|
||||||
return False
|
return False
|
||||||
# TODO: check against other cosigner xpubs
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
raise Exception(f'Unsupported wallet type: {wallet_type}')
|
raise Exception(f'Unsupported wallet type: {wallet_type}')
|
||||||
@@ -167,9 +166,13 @@ class QEBitcoin(QObject):
|
|||||||
def isPrivateKeyList(self, csv: str):
|
def isPrivateKeyList(self, csv: str):
|
||||||
return keystore.is_private_key_list(csv)
|
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, result=str)
|
||||||
@pyqtSlot(str, str, str, str, result=str)
|
@pyqtSlot(str, str, str, str, result=str)
|
||||||
def getMultisigMasterPubkey(self, seed_variant, seed, seed_extra_words, derivation_path = None):
|
def getMultisigMasterPubkeyFromSeed(self, seed_variant, seed, seed_extra_words, derivation_path = None):
|
||||||
if seed_variant == 'electrum':
|
if seed_variant == 'electrum':
|
||||||
k = keystore.from_seed(seed, seed_extra_words, True)
|
k = keystore.from_seed(seed, seed_extra_words, True)
|
||||||
elif seed_variant == 'bip39':
|
elif seed_variant == 'bip39':
|
||||||
|
|||||||
@@ -256,16 +256,17 @@ class NewWalletWizard(AbstractWizard):
|
|||||||
|
|
||||||
# if last cosigner uses bip39 seed, we still need derivation path
|
# if last cosigner uses bip39 seed, we still need derivation path
|
||||||
current_cosigner_data = wizard_data['multisig_cosigner_data'][str(wizard_data['multisig_current_cosigner'])]
|
current_cosigner_data = wizard_data['multisig_cosigner_data'][str(wizard_data['multisig_current_cosigner'])]
|
||||||
if current_cosigner_data['seed_type'] == 'bip39' and 'derivation_path' not in current_cosigner_data:
|
if 'seed_type' in current_cosigner_data and current_cosigner_data['seed_type'] == 'bip39' and 'derivation_path' not in current_cosigner_data:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def has_duplicate_keys(self, wizard_data):
|
def has_duplicate_keys(self, wizard_data):
|
||||||
xpubs = []
|
xpubs = []
|
||||||
xpubs.append(self.xpub_from_data(wizard_data))
|
xpubs.append(self.keystore_from_data(wizard_data).get_master_public_key())
|
||||||
for cosigner in wizard_data['multisig_cosigner_data']:
|
for cosigner in wizard_data['multisig_cosigner_data']:
|
||||||
xpubs.append(self.xpub_from_data(wizard_data['multisig_cosigner_data'][cosigner]))
|
data = wizard_data['multisig_cosigner_data'][cosigner]
|
||||||
|
xpubs.append(self.keystore_from_data(data).get_master_public_key())
|
||||||
|
|
||||||
while len(xpubs):
|
while len(xpubs):
|
||||||
xpub = xpubs.pop()
|
xpub = xpubs.pop()
|
||||||
@@ -274,21 +275,18 @@ class NewWalletWizard(AbstractWizard):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def xpub_from_data(self, data):
|
def keystore_from_data(self, data):
|
||||||
if 'seed' in data:
|
if 'seed' in data:
|
||||||
if data['seed_variant'] == 'electrum':
|
if data['seed_variant'] == 'electrum':
|
||||||
k = keystore.from_seed(data['seed'], data['seed_extra_words'], True)
|
return keystore.from_seed(data['seed'], data['seed_extra_words'], True)
|
||||||
elif data['seed_variant'] == 'bip39':
|
elif data['seed_variant'] == 'bip39':
|
||||||
root_seed = keystore.bip39_to_seed(data['seed'], data['seed_extra_words'])
|
root_seed = keystore.bip39_to_seed(data['seed'], data['seed_extra_words'])
|
||||||
derivation = normalize_bip32_derivation(data['derivation_path'])
|
derivation = normalize_bip32_derivation(data['derivation_path'])
|
||||||
k = keystore.from_bip43_rootseed(root_seed, derivation, xtype='p2wsh')
|
return keystore.from_bip43_rootseed(root_seed, derivation, xtype='p2wsh')
|
||||||
else:
|
else:
|
||||||
raise Exception('Unsupported seed variant %s' % data['seed_variant'])
|
raise Exception('Unsupported seed variant %s' % data['seed_variant'])
|
||||||
|
|
||||||
return k.get_master_public_key()
|
|
||||||
elif 'master_key' in data:
|
elif 'master_key' in data:
|
||||||
k = keystore.from_master_key(data['master_key'])
|
return keystore.from_master_key(data['master_key'])
|
||||||
return k.get_master_public_key()
|
|
||||||
else:
|
else:
|
||||||
raise Exception('no seed or master_key in data')
|
raise Exception('no seed or master_key in data')
|
||||||
|
|
||||||
@@ -297,13 +295,13 @@ class NewWalletWizard(AbstractWizard):
|
|||||||
# override
|
# override
|
||||||
|
|
||||||
def create_storage(self, path, data):
|
def create_storage(self, path, data):
|
||||||
# only standard, 2fa and imported wallets for now
|
assert data['wallet_type'] in ['standard', '2fa', 'imported', 'multisig']
|
||||||
assert data['wallet_type'] in ['standard', '2fa', 'imported']
|
|
||||||
|
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
raise Exception('file already exists at path')
|
raise Exception('file already exists at path')
|
||||||
storage = WalletStorage(path)
|
storage = WalletStorage(path)
|
||||||
|
|
||||||
|
# TODO: refactor using self.keystore_from_data
|
||||||
k = None
|
k = None
|
||||||
if 'keystore_type' not in data:
|
if 'keystore_type' not in data:
|
||||||
assert data['wallet_type'] == 'imported'
|
assert data['wallet_type'] == 'imported'
|
||||||
@@ -339,8 +337,12 @@ class NewWalletWizard(AbstractWizard):
|
|||||||
has_xpub = isinstance(k, keystore.Xpub)
|
has_xpub = isinstance(k, keystore.Xpub)
|
||||||
assert has_xpub
|
assert has_xpub
|
||||||
t1 = xpub_type(k.xpub)
|
t1 = xpub_type(k.xpub)
|
||||||
if t1 not in ['standard', 'p2wpkh', 'p2wpkh-p2sh']:
|
if data['wallet_type'] == 'multisig':
|
||||||
raise Exception('wrong key type %s' % t1)
|
if t1 not in ['standard', 'p2wsh', 'p2wsh-p2sh']:
|
||||||
|
raise Exception('wrong key type %s' % t1)
|
||||||
|
else:
|
||||||
|
if t1 not in ['standard', 'p2wpkh', 'p2wpkh-p2sh']:
|
||||||
|
raise Exception('wrong key type %s' % t1)
|
||||||
else:
|
else:
|
||||||
raise Exception('unsupported/unknown keystore_type %s' % data['keystore_type'])
|
raise Exception('unsupported/unknown keystore_type %s' % data['keystore_type'])
|
||||||
|
|
||||||
@@ -369,6 +371,14 @@ class NewWalletWizard(AbstractWizard):
|
|||||||
db.put('x2/', data['x2/'])
|
db.put('x2/', data['x2/'])
|
||||||
db.put('x3/', data['x3/'])
|
db.put('x3/', data['x3/'])
|
||||||
db.put('use_trustedcoin', True)
|
db.put('use_trustedcoin', True)
|
||||||
|
elif data['wallet_type'] == 'multisig':
|
||||||
|
db.put('wallet_type', '%dof%d' % (data['multisig_signatures'],data['multisig_participants']))
|
||||||
|
db.put('x1/', k.dump())
|
||||||
|
for cosigner in data['multisig_cosigner_data']:
|
||||||
|
cosigner_keystore = self.keystore_from_data(data['multisig_cosigner_data'][cosigner])
|
||||||
|
if data['encrypt'] and cosigner_keystore.may_have_password():
|
||||||
|
cosigner_keystore.update_password(None, data['password'])
|
||||||
|
db.put(f'x{cosigner}/', cosigner_keystore.dump())
|
||||||
elif data['wallet_type'] == 'imported':
|
elif data['wallet_type'] == 'imported':
|
||||||
if k:
|
if k:
|
||||||
db.put('keystore', k.dump())
|
db.put('keystore', k.dump())
|
||||||
|
|||||||
Reference in New Issue
Block a user