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()