PIVX Core  5.6.99
P2P Digital Currency
wallet_zkeys_tests.cpp
Go to the documentation of this file.
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 
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 
24 BOOST_AUTO_TEST_SUITE(wallet_zkeys_tests)
25 
26 
33 BOOST_FIXTURE_TEST_CASE(StoreAndLoadSaplingZkeys, TestingSetup) {
34  CWallet wallet("dummy", WalletDatabase::CreateDummy());
35  LOCK(wallet.cs_wallet);
36  // wallet should be empty
37  std::set<libzcash::SaplingPaymentAddress> addrs;
38  wallet.GetSaplingPaymentAddresses(addrs);
39  BOOST_CHECK_EQUAL(0, addrs.size());
40 
41  // No HD seed in the wallet
42  BOOST_CHECK_THROW(wallet.GenerateNewSaplingZKey(), std::runtime_error);
43 
44  // Random seed
45  CKey seed;
46  seed.MakeNewKey(true);
47  wallet.AddKeyPubKey(seed, seed.GetPubKey());
48  wallet.GetSaplingScriptPubKeyMan()->SetHDSeed(seed.GetPubKey(), false, true);
49 
50  // wallet should have one key
51  auto address = wallet.GenerateNewSaplingZKey();
52  wallet.GetSaplingPaymentAddresses(addrs);
53  BOOST_CHECK_EQUAL(1, addrs.size());
54 
55  // verify wallet has incoming viewing key for the address
57 
58  // manually add new spending key to wallet
59  HDSeed seed1(seed.GetPrivKey());
61  auto sk = m.Derive(0);
62  BOOST_CHECK(wallet.AddSaplingZKey(sk));
63 
64  // verify wallet did add it
65  auto extfvk = sk.ToXFVK();
66  BOOST_CHECK(wallet.HaveSaplingSpendingKey(extfvk));
67 
68  // verify spending key stored correctly
70  wallet.GetSaplingSpendingKey(extfvk, keyOut);
71  BOOST_CHECK(sk == keyOut);
72 
73  // verify there are two keys
74  wallet.GetSaplingPaymentAddresses(addrs);
75  BOOST_CHECK_EQUAL(2, addrs.size());
76  BOOST_CHECK_EQUAL(1, addrs.count(address));
77  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  blob88 diversifier;
82  diversifier.begin()[0] = 10;
83  auto dpa = sk.ToXFVK().Address(diversifier).get().second;
84 
85  // verify wallet only has the default address
86  libzcash::SaplingPaymentAddress defaultAddr = sk.DefaultAddress();
87  BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(defaultAddr));
88 
89  // Keep trying different diversifiers until we get a different address
90  while (dpa == defaultAddr && diversifier.begin()[0] < 255) {
91  diversifier.begin()[0] += 1;
92  dpa = sk.ToXFVK().Address(diversifier).get().second;
93  }
95 
96  // manually add a diversified address
97  auto ivk = extfvk.fvk.in_viewing_key();
99 
100  // verify wallet did add it
101  BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(sk.DefaultAddress()));
103 
104  // Load a third key into the wallet
105  auto sk2 = m.Derive(1);
106  BOOST_CHECK(wallet.LoadSaplingZKey(sk2));
107 
108  // attach metadata to this third key
109  auto ivk2 = sk2.expsk.full_viewing_key().in_viewing_key();
110  int64_t now = GetTime();
111  CKeyMetadata meta(now);
112  BOOST_CHECK(wallet.LoadSaplingZKeyMetadata(ivk2, meta));
113 
114  // check metadata is the same
115  BOOST_CHECK_EQUAL(wallet.GetSaplingScriptPubKeyMan()->mapSaplingZKeyMetadata[ivk2].nCreateTime, now);
116 
117  // Load a diversified address for the third key into the wallet
118  libzcash::SaplingPaymentAddress defaultAddr2 = sk2.DefaultAddress();
119  diversifier.begin()[0] = 10;
120  auto dpa2 = sk2.ToXFVK().Address(diversifier).get().second;
121  while (dpa2 == defaultAddr2 && diversifier.begin()[0] < 255) {
122  diversifier.begin()[0] += 1;
123  dpa2 = sk2.ToXFVK().Address(diversifier).get().second;
124  }
125  BOOST_CHECK(wallet.HaveSaplingIncomingViewingKey(sk2.DefaultAddress()));
127  BOOST_CHECK(wallet.LoadSaplingPaymentAddress(dpa2, ivk2));
129 }
130 
134 BOOST_FIXTURE_TEST_CASE(WriteCryptedSaplingZkeyDirectToDb, BasicTestingSetup) {
135  fs::path path = fs::absolute("testWallet1", GetWalletDir());
136  path.make_preferred();
137  std::unique_ptr<CWallet> testWallet = std::make_unique<CWallet>("testWallet1", WalletDatabase::Create(path));
138  bool fFirstRun;
139  BOOST_CHECK_EQUAL(testWallet->LoadWallet(fFirstRun), DB_LOAD_OK);
140  BOOST_CHECK(!testWallet->HasSaplingSPKM());
141  assert(testWallet->SetupSPKM(true));
142 
143  // wallet should be empty
144  std::set<libzcash::SaplingPaymentAddress> addrs;
145  testWallet->GetSaplingPaymentAddresses(addrs);
146  BOOST_CHECK_EQUAL(0, addrs.size());
147 
148  // Add random key to the wallet
149  auto address = testWallet->GenerateNewSaplingZKey();
150 
151  // wallet should have one key
152  testWallet->GetSaplingPaymentAddresses(addrs);
153  BOOST_CHECK_EQUAL(1, addrs.size());
154 
155  // encrypt wallet
156  SecureString strWalletPass;
157  strWalletPass.reserve(100);
158  strWalletPass = "hello";
159  BOOST_CHECK(testWallet->EncryptWallet(strWalletPass));
160 
161  // adding a new key will fail as the wallet is locked
162  BOOST_CHECK_THROW(testWallet->GenerateNewSaplingZKey(), std::runtime_error);
163 
164  // unlock wallet and then add
165  testWallet->Unlock(strWalletPass);
166  libzcash::SaplingPaymentAddress address2 = testWallet->GenerateNewSaplingZKey();
167 
168  // Force db close
169  testWallet->Flush(true);
170  testWallet.reset();
171 
172  // Create a new wallet from the existing wallet path
173  fFirstRun = false;
174  std::unique_ptr<CWallet> wallet2 = std::make_unique<CWallet>("testWallet1", WalletDatabase::Create(path));
175  BOOST_CHECK_EQUAL(DB_LOAD_OK, wallet2->LoadWallet(fFirstRun));
176 
177  // Confirm it's not the same as the other wallet
178  BOOST_CHECK(wallet2->HasSaplingSPKM());
179 
180  // wallet should have two keys
181  wallet2->GetSaplingPaymentAddresses(addrs);
182  BOOST_CHECK_EQUAL(2, addrs.size());
183 
184  //check we have entries for our payment addresses
185  BOOST_CHECK(addrs.count(address));
186  BOOST_CHECK(addrs.count(address2));
187 
188  // spending key is crypted, so we can't extract valid payment address
190  BOOST_CHECK(!wallet2->GetSaplingExtendedSpendingKey(address, keyOut));
191 
192  // unlock wallet to get spending keys and verify payment addresses
193  wallet2->Unlock(strWalletPass);
194 
195  BOOST_CHECK(wallet2->GetSaplingExtendedSpendingKey(address, keyOut));
196  BOOST_CHECK(address == keyOut.DefaultAddress());
197 
198  BOOST_CHECK(wallet2->GetSaplingExtendedSpendingKey(address2, keyOut));
199  BOOST_CHECK(address2 == keyOut.DefaultAddress());
200 
201  // Force db close
202  wallet2->Flush(true);
203  wallet2.reset();
204 }
205 
206 
static std::unique_ptr< BerkeleyDatabase > CreateDummy()
Return object for accessing dummy database with no read/write capabilities.
Definition: db.h:132
static std::unique_ptr< BerkeleyDatabase > Create(const fs::path &path)
Return object for accessing database at specified path.
Definition: db.h:126
virtual bool HaveSaplingIncomingViewingKey(const libzcash::SaplingPaymentAddress &addr) const
Definition: keystore.cpp:199
void GetSaplingPaymentAddresses(std::set< libzcash::SaplingPaymentAddress > &setAddress) const
Definition: keystore.cpp:252
bool HaveSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk) const override
bool GetSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, libzcash::SaplingExtendedSpendingKey &skOut) const override
An encapsulated private key.
Definition: key.h:30
CPrivKey GetPrivKey() const
Convert the private key to a CPrivKey (serialized secp256k1 private key data).
Definition: key.cpp:173
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:158
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:186
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
bool LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
Load spending key metadata (used by LoadWallet)
Definition: wallet.cpp:4740
RecursiveMutex cs_wallet
Definition: wallet.h:720
bool AddSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
Adds Sapling spending key to the store, and saves it to disk.
Definition: wallet.cpp:4728
bool LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
Adds spending key to the store, without saving it to disk (used by LoadWallet)
Definition: wallet.cpp:4739
SaplingScriptPubKeyMan * GetSaplingScriptPubKeyMan() const
Definition: wallet.h:712
libzcash::SaplingPaymentAddress GenerateNewSaplingZKey(std::string label="")
Generates new Sapling key.
Definition: wallet.cpp:4710
bool LoadSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr, const libzcash::SaplingIncomingViewingKey &ivk)
Adds a Sapling payment address -> incoming viewing key map entry, without saving it to disk (used by ...
Definition: wallet.cpp:4744
bool AddSaplingIncomingViewingKeyW(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingPaymentAddress &addr)
Definition: wallet.cpp:4730
Definition: zip32.h:20
std::map< libzcash::SaplingIncomingViewingKey, CKeyMetadata > mapSaplingZKeyMetadata
void SetHDSeed(const CPubKey &key, bool force=false, bool memonly=false)
unsigned char * begin()
Definition: uint256.h:63
88-bit opaque blob.
Definition: uint256.h:116
Sapling functions.
Definition: address.h:30
BOOST_AUTO_TEST_SUITE(cuckoocache_tests)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
Adds a key to the store, and saves it to disk.
Definition: wallet.cpp:252
@ LOCK
Definition: lockunlock.h:16
#define BOOST_CHECK_THROW(stmt, excMatch)
Definition: object.cpp:19
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:61
Basic testing setup.
Definition: test_pivx.h:51
libzcash::SaplingPaymentAddress DefaultAddress() const
Definition: zip32.cpp:162
static SaplingExtendedSpendingKey Master(const HDSeed &seed)
Definition: zip32.cpp:117
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: utiltime.cpp:27
BOOST_FIXTURE_TEST_CASE(StoreAndLoadSaplingZkeys, TestingSetup)
This test covers methods on CWallet GenerateNewZKey() AddZKey() LoadZKey() LoadZKeyMetadata()
@ DB_LOAD_OK
Definition: walletdb.h:51
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:8