diff --git a/src/gtest/test_keystore.cpp b/src/gtest/test_keystore.cpp index a0b79cfda..90a60d9fa 100644 --- a/src/gtest/test_keystore.cpp +++ b/src/gtest/test_keystore.cpp @@ -251,7 +251,7 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingSpendingKey) { auto sk = GetTestMasterSaplingSpendingKey(); auto extfvk = sk.ToXFVK(); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); auto addr = sk.ToXFVK().DefaultAddress(); // Sanity-check: we can't get a key we haven't added @@ -286,7 +286,7 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingFullViewingKey) { auto sk = GetTestMasterSaplingSpendingKey(); auto extfvk = sk.ToXFVK(); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); auto addr = sk.ToXFVK().DefaultAddress(); // Sanity-check: we can't get a full viewing key we haven't added @@ -560,7 +560,7 @@ TEST(KeystoreTests, StoreAndRetrieveUFVK) { auto ufvkmeta = keyStore.GetUFVKMetadataForReceiver(saplingReceiver); EXPECT_FALSE(ufvkmeta.has_value()); - auto saplingIvk = zufvk.GetSaplingKey().value().fvk.in_viewing_key(); + auto saplingIvk = zufvk.GetSaplingKey().value().ToIncomingViewingKey(); keyStore.AddSaplingPaymentAddress(saplingIvk, saplingReceiver); ufvkmeta = keyStore.GetUFVKMetadataForReceiver(saplingReceiver); diff --git a/src/gtest/test_zip32.cpp b/src/gtest/test_zip32.cpp index 78b18ad8c..9361ccb72 100644 --- a/src/gtest/test_zip32.cpp +++ b/src/gtest/test_zip32.cpp @@ -182,9 +182,7 @@ TEST(ZIP32, DeriveChangeAddress) auto accountSk = libzcash::SaplingExtendedSpendingKey::ForAccount(seed, 1, 0); auto extfvk = accountSk.first.ToXFVK(); auto changeSk = accountSk.first.DeriveInternalKey(); - auto changeDfvk = extfvk.GetInternalDFVK(); - EXPECT_EQ(changeDfvk.DefaultAddress(), extfvk.GetChangeAddress()); EXPECT_EQ(changeSk.ToXFVK().DefaultAddress(), extfvk.GetChangeAddress()); } diff --git a/src/keystore.cpp b/src/keystore.cpp index 558477e31..d8b06b420 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -193,7 +193,7 @@ bool CBasicKeyStore::AddSaplingFullViewingKey( const libzcash::SaplingExtendedFullViewingKey &extfvk) { LOCK(cs_KeyStore); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); mapSaplingFullViewingKeys[ivk] = extfvk; return true; @@ -311,9 +311,10 @@ bool CBasicKeyStore::AddUnifiedFullViewingKey( // Add the Sapling component of the UFVK to the wallet. auto saplingKey = ufvk.GetSaplingKey(); if (saplingKey.has_value()) { - auto ivk = saplingKey.value().fvk.in_viewing_key(); + auto ivk = saplingKey.value().ToIncomingViewingKey(); mapSaplingKeyUnified.insert(std::make_pair(ivk, ufvk.GetKeyID())); - auto changeIvk = saplingKey.value().GetInternalDFVK().fvk.in_viewing_key(); + + auto changeIvk = saplingKey.value().GetChangeIVK(); mapSaplingKeyUnified.insert(std::make_pair(changeIvk, ufvk.GetKeyID())); } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 3ca5b4d45..167c6533f 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -461,8 +461,9 @@ std::pair AsyncRPCOperation_sendmany::SelectOVKs(const Spendab }, this->ztxoSelector_.GetPattern()); assert(dfvk.has_value()); - externalOVK = dfvk.value().fvk.ovk; - internalOVK = dfvk.value().GetInternalDFVK().fvk.ovk; + auto ovks = dfvk.value().GetOVKs(); + internalOVK = ovks.first; + externalOVK = ovks.second; } else if (!spendable.utxos.empty()) { std::optional tfvk; std::visit(match { diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index dc5d7ddd3..9c58be570 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -667,7 +667,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) { auto sk = GetTestMasterSaplingSpendingKey(); auto expsk = sk.expsk; auto extfvk = sk.ToXFVK(); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); auto pk = extfvk.DefaultAddress(); ASSERT_TRUE(wallet.AddSaplingZKey(sk)); @@ -1042,7 +1042,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { auto sk = GetTestMasterSaplingSpendingKey(); auto expsk = sk.expsk; auto extfvk = sk.ToXFVK(); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); auto pk = extfvk.DefaultAddress(); // Generate Sapling note A @@ -1991,7 +1991,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { auto sk = GetTestMasterSaplingSpendingKey(); auto expsk = sk.expsk; auto extfvk = sk.ToXFVK(); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); auto pk = extfvk.DefaultAddress(); ASSERT_TRUE(wallet.AddSaplingZKey(sk)); diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp index 219ae8d2d..728e14240 100644 --- a/src/wallet/gtest/test_wallet_zkeys.cpp +++ b/src/wallet/gtest/test_wallet_zkeys.cpp @@ -72,14 +72,14 @@ TEST(WalletZkeysTest, StoreAndLoadSaplingZkeys) { auto dpa = sk.ToXFVK().FindAddress(j).first; // add the default address - EXPECT_TRUE(wallet.AddSaplingPaymentAddress(sk.ToXFVK().fvk.in_viewing_key(), sk.ToXFVK().DefaultAddress())); + EXPECT_TRUE(wallet.AddSaplingPaymentAddress(sk.ToXFVK().ToIncomingViewingKey(), sk.ToXFVK().DefaultAddress())); // verify wallet only has the default address EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(sk.ToXFVK().DefaultAddress())); EXPECT_FALSE(wallet.HaveSaplingIncomingViewingKey(dpa)); // manually add a diversified address - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); EXPECT_TRUE(wallet.AddSaplingPaymentAddress(ivk, dpa)); // verify wallet did add it diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 14dbeb567..3dd295664 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -160,7 +160,7 @@ std::pair CWallet::GenerateLegacySaplingZKey(uint32 auto xsk = libzcash::SaplingExtendedSpendingKey::Legacy(seed, BIP44CoinType(), addrIndex); auto extfvk = xsk.first.ToXFVK(); if (!HaveSaplingSpendingKey(extfvk)) { - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); CKeyMetadata keyMeta(GetTime()); keyMeta.hdKeypath = xsk.second; keyMeta.seedFp = seed.Fingerprint(); @@ -409,11 +409,11 @@ bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullVi if (pwalletdbEncryption) { return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk, vchCryptedSecret, - mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]); + mapSaplingZKeyMetadata[extfvk.ToIncomingViewingKey()]); } else { return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk, vchCryptedSecret, - mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]); + mapSaplingZKeyMetadata[extfvk.ToIncomingViewingKey()]); } } return false; @@ -517,20 +517,19 @@ std::optional auto saplingEsk = usk.value().GetSaplingExtendedSpendingKey(); if (addSaplingKey(saplingEsk) == KeyNotAdded) { // If adding the Sapling key to the wallet failed, abort the process. - throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Unable to add Sapling key component to the wallet."); + throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Unable to add Sapling spending key to the wallet."); } // Add the Sapling change spending key to the wallet auto saplingChangeEsk = saplingEsk.DeriveInternalKey(); if (addSaplingKey(saplingChangeEsk) == KeyNotAdded) { // If adding the Sapling change key to the wallet failed, abort the process. - throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Unable to add Sapling key component to the wallet."); + throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Unable to add Sapling change key to the wallet."); } - // Associate the Sapling default change address with the IVK - auto saplingChangeDFVK = saplingEsk.ToXFVK().GetInternalDFVK(); - auto saplingChangeIVK = saplingChangeDFVK.fvk.in_viewing_key(); - if (!AddSaplingPaymentAddress(saplingChangeIVK, saplingChangeDFVK.GetChangeAddress())) { + // Associate the Sapling default change address with its IVK + auto saplingXFVK = saplingEsk.ToXFVK(); + if (!AddSaplingPaymentAddress(saplingXFVK.GetChangeIVK(), saplingXFVK.GetChangeAddress())) { throw std::runtime_error("CWallet::GenerateUnifiedSpendingKeyForAccount(): Failed to add Sapling change address to the wallet."); }; @@ -718,7 +717,7 @@ WalletUAGenerationResult CWallet::GenerateUnifiedAddress( auto saplingAddress = address.first.GetSaplingReceiver(); assert (dfvk.has_value() && saplingAddress.has_value()); - AddSaplingPaymentAddress(dfvk.value().fvk.in_viewing_key(), saplingAddress.value()); + AddSaplingPaymentAddress(dfvk.value().ToIncomingViewingKey(), saplingAddress.value()); } // Save the metadata for the generated address so that we can re-derive @@ -6240,11 +6239,11 @@ KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SproutViewingKey KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SaplingExtendedFullViewingKey &extfvk) const { if (m_wallet->HaveSaplingSpendingKey(extfvk)) { return SpendingKeyExists; - } else if (m_wallet->HaveSaplingFullViewingKey(extfvk.fvk.in_viewing_key())) { + } else if (m_wallet->HaveSaplingFullViewingKey(extfvk.ToIncomingViewingKey())) { return KeyAlreadyExists; } else if ( m_wallet->AddSaplingFullViewingKey(extfvk) && - (!addDefaultAddress || m_wallet->AddSaplingPaymentAddress(extfvk.fvk.in_viewing_key(), extfvk.DefaultAddress()))) { + (!addDefaultAddress || m_wallet->AddSaplingPaymentAddress(extfvk.ToIncomingViewingKey(), extfvk.DefaultAddress()))) { return KeyAdded; } else { return KeyNotAdded; @@ -6273,7 +6272,7 @@ KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKe } KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const { auto extfvk = sk.ToXFVK(); - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); auto addr = extfvk.DefaultAddress(); KeyIO keyIO(Params()); { // TODO: why is this extra scope here? diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 004467372..aa29b948e 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -138,7 +138,7 @@ bool CWalletDB::WriteCryptedSaplingZKey( { const bool fEraseUnencryptedKey = true; nWalletDBUpdateCounter++; - auto ivk = extfvk.fvk.in_viewing_key(); + auto ivk = extfvk.ToIncomingViewingKey(); if (!Write(std::make_pair(std::string("sapzkeymeta"), ivk), keyMeta)) return false; diff --git a/src/zcash/address/zip32.cpp b/src/zcash/address/zip32.cpp index f5507473c..700057d03 100644 --- a/src/zcash/address/zip32.cpp +++ b/src/zcash/address/zip32.cpp @@ -56,7 +56,7 @@ std::optional diversifier_index_t::ToTransparentChildIndex() const { } // -// Sapling +// SaplingExtendedFullViewingKey // std::optional SaplingExtendedFullViewingKey::Derive(uint32_t i) const @@ -80,6 +80,10 @@ std::optional SaplingExtendedFullViewingKey::Deri } } +// +// SaplingDiversifiableFullViewingKey +// + std::optional SaplingDiversifiableFullViewingKey::Address(diversifier_index_t j) const { @@ -144,11 +148,24 @@ libzcash::SaplingDiversifiableFullViewingKey SaplingDiversifiableFullViewingKey: return internalDFVK; } +libzcash::SaplingIncomingViewingKey SaplingDiversifiableFullViewingKey::GetChangeIVK() const { + auto internalDFVK = this->GetInternalDFVK(); + return internalDFVK.fvk.in_viewing_key(); +} + libzcash::SaplingPaymentAddress SaplingDiversifiableFullViewingKey::GetChangeAddress() const { auto internalDFVK = this->GetInternalDFVK(); return internalDFVK.DefaultAddress(); } +std::pair SaplingDiversifiableFullViewingKey::GetOVKs() const { + return std::make_pair(this->GetInternalDFVK().fvk.ovk, fvk.ovk); +} + +// +// SaplingExtendedSpendingKey +// + SaplingExtendedSpendingKey SaplingExtendedSpendingKey::Master(const HDSeed& seed) { auto rawSeed = seed.RawSeed(); diff --git a/src/zcash/address/zip32.h b/src/zcash/address/zip32.h index 9b30b93f8..9f2b18397 100644 --- a/src/zcash/address/zip32.h +++ b/src/zcash/address/zip32.h @@ -131,6 +131,9 @@ public: const libzcash::diversifier_index_t MAX_TRANSPARENT_CHILD_IDX(0x7FFFFFFF); class SaplingDiversifiableFullViewingKey { +protected: + SaplingDiversifiableFullViewingKey GetInternalDFVK() const; + public: libzcash::SaplingFullViewingKey fvk; uint256 dk; @@ -153,12 +156,21 @@ public: return std::make_pair(addr.value(), j); } - SaplingDiversifiableFullViewingKey GetInternalDFVK() const; + libzcash::SaplingIncomingViewingKey ToIncomingViewingKey() const { + return fvk.in_viewing_key(); + } libzcash::SaplingPaymentAddress DefaultAddress() const; + libzcash::SaplingIncomingViewingKey GetChangeIVK() const; libzcash::SaplingPaymentAddress GetChangeAddress() const; + /** + * Returns the (internal, external) OVKs for shielded spends + * from the associated spend authority. + */ + std::pair GetOVKs() const; + ADD_SERIALIZE_METHODS; template