diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp index 85f74ab7b..ebd6c3bf0 100644 --- a/src/wallet/gtest/test_wallet_zkeys.cpp +++ b/src/wallet/gtest/test_wallet_zkeys.cpp @@ -10,8 +10,11 @@ /** * This test covers Sapling methods on CWallet * GenerateNewSaplingZKey() + * AddSaplingZKey() + * LoadSaplingZKey() + * LoadSaplingZKeyMetadata() */ -TEST(wallet_zkeys_tests, store_and_load_sapling_zkeys) { +TEST(wallet_zkeys_tests, StoreAndLoadSaplingZkeys) { SelectParams(CBaseChainParams::MAIN); CWallet wallet; @@ -58,6 +61,19 @@ TEST(wallet_zkeys_tests, store_and_load_sapling_zkeys) { EXPECT_EQ(2, addrs.size()); EXPECT_EQ(1, addrs.count(address)); EXPECT_EQ(1, addrs.count(sk.DefaultAddress())); + + // Load a third key into the wallet + auto sk2 = m.Derive(1); + ASSERT_TRUE(wallet.LoadSaplingZKey(sk2)); + + // attach metadata to this third key + auto ivk2 = sk2.expsk.full_viewing_key().in_viewing_key(); + int64_t now = GetTime(); + CKeyMetadata meta(now); + ASSERT_TRUE(wallet.LoadSaplingZKeyMetadata(ivk2, meta)); + + // check metadata is the same + ASSERT_EQ(wallet.mapSaplingZKeyMetadata[ivk2].nCreateTime, now); } /** @@ -363,3 +379,80 @@ TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) { ASSERT_EQ(paymentAddress2, keyOut.address()); } +/** + * This test covers methods on CWalletDB to load/save crypted sapling z keys. + */ +TEST(wallet_zkeys_tests, WriteCryptedSaplingZkeyDirectToDb) { + SelectParams(CBaseChainParams::TESTNET); + + // Get temporary and unique path for file. + // Note: / operator to append paths + boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + boost::filesystem::create_directories(pathTemp); + mapArgs["-datadir"] = pathTemp.string(); + + bool fFirstRun; + CWallet wallet("wallet_crypted_sapling.dat"); + ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun)); + + // No default CPubKey set + ASSERT_TRUE(fFirstRun); + + ASSERT_FALSE(wallet.HaveHDSeed()); + wallet.GenerateNewSeed(); + + // wallet should be empty + std::set addrs; + wallet.GetSaplingPaymentAddresses(addrs); + ASSERT_EQ(0, addrs.size()); + + // Add random key to the wallet + auto address = wallet.GenerateNewSaplingZKey(); + + // wallet should have one key + wallet.GetSaplingPaymentAddresses(addrs); + ASSERT_EQ(1, addrs.size()); + + // encrypt wallet + SecureString strWalletPass; + strWalletPass.reserve(100); + strWalletPass = "hello"; + ASSERT_TRUE(wallet.EncryptWallet(strWalletPass)); + + // adding a new key will fail as the wallet is locked + EXPECT_ANY_THROW(wallet.GenerateNewSaplingZKey()); + + // unlock wallet and then add + wallet.Unlock(strWalletPass); + auto address2 = wallet.GenerateNewSaplingZKey(); + + // Create a new wallet from the existing wallet path + CWallet wallet2("wallet_crypted_sapling.dat"); + ASSERT_EQ(DB_LOAD_OK, wallet2.LoadWallet(fFirstRun)); + + // Confirm it's not the same as the other wallet + ASSERT_TRUE(&wallet != &wallet2); + ASSERT_TRUE(wallet2.HaveHDSeed()); + + // wallet should have two keys + wallet2.GetSaplingPaymentAddresses(addrs); + ASSERT_EQ(2, addrs.size()); + + //check we have entries for our payment addresses + ASSERT_TRUE(addrs.count(address)); + ASSERT_TRUE(addrs.count(address2)); + + // spending key is crypted, so we can't extract valid payment address + libzcash::SaplingExtendedSpendingKey keyOut; + EXPECT_FALSE(wallet2.GetSaplingExtendedSpendingKey(address, keyOut)); + ASSERT_FALSE(address == keyOut.DefaultAddress()); + + // unlock wallet to get spending keys and verify payment addresses + wallet2.Unlock(strWalletPass); + + EXPECT_TRUE(wallet2.GetSaplingExtendedSpendingKey(address, keyOut)); + ASSERT_EQ(address, keyOut.DefaultAddress()); + + EXPECT_TRUE(wallet2.GetSaplingExtendedSpendingKey(address2, keyOut)); + ASSERT_EQ(address2, keyOut.DefaultAddress()); +}