From 472f75bc2dba93ce38856deb1a77eabb52e2495a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 24 Apr 2018 15:16:27 +0100 Subject: [PATCH] Introduce wrappers around CZCSpendingKey --- src/base58.cpp | 15 +++++++++++++++ src/base58.h | 3 +++ src/test/key_tests.cpp | 8 ++++---- src/test/rpc_wallet_tests.cpp | 11 +++++------ src/wallet/rpcdump.cpp | 23 ++++++++++++----------- src/wallet/rpcwallet.cpp | 17 +++++++++++------ 6 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index fc57966fe..90982cf95 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -378,3 +378,18 @@ boost::optional DecodePaymentAddress(const std::string return boost::none; } } + +std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey) +{ + return CZCSpendingKey(zkey).ToString(); +} + +boost::optional DecodeSpendingKey(const std::string& str) +{ + CZCSpendingKey key(str); + try { + return key.Get(); + } catch (const std::runtime_error&) { + return boost::none; + } +} diff --git a/src/base58.h b/src/base58.h index 135005442..da9b7dd1e 100644 --- a/src/base58.h +++ b/src/base58.h @@ -182,4 +182,7 @@ bool IsValidDestinationString(const std::string& str, const CChainParams& params std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr); boost::optional DecodePaymentAddress(const std::string& str); +std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey); +boost::optional DecodeSpendingKey(const std::string& str); + #endif // BITCOIN_BASE58_H diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 829fd1377..6292e7eb1 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -190,14 +190,14 @@ BOOST_AUTO_TEST_CASE(zc_address_test) for (size_t i = 0; i < 1000; i++) { auto sk = SpendingKey::random(); { - CZCSpendingKey spendingkey(sk); - string sk_string = spendingkey.ToString(); + string sk_string = EncodeSpendingKey(sk); BOOST_CHECK(sk_string[0] == 'S'); BOOST_CHECK(sk_string[1] == 'K'); - CZCSpendingKey spendingkey2(sk_string); - SpendingKey sk2 = spendingkey2.Get(); + auto spendingkey2 = DecodeSpendingKey(sk_string); + BOOST_ASSERT(static_cast(spendingkey2)); + SpendingKey sk2 = *spendingkey2; BOOST_CHECK(sk.inner() == sk2.inner()); } { diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index a6353c01c..3c657a3db 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -415,7 +415,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) BOOST_CHECK(pwalletMain->GetSpendingKey(addr, key)); std::string s1 = EncodePaymentAddress(addr); - std::string s2 = CZCSpendingKey(key).ToString(); + std::string s2 = EncodeSpendingKey(key); // There's no way to really delete a private key so we will read in the // exported wallet file and search for the spending key and payment address. @@ -459,7 +459,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) auto testSpendingKey = libzcash::SpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); std::string testAddr = EncodePaymentAddress(testPaymentAddress); - std::string testKey = CZCSpendingKey(testSpendingKey).ToString(); + std::string testKey = EncodeSpendingKey(testSpendingKey); // create test data using the random key std::string format_str = "# Wallet dump created by Zcash v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n" @@ -503,8 +503,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) // Verify the spending key is the same as the test data libzcash::SpendingKey k; BOOST_CHECK(pwalletMain->GetSpendingKey(addr, k)); - CZCSpendingKey spendingkey(k); - BOOST_CHECK_EQUAL(testKey, spendingkey.ToString()); + BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k)); } @@ -528,7 +527,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // error if invalid args auto sk = libzcash::SpendingKey::random(); - std::string prefix = std::string("z_importkey ") + CZCSpendingKey(sk).ToString() + " yes "; + std::string prefix = std::string("z_importkey ") + EncodeSpendingKey(sk) + " yes "; BOOST_CHECK_THROW(CallRPC(prefix + "-1"), runtime_error); BOOST_CHECK_THROW(CallRPC(prefix + "2147483647"), runtime_error); // allowed, but > height of active chain tip BOOST_CHECK_THROW(CallRPC(prefix + "2147483648"), runtime_error); // not allowed, > int32 used for nHeight @@ -545,7 +544,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) auto testSpendingKey = libzcash::SpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); std::string testAddr = EncodePaymentAddress(testPaymentAddress); - std::string testKey = CZCSpendingKey(testSpendingKey).ToString(); + std::string testKey = EncodeSpendingKey(testSpendingKey); BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testKey)); BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testAddr)); BOOST_CHECK_EQUAL(retValue.get_str(), testKey); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 9b5d35072..e9354d179 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -295,9 +295,9 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys // Let's see if the address is a valid Zcash spending key if (fImportZKeys) { - try { - CZCSpendingKey spendingkey(vstr[0]); - libzcash::SpendingKey key = spendingkey.Get(); + auto spendingkey = DecodeSpendingKey(vstr[0]); + if (spendingkey) { + libzcash::SpendingKey key = *spendingkey; libzcash::PaymentAddress addr = key.address(); if (pwalletMain->HaveSpendingKey(addr)) { LogPrint("zrpc", "Skipping import of zaddr %s (key already present)\n", EncodePaymentAddress(addr)); @@ -313,9 +313,8 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys // Successfully imported zaddr. Now import the metadata. pwalletMain->mapZKeyMetadata[addr].nCreateTime = nTime; continue; - } - catch (const std::runtime_error &e) { - LogPrint("zrpc","Importing detected an error: %s\n", e.what()); + } else { + LogPrint("zrpc", "Importing detected an error: invalid spending key. Trying as a transparent key...\n"); // Not a valid spending key, so carry on and see if it's a Zcash style address. } } @@ -536,7 +535,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) 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, EncodePaymentAddress(addr)); + file << strprintf("%s %s # zaddr=%s\n", EncodeSpendingKey(key), strTime, EncodePaymentAddress(addr)); } } file << "\n"; @@ -614,8 +613,11 @@ UniValue z_importkey(const UniValue& params, bool fHelp) } string strSecret = params[0].get_str(); - CZCSpendingKey spendingkey(strSecret); - auto key = spendingkey.Get(); + auto spendingkey = DecodeSpendingKey(strSecret); + if (!spendingkey) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); + } + auto key = *spendingkey; auto addr = key.address(); { @@ -770,8 +772,7 @@ UniValue z_exportkey(const UniValue& params, bool fHelp) 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(); + return EncodeSpendingKey(k); } UniValue z_exportviewingkey(const UniValue& params, bool fHelp) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ca6c216e6..7f433bb3c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2792,8 +2792,11 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp) LOCK(cs_main); - CZCSpendingKey spendingkey(params[0].get_str()); - SpendingKey k = spendingkey.Get(); + auto spendingkey = DecodeSpendingKey(params[0].get_str()); + if (!spendingkey) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); + } + SpendingKey k = *spendingkey; uint256 epk; unsigned char nonce; @@ -2903,8 +2906,11 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) std::vector commitments; for (const string& name_ : inputs.getKeys()) { - CZCSpendingKey spendingkey(inputs[name_].get_str()); - SpendingKey k = spendingkey.Get(); + auto spendingkey = DecodeSpendingKey(inputs[name_].get_str()); + if (!spendingkey) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); + } + SpendingKey k = *spendingkey; keys.push_back(k); @@ -3061,12 +3067,11 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp) auto addr = k.address(); auto viewing_key = k.viewing_key(); - CZCSpendingKey spendingkey(k); CZCViewingKey viewingkey(viewing_key); UniValue result(UniValue::VOBJ); result.push_back(Pair("zcaddress", EncodePaymentAddress(addr))); - result.push_back(Pair("zcsecretkey", spendingkey.ToString())); + result.push_back(Pair("zcsecretkey", EncodeSpendingKey(k))); result.push_back(Pair("zcviewingkey", viewingkey.ToString())); return result; }