LCOV - code coverage report
Current view: top level - src/test/librust - wallet_zkeys_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 96 100 96.0 %
Date: 2025-04-02 01:23:23 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2016-2020 The ZCash developers
       2             : // Copyright (c) 2020-2021 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "wallet/test/wallet_test_fixture.h"
       7             : 
       8             : #include "sapling/sapling_util.h"
       9             : #include "sapling/address.h"
      10             : #include "wallet/wallet.h"
      11             : #include "wallet/walletdb.h"
      12             : #include "wallet/walletutil.h"
      13             : #include "util/system.h"
      14             : #include <boost/test/unit_test.hpp>
      15             : 
      16             : /**
      17             :  * This test covers methods on CWallet
      18             :  * GenerateNewZKey()
      19             :  * AddZKey()
      20             :  * LoadZKey()
      21             :  * LoadZKeyMetadata()
      22             :  */
      23             : 
      24             : BOOST_AUTO_TEST_SUITE(wallet_zkeys_tests)
      25             : 
      26             : /**
      27             :   * This test covers Sapling methods on CWallet
      28             :   * GenerateNewSaplingZKey()
      29             :   * AddSaplingZKey()
      30             :   * LoadSaplingZKey()
      31             :   * LoadSaplingZKeyMetadata()
      32             :   */
      33           2 : BOOST_FIXTURE_TEST_CASE(StoreAndLoadSaplingZkeys, TestingSetup) {
      34           2 :     CWallet wallet("dummy", WalletDatabase::CreateDummy());
      35           2 :     LOCK(wallet.cs_wallet);
      36             :     // wallet should be empty
      37           2 :     std::set<libzcash::SaplingPaymentAddress> addrs;
      38           1 :     wallet.GetSaplingPaymentAddresses(addrs);
      39           1 :     BOOST_CHECK_EQUAL(0, addrs.size());
      40             : 
      41             :     // No HD seed in the wallet
      42           3 :     BOOST_CHECK_THROW(wallet.GenerateNewSaplingZKey(), std::runtime_error);
      43             : 
      44             :     // Random seed
      45           1 :     CKey seed;
      46           1 :     seed.MakeNewKey(true);
      47           1 :     wallet.AddKeyPubKey(seed, seed.GetPubKey());
      48           1 :     wallet.GetSaplingScriptPubKeyMan()->SetHDSeed(seed.GetPubKey(), false, true);
      49             : 
      50             :     // wallet should have one key
      51           1 :     auto address = wallet.GenerateNewSaplingZKey();
      52           1 :     wallet.GetSaplingPaymentAddresses(addrs);
      53           1 :     BOOST_CHECK_EQUAL(1, addrs.size());
      54             : 
      55             :     // verify wallet has incoming viewing key for the address
      56           2 :     BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(address));
      57             : 
      58             :     // manually add new spending key to wallet
      59           3 :     HDSeed seed1(seed.GetPrivKey());
      60           1 :     auto m = libzcash::SaplingExtendedSpendingKey::Master(seed1);
      61           1 :     auto sk = m.Derive(0);
      62           2 :     BOOST_CHECK(wallet.AddSaplingZKey(sk));
      63             : 
      64             :     // verify wallet did add it
      65           1 :     auto extfvk = sk.ToXFVK();
      66           2 :     BOOST_CHECK(wallet.HaveSaplingSpendingKey(extfvk));
      67             : 
      68             :     // verify spending key stored correctly
      69           1 :     libzcash::SaplingExtendedSpendingKey keyOut;
      70           1 :     wallet.GetSaplingSpendingKey(extfvk, keyOut);
      71           2 :     BOOST_CHECK(sk == keyOut);
      72             : 
      73             :     // verify there are two keys
      74           1 :     wallet.GetSaplingPaymentAddresses(addrs);
      75           1 :     BOOST_CHECK_EQUAL(2, addrs.size());
      76           2 :     BOOST_CHECK_EQUAL(1, addrs.count(address));
      77           2 :     BOOST_CHECK_EQUAL(1, addrs.count(sk.DefaultAddress()));
      78             : 
      79             :     // Generate a diversified address different to the default
      80             :     // If we can't get an early diversified address, we are very unlucky
      81           1 :     blob88 diversifier;
      82           1 :     diversifier.begin()[0] = 10;
      83           2 :     auto dpa = sk.ToXFVK().Address(diversifier).get().second;
      84             : 
      85             :     // verify wallet only has the default address
      86           1 :     libzcash::SaplingPaymentAddress defaultAddr = sk.DefaultAddress();
      87           2 :     BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(defaultAddr));
      88             : 
      89             :     // Keep trying different diversifiers until we get a different address
      90           1 :     while (dpa == defaultAddr && diversifier.begin()[0] < 255) {
      91           0 :         diversifier.begin()[0] += 1;
      92           0 :         dpa = sk.ToXFVK().Address(diversifier).get().second;
      93             :     }
      94           2 :     BOOST_CHECK(!wallet.HaveSaplingIncomingViewingKey(dpa));
      95             : 
      96             :     // manually add a diversified address
      97           1 :     auto ivk = extfvk.fvk.in_viewing_key();
      98           2 :     BOOST_CHECK(wallet.AddSaplingIncomingViewingKeyW(ivk, dpa));
      99             : 
     100             :     // verify wallet did add it
     101           2 :     BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(sk.DefaultAddress()));
     102           2 :     BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(dpa));
     103             : 
     104             :     // Load a third key into the wallet
     105           1 :     auto sk2 = m.Derive(1);
     106           2 :     BOOST_CHECK(wallet.LoadSaplingZKey(sk2));
     107             : 
     108             :     // attach metadata to this third key
     109           1 :     auto ivk2 = sk2.expsk.full_viewing_key().in_viewing_key();
     110           1 :     int64_t now = GetTime();
     111           2 :     CKeyMetadata meta(now);
     112           2 :     BOOST_CHECK(wallet.LoadSaplingZKeyMetadata(ivk2, meta));
     113             : 
     114             :     // check metadata is the same
     115           1 :     BOOST_CHECK_EQUAL(wallet.GetSaplingScriptPubKeyMan()->mapSaplingZKeyMetadata[ivk2].nCreateTime, now);
     116             : 
     117             :     // Load a diversified address for the third key into the wallet
     118           1 :     libzcash::SaplingPaymentAddress defaultAddr2 = sk2.DefaultAddress();
     119           1 :     diversifier.begin()[0] = 10;
     120           2 :     auto dpa2 = sk2.ToXFVK().Address(diversifier).get().second;
     121           1 :     while (dpa2 == defaultAddr2 && diversifier.begin()[0] < 255) {
     122           0 :         diversifier.begin()[0] += 1;
     123           0 :         dpa2 = sk2.ToXFVK().Address(diversifier).get().second;
     124             :     }
     125           2 :     BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(sk2.DefaultAddress()));
     126           2 :     BOOST_CHECK(!wallet.HaveSaplingIncomingViewingKey(dpa2));
     127           2 :     BOOST_CHECK(wallet.LoadSaplingPaymentAddress(dpa2, ivk2));
     128           2 :     BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(dpa2));
     129           1 : }
     130             : 
     131             : /**
     132             :   * This test covers methods on WalletBatch to load/save crypted sapling z keys.
     133             :   */
     134           2 : BOOST_FIXTURE_TEST_CASE(WriteCryptedSaplingZkeyDirectToDb, BasicTestingSetup) {
     135           2 :     fs::path path = fs::absolute("testWallet1", GetWalletDir());
     136           1 :     path.make_preferred();
     137           2 :     std::unique_ptr<CWallet> testWallet = std::make_unique<CWallet>("testWallet1", WalletDatabase::Create(path));
     138           1 :     bool fFirstRun;
     139           1 :     BOOST_CHECK_EQUAL(testWallet->LoadWallet(fFirstRun), DB_LOAD_OK);
     140           2 :     BOOST_CHECK(!testWallet->HasSaplingSPKM());
     141           1 :     assert(testWallet->SetupSPKM(true));
     142             : 
     143             :     // wallet should be empty
     144           2 :     std::set<libzcash::SaplingPaymentAddress> addrs;
     145           1 :     testWallet->GetSaplingPaymentAddresses(addrs);
     146           1 :     BOOST_CHECK_EQUAL(0, addrs.size());
     147             : 
     148             :     // Add random key to the wallet
     149           1 :     auto address = testWallet->GenerateNewSaplingZKey();
     150             : 
     151             :     // wallet should have one key
     152           1 :     testWallet->GetSaplingPaymentAddresses(addrs);
     153           1 :     BOOST_CHECK_EQUAL(1, addrs.size());
     154             : 
     155             :     // encrypt wallet
     156           2 :     SecureString strWalletPass;
     157           1 :     strWalletPass.reserve(100);
     158           1 :     strWalletPass = "hello";
     159           2 :     BOOST_CHECK(testWallet->EncryptWallet(strWalletPass));
     160             : 
     161             :     // adding a new key will fail as the wallet is locked
     162           3 :     BOOST_CHECK_THROW(testWallet->GenerateNewSaplingZKey(), std::runtime_error);
     163             : 
     164             :     // unlock wallet and then add
     165           1 :     testWallet->Unlock(strWalletPass);
     166           1 :     libzcash::SaplingPaymentAddress address2 = testWallet->GenerateNewSaplingZKey();
     167             : 
     168             :     // Force db close
     169           1 :     testWallet->Flush(true);
     170           1 :     testWallet.reset();
     171             : 
     172             :     // Create a new wallet from the existing wallet path
     173           1 :     fFirstRun = false;
     174           2 :     std::unique_ptr<CWallet> wallet2 = std::make_unique<CWallet>("testWallet1", WalletDatabase::Create(path));
     175           1 :     BOOST_CHECK_EQUAL(DB_LOAD_OK, wallet2->LoadWallet(fFirstRun));
     176             : 
     177             :     // Confirm it's not the same as the other wallet
     178           2 :     BOOST_CHECK(wallet2->HasSaplingSPKM());
     179             : 
     180             :     // wallet should have two keys
     181           1 :     wallet2->GetSaplingPaymentAddresses(addrs);
     182           1 :     BOOST_CHECK_EQUAL(2, addrs.size());
     183             : 
     184             :     //check we have entries for our payment addresses
     185           3 :     BOOST_CHECK(addrs.count(address));
     186           3 :     BOOST_CHECK(addrs.count(address2));
     187             : 
     188             :     // spending key is crypted, so we can't extract valid payment address
     189           1 :     libzcash::SaplingExtendedSpendingKey keyOut;
     190           2 :     BOOST_CHECK(!wallet2->GetSaplingExtendedSpendingKey(address, keyOut));
     191             : 
     192             :     // unlock wallet to get spending keys and verify payment addresses
     193           1 :     wallet2->Unlock(strWalletPass);
     194             : 
     195           2 :     BOOST_CHECK(wallet2->GetSaplingExtendedSpendingKey(address, keyOut));
     196           2 :     BOOST_CHECK(address == keyOut.DefaultAddress());
     197             : 
     198           2 :     BOOST_CHECK(wallet2->GetSaplingExtendedSpendingKey(address2, keyOut));
     199           2 :     BOOST_CHECK(address2 == keyOut.DefaultAddress());
     200             : 
     201             :     // Force db close
     202           1 :     wallet2->Flush(true);
     203           2 :     wallet2.reset();
     204           1 : }
     205             : 
     206             : 
     207             : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.14