Browse Source

Add RPC methods for exporting/importing viewing keys

metaverse
Jack Grigg 7 years ago
parent
commit
e85b33a52e
No known key found for this signature in database GPG Key ID: 665DBCD284F7DAFF
  1. 6
      contrib/zcash-cli.bash-completion
  2. 1
      src/rpcclient.cpp
  3. 2
      src/rpcserver.cpp
  4. 2
      src/rpcserver.h
  5. 125
      src/wallet/rpcdump.cpp

6
contrib/zcash-cli.bash-completion

@ -82,10 +82,14 @@ _zcash_cli() {
COMPREPLY=( $( compgen -W "add remove" -- "$cur" ) )
return 0
;;
fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction|z_importkey)
fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction)
COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
return 0
;;
z_importkey|z_importviewingkey)
COMPREPLY=( $( compgen -W "yes no whenkeyisnew" -- "$cur" ) )
return 0
;;
move|setaccount)
_zcash_accounts
return 0

1
src/rpcclient.cpp

@ -114,6 +114,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "z_getoperationstatus", 0},
{ "z_getoperationresult", 0},
{ "z_importkey", 2 },
{ "z_importviewingkey", 2 },
{ "z_getpaymentdisclosure", 1},
{ "z_getpaymentdisclosure", 2}
};

2
src/rpcserver.cpp

@ -395,6 +395,8 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "z_listaddresses", &z_listaddresses, true },
{ "wallet", "z_exportkey", &z_exportkey, true },
{ "wallet", "z_importkey", &z_importkey, true },
{ "wallet", "z_exportviewingkey", &z_exportviewingkey, true },
{ "wallet", "z_importviewingkey", &z_importviewingkey, true },
{ "wallet", "z_exportwallet", &z_exportwallet, true },
{ "wallet", "z_importwallet", &z_importwallet, true },

2
src/rpcserver.h

@ -279,6 +279,8 @@ extern UniValue getblocksubsidy(const UniValue& params, bool fHelp);
extern UniValue z_exportkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_importkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_importviewingkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_listaddresses(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_exportwallet(const UniValue& params, bool fHelp); // in rpcdump.cpp

125
src/wallet/rpcdump.cpp

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

Loading…
Cancel
Save