Implemented RPC calls z_importkey, z_exportkey, z_getnewaddress.
Modified RPC calls dumpwallet and importwallet to include spending keys.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user