|
|
@ -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(); |
|
|
|
} |
|
|
|