Persist Sapling payment address to IVK map
This ensures we remember any diversified addresses manually generated outside the wallet.
This commit is contained in:
parent
9ce6f8425b
commit
3e471410f1
|
@ -11,7 +11,9 @@
|
|||
* This test covers Sapling methods on CWallet
|
||||
* GenerateNewSaplingZKey()
|
||||
* AddSaplingZKey()
|
||||
* AddSaplingIncomingViewingKey()
|
||||
* LoadSaplingZKey()
|
||||
* LoadSaplingIncomingViewingKey()
|
||||
* LoadSaplingZKeyMetadata()
|
||||
*/
|
||||
TEST(wallet_zkeys_tests, StoreAndLoadSaplingZkeys) {
|
||||
|
@ -62,6 +64,24 @@ TEST(wallet_zkeys_tests, StoreAndLoadSaplingZkeys) {
|
|||
EXPECT_EQ(1, addrs.count(address));
|
||||
EXPECT_EQ(1, addrs.count(sk.DefaultAddress()));
|
||||
|
||||
// Generate a diversified address different to the default
|
||||
// If we can't get an early diversified address, we are very unlucky
|
||||
blob88 diversifier;
|
||||
diversifier.begin()[0] = 10;
|
||||
auto dpa = sk.ToXFVK().Address(diversifier).get().second;
|
||||
|
||||
// verify wallet only has the default address
|
||||
EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(sk.DefaultAddress()));
|
||||
EXPECT_FALSE(wallet.HaveSaplingIncomingViewingKey(dpa));
|
||||
|
||||
// manually add a diversified address
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
EXPECT_TRUE(wallet.AddSaplingIncomingViewingKey(ivk, dpa));
|
||||
|
||||
// verify wallet did add it
|
||||
EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(sk.DefaultAddress()));
|
||||
EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(dpa));
|
||||
|
||||
// Load a third key into the wallet
|
||||
auto sk2 = m.Derive(1);
|
||||
ASSERT_TRUE(wallet.LoadSaplingZKey(sk2));
|
||||
|
@ -74,6 +94,13 @@ TEST(wallet_zkeys_tests, StoreAndLoadSaplingZkeys) {
|
|||
|
||||
// check metadata is the same
|
||||
ASSERT_EQ(wallet.mapSaplingZKeyMetadata[ivk2].nCreateTime, now);
|
||||
|
||||
// Load a diversified address for the third key into the wallet
|
||||
auto dpa2 = sk2.ToXFVK().Address(diversifier).get().second;
|
||||
EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(sk2.DefaultAddress()));
|
||||
EXPECT_FALSE(wallet.HaveSaplingIncomingViewingKey(dpa2));
|
||||
EXPECT_TRUE(wallet.LoadSaplingPaymentAddress(dpa2, ivk2));
|
||||
EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(dpa2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,6 +440,18 @@ TEST(wallet_zkeys_tests, WriteCryptedSaplingZkeyDirectToDb) {
|
|||
wallet.GetSaplingPaymentAddresses(addrs);
|
||||
ASSERT_EQ(1, addrs.size());
|
||||
|
||||
// Generate a diversified address different to the default
|
||||
// If we can't get an early diversified address, we are very unlucky
|
||||
libzcash::SaplingExtendedSpendingKey extsk;
|
||||
EXPECT_TRUE(wallet.GetSaplingExtendedSpendingKey(address, extsk));
|
||||
blob88 diversifier;
|
||||
diversifier.begin()[0] = 10;
|
||||
auto dpa = extsk.ToXFVK().Address(diversifier).get().second;
|
||||
|
||||
// Add diversified address to the wallet
|
||||
auto ivk = extsk.expsk.full_viewing_key().in_viewing_key();
|
||||
EXPECT_TRUE(wallet.AddSaplingIncomingViewingKey(ivk, dpa));
|
||||
|
||||
// encrypt wallet
|
||||
SecureString strWalletPass;
|
||||
strWalletPass.reserve(100);
|
||||
|
@ -434,19 +473,25 @@ TEST(wallet_zkeys_tests, WriteCryptedSaplingZkeyDirectToDb) {
|
|||
ASSERT_TRUE(&wallet != &wallet2);
|
||||
ASSERT_TRUE(wallet2.HaveHDSeed());
|
||||
|
||||
// wallet should have two keys
|
||||
// wallet should have three addresses
|
||||
wallet2.GetSaplingPaymentAddresses(addrs);
|
||||
ASSERT_EQ(2, addrs.size());
|
||||
ASSERT_EQ(3, addrs.size());
|
||||
|
||||
//check we have entries for our payment addresses
|
||||
ASSERT_TRUE(addrs.count(address));
|
||||
ASSERT_TRUE(addrs.count(address2));
|
||||
ASSERT_TRUE(addrs.count(dpa));
|
||||
|
||||
// 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());
|
||||
|
||||
// address -> ivk mapping is not crypted
|
||||
libzcash::SaplingIncomingViewingKey ivkOut;
|
||||
EXPECT_TRUE(wallet2.GetSaplingIncomingViewingKey(dpa, ivkOut));
|
||||
EXPECT_EQ(ivk, ivkOut);
|
||||
|
||||
// unlock wallet to get spending keys and verify payment addresses
|
||||
wallet2.Unlock(strWalletPass);
|
||||
|
||||
|
|
|
@ -174,6 +174,28 @@ bool CWallet::AddSaplingZKey(
|
|||
return true;
|
||||
}
|
||||
|
||||
// Add payment address -> incoming viewing key map entry
|
||||
bool CWallet::AddSaplingIncomingViewingKey(
|
||||
const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
const libzcash::SaplingPaymentAddress &addr)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||
|
||||
if (!CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fFileBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsCrypted()) {
|
||||
return CWalletDB(strWalletFile).WriteSaplingPaymentAddress(addr, ivk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Add spending key to keystore and persist to disk
|
||||
bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key)
|
||||
|
@ -365,6 +387,13 @@ bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
|
|||
return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
|
||||
}
|
||||
|
||||
bool CWallet::LoadSaplingPaymentAddress(
|
||||
const libzcash::SaplingPaymentAddress &addr,
|
||||
const libzcash::SaplingIncomingViewingKey &ivk)
|
||||
{
|
||||
return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr);
|
||||
}
|
||||
|
||||
bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key)
|
||||
{
|
||||
return CCryptoKeyStore::AddSproutSpendingKey(key);
|
||||
|
|
|
@ -1075,6 +1075,9 @@ public:
|
|||
bool AddSaplingZKey(
|
||||
const libzcash::SaplingExtendedSpendingKey &key,
|
||||
const libzcash::SaplingPaymentAddress &defaultAddr);
|
||||
bool AddSaplingIncomingViewingKey(
|
||||
const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
const libzcash::SaplingPaymentAddress &addr);
|
||||
bool AddCryptedSaplingSpendingKey(
|
||||
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::vector<unsigned char> &vchCryptedSecret,
|
||||
|
@ -1083,6 +1086,11 @@ public:
|
|||
bool LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key);
|
||||
//! Load spending key metadata (used by LoadWallet)
|
||||
bool LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta);
|
||||
//! Adds a Sapling payment address -> incoming viewing key map entry,
|
||||
//! without saving it to disk (used by LoadWallet)
|
||||
bool LoadSaplingPaymentAddress(
|
||||
const libzcash::SaplingPaymentAddress &addr,
|
||||
const libzcash::SaplingIncomingViewingKey &ivk);
|
||||
//! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::vector<unsigned char> &vchCryptedSecret);
|
||||
|
|
|
@ -175,6 +175,15 @@ bool CWalletDB::WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
|||
return Write(std::make_pair(std::string("sapzkey"), ivk), key, false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteSaplingPaymentAddress(
|
||||
const libzcash::SaplingPaymentAddress &addr,
|
||||
const libzcash::SaplingIncomingViewingKey &ivk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
|
||||
return Write(std::make_pair(std::string("sapzaddr"), addr), ivk, false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteSproutViewingKey(const libzcash::SproutViewingKey &vk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
|
@ -416,13 +425,14 @@ public:
|
|||
unsigned int nZKeys;
|
||||
unsigned int nCZKeys;
|
||||
unsigned int nZKeyMeta;
|
||||
unsigned int nSapZAddrs;
|
||||
bool fIsEncrypted;
|
||||
bool fAnyUnordered;
|
||||
int nFileVersion;
|
||||
vector<uint256> vWalletUpgrade;
|
||||
|
||||
CWalletScanState() {
|
||||
nKeys = nCKeys = nKeyMeta = nZKeys = nCZKeys = nZKeyMeta = 0;
|
||||
nKeys = nCKeys = nKeyMeta = nZKeys = nCZKeys = nZKeyMeta = nSapZAddrs = 0;
|
||||
fIsEncrypted = false;
|
||||
fAnyUnordered = false;
|
||||
nFileVersion = 0;
|
||||
|
@ -729,6 +739,21 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
|
||||
pwallet->LoadSaplingZKeyMetadata(ivk, keyMeta);
|
||||
}
|
||||
else if (strType == "sapzaddr")
|
||||
{
|
||||
libzcash::SaplingPaymentAddress addr;
|
||||
ssKey >> addr;
|
||||
libzcash::SaplingIncomingViewingKey ivk;
|
||||
ssValue >> ivk;
|
||||
|
||||
wss.nSapZAddrs++;
|
||||
|
||||
if (!pwallet->LoadSaplingPaymentAddress(addr, ivk))
|
||||
{
|
||||
strErr = "Error reading wallet database: LoadSaplingPaymentAddress failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (strType == "defaultkey")
|
||||
{
|
||||
ssValue >> pwallet->vchDefaultKey;
|
||||
|
|
|
@ -187,6 +187,8 @@ public:
|
|||
bool WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
const libzcash::SaplingExtendedSpendingKey &key,
|
||||
const CKeyMetadata &keyMeta);
|
||||
bool WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr,
|
||||
const libzcash::SaplingIncomingViewingKey &ivk);
|
||||
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
||||
const libzcash::ReceivingKey & rk,
|
||||
const std::vector<unsigned char>& vchCryptedSecret,
|
||||
|
|
Loading…
Reference in New Issue