|
|
@ -265,6 +265,32 @@ Value importwallet(const Array& params, bool fHelp) |
|
|
|
boost::split(vstr, line, boost::is_any_of(" ")); |
|
|
|
if (vstr.size() < 2) |
|
|
|
continue; |
|
|
|
|
|
|
|
// Let's see if the address is a valid Zcash spending key
|
|
|
|
try { |
|
|
|
CZCSpendingKey spendingkey(vstr[0]); |
|
|
|
libzcash::SpendingKey key = spendingkey.Get(); |
|
|
|
libzcash::PaymentAddress addr = key.address(); |
|
|
|
if (pwalletMain->HaveSpendingKey(addr)) { |
|
|
|
LogPrintf("Skipping import of zaddr %s (key already present)\n", CZCPaymentAddress(addr).ToString()); |
|
|
|
continue; |
|
|
|
} |
|
|
|
int64_t nTime = DecodeDumpTime(vstr[1]); |
|
|
|
LogPrintf("Importing zaddr %s...\n", CZCPaymentAddress(addr).ToString()); |
|
|
|
if (!pwalletMain->AddZKey(key)) { |
|
|
|
// Something went wrong
|
|
|
|
fGood = false; |
|
|
|
continue; |
|
|
|
} |
|
|
|
// Successfully imported zaddr. Now import the metadata.
|
|
|
|
pwalletMain->mapZKeyMetadata[addr].nCreateTime = nTime; |
|
|
|
continue; |
|
|
|
} |
|
|
|
catch (...) { |
|
|
|
// Not a valid spending key, so carry on and see if it's a Bitcoin style address.
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CBitcoinSecret vchSecret; |
|
|
|
if (!vchSecret.SetString(vstr[0])) |
|
|
|
continue; |
|
|
@ -419,7 +445,124 @@ Value dumpwallet(const Array& params, bool fHelp) |
|
|
|
} |
|
|
|
} |
|
|
|
file << "\n"; |
|
|
|
|
|
|
|
// dump the zkeys
|
|
|
|
std::set<libzcash::PaymentAddress> addresses; |
|
|
|
pwalletMain->GetPaymentAddresses(addresses); |
|
|
|
file << "\n"; |
|
|
|
file << "# Zkeys\n"; |
|
|
|
file << "\n"; |
|
|
|
for (auto addr : addresses ) { |
|
|
|
libzcash::SpendingKey key; |
|
|
|
if (pwalletMain->GetSpendingKey(addr, key)) { |
|
|
|
std::string strTime = EncodeDumpTime(pwalletMain->mapZKeyMetadata[addr].nCreateTime); |
|
|
|
file << strprintf("%s %s # zaddr=%s\n", CZCSpendingKey(key).ToString(), strTime, CZCPaymentAddress(addr).ToString()); |
|
|
|
} |
|
|
|
} |
|
|
|
file << "\n"; |
|
|
|
|
|
|
|
file << "# End of dump\n"; |
|
|
|
file.close(); |
|
|
|
return Value::null; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Value z_importkey(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
if (!EnsureWalletIsAvailable(fHelp)) |
|
|
|
return Value::null; |
|
|
|
|
|
|
|
if (fHelp || params.size() < 1 || params.size() > 3) |
|
|
|
throw runtime_error( |
|
|
|
"z_importkey \"zkey\" ( \"label\" rescan )\n" |
|
|
|
"\nAdds a zkey (as returned by z_exportkey) to your wallet.\n" |
|
|
|
"\nArguments:\n" |
|
|
|
"1. \"zkey\" (string, required) The zkey (see z_exportkey)\n" |
|
|
|
"2. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" |
|
|
|
"\nNote: This call can take minutes to complete if rescan is true.\n" |
|
|
|
"\nExamples:\n" |
|
|
|
"\nExport a zkey\n" |
|
|
|
+ HelpExampleCli("z_exportkey", "\"myaddress\"") + |
|
|
|
"\nImport the zkey with rescan\n" |
|
|
|
+ HelpExampleCli("z_importkey", "\"mykey\"") + |
|
|
|
"\nImport using a label and without rescan\n" |
|
|
|
+ HelpExampleCli("z_importkey", "\"mykey\" \"testing\" false") + |
|
|
|
"\nAs a JSON-RPC call\n" |
|
|
|
+ HelpExampleRpc("z_importkey", "\"mykey\", \"testing\", false") |
|
|
|
); |
|
|
|
|
|
|
|
LOCK2(cs_main, pwalletMain->cs_wallet); |
|
|
|
|
|
|
|
EnsureWalletIsUnlocked(); |
|
|
|
|
|
|
|
// Whether to perform rescan after import
|
|
|
|
bool fRescan = true; |
|
|
|
if (params.size() > 1) |
|
|
|
fRescan = params[1].get_bool(); |
|
|
|
|
|
|
|
string strSecret = params[0].get_str(); |
|
|
|
CZCSpendingKey spendingkey(strSecret); |
|
|
|
auto key = spendingkey.Get(); |
|
|
|
auto addr = key.address(); |
|
|
|
|
|
|
|
{ |
|
|
|
pwalletMain->MarkDirty(); |
|
|
|
|
|
|
|
// Don't throw error in case a key is already there
|
|
|
|
if (pwalletMain->HaveSpendingKey(addr)) |
|
|
|
return Value::null; |
|
|
|
|
|
|
|
if (!pwalletMain-> AddZKey(key)) |
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet"); |
|
|
|
|
|
|
|
pwalletMain->mapZKeyMetadata[addr].nCreateTime = 1; |
|
|
|
|
|
|
|
// We want to scan for transactions and notes
|
|
|
|
if (fRescan) { |
|
|
|
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return Value::null; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Value z_exportkey(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
if (!EnsureWalletIsAvailable(fHelp)) |
|
|
|
return Value::null; |
|
|
|
|
|
|
|
if (fHelp || params.size() != 1) |
|
|
|
throw runtime_error( |
|
|
|
"z_exportkey \"zaddr\"\n" |
|
|
|
"\nReveals the zkey corresponding to 'zaddr'.\n" |
|
|
|
"Then the z_importkey can be used with this output\n" |
|
|
|
"\nArguments:\n" |
|
|
|
"1. \"zaddr\" (string, required) The zaddr for the private key\n" |
|
|
|
"\nResult:\n" |
|
|
|
"\"key\" (string) The private key\n" |
|
|
|
"\nExamples:\n" |
|
|
|
+ HelpExampleCli("z_exportkey", "\"myaddress\"") |
|
|
|
+ HelpExampleCli("z_importkey", "\"mykey\"") |
|
|
|
+ HelpExampleRpc("z_exportkey", "\"myaddress\"") |
|
|
|
); |
|
|
|
|
|
|
|
LOCK2(cs_main, pwalletMain->cs_wallet); |
|
|
|
|
|
|
|
EnsureWalletIsUnlocked(); |
|
|
|
|
|
|
|
string strAddress = params[0].get_str(); |
|
|
|
|
|
|
|
CZCPaymentAddress address(strAddress); |
|
|
|
auto addr = address.Get(); |
|
|
|
if (!pwalletMain->HaveSpendingKey(addr)) |
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private zkey for this zaddr"); |
|
|
|
|
|
|
|
libzcash::SpendingKey k; |
|
|
|
if (!pwalletMain->GetSpendingKey(addr, k)) |
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private zkey for this zaddr"); |
|
|
|
|
|
|
|
CZCSpendingKey spendingkey(k); |
|
|
|
return spendingkey.ToString(); |
|
|
|
} |
|
|
|
|
|
|
|