diff --git a/src/base58.cpp b/src/base58.cpp index 55b065cbe..fc57966fe 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -363,3 +363,18 @@ template bool CZCEncoding::Get() const; + +std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr) +{ + return CZCPaymentAddress(zaddr).ToString(); +} + +boost::optional DecodePaymentAddress(const std::string& str) +{ + CZCPaymentAddress addr(str); + try { + return addr.Get(); + } catch (const std::runtime_error&) { + return boost::none; + } +} diff --git a/src/base58.h b/src/base58.h index f30479214..135005442 100644 --- a/src/base58.h +++ b/src/base58.h @@ -179,4 +179,7 @@ CTxDestination DecodeDestination(const std::string& str); bool IsValidDestinationString(const std::string& str); bool IsValidDestinationString(const std::string& str, const CChainParams& params); +std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr); +boost::optional DecodePaymentAddress(const std::string& str); + #endif // BITCOIN_BASE58_H diff --git a/src/paymentdisclosure.cpp b/src/paymentdisclosure.cpp index a33b1c604..e9a193cae 100644 --- a/src/paymentdisclosure.cpp +++ b/src/paymentdisclosure.cpp @@ -7,7 +7,7 @@ std::string PaymentDisclosureInfo::ToString() const { return strprintf("PaymentDisclosureInfo(version=%d, esk=%s, joinSplitPrivKey=, address=%s)", - version, esk.ToString(), CZCPaymentAddress(zaddr).ToString()); + version, esk.ToString(), EncodePaymentAddress(zaddr)); } std::string PaymentDisclosure::ToString() const { @@ -17,7 +17,7 @@ std::string PaymentDisclosure::ToString() const { std::string PaymentDisclosurePayload::ToString() const { return strprintf("PaymentDisclosurePayload(version=%d, esk=%s, txid=%s, js=%d, n=%d, address=%s, message=%s)", - version, esk.ToString(), txid.ToString(), js, n, CZCPaymentAddress(zaddr).ToString(), message); + version, esk.ToString(), txid.ToString(), js, n, EncodePaymentAddress(zaddr), message); } PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const PaymentDisclosureKey &key, const PaymentDisclosureInfo &info, const std::string &message) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 1f863ae70..050e95370 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -235,27 +235,23 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp) LOCK(cs_main); #endif - bool isValid = false; bool isMine = false; std::string payingKey, transmissionKey; string strAddress = params[0].get_str(); - try { - CZCPaymentAddress address(strAddress); - libzcash::PaymentAddress addr = address.Get(); + auto isValid = DecodePaymentAddress(strAddress); + if (isValid) { + libzcash::PaymentAddress addr = *isValid; #ifdef ENABLE_WALLET isMine = pwalletMain->HaveSpendingKey(addr); #endif payingKey = addr.a_pk.GetHex(); transmissionKey = addr.pk_enc.GetHex(); - isValid = true; - } catch (std::runtime_error e) { - // address is invalid, nop here as isValid is false. } UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("isvalid", isValid)); + ret.push_back(Pair("isvalid", static_cast(isValid))); if (isValid) { ret.push_back(Pair("address", strAddress)); diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 6caaed391..829fd1377 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -203,15 +203,15 @@ BOOST_AUTO_TEST_CASE(zc_address_test) { auto addr = sk.address(); - CZCPaymentAddress paymentaddr(addr); - string addr_string = paymentaddr.ToString(); + std::string addr_string = EncodePaymentAddress(addr); BOOST_CHECK(addr_string[0] == 'z'); BOOST_CHECK(addr_string[1] == 'c'); - CZCPaymentAddress paymentaddr2(addr_string); + auto paymentaddr2 = DecodePaymentAddress(addr_string); + BOOST_ASSERT(static_cast(paymentaddr2)); - PaymentAddress addr2 = paymentaddr2.Get(); + PaymentAddress addr2 = *paymentaddr2; BOOST_CHECK(addr.a_pk == addr2.a_pk); BOOST_CHECK(addr.pk_enc == addr2.pk_enc); } diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index f4e892f8c..a6353c01c 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -386,7 +386,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) BOOST_CHECK(addrs.size()==0); // wallet should have one key - CZCPaymentAddress paymentAddress = pwalletMain->GenerateNewZKey(); + auto addr = pwalletMain->GenerateNewZKey(); pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==1); @@ -411,11 +411,10 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string())); - auto addr = paymentAddress.Get(); libzcash::SpendingKey key; BOOST_CHECK(pwalletMain->GetSpendingKey(addr, key)); - std::string s1 = paymentAddress.ToString(); + std::string s1 = EncodePaymentAddress(addr); std::string s2 = CZCSpendingKey(key).ToString(); // There's no way to really delete a private key so we will read in the @@ -459,7 +458,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) // create a random key locally auto testSpendingKey = libzcash::SpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); - std::string testAddr = CZCPaymentAddress(testPaymentAddress).ToString(); + std::string testAddr = EncodePaymentAddress(testPaymentAddress); std::string testKey = CZCSpendingKey(testSpendingKey).ToString(); // create test data using the random key @@ -498,8 +497,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) BOOST_CHECK(addrs.size()==1); // check that we have the spending key for the address - CZCPaymentAddress address(testAddr); - auto addr = address.Get(); + auto addr = *DecodePaymentAddress(testAddr); BOOST_CHECK(pwalletMain->HaveSpendingKey(addr)); // Verify the spending key is the same as the test data @@ -546,7 +544,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // create a random key locally auto testSpendingKey = libzcash::SpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); - std::string testAddr = CZCPaymentAddress(testPaymentAddress).ToString(); + std::string testAddr = EncodePaymentAddress(testPaymentAddress); std::string testKey = CZCSpendingKey(testSpendingKey).ToString(); BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testKey)); BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testAddr)); @@ -566,7 +564,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // Make new addresses for the set for (int i=0; iGenerateNewZKey()).ToString()); + myaddrs.insert(EncodePaymentAddress(pwalletMain->GenerateNewZKey())); } // Verify number of addresses stored in wallet is n1+n2 @@ -593,8 +591,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // Add one more address BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getnewaddress")); std::string newaddress = retValue.get_str(); - CZCPaymentAddress pa(newaddress); - auto newAddr = pa.Get(); + auto newAddr = *DecodePaymentAddress(newaddress); BOOST_CHECK(pwalletMain->HaveSpendingKey(newAddr)); // Check if too many args @@ -916,8 +913,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) std::vector v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format std::fill(v.begin(),v.end(), 'A'); std::string badmemo(v.begin(), v.end()); - CZCPaymentAddress pa = pwalletMain->GenerateNewZKey(); - std::string zaddr1 = pa.ToString(); + auto pa = pwalletMain->GenerateNewZKey(); + std::string zaddr1 = EncodePaymentAddress(pa); BOOST_CHECK_THROW(CallRPC(string("z_sendmany tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ ") + "[{\"address\":\"" + zaddr1 + "\", \"amount\":123.456}]"), runtime_error); @@ -952,7 +949,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) std::vector recipients = { SendManyRecipient("dummy",1.0, "") }; std::shared_ptr operation( new AsyncRPCOperation_sendmany(mtx, "INVALID", recipients, {}, 1) ); } catch (const UniValue& objError) { - BOOST_CHECK( find_error(objError, "payment address is invalid")); + BOOST_CHECK( find_error(objError, "Invalid from address")); } // Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix. @@ -960,7 +957,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) std::vector recipients = { SendManyRecipient("dummy",1.0, "") }; std::shared_ptr operation( new AsyncRPCOperation_sendmany(mtx, "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U", recipients, {}, 1) ); } catch (const UniValue& objError) { - BOOST_CHECK( find_error(objError, "payment address is for wrong network type")); + BOOST_CHECK( find_error(objError, "Invalid from address")); } // Note: The following will crash as a google test because AsyncRPCOperation_sendmany @@ -994,8 +991,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) // add keys manually BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress")); std::string taddr1 = retValue.get_str(); - CZCPaymentAddress pa = pwalletMain->GenerateNewZKey(); - std::string zaddr1 = pa.ToString(); + auto pa = pwalletMain->GenerateNewZKey(); + std::string zaddr1 = EncodePaymentAddress(pa); // there are no utxos to spend { @@ -1392,7 +1389,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters) std::vector inputs = { ShieldCoinbaseUTXO{uint256(),0,0} }; std::shared_ptr operation( new AsyncRPCOperation_shieldcoinbase(mtx, inputs, mainnetzaddr, 1) ); } catch (const UniValue& objError) { - BOOST_CHECK( find_error(objError, "payment address is for wrong network type")); + BOOST_CHECK( find_error(objError, "Invalid to address")); } } @@ -1417,8 +1414,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals) mapArgs["-mempooltxinputlimit"] = "1"; // Add keys manually - CZCPaymentAddress pa = pwalletMain->GenerateNewZKey(); - std::string zaddr = pa.ToString(); + auto pa = pwalletMain->GenerateNewZKey(); + std::string zaddr = EncodePaymentAddress(pa); // Supply 2 inputs when mempool limit is 1 { @@ -1542,8 +1539,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters) std::vector v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format std::fill(v.begin(),v.end(), 'A'); std::string badmemo(v.begin(), v.end()); - CZCPaymentAddress pa = pwalletMain->GenerateNewZKey(); - std::string zaddr1 = pa.ToString(); + auto pa = pwalletMain->GenerateNewZKey(); + std::string zaddr1 = EncodePaymentAddress(pa); BOOST_CHECK_THROW(CallRPC(string("z_mergetoaddress [\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] ") + zaddr1 + " 0.0001 100 100 " + badmemo), runtime_error); @@ -1590,7 +1587,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters) std::shared_ptr operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, mainnetzaddr, 1) ); BOOST_FAIL("Should have caused an error"); } catch (const UniValue& objError) { - BOOST_CHECK( find_error(objError, "payment address is for wrong network type")); + BOOST_CHECK( find_error(objError, "Invalid recipient address")); } } @@ -1613,8 +1610,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals) // Add keys manually BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress")); MergeToAddressRecipient taddr1(retValue.get_str(), ""); - CZCPaymentAddress pa = pwalletMain->GenerateNewZKey(); - MergeToAddressRecipient zaddr1(pa.ToString(), "DEADBEEF"); + auto pa = pwalletMain->GenerateNewZKey(); + MergeToAddressRecipient zaddr1(EncodePaymentAddress(pa), "DEADBEEF"); // Supply 2 inputs when mempool limit is 1 { diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 916ad862b..7ac680186 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -78,14 +78,12 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress( isToZaddr_ = false; if (!isToTaddr_) { - CZCPaymentAddress address(std::get<0>(recipient)); - try { - PaymentAddress addr = address.Get(); - + auto address = DecodePaymentAddress(std::get<0>(recipient)); + if (address) { isToZaddr_ = true; - toPaymentAddress_ = addr; - } catch (const std::runtime_error& e) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what()); + toPaymentAddress_ = *address; + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address"); } } @@ -857,8 +855,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - CZCPaymentAddress address(zaddr); - LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString()); + LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); } // !!! Payment disclosure END diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index ba9f566f6..b6d30a4b1 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -79,9 +79,9 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( isfromzaddr_ = false; if (!isfromtaddr_) { - CZCPaymentAddress address(fromAddress); - try { - PaymentAddress addr = address.Get(); + auto address = DecodePaymentAddress(fromAddress); + if (address) { + PaymentAddress addr = *address; // We don't need to lock on the wallet as spending key related methods are thread-safe SpendingKey key; @@ -92,8 +92,8 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( isfromzaddr_ = true; frompaymentaddress_ = addr; spendingkey_ = key; - } catch (const std::runtime_error& e) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what()); + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address"); } } @@ -467,7 +467,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { std::string hexMemo = std::get<2>(smr); zOutputsDeque.pop_front(); - PaymentAddress pa = CZCPaymentAddress(address).Get(); + PaymentAddress pa = *DecodePaymentAddress(address); JSOutput jso = JSOutput(pa, value); if (hexMemo.size() > 0) { jso.memo = get_memo_from_hex_string(hexMemo); @@ -726,7 +726,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { assert(value==0); info.vjsout.push_back(JSOutput()); // dummy output while we accumulate funds into a change note for vpub_new } else { - PaymentAddress pa = CZCPaymentAddress(address).Get(); + PaymentAddress pa = *DecodePaymentAddress(address); JSOutput jso = JSOutput(pa, value); if (hexMemo.size() > 0) { jso.memo = get_memo_from_hex_string(hexMemo); @@ -1080,8 +1080,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - CZCPaymentAddress address(zaddr); - LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString()); + LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); } // !!! Payment disclosure END diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 45d9321dd..69bde8526 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -71,11 +71,11 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( } // Check the destination address is valid for this network i.e. not testnet being used on mainnet - CZCPaymentAddress address(toAddress); - try { - tozaddr_ = address.Get(); - } catch (const std::runtime_error& e) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what()); + auto address = DecodePaymentAddress(toAddress); + if (address) { + tozaddr_ = *address; + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid to address"); } // Log the context info @@ -451,8 +451,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - CZCPaymentAddress address(zaddr); - LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString()); + LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); } // !!! Payment disclosure END diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp index b40479e87..474656474 100644 --- a/src/wallet/gtest/test_wallet_zkeys.cpp +++ b/src/wallet/gtest/test_wallet_zkeys.cpp @@ -25,12 +25,11 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) { ASSERT_EQ(0, addrs.size()); // wallet should have one key - CZCPaymentAddress paymentAddress = wallet.GenerateNewZKey(); + auto addr = wallet.GenerateNewZKey(); wallet.GetPaymentAddresses(addrs); ASSERT_EQ(1, addrs.size()); // verify wallet has spending key for the address - auto addr = paymentAddress.Get(); ASSERT_TRUE(wallet.HaveSpendingKey(addr)); // manually add new spending key to wallet @@ -289,22 +288,22 @@ TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) { ASSERT_EQ(2, addrs.size()); // check we have entries for our payment addresses - ASSERT_TRUE(addrs.count(paymentAddress.Get())); - ASSERT_TRUE(addrs.count(paymentAddress2.Get())); + ASSERT_TRUE(addrs.count(paymentAddress)); + ASSERT_TRUE(addrs.count(paymentAddress2)); // spending key is crypted, so we can't extract valid payment address libzcash::SpendingKey keyOut; - wallet2.GetSpendingKey(paymentAddress.Get(), keyOut); - ASSERT_FALSE(paymentAddress.Get() == keyOut.address()); + wallet2.GetSpendingKey(paymentAddress, keyOut); + ASSERT_FALSE(paymentAddress == keyOut.address()); // unlock wallet to get spending keys and verify payment addresses wallet2.Unlock(strWalletPass); - wallet2.GetSpendingKey(paymentAddress.Get(), keyOut); - ASSERT_EQ(paymentAddress.Get(), keyOut.address()); + wallet2.GetSpendingKey(paymentAddress, keyOut); + ASSERT_EQ(paymentAddress, keyOut.address()); - wallet2.GetSpendingKey(paymentAddress2.Get(), keyOut); - ASSERT_EQ(paymentAddress2.Get(), keyOut.address()); + wallet2.GetSpendingKey(paymentAddress2, keyOut); + ASSERT_EQ(paymentAddress2, keyOut.address()); ECC_Stop(); } diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index d4f87ab39..7ca6086ae 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -254,11 +254,8 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) // Check the payment address is valid PaymentAddress zaddr = pd.payload.zaddr; - CZCPaymentAddress address; - if (!address.Set(zaddr)) { - errs.push_back("Payment disclosure refers to an invalid payment address"); - } else { - o.push_back(Pair("paymentAddress", address.ToString())); + { + o.push_back(Pair("paymentAddress", EncodePaymentAddress(zaddr))); try { // Decrypt the note to get value and memo field diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index c29972fc1..9b5d35072 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -300,11 +300,11 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys libzcash::SpendingKey key = spendingkey.Get(); libzcash::PaymentAddress addr = key.address(); if (pwalletMain->HaveSpendingKey(addr)) { - LogPrint("zrpc", "Skipping import of zaddr %s (key already present)\n", CZCPaymentAddress(addr).ToString()); + LogPrint("zrpc", "Skipping import of zaddr %s (key already present)\n", EncodePaymentAddress(addr)); continue; } int64_t nTime = DecodeDumpTime(vstr[1]); - LogPrint("zrpc", "Importing zaddr %s...\n", CZCPaymentAddress(addr).ToString()); + LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr)); if (!pwalletMain->AddZKey(key)) { // Something went wrong fGood = false; @@ -536,7 +536,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, CZCPaymentAddress(addr).ToString()); + file << strprintf("%s %s # zaddr=%s\n", CZCSpendingKey(key).ToString(), strTime, EncodePaymentAddress(addr)); } } file << "\n"; @@ -760,8 +760,11 @@ UniValue z_exportkey(const UniValue& params, bool fHelp) string strAddress = params[0].get_str(); - CZCPaymentAddress address(strAddress); - auto addr = address.Get(); + auto address = DecodePaymentAddress(strAddress); + if (!address) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); + } + auto addr = *address; libzcash::SpendingKey k; if (!pwalletMain->GetSpendingKey(addr, k)) @@ -796,8 +799,11 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp) string strAddress = params[0].get_str(); - CZCPaymentAddress address(strAddress); - auto addr = address.Get(); + auto address = DecodePaymentAddress(strAddress); + if (!address) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); + } + auto addr = *address; libzcash::ViewingKey vk; if (!pwalletMain->GetViewingKey(addr, vk)) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5de71c2c6..ca6c216e6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2521,14 +2521,14 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string"); } string address = o.get_str(); - try { - CZCPaymentAddress zaddr(address); - libzcash::PaymentAddress addr = zaddr.Get(); + auto zaddr = DecodePaymentAddress(address); + if (zaddr) { + libzcash::PaymentAddress addr = *zaddr; if (!fIncludeWatchonly && !pwalletMain->HaveSpendingKey(addr)) { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address); } zaddrs.insert(addr); - } catch (const std::runtime_error&) { + } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid zaddr: ") + address); } @@ -2555,7 +2555,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) obj.push_back(Pair("jsoutindex", (int)entry.jsop.n)); obj.push_back(Pair("confirmations", entry.nHeight)); obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(entry.address))); - obj.push_back(Pair("address", CZCPaymentAddress(entry.address).ToString())); + obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); obj.push_back(Pair("memo", HexStr(data))); @@ -2945,11 +2945,13 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) } for (const string& name_ : outputs.getKeys()) { - CZCPaymentAddress pubaddr(name_); - PaymentAddress addrTo = pubaddr.Get(); + auto addrTo = DecodePaymentAddress(name_); + if (!addrTo) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address."); + } CAmount nAmount = AmountFromValue(outputs[name_]); - vjsout.push_back(JSOutput(addrTo, nAmount)); + vjsout.push_back(JSOutput(*addrTo, nAmount)); } while (vjsout.size() < ZC_NUM_JS_OUTPUTS) { @@ -3059,12 +3061,11 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp) auto addr = k.address(); auto viewing_key = k.viewing_key(); - CZCPaymentAddress pubaddr(addr); CZCSpendingKey spendingkey(k); CZCViewingKey viewingkey(viewing_key); UniValue result(UniValue::VOBJ); - result.push_back(Pair("zcaddress", pubaddr.ToString())); + result.push_back(Pair("zcaddress", EncodePaymentAddress(addr))); result.push_back(Pair("zcsecretkey", spendingkey.ToString())); result.push_back(Pair("zcviewingkey", viewingkey.ToString())); return result; @@ -3092,9 +3093,8 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - CZCPaymentAddress pubaddr = pwalletMain->GenerateNewZKey(); - std::string result = pubaddr.ToString(); - return result; + auto zaddr = pwalletMain->GenerateNewZKey(); + return EncodePaymentAddress(zaddr); } @@ -3131,7 +3131,7 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp) pwalletMain->GetPaymentAddresses(addresses); for (auto addr : addresses ) { if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) { - ret.push_back(CZCPaymentAddress(addr).ToString()); + ret.push_back(EncodePaymentAddress(addr)); } } return ret; @@ -3228,15 +3228,12 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) // Check that the from address is valid. auto fromaddress = params[0].get_str(); - libzcash::PaymentAddress zaddr; - CZCPaymentAddress address(fromaddress); - try { - zaddr = address.Get(); - } catch (const std::runtime_error&) { + auto zaddr = DecodePaymentAddress(fromaddress); + if (!zaddr) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr."); } - if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) { + if (!(pwalletMain->HaveSpendingKey(*zaddr) || pwalletMain->HaveViewingKey(*zaddr))) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found."); } @@ -3301,12 +3298,11 @@ UniValue z_getbalance(const UniValue& params, bool fHelp) fromTaddr = IsValidDestination(taddr); libzcash::PaymentAddress zaddr; if (!fromTaddr) { - CZCPaymentAddress address(fromaddress); - try { - zaddr = address.Get(); - } catch (const std::runtime_error&) { + auto res = DecodePaymentAddress(fromaddress); + if (!res) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr."); } + zaddr = *res; if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found."); } @@ -3537,13 +3533,12 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) fromTaddr = IsValidDestination(taddr); libzcash::PaymentAddress zaddr; if (!fromTaddr) { - CZCPaymentAddress address(fromaddress); - try { - zaddr = address.Get(); - } catch (const std::runtime_error&) { + auto res = DecodePaymentAddress(fromaddress); + if (!res) { // invalid throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr."); } + zaddr = *res; } // Check that we have the spending key @@ -3581,11 +3576,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) bool isZaddr = false; CTxDestination taddr = DecodeDestination(address); if (!IsValidDestination(taddr)) { - try { - CZCPaymentAddress zaddr(address); - zaddr.Get(); + if (DecodePaymentAddress(address)) { isZaddr = true; - } catch (const std::runtime_error&) { + } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address ); } } @@ -3777,10 +3770,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) // Validate the destination address auto destaddress = params[1].get_str(); - try { - CZCPaymentAddress pa(destaddress); - libzcash::PaymentAddress zaddr = pa.Get(); - } catch (const std::runtime_error&) { + if (!DecodePaymentAddress(destaddress)) { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); } @@ -4021,13 +4011,13 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) taddrs.insert(taddr); } } else { - try { - CZCPaymentAddress zaddr(address); + auto zaddr = DecodePaymentAddress(address); + if (zaddr) { // Ignore listed z-addrs if we are using all of them if (!(useAny || useAnyNote)) { - zaddrs.insert(zaddr.Get()); + zaddrs.insert(*zaddr); } - } catch (const std::runtime_error&) { + } else { throw JSONRPCError( RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + address); @@ -4045,11 +4035,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) bool isToZaddr = false; CTxDestination taddr = DecodeDestination(destaddress); if (!IsValidDestination(taddr)) { - try { - CZCPaymentAddress zaddr(destaddress); - zaddr.Get(); + if (DecodePaymentAddress(destaddress)) { isToZaddr = true; - } catch (const std::runtime_error&) { + } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9aa4c4918..044313a18 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -80,7 +80,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const } // Generate a new spending key and return its public payment address -CZCPaymentAddress CWallet::GenerateNewZKey() +libzcash::PaymentAddress CWallet::GenerateNewZKey() { AssertLockHeld(cs_wallet); // mapZKeyMetadata auto k = SpendingKey::random(); @@ -94,10 +94,9 @@ CZCPaymentAddress CWallet::GenerateNewZKey() int64_t nCreationTime = GetTime(); mapZKeyMetadata[addr] = CKeyMetadata(nCreationTime); - CZCPaymentAddress pubaddr(addr); if (!AddZKey(k)) throw std::runtime_error("CWallet::GenerateNewZKey(): AddZKey failed"); - return pubaddr; + return addr; } // Add spending key to keystore and persist to disk @@ -3718,7 +3717,7 @@ void CWallet::GetFilteredNotes(std::vector & outEntri std::set filterAddresses; if (address.length() > 0) { - filterAddresses.insert(CZCPaymentAddress(address).Get()); + filterAddresses.insert(*DecodePaymentAddress(address)); } GetFilteredNotes(outEntries, filterAddresses, minDepth, ignoreSpent, ignoreUnspendable); @@ -3781,7 +3780,7 @@ void CWallet::GetFilteredNotes( ZCNoteDecryption decryptor; if (!GetNoteDecryptor(pa, decryptor)) { // Note decryptors are created when the wallet is loaded, so it should always exist - throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", CZCPaymentAddress(pa).ToString())); + throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa))); } // determine amount of funds in the note @@ -3798,10 +3797,10 @@ void CWallet::GetFilteredNotes( } catch (const note_decryption_failed &err) { // Couldn't decrypt with this spending key - throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", CZCPaymentAddress(pa).ToString())); + throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa))); } catch (const std::exception &exc) { // Unexpected failure - throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", CZCPaymentAddress(pa).ToString(), exc.what())); + throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what())); } } } @@ -3857,7 +3856,7 @@ void CWallet::GetUnspentFilteredNotes( ZCNoteDecryption decryptor; if (!GetNoteDecryptor(pa, decryptor)) { // Note decryptors are created when the wallet is loaded, so it should always exist - throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", CZCPaymentAddress(pa).ToString())); + throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa))); } // determine amount of funds in the note @@ -3874,10 +3873,10 @@ void CWallet::GetUnspentFilteredNotes( } catch (const note_decryption_failed &err) { // Couldn't decrypt with this spending key - throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", CZCPaymentAddress(pa).ToString())); + throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa))); } catch (const std::exception &exc) { // Unexpected failure - throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", CZCPaymentAddress(pa).ToString(), exc.what())); + throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what())); } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 08f22f97e..a9b8bc7e1 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -960,7 +960,7 @@ public: * ZKeys */ //! Generates a new zaddr - CZCPaymentAddress GenerateNewZKey(); + libzcash::PaymentAddress GenerateNewZKey(); //! Adds spending key to the store, and saves it to disk bool AddZKey(const libzcash::SpendingKey &key); //! Adds spending key to the store, without saving it to disk (used by LoadWallet)