mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +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", 1 },
|
||||
{ "importprivkey", 2 },
|
||||
{ "importelectrumwallet", 1 },
|
||||
{ "importaddress", 2 },
|
||||
{ "importaddress", 3 },
|
||||
{ "importpubkey", 2 },
|
||||
|
@ -378,6 +378,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "wallet", "getwalletinfo", &getwalletinfo, false },
|
||||
{ "wallet", "importprivkey", &importprivkey, true },
|
||||
{ "wallet", "importwallet", &importwallet, true },
|
||||
{ "wallet", "importelectrumwallet", &importelectrumwallet, true },
|
||||
{ "wallet", "importaddress", &importaddress, true },
|
||||
{ "wallet", "importpubkey", &importpubkey, 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 dumpwallet(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 setgenerate(const UniValue& params, bool fHelp);
|
||||
|
@ -409,6 +409,140 @@ UniValue importwallet(const UniValue& params, bool fHelp)
|
||||
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)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
|
Loading…
Reference in New Issue
Block a user