Implemented RPC calls z_importkey, z_exportkey, z_getnewaddress.

Modified RPC calls dumpwallet and importwallet to include spending keys.
This commit is contained in:
Simon
2016-08-09 23:15:22 -07:00
parent 2833fb14af
commit c1c4594371
9 changed files with 300 additions and 3 deletions

View File

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