From e7ca4eb3c31e1382784bf8089a7b3d8a2e0bfc35 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 13 Aug 2018 13:20:07 +0100 Subject: [PATCH 1/3] test: gtest for Sapling encoding and decoding --- src/Makefile.gtest.include | 1 + src/gtest/test_keys.cpp | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/gtest/test_keys.cpp diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index e089d5783..65e067b81 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -23,6 +23,7 @@ zcash_gtest_SOURCES += \ gtest/test_equihash.cpp \ gtest/test_httprpc.cpp \ gtest/test_joinsplit.cpp \ + gtest/test_keys.cpp \ gtest/test_keystore.cpp \ gtest/test_noteencryption.cpp \ gtest/test_mempool.cpp \ diff --git a/src/gtest/test_keys.cpp b/src/gtest/test_keys.cpp new file mode 100644 index 000000000..74a3bb642 --- /dev/null +++ b/src/gtest/test_keys.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include + +TEST(Keys, EncodeAndDecodeSapling) +{ + SelectParams(CBaseChainParams::MAIN); + + for (size_t i = 0; i < 1000; i++) { + auto sk = libzcash::SaplingSpendingKey::random(); + { + std::string sk_string = EncodeSpendingKey(sk); + EXPECT_EQ( + sk_string.substr(0, 24), + Params().Bech32HRP(CChainParams::SAPLING_SPENDING_KEY)); + + auto spendingkey2 = DecodeSpendingKey(sk_string); + EXPECT_TRUE(IsValidSpendingKey(spendingkey2)); + + ASSERT_TRUE(boost::get(&spendingkey2) != nullptr); + auto sk2 = boost::get(spendingkey2); + EXPECT_EQ(sk, sk2); + } + { + auto addr = sk.default_address(); + + std::string addr_string = EncodePaymentAddress(addr); + EXPECT_EQ( + addr_string.substr(0, 2), + Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS)); + + auto paymentaddr2 = DecodePaymentAddress(addr_string); + EXPECT_TRUE(IsValidPaymentAddress(paymentaddr2)); + + ASSERT_TRUE(boost::get(&paymentaddr2) != nullptr); + auto addr2 = boost::get(paymentaddr2); + EXPECT_EQ(addr, addr2); + } + } +} From dfcf33fe151d9d7050ac9db9755160847e4ef0fa Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 13 Aug 2018 14:17:17 +0100 Subject: [PATCH 2/3] test: Use regtest in key_tests/zs_address_test --- src/test/key_tests.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index d864ca8be..5f72b25a7 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -223,11 +223,13 @@ BOOST_AUTO_TEST_CASE(zc_address_test) BOOST_AUTO_TEST_CASE(zs_address_test) { + SelectParams(CBaseChainParams::REGTEST); + for (size_t i = 0; i < 1000; i++) { auto sk = SaplingSpendingKey::random(); { std::string sk_string = EncodeSpendingKey(sk); - BOOST_CHECK(sk_string.compare(0, 24, Params().Bech32HRP(CChainParams::SAPLING_SPENDING_KEY)) == 0); + BOOST_CHECK(sk_string.compare(0, 27, Params().Bech32HRP(CChainParams::SAPLING_SPENDING_KEY)) == 0); auto spendingkey2 = DecodeSpendingKey(sk_string); BOOST_CHECK(IsValidSpendingKey(spendingkey2)); @@ -240,7 +242,7 @@ BOOST_AUTO_TEST_CASE(zs_address_test) auto addr = sk.default_address(); std::string addr_string = EncodePaymentAddress(addr); - BOOST_CHECK(addr_string.compare(0, 2, Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS)) == 0); + BOOST_CHECK(addr_string.compare(0, 15, Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS)) == 0); auto paymentaddr2 = DecodePaymentAddress(addr_string); BOOST_CHECK(IsValidPaymentAddress(paymentaddr2)); From 554e00e8f9ca7edb8a34306e4f2b4a93e3319a01 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 13 Aug 2018 14:18:18 +0100 Subject: [PATCH 3/3] Disable Sapling features on mainnet Also places them behind an experimental features flag on testnet --- src/gtest/test_keys.cpp | 2 +- src/key_io.cpp | 12 ++++++++++-- src/test/rpc_wallet_tests.cpp | 13 ++++++++----- src/wallet/rpcwallet.cpp | 6 +++++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/gtest/test_keys.cpp b/src/gtest/test_keys.cpp index 74a3bb642..23ed00a65 100644 --- a/src/gtest/test_keys.cpp +++ b/src/gtest/test_keys.cpp @@ -4,7 +4,7 @@ #include -TEST(Keys, EncodeAndDecodeSapling) +TEST(Keys, DISABLED_EncodeAndDecodeSapling) { SelectParams(CBaseChainParams::MAIN); diff --git a/src/key_io.cpp b/src/key_io.cpp index f01e6d627..b129ce37b 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -286,7 +286,11 @@ libzcash::PaymentAddress DecodePaymentAddress(const std::string& str) } data.clear(); auto bech = bech32::Decode(str); - if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) && + bool allowSapling = Params().NetworkIDString() == "regtest" || ( + Params().NetworkIDString() == "test" && + GetBoolArg("-experimentalfeatures", false) && + GetBoolArg("-developersapling", false)); + if (allowSapling && bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) && bech.second.size() == ConvertedSaplingPaymentAddressSize) { // Bech32 decoding data.reserve((bech.second.size() * 5) / 8); @@ -352,7 +356,11 @@ libzcash::SpendingKey DecodeSpendingKey(const std::string& str) } data.clear(); auto bech = bech32::Decode(str); - if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_SPENDING_KEY) && + bool allowSapling = Params().NetworkIDString() == "regtest" || ( + Params().NetworkIDString() == "test" && + GetBoolArg("-experimentalfeatures", false) && + GetBoolArg("-developersapling", false)); + if (allowSapling && bech.first == Params().Bech32HRP(CChainParams::SAPLING_SPENDING_KEY) && bech.second.size() == ConvertedSaplingSpendingKeySize) { // Bech32 decoding data.reserve((bech.second.size() * 5) / 8); diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 7b04b8ebd..edbcb6552 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -383,12 +383,13 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress) BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zs1z7rejlpsa98s2rrrfkwmaxu53e4ue0ulcrw0h4x5g8jl04tak0d3mm47vdtahatqrlkngh9slya")); resultObj = retValue.get_obj(); b = find_value(resultObj, "isvalid").get_bool(); - BOOST_CHECK_EQUAL(b, true); - BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sapling"); - b = find_value(resultObj, "ismine").get_bool(); + // TODO: Revert when we re-enable Sapling addresses on mainnet BOOST_CHECK_EQUAL(b, false); - BOOST_CHECK_EQUAL(find_value(resultObj, "diversifier").get_str(), "1787997c30e94f050c634d"); - BOOST_CHECK_EQUAL(find_value(resultObj, "diversifiedtransmissionkey").get_str(), "34ed1f60f5db5763beee1ddbb37dd5f7e541d4d4fbdcc09fbfcc6b8e949bbe9d"); + // BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sapling"); + // b = find_value(resultObj, "ismine").get_bool(); + // BOOST_CHECK_EQUAL(b, false); + // BOOST_CHECK_EQUAL(find_value(resultObj, "diversifier").get_str(), "1787997c30e94f050c634d"); + // BOOST_CHECK_EQUAL(find_value(resultObj, "diversifiedtransmissionkey").get_str(), "34ed1f60f5db5763beee1ddbb37dd5f7e541d4d4fbdcc09fbfcc6b8e949bbe9d"); } /* @@ -536,6 +537,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) */ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) { + SelectParams(CBaseChainParams::REGTEST); + LOCK2(cs_main, pwalletMain->cs_wallet); UniValue retValue; int n1 = 1000; // number of times to import/export diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0d7861aa2..18986b0aa 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3133,9 +3133,13 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp) addrType = params[0].get_str(); } + bool allowSapling = Params().NetworkIDString() == "regtest" || ( + Params().NetworkIDString() == "test" && + GetBoolArg("-experimentalfeatures", false) && + GetBoolArg("-developersapling", false)); if (addrType == ADDR_TYPE_SPROUT) { return EncodePaymentAddress(pwalletMain->GenerateNewZKey()); - } else if (addrType == ADDR_TYPE_SAPLING) { + } else if (addrType == ADDR_TYPE_SAPLING && allowSapling) { return EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey()); } else { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type");