Add RPC methods for exporting/importing viewing keys
This commit is contained in:
@@ -644,6 +644,91 @@ UniValue z_importkey(const UniValue& params, bool fHelp)
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
UniValue z_importviewingkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"z_importviewingkey \"vkey\" ( rescan startHeight )\n"
|
||||
"\nAdds a viewing key (as returned by z_exportviewingkey) to your wallet.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"vkey\" (string, required) The viewing key (see z_exportviewingkey)\n"
|
||||
"2. rescan (string, optional, default=\"whenkeyisnew\") Rescan the wallet for transactions - can be \"yes\", \"no\" or \"whenkeyisnew\"\n"
|
||||
"3. startHeight (numeric, optional, default=0) Block height to start rescan from\n"
|
||||
"\nNote: This call can take minutes to complete if rescan is true.\n"
|
||||
"\nExamples:\n"
|
||||
"\nImport a viewing key\n"
|
||||
+ HelpExampleCli("z_importviewingkey", "\"vkey\"") +
|
||||
"\nImport the viewing key without rescan\n"
|
||||
+ HelpExampleCli("z_importviewingkey", "\"vkey\", no") +
|
||||
"\nImport the viewing key with partial rescan\n"
|
||||
+ HelpExampleCli("z_importviewingkey", "\"vkey\" whenkeyisnew 30000") +
|
||||
"\nRe-import the viewing key with longer partial rescan\n"
|
||||
+ HelpExampleCli("z_importviewingkey", "\"vkey\" yes 20000") +
|
||||
"\nAs a JSON-RPC call\n"
|
||||
+ HelpExampleRpc("z_importviewingkey", "\"vkey\", \"no\"")
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
// Whether to perform rescan after import
|
||||
bool fRescan = true;
|
||||
bool fIgnoreExistingKey = true;
|
||||
if (params.size() > 1) {
|
||||
auto rescan = params[1].get_str();
|
||||
if (rescan.compare("whenkeyisnew") != 0) {
|
||||
fIgnoreExistingKey = false;
|
||||
if (rescan.compare("no") == 0) {
|
||||
fRescan = false;
|
||||
} else if (rescan.compare("yes") != 0) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"rescan must be \"yes\", \"no\" or \"whenkeyisnew\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Height to rescan from
|
||||
int nRescanHeight = 0;
|
||||
if (params.size() > 2)
|
||||
nRescanHeight = params[2].get_int();
|
||||
if (nRescanHeight < 0 || nRescanHeight > chainActive.Height()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
}
|
||||
|
||||
string strVKey = params[0].get_str();
|
||||
CZCViewingKey viewingkey(strVKey);
|
||||
auto vkey = viewingkey.Get();
|
||||
auto addr = vkey.address();
|
||||
|
||||
{
|
||||
if (pwalletMain->HaveSpendingKey(addr))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this viewing key");
|
||||
|
||||
// Don't throw error in case a viewing key is already there
|
||||
if (pwalletMain->HaveViewingKey(addr)) {
|
||||
if (fIgnoreExistingKey) {
|
||||
return NullUniValue;
|
||||
}
|
||||
} else {
|
||||
pwalletMain->MarkDirty();
|
||||
|
||||
if (!pwalletMain->AddViewingKey(vkey))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet");
|
||||
}
|
||||
|
||||
// We want to scan for transactions and notes
|
||||
if (fRescan) {
|
||||
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], true);
|
||||
}
|
||||
}
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
UniValue z_exportkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
@@ -682,3 +767,43 @@ UniValue z_exportkey(const UniValue& params, bool fHelp)
|
||||
return spendingkey.ToString();
|
||||
}
|
||||
|
||||
UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"z_exportviewingkey \"zaddr\"\n"
|
||||
"\nReveals the viewing key corresponding to 'zaddr'.\n"
|
||||
"Then the z_importviewingkey can be used with this output\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"zaddr\" (string, required) The zaddr for the viewing key\n"
|
||||
"\nResult:\n"
|
||||
"\"vkey\" (string) The viewing key\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("z_exportviewingkey", "\"myaddress\"")
|
||||
+ HelpExampleRpc("z_exportviewingkey", "\"myaddress\"")
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
string strAddress = params[0].get_str();
|
||||
|
||||
CZCPaymentAddress address(strAddress);
|
||||
auto addr = address.Get();
|
||||
|
||||
libzcash::ViewingKey vk;
|
||||
if (!pwalletMain->GetViewingKey(addr, vk)) {
|
||||
libzcash::SpendingKey k;
|
||||
if (!pwalletMain->GetSpendingKey(addr, k)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private key or viewing key for this zaddr");
|
||||
}
|
||||
vk = k.viewing_key();
|
||||
}
|
||||
|
||||
CZCViewingKey viewingkey(vk);
|
||||
return viewingkey.ToString();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user