Browse Source

Store ExtFVK with encrypted Sapling spending key instead of FVK

This ensures that even when the wallet is encrypted, we can derive the default
Sapling payment address for our spending keys.
pull/4/head
Jack Grigg 6 years ago
parent
commit
1b79de781c
No known key found for this signature in database GPG Key ID: 1B8D649257DB0829
  1. 2
      src/keystore.h
  2. 38
      src/wallet/crypter.cpp
  3. 8
      src/wallet/crypter.h
  4. 4
      src/wallet/wallet.cpp
  5. 2
      src/wallet/wallet.h
  6. 15
      src/zcash/zip32.h

2
src/keystore.h

@ -311,6 +311,6 @@ typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > Crypt
typedef std::map<libzcash::SproutPaymentAddress, std::vector<unsigned char> > CryptedSproutSpendingKeyMap;
//! Sapling
typedef std::map<libzcash::SaplingFullViewingKey, std::vector<unsigned char> > CryptedSaplingSpendingKeyMap;
typedef std::map<libzcash::SaplingExtendedFullViewingKey, std::vector<unsigned char> > CryptedSaplingSpendingKeyMap;
#endif // BITCOIN_KEYSTORE_H

38
src/wallet/crypter.cpp

@ -170,11 +170,11 @@ static bool DecryptSproutSpendingKey(const CKeyingMaterial& vMasterKey,
static bool DecryptSaplingSpendingKey(const CKeyingMaterial& vMasterKey,
const std::vector<unsigned char>& vchCryptedSecret,
const libzcash::SaplingFullViewingKey& fvk,
const libzcash::SaplingExtendedFullViewingKey& extfvk,
libzcash::SaplingExtendedSpendingKey& sk)
{
CKeyingMaterial vchSecret;
if (!DecryptSecret(vMasterKey, vchCryptedSecret, fvk.GetFingerprint(), vchSecret))
if (!DecryptSecret(vMasterKey, vchCryptedSecret, extfvk.fvk.GetFingerprint(), vchSecret))
return false;
if (vchSecret.size() != ZIP32_XSK_SIZE)
@ -182,7 +182,7 @@ static bool DecryptSaplingSpendingKey(const CKeyingMaterial& vMasterKey,
CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION);
ss >> sk;
return sk.expsk.full_viewing_key() == fvk;
return sk.expsk.full_viewing_key() == extfvk.fvk;
}
bool CCryptoKeyStore::SetCrypted()
@ -261,10 +261,10 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
CryptedSaplingSpendingKeyMap::const_iterator miSapling = mapCryptedSaplingSpendingKeys.begin();
for (; miSapling != mapCryptedSaplingSpendingKeys.end(); ++miSapling)
{
const libzcash::SaplingFullViewingKey &fvk = (*miSapling).first;
const libzcash::SaplingExtendedFullViewingKey &extfvk = (*miSapling).first;
const std::vector<unsigned char> &vchCryptedSecret = (*miSapling).second;
libzcash::SaplingExtendedSpendingKey sk;
if (!DecryptSaplingSpendingKey(vMasterKeyIn, vchCryptedSecret, fvk, sk))
if (!DecryptSaplingSpendingKey(vMasterKeyIn, vchCryptedSecret, extfvk, sk))
{
keyFail = true;
break;
@ -465,12 +465,12 @@ bool CCryptoKeyStore::AddSaplingSpendingKey(
CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << sk;
CKeyingMaterial vchSecret(ss.begin(), ss.end());
auto fvk = sk.expsk.full_viewing_key();
if (!EncryptSecret(vMasterKey, vchSecret, fvk.GetFingerprint(), vchCryptedSecret)) {
auto extfvk = sk.ToXFVK();
if (!EncryptSecret(vMasterKey, vchSecret, extfvk.fvk.GetFingerprint(), vchCryptedSecret)) {
return false;
}
if (!AddCryptedSaplingSpendingKey(fvk, vchCryptedSecret, defaultAddr)) {
if (!AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr)) {
return false;
}
}
@ -494,7 +494,7 @@ bool CCryptoKeyStore::AddCryptedSproutSpendingKey(
}
bool CCryptoKeyStore::AddCryptedSaplingSpendingKey(
const libzcash::SaplingFullViewingKey &fvk,
const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret,
const libzcash::SaplingPaymentAddress &defaultAddr)
{
@ -505,11 +505,11 @@ bool CCryptoKeyStore::AddCryptedSaplingSpendingKey(
}
// if SaplingFullViewingKey is not in SaplingFullViewingKeyMap, add it
if (!AddSaplingFullViewingKey(fvk, defaultAddr)) {
if (!AddSaplingFullViewingKey(extfvk.fvk, defaultAddr)) {
return false;
}
mapCryptedSaplingSpendingKeys[fvk] = vchCryptedSecret;
mapCryptedSaplingSpendingKeys[extfvk] = vchCryptedSecret;
}
return true;
}
@ -538,11 +538,11 @@ bool CCryptoKeyStore::GetSaplingSpendingKey(const libzcash::SaplingFullViewingKe
if (!IsCrypted())
return CBasicKeyStore::GetSaplingSpendingKey(fvk, skOut);
CryptedSaplingSpendingKeyMap::const_iterator mi = mapCryptedSaplingSpendingKeys.find(fvk);
if (mi != mapCryptedSaplingSpendingKeys.end())
{
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
return DecryptSaplingSpendingKey(vMasterKey, vchCryptedSecret, fvk, skOut);
for (auto entry : mapCryptedSaplingSpendingKeys) {
if (entry.first.fvk == fvk) {
const std::vector<unsigned char> &vchCryptedSecret = entry.second;
return DecryptSaplingSpendingKey(vMasterKey, vchCryptedSecret, entry.first, skOut);
}
}
}
return false;
@ -609,12 +609,12 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << sk;
CKeyingMaterial vchSecret(ss.begin(), ss.end());
libzcash::SaplingFullViewingKey fvk = sk.expsk.full_viewing_key();
auto extfvk = sk.ToXFVK();
std::vector<unsigned char> vchCryptedSecret;
if (!EncryptSecret(vMasterKeyIn, vchSecret, fvk.GetFingerprint(), vchCryptedSecret)) {
if (!EncryptSecret(vMasterKeyIn, vchSecret, extfvk.fvk.GetFingerprint(), vchCryptedSecret)) {
return false;
}
if (!AddCryptedSaplingSpendingKey(fvk, vchCryptedSecret, sk.DefaultAddress())) {
if (!AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, sk.DefaultAddress())) {
return false;
}
}

8
src/wallet/crypter.h

@ -241,7 +241,7 @@ public:
}
//! Sapling
virtual bool AddCryptedSaplingSpendingKey(
const libzcash::SaplingFullViewingKey &fvk,
const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret,
const libzcash::SaplingPaymentAddress &defaultAddr);
bool AddSaplingSpendingKey(
@ -253,7 +253,11 @@ public:
LOCK(cs_SpendingKeyStore);
if (!IsCrypted())
return CBasicKeyStore::HaveSaplingSpendingKey(fvk);
return mapCryptedSaplingSpendingKeys.count(fvk) > 0;
for (auto entry : mapCryptedSaplingSpendingKeys) {
if (entry.first.fvk == fvk) {
return true;
}
}
}
return false;
}

4
src/wallet/wallet.cpp

@ -293,11 +293,11 @@ bool CWallet::AddCryptedSproutSpendingKey(
return false;
}
bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk,
bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret,
const libzcash::SaplingPaymentAddress &defaultAddr)
{
if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(fvk, vchCryptedSecret, defaultAddr))
if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr))
return false;
if (!fFileBacked)
return true;

2
src/wallet/wallet.h

@ -1060,7 +1060,7 @@ public:
const libzcash::SaplingExtendedSpendingKey &key,
const libzcash::SaplingPaymentAddress &defaultAddr);
bool AddCryptedSaplingSpendingKey(
const libzcash::SaplingFullViewingKey &fvk,
const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret,
const libzcash::SaplingPaymentAddress &defaultAddr);

15
src/zcash/zip32.h

@ -78,6 +78,21 @@ struct SaplingExtendedFullViewingKey {
Address(diversifier_index_t j) const;
libzcash::SaplingPaymentAddress DefaultAddress() const;
friend inline bool operator==(const SaplingExtendedFullViewingKey& a, const SaplingExtendedFullViewingKey& b) {
return (
a.depth == b.depth &&
a.parentFVKTag == b.parentFVKTag &&
a.childIndex == b.childIndex &&
a.chaincode == b.chaincode &&
a.fvk == b.fvk &&
a.dk == b.dk);
}
friend inline bool operator<(const SaplingExtendedFullViewingKey& a, const SaplingExtendedFullViewingKey& b) {
return (a.depth < b.depth ||
(a.depth == b.depth && a.childIndex < b.childIndex) ||
(a.depth == b.depth && a.childIndex == b.childIndex && a.fvk < b.fvk));
}
};
struct SaplingExtendedSpendingKey {

Loading…
Cancel
Save