|
|
@ -1132,21 +1132,22 @@ void MainWindow::doImport(QList<QString>* keys) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
DEBUG(" keys.size= " << keys->size() ); |
|
|
|
|
|
|
|
if (keys->isEmpty()) { |
|
|
|
delete keys; |
|
|
|
ui->statusBar->showMessage(tr("Private key import rescan finished")); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Pop the first key
|
|
|
|
QString key = keys->first(); |
|
|
|
keys->pop_front(); |
|
|
|
bool rescan = keys->isEmpty(); |
|
|
|
// Get the first key
|
|
|
|
QString key = keys->takeFirst(); |
|
|
|
|
|
|
|
if (key.startsWith("SK") || |
|
|
|
key.startsWith("secret")) { // Z key
|
|
|
|
bool rescan = false; |
|
|
|
if (Settings::getInstance()->isValidSaplingPrivateKey(key) ) { |
|
|
|
DEBUG("importing zaddr privkey with rescan=" << rescan); |
|
|
|
rpc->importZPrivKey(key, rescan, [=] (auto) { this->doImport(keys); }); |
|
|
|
} else { |
|
|
|
DEBUG("importing taddr privkey with rescan=" << rescan); |
|
|
|
rpc->importTPrivKey(key, rescan, [=] (auto) { this->doImport(keys); }); |
|
|
|
} |
|
|
|
} |
|
|
@ -1247,7 +1248,6 @@ void MainWindow::payHushURI(QString uri, QString myAddr) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::importPrivKey() { |
|
|
|
QDialog d(this); |
|
|
|
Ui_PrivKey pui; |
|
|
@ -1259,20 +1259,27 @@ void MainWindow::importPrivKey() { |
|
|
|
tr("Please paste your private keys here, one per line") % ".\n" % |
|
|
|
tr("The keys will be imported into your connected Hush node")); |
|
|
|
|
|
|
|
// if rescan is not checked, disable the rescan height input
|
|
|
|
QObject::connect(pui.chkrescan, &QCheckBox::stateChanged, [=](auto checked) { |
|
|
|
pui.rescanfrom->setEnabled(checked); |
|
|
|
}); |
|
|
|
|
|
|
|
if (d.exec() == QDialog::Accepted && !pui.privKeyTxt->toPlainText().trimmed().isEmpty()) { |
|
|
|
auto rawkeys = pui.privKeyTxt->toPlainText().trimmed().split("\n"); |
|
|
|
|
|
|
|
QList<QString> keysTmp; |
|
|
|
// Filter out all the empty keys.
|
|
|
|
// Filter out all the empty keys and comment lines
|
|
|
|
std::copy_if(rawkeys.begin(), rawkeys.end(), std::back_inserter(keysTmp), [=] (auto key) { |
|
|
|
return !key.startsWith("#") && !key.trimmed().isEmpty(); |
|
|
|
}); |
|
|
|
|
|
|
|
auto keys = new QList<QString>(); |
|
|
|
// ignore anything after the first space of a line, such as if you paste a line from z_exportwallet output
|
|
|
|
std::transform(keysTmp.begin(), keysTmp.end(), std::back_inserter(*keys), [=](auto key) { |
|
|
|
return key.trimmed().split(" ")[0]; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Special case.
|
|
|
|
// Sometimes, when importing from a paperwallet or such, the key is split by newlines, and might have
|
|
|
|
// been pasted like that. So check to see if the whole thing is one big private key
|
|
|
@ -1283,13 +1290,52 @@ void MainWindow::importPrivKey() { |
|
|
|
delete multiline; |
|
|
|
} |
|
|
|
|
|
|
|
// Start the import. The function takes ownership of keys
|
|
|
|
QTimer::singleShot(1, [=]() {doImport(keys);}); |
|
|
|
// Finally, validate all keys, removing any which are invalid
|
|
|
|
auto keysValidated = new QList<QString>(); |
|
|
|
auto settings = Settings::getInstance(); |
|
|
|
std::copy_if(keys->begin(), keys->end(), std::back_inserter(*keysValidated), [=] (auto key) { |
|
|
|
bool isValid = settings->isValidSaplingPrivateKey(key) || settings->isValidTransparentPrivateKey(key); |
|
|
|
if (!isValid) { DEBUG("privkey " << key << " is not valid"); } |
|
|
|
return isValid; |
|
|
|
}); |
|
|
|
DEBUG("found " << keysValidated->size() << " valid privkeys"); |
|
|
|
|
|
|
|
|
|
|
|
bool rescan = pui.chkrescan->isChecked(); |
|
|
|
|
|
|
|
// avoid giving invalid data to RPCs and a rescan if there were no valid privkeys
|
|
|
|
if(keysValidated->size() == 0) { |
|
|
|
QMessageBox::information(this, "No valid keys", |
|
|
|
tr("No valid private keys were found, please make sure you copy and pasted correctly"), |
|
|
|
QMessageBox::Ok); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Start the import. The function takes ownership of keysValidated
|
|
|
|
QTimer::singleShot(1, [=]() { |
|
|
|
// we import all keys without rescanning and then finally decide if we will rescan once
|
|
|
|
doImport(keysValidated); |
|
|
|
|
|
|
|
if (rescan) { |
|
|
|
//TODO: verify rescanfrom is a valid integer
|
|
|
|
rpc->rescan(pui.rescanfrom->text().trimmed().toInt() , [=] (QJsonValue response){ |
|
|
|
qDebug() << __func__ << ":rescanning from height " << pui.rescanfrom->text().toInt() << " finished" << response; |
|
|
|
ui->statusBar->showMessage(tr("Rescanning finished"), 5000); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
// Show the dialog that keys will be imported.
|
|
|
|
QMessageBox::information(this, |
|
|
|
"Imported", tr("The keys were imported! It may take several minutes to rescan the blockchain. Until then, functionality may be limited"), |
|
|
|
if(rescan) { |
|
|
|
QMessageBox::information(this, "Imported", |
|
|
|
tr("The keys were imported! It may take several hours to rescan the blockchain. Until then, functionality may be limited"), |
|
|
|
QMessageBox::Ok); |
|
|
|
} else { |
|
|
|
QMessageBox::information(this, "Imported", |
|
|
|
tr("The keys were imported! You chose to not rescan, so funds in that address will not show up in your wallet yet."), |
|
|
|
QMessageBox::Ok); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|