mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
implement importelectrumwallet (#1377)
Imports keys from an Electrum wallet export file (.csv or .json)
This commit is contained in:
parent
fb3db0a57e
commit
c523205386
@ -99,6 +99,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "lockunspent", 0 },
|
{ "lockunspent", 0 },
|
||||||
{ "lockunspent", 1 },
|
{ "lockunspent", 1 },
|
||||||
{ "importprivkey", 2 },
|
{ "importprivkey", 2 },
|
||||||
|
{ "importelectrumwallet", 1 },
|
||||||
{ "importaddress", 2 },
|
{ "importaddress", 2 },
|
||||||
{ "importaddress", 3 },
|
{ "importaddress", 3 },
|
||||||
{ "importpubkey", 2 },
|
{ "importpubkey", 2 },
|
||||||
|
@ -378,6 +378,7 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "wallet", "getwalletinfo", &getwalletinfo, false },
|
{ "wallet", "getwalletinfo", &getwalletinfo, false },
|
||||||
{ "wallet", "importprivkey", &importprivkey, true },
|
{ "wallet", "importprivkey", &importprivkey, true },
|
||||||
{ "wallet", "importwallet", &importwallet, true },
|
{ "wallet", "importwallet", &importwallet, true },
|
||||||
|
{ "wallet", "importelectrumwallet", &importelectrumwallet, true },
|
||||||
{ "wallet", "importaddress", &importaddress, true },
|
{ "wallet", "importaddress", &importaddress, true },
|
||||||
{ "wallet", "importpubkey", &importpubkey, true },
|
{ "wallet", "importpubkey", &importpubkey, true },
|
||||||
{ "wallet", "keypoolrefill", &keypoolrefill, true },
|
{ "wallet", "keypoolrefill", &keypoolrefill, true },
|
||||||
|
@ -194,6 +194,7 @@ extern UniValue importaddress(const UniValue& params, bool fHelp);
|
|||||||
extern UniValue importpubkey(const UniValue& params, bool fHelp);
|
extern UniValue importpubkey(const UniValue& params, bool fHelp);
|
||||||
extern UniValue dumpwallet(const UniValue& params, bool fHelp);
|
extern UniValue dumpwallet(const UniValue& params, bool fHelp);
|
||||||
extern UniValue importwallet(const UniValue& params, bool fHelp);
|
extern UniValue importwallet(const UniValue& params, bool fHelp);
|
||||||
|
extern UniValue importelectrumwallet(const UniValue& params, bool fHelp);
|
||||||
|
|
||||||
extern UniValue getgenerate(const UniValue& params, bool fHelp); // in rpcmining.cpp
|
extern UniValue getgenerate(const UniValue& params, bool fHelp); // in rpcmining.cpp
|
||||||
extern UniValue setgenerate(const UniValue& params, bool fHelp);
|
extern UniValue setgenerate(const UniValue& params, bool fHelp);
|
||||||
|
@ -409,6 +409,140 @@ UniValue importwallet(const UniValue& params, bool fHelp)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue importelectrumwallet(const UniValue& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
|
return NullUniValue;
|
||||||
|
|
||||||
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
|
throw runtime_error(
|
||||||
|
"importelectrumwallet \"filename\" index\n"
|
||||||
|
"\nImports keys from an Electrum wallet export file (.csv or .json)\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"filename\" (string, required) The Electrum wallet export file, should be in csv or json format\n"
|
||||||
|
"2. index (numeric, optional, default=0) Rescan the wallet for transactions starting from this block index\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
"\nImport the wallet\n"
|
||||||
|
+ HelpExampleCli("importelectrumwallet", "\"test.csv\"")
|
||||||
|
+ HelpExampleCli("importelectrumwallet", "\"test.json\"") +
|
||||||
|
"\nImport using the json rpc call\n"
|
||||||
|
+ HelpExampleRpc("importelectrumwallet", "\"test.csv\"")
|
||||||
|
+ HelpExampleRpc("importelectrumwallet", "\"test.json\"")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (fPruneMode)
|
||||||
|
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
|
||||||
|
|
||||||
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
|
EnsureWalletIsUnlocked();
|
||||||
|
|
||||||
|
ifstream file;
|
||||||
|
std::string strFileName = params[0].get_str();
|
||||||
|
size_t nDotPos = strFileName.find_last_of(".");
|
||||||
|
if(nDotPos == string::npos)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "File has no extension, should be .json or .csv");
|
||||||
|
|
||||||
|
std::string strFileExt = strFileName.substr(nDotPos+1);
|
||||||
|
if(strFileExt != "json" && strFileExt != "csv")
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "File has wrong extension, should be .json or .csv");
|
||||||
|
|
||||||
|
file.open(strFileName.c_str(), std::ios::in | std::ios::ate);
|
||||||
|
if (!file.is_open())
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open Electrum wallet export file");
|
||||||
|
|
||||||
|
bool fGood = true;
|
||||||
|
|
||||||
|
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
|
||||||
|
file.seekg(0, file.beg);
|
||||||
|
|
||||||
|
pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
|
||||||
|
|
||||||
|
if(strFileExt == "csv") {
|
||||||
|
while (file.good()) {
|
||||||
|
pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
|
||||||
|
std::string line;
|
||||||
|
std::getline(file, line);
|
||||||
|
if (line.empty() || line == "address,private_key")
|
||||||
|
continue;
|
||||||
|
std::vector<std::string> vstr;
|
||||||
|
boost::split(vstr, line, boost::is_any_of(","));
|
||||||
|
if (vstr.size() < 2)
|
||||||
|
continue;
|
||||||
|
CBitcoinSecret vchSecret;
|
||||||
|
if (!vchSecret.SetString(vstr[1]))
|
||||||
|
continue;
|
||||||
|
CKey key = vchSecret.GetKey();
|
||||||
|
CPubKey pubkey = key.GetPubKey();
|
||||||
|
assert(key.VerifyPubKey(pubkey));
|
||||||
|
CKeyID keyid = pubkey.GetID();
|
||||||
|
if (pwalletMain->HaveKey(keyid)) {
|
||||||
|
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
|
||||||
|
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
|
||||||
|
fGood = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// json
|
||||||
|
char* buffer = new char [nFilesize];
|
||||||
|
file.read(buffer, nFilesize);
|
||||||
|
UniValue data(UniValue::VOBJ);
|
||||||
|
if(!data.read(buffer))
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot parse Electrum wallet export file");
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
std::vector<std::string> vKeys = data.getKeys();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < data.size(); i++) {
|
||||||
|
pwalletMain->ShowProgress("", std::max(1, std::min(99, int(i*100/data.size()))));
|
||||||
|
if(!data[vKeys[i]].isStr())
|
||||||
|
continue;
|
||||||
|
CBitcoinSecret vchSecret;
|
||||||
|
if (!vchSecret.SetString(data[vKeys[i]].get_str()))
|
||||||
|
continue;
|
||||||
|
CKey key = vchSecret.GetKey();
|
||||||
|
CPubKey pubkey = key.GetPubKey();
|
||||||
|
assert(key.VerifyPubKey(pubkey));
|
||||||
|
CKeyID keyid = pubkey.GetID();
|
||||||
|
if (pwalletMain->HaveKey(keyid)) {
|
||||||
|
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
|
||||||
|
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
|
||||||
|
fGood = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
|
||||||
|
|
||||||
|
// Whether to perform rescan after import
|
||||||
|
int nStartHeight = 0;
|
||||||
|
if (params.size() > 1)
|
||||||
|
nStartHeight = params[1].get_int();
|
||||||
|
if (chainActive.Height() < nStartHeight)
|
||||||
|
nStartHeight = chainActive.Height();
|
||||||
|
|
||||||
|
// Assume that electrum wallet was created at that block
|
||||||
|
int nTimeBegin = chainActive[nStartHeight]->GetBlockTime();
|
||||||
|
if (!pwalletMain->nTimeFirstKey || nTimeBegin < pwalletMain->nTimeFirstKey)
|
||||||
|
pwalletMain->nTimeFirstKey = nTimeBegin;
|
||||||
|
|
||||||
|
LogPrintf("Rescanning %i blocks\n", chainActive.Height() - nStartHeight + 1);
|
||||||
|
pwalletMain->ScanForWalletTransactions(chainActive[nStartHeight], true);
|
||||||
|
|
||||||
|
if (!fGood)
|
||||||
|
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
|
||||||
|
|
||||||
|
return NullUniValue;
|
||||||
|
}
|
||||||
|
|
||||||
UniValue dumpprivkey(const UniValue& params, bool fHelp)
|
UniValue dumpprivkey(const UniValue& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (!EnsureWalletIsAvailable(fHelp))
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
|
Loading…
Reference in New Issue
Block a user