Add accessor method for Sapling IVKs to SaplingDiversifiableFullViewingKey

This commit is contained in:
Kris Nuttycombe 2022-01-30 17:14:03 -07:00
parent 2209a74f38
commit a46720aab1
10 changed files with 59 additions and 31 deletions

View File

@ -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);

View File

@ -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());
}

View File

@ -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()));
}

View File

@ -461,8 +461,9 @@ std::pair<uint256, uint256> 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<transparent::AccountPubKey> tfvk;
std::visit(match {

View File

@ -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));

View File

@ -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

View File

@ -160,7 +160,7 @@ std::pair<SaplingPaymentAddress, bool> 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<libzcash::ZcashdUnifiedSpendingKey>
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?

View File

@ -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;

View File

@ -56,7 +56,7 @@ std::optional<uint32_t> diversifier_index_t::ToTransparentChildIndex() const {
}
//
// Sapling
// SaplingExtendedFullViewingKey
//
std::optional<SaplingExtendedFullViewingKey> SaplingExtendedFullViewingKey::Derive(uint32_t i) const
@ -80,6 +80,10 @@ std::optional<SaplingExtendedFullViewingKey> SaplingExtendedFullViewingKey::Deri
}
}
//
// SaplingDiversifiableFullViewingKey
//
std::optional<libzcash::SaplingPaymentAddress>
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<uint256, uint256> SaplingDiversifiableFullViewingKey::GetOVKs() const {
return std::make_pair(this->GetInternalDFVK().fvk.ovk, fvk.ovk);
}
//
// SaplingExtendedSpendingKey
//
SaplingExtendedSpendingKey SaplingExtendedSpendingKey::Master(const HDSeed& seed)
{
auto rawSeed = seed.RawSeed();

View File

@ -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<uint256, uint256> GetOVKs() const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>