Browse Source

Allow importing of ethersale wallets in CLI.

Fixes #2606.
cl-refactor
Gav Wood 10 years ago
parent
commit
6ee25c93d6
  1. 40
      alethzero/MainWin.cpp
  2. 13
      eth/main.cpp
  3. 19
      ethkey/KeyAux.h
  4. 35
      libethcore/KeyManager.cpp
  5. 3
      libethcore/KeyManager.h

40
alethzero/MainWin.cpp

@ -1017,46 +1017,18 @@ void Main::on_claimPresale_triggered()
QString s = QFileDialog::getOpenFileName(this, "Claim Account Contents", QDir::homePath(), "JSON Files (*.json);;All Files (*)"); QString s = QFileDialog::getOpenFileName(this, "Claim Account Contents", QDir::homePath(), "JSON Files (*.json);;All Files (*)");
try try
{ {
js::mValue val; KeyPair k = m_keyManager.presaleSecret(dev::contentsString(s.toStdString()), [&](bool){ return QInputDialog::getText(this, "Enter Password", "Enter the wallet's passphrase", QLineEdit::Password).toStdString(); });
json_spirit::read_string(asString(dev::contents(s.toStdString())), val); cnote << k.address();
auto obj = val.get_obj(); if (!m_keyManager.hasAccount(k.address()))
if (obj["encseed"].type() == js::str_type) ethereum()->submitTransaction(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_beneficiary, {}, c_txGas, gasPrice());
{
auto encseed = fromHex(obj["encseed"].get_str());
KeyPair k;
for (bool gotit = false; !gotit;)
{
gotit = true;
k = KeyPair::fromEncryptedSeed(&encseed, QInputDialog::getText(this, "Enter Password", "Enter the wallet's passphrase", QLineEdit::Password).toStdString());
if (obj["ethaddr"].type() == js::str_type)
{
Address a(obj["ethaddr"].get_str());
Address b = k.address();
if (a != b)
{
if (QMessageBox::warning(this, "Password Wrong", "Could not import the secret key: the password you gave appears to be wrong.", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
else
gotit = false;
}
}
}
cnote << k.address();
if (!m_keyManager.hasAccount(k.address()))
ethereum()->submitTransaction(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_beneficiary, {}, c_txGas, gasPrice());
else
QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account.");
}
else else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("encseed type is not js::str_type") ); QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account.");
} }
catch (dev::eth::PasswordUnknown&) {}
catch (...) catch (...)
{ {
cerr << "Unhandled exception!" << endl << cerr << "Unhandled exception!" << endl <<
boost::current_exception_diagnostic_information(); boost::current_exception_diagnostic_information();
QMessageBox::warning(this, "Key File Invalid", "Could not find secret key definition. This is probably not an Ethereum key file."); QMessageBox::warning(this, "Key File Invalid", "Could not find secret key definition. This is probably not an Ethereum key file.");
} }
} }

13
eth/main.cpp

@ -140,6 +140,7 @@ void help()
<< " -R,--rebuild Rebuild the blockchain from the existing database." << endl << " -R,--rebuild Rebuild the blockchain from the existing database." << endl
<< " --rescue Attempt to rescue a corrupt database." << endl << " --rescue Attempt to rescue a corrupt database." << endl
<< endl << endl
<< " --import-presale <file> Import a presale key; you'll need to type the password to this." << endl
<< " -s,--import-secret <secret> Import a secret key into the key store and use as the default." << endl << " -s,--import-secret <secret> Import a secret key into the key store and use as the default." << endl
<< " -S,--import-session-secret <secret> Import a secret key into the key store and use as the default for this session only." << endl << " -S,--import-session-secret <secret> Import a secret key into the key store and use as the default for this session only." << endl
<< " --sign-key <address> Sign all transactions with the key of the given address." << endl << " --sign-key <address> Sign all transactions with the key of the given address." << endl
@ -226,6 +227,12 @@ void version()
exit(0); exit(0);
} }
void importPresale(KeyManager& _km, string const& _file, function<string()> _pass)
{
KeyPair k = _km.presaleSecret(contentsString(_file), [&](bool){ return _pass(); });
_km.import(k.secret(), "Presale wallet" + _file + " (insecure)");
}
Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250"); Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250");
string pretty(h160 _a, dev::eth::State const& _st) string pretty(h160 _a, dev::eth::State const& _st)
{ {
@ -1120,6 +1127,7 @@ int main(int argc, char** argv)
Address signingKey; Address signingKey;
Address sessionKey; Address sessionKey;
Address beneficiary = signingKey; Address beneficiary = signingKey;
strings presaleImports;
/// Structured logging params /// Structured logging params
bool structuredLogging = false; bool structuredLogging = false;
@ -1434,6 +1442,8 @@ int main(int argc, char** argv)
pinning = true; pinning = true;
else if (arg == "--hermit") else if (arg == "--hermit")
pinning = disableDiscovery = true; pinning = disableDiscovery = true;
else if (arg == "--import-presale" && i + 1 < argc)
presaleImports.push_back(argv[++i]);
else if (arg == "-f" || arg == "--force-mining") else if (arg == "-f" || arg == "--force-mining")
forceMining = true; forceMining = true;
else if (arg == "--old-interactive") else if (arg == "--old-interactive")
@ -1711,6 +1721,9 @@ int main(int argc, char** argv)
keyManager.create(masterPassword); keyManager.create(masterPassword);
} }
for (auto const& presale: presaleImports)
importPresale(keyManager, presale, [&](){ return getPassword("Enter your wallet password for " + presale + ": "); });
for (auto const& s: toImport) for (auto const& s: toImport)
{ {
keyManager.import(s, "Imported key (UNSAFE)"); keyManager.import(s, "Imported key (UNSAFE)");

19
ethkey/KeyAux.h

@ -104,6 +104,7 @@ public:
New, New,
Import, Import,
ImportWithAddress, ImportWithAddress,
ImportPresale,
Export, Export,
Recode, Recode,
Kill, Kill,
@ -143,7 +144,7 @@ public:
m_mode = OperationMode::DecodeTx; m_mode = OperationMode::DecodeTx;
else if (arg == "--import-bare") else if (arg == "--import-bare")
m_mode = OperationMode::ImportBare; m_mode = OperationMode::ImportBare;
else if (arg == "--list-bare") else if (arg == "-l" || arg == "--list-bare")
m_mode = OperationMode::ListBare; m_mode = OperationMode::ListBare;
else if (arg == "--export-bare") else if (arg == "--export-bare")
m_mode = OperationMode::ExportBare; m_mode = OperationMode::ExportBare;
@ -168,7 +169,13 @@ public:
m_inputs = strings(1, argv[++i]); m_inputs = strings(1, argv[++i]);
m_name = argv[++i]; m_name = argv[++i];
} }
else if ((arg == "-i" || arg == "--import-with-address") && i + 3 < argc) else if (arg == "--import-presale" && i + 2 < argc)
{
m_mode = OperationMode::ImportPresale;
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if (arg == "--import-with-address" && i + 3 < argc)
{ {
m_mode = OperationMode::ImportWithAddress; m_mode = OperationMode::ImportWithAddress;
m_inputs = strings(1, argv[++i]); m_inputs = strings(1, argv[++i]);
@ -477,6 +484,13 @@ public:
cout << " UUID: " << toUUID(u) << endl; cout << " UUID: " << toUUID(u) << endl;
break; break;
} }
case OperationMode::ImportPresale:
{
std::string pw;
KeyPair k = wallet.presaleSecret(contentsString(m_inputs[0]), [&](bool){ return (pw = getPassword("Enter the password for the presale key: ")); });
wallet.import(k.secret(), m_name, pw, "Same password as used for presale key");
break;
}
case OperationMode::List: case OperationMode::List:
{ {
vector<u128> bare; vector<u128> bare;
@ -530,6 +544,7 @@ public:
<< " -l,--list List all keys available in wallet." << endl << " -l,--list List all keys available in wallet." << endl
<< " -n,--new <name> Create a new key with given name and add it in the wallet." << endl << " -n,--new <name> Create a new key with given name and add it in the wallet." << endl
<< " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl << " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl
<< " --import-presale <file> <name> Import a presale wallet into a key with the given name." << endl
<< " --import-with-address [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl << " --import-with-address [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl << " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl << " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl

35
libethcore/KeyManager.cpp

@ -23,12 +23,14 @@
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <test/JsonSpiritHeaders.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace eth; using namespace eth;
namespace js = json_spirit;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
KeyManager::KeyManager(string const& _keysFile, string const& _secretsPath): KeyManager::KeyManager(string const& _keysFile, string const& _secretsPath):
@ -216,6 +218,39 @@ void KeyManager::kill(Address const& _a)
write(m_keysFile); write(m_keysFile);
} }
KeyPair KeyManager::presaleSecret(std::string const& _json, function<string(bool)> const& _password)
{
js::mValue val;
json_spirit::read_string(_json, val);
auto obj = val.get_obj();
string p = _password(true);
if (obj["encseed"].type() == js::str_type)
{
auto encseed = fromHex(obj["encseed"].get_str());
KeyPair k;
for (bool gotit = false; !gotit;)
{
gotit = true;
k = KeyPair::fromEncryptedSeed(&encseed, p);
if (obj["ethaddr"].type() == js::str_type)
{
Address a(obj["ethaddr"].get_str());
Address b = k.address();
if (a != b)
{
if ((p = _password(false)).empty())
BOOST_THROW_EXCEPTION(PasswordUnknown());
else
gotit = false;
}
}
}
return k;
}
else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("encseed type is not js::str_type"));
}
Addresses KeyManager::accounts() const Addresses KeyManager::accounts() const
{ {
Addresses ret; Addresses ret;

3
libethcore/KeyManager.h

@ -123,6 +123,9 @@ public:
static std::string defaultPath() { return getDataDir("ethereum") + "/keys.info"; } static std::string defaultPath() { return getDataDir("ethereum") + "/keys.info"; }
/// Extracts the secret key from the presale wallet.
KeyPair presaleSecret(std::string const& _json, std::function<std::string(bool)> const& _password);
private: private:
std::string getPassword(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow) const; std::string getPassword(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow) const;
std::string getPassword(h256 const& _passHash, std::function<std::string()> const& _pass = DontKnowThrow) const; std::string getPassword(h256 const& _passHash, std::function<std::string()> const& _pass = DontKnowThrow) const;

Loading…
Cancel
Save