Store ufvks to the wallet database.
This commit is contained in:
parent
6d36921b94
commit
ef068c51a9
|
@ -287,3 +287,31 @@ bool CBasicKeyStore::GetSaplingExtendedSpendingKey(const libzcash::SaplingPaymen
|
|||
GetSaplingFullViewingKey(ivk, extfvk) &&
|
||||
GetSaplingSpendingKey(extfvk, extskOut);
|
||||
}
|
||||
|
||||
//
|
||||
// Unified Keys
|
||||
//
|
||||
|
||||
bool CBasicKeyStore::AddUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& keyId,
|
||||
const libzcash::ZcashdUnifiedFullViewingKey &ufvk)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
|
||||
auto tKey = ufvk.GetTransparentKey();
|
||||
if (tKey.has_value()) {
|
||||
// FIXME: this is probably not the right thing; we need to actually track
|
||||
// addresses, not the id at the FVK level?
|
||||
mapTKeyUnified.insert(std::make_pair(tKey.value().GetPubKey().GetID(), keyId));
|
||||
}
|
||||
|
||||
auto saplingKey = ufvk.GetSaplingKey();
|
||||
if (saplingKey.has_value()) {
|
||||
auto ivk = saplingKey.value().fvk.in_viewing_key();
|
||||
mapSaplingKeyUnified.insert(std::make_pair(ivk, keyId));
|
||||
}
|
||||
|
||||
mapUnifiedFullViewingKeys.insert({keyId, ufvk});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "script/standard.h"
|
||||
#include "sync.h"
|
||||
#include "zcash/address/mnemonic.h"
|
||||
#include "zcash/address/unified.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "zcash/NoteEncryption.hpp"
|
||||
|
||||
|
@ -100,6 +101,12 @@ public:
|
|||
virtual bool GetSproutViewingKey(
|
||||
const libzcash::SproutPaymentAddress &address,
|
||||
libzcash::SproutViewingKey& vkOut) const =0;
|
||||
|
||||
//! Unified addresses and keys
|
||||
virtual bool AddUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& keyId,
|
||||
const libzcash::ZcashdUnifiedFullViewingKey &ufvk
|
||||
) = 0;
|
||||
};
|
||||
|
||||
typedef std::map<CKeyID, CKey> KeyMap;
|
||||
|
@ -142,6 +149,10 @@ protected:
|
|||
SaplingFullViewingKeyMap mapSaplingFullViewingKeys;
|
||||
SaplingIncomingViewingKeyMap mapSaplingIncomingViewingKeys;
|
||||
|
||||
// Unified key support
|
||||
std::map<CKeyID, libzcash::UFVKId> mapTKeyUnified;
|
||||
std::map<libzcash::SaplingIncomingViewingKey, libzcash::UFVKId> mapSaplingKeyUnified;
|
||||
std::map<libzcash::UFVKId, libzcash::ZcashdUnifiedFullViewingKey> mapUnifiedFullViewingKeys;
|
||||
public:
|
||||
bool SetMnemonicSeed(const MnemonicSeed& seed);
|
||||
bool HaveMnemonicSeed() const;
|
||||
|
@ -314,6 +325,10 @@ public:
|
|||
virtual bool GetSproutViewingKey(
|
||||
const libzcash::SproutPaymentAddress &address,
|
||||
libzcash::SproutViewingKey& vkOut) const;
|
||||
|
||||
virtual bool AddUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& keyId,
|
||||
const libzcash::ZcashdUnifiedFullViewingKey &ufvk);
|
||||
};
|
||||
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||
|
|
|
@ -195,7 +195,9 @@ bool CWallet::AddSaplingZKey(const libzcash::SaplingExtendedSpendingKey &sk)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::AddSaplingFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk)
|
||||
bool CWallet::AddSaplingFullViewingKey(
|
||||
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::optional<libzcash::UFVKId>& ufvkId)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
|
@ -287,7 +289,7 @@ CPubKey CWallet::GenerateNewKey()
|
|||
// if we did not successfully generate a key, try again.
|
||||
} while (!extKey.has_value());
|
||||
|
||||
auto pubkey = AddKey(seed.Fingerprint(), extKey.value());
|
||||
auto pubkey = AddTransparentSecretKey(seed.Fingerprint(), extKey.value());
|
||||
|
||||
// Update the persisted chain information
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteMnemonicHDChain(hdChain)) {
|
||||
|
@ -297,7 +299,10 @@ CPubKey CWallet::GenerateNewKey()
|
|||
return pubkey;
|
||||
}
|
||||
|
||||
CPubKey CWallet::AddKey(const uint256& seedFingerprint, const std::pair<CExtKey, HDKeyPath>& extSecret)
|
||||
CPubKey CWallet::AddTransparentSecretKey(
|
||||
const uint256& seedFingerprint,
|
||||
const std::pair<CExtKey, HDKeyPath>& extSecret,
|
||||
const std::optional<libzcash::UFVKId>& ufvkId)
|
||||
{
|
||||
CKey secret = extSecret.first.key;
|
||||
CPubKey pubkey = secret.GetPubKey();
|
||||
|
@ -311,13 +316,16 @@ CPubKey CWallet::AddKey(const uint256& seedFingerprint, const std::pair<CExtKey,
|
|||
if (nTimeFirstKey == 0 || keyMeta.nCreateTime < nTimeFirstKey)
|
||||
nTimeFirstKey = keyMeta.nCreateTime;
|
||||
|
||||
if (!AddKeyPubKey(secret, pubkey))
|
||||
throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
|
||||
if (!AddKeyPubKey(secret, pubkey, ufvkId))
|
||||
throw std::runtime_error("CWallet::GenerateNewKey(): AddKeyPubKey failed");
|
||||
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||
bool CWallet::AddKeyPubKey(
|
||||
const CKey& secret,
|
||||
const CPubKey &pubkey,
|
||||
const std::optional<libzcash::UFVKId>& ufvkId)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
|
||||
|
@ -334,11 +342,13 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
|||
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
|
||||
if (!IsCrypted()) {
|
||||
return CWalletDB(strWalletFile).WriteKey(pubkey,
|
||||
secret.GetPrivKey(),
|
||||
mapKeyMetadata[pubkey.GetID()]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -456,29 +466,42 @@ std::optional<std::pair<libzcash::ZcashdUnifiedSpendingKey, libzcash::ZcashdUnif
|
|||
}
|
||||
}
|
||||
|
||||
// Add spending key to keystore
|
||||
bool CWallet::AddUnifiedSpendingKey(
|
||||
const libzcash::ZcashdUnifiedSpendingKey& sk,
|
||||
const libzcash::ZcashdUnifiedKeyMetadata& metadata) {
|
||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||
AssertLockHeld(cs_wallet); // mapUnifiedKeyMetadata
|
||||
|
||||
auto ufvk = sk.ToFullViewingKey();
|
||||
// We don't store the spending key directly; instead, we store each of the spending key's
|
||||
// components, in order to not violate invariants with respect to the encryption of the
|
||||
// wallet. Instead, we store each component in the appropriate wallet subsystem, and
|
||||
// store the metadata that can be used to re-derive the key associated with the fingerprint
|
||||
// of the associated full viewing key.
|
||||
|
||||
auto zufvk = sk.ToFullViewingKey();
|
||||
auto metaKey = std::make_pair(metadata.GetSeedFingerprint(), metadata.GetAccountId());
|
||||
mapUnifiedKeyMetadata.insert({metaKey, metadata});
|
||||
|
||||
// Add Transparent component to the wallet
|
||||
if (sk.GetTransparentKey().has_value()) {
|
||||
AddKey(metadata.GetSeedFingerprint(),
|
||||
AddTransparentSecretKey(metadata.GetSeedFingerprint(),
|
||||
std::make_pair(sk.GetTransparentKey().value(), metadata.TransparentKeyPath().value()));
|
||||
}
|
||||
|
||||
// Add Sapling component to the wallet
|
||||
auto addSpendingKey = AddSpendingKeyToWallet(
|
||||
if (sk.GetSaplingExtendedSpendingKey().has_value()) {
|
||||
auto esk = sk.GetSaplingExtendedSpendingKey().value();
|
||||
auto addSpendingKey = AddSpendingKeyToWallet(
|
||||
this, Params().GetConsensus(), GetTime(),
|
||||
metadata.SaplingKeyPath(), metadata.GetSeedFingerprint().GetHex(), true);
|
||||
if (sk.GetSaplingExtendedSpendingKey().has_value() &&
|
||||
addSpendingKey(sk.GetSaplingExtendedSpendingKey().value()) == KeyNotAdded) {
|
||||
// If adding the Sapling key to the wallet failed, abort the process.
|
||||
if (addSpendingKey(esk) == KeyNotAdded) {
|
||||
// If adding the Sapling key to the wallet failed, abort the process.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto ufvk = UnifiedFullViewingKey::FromZcashdUFVK(zufvk);
|
||||
auto ufvkid = ufvk.GetKeyID(Params());
|
||||
if (!CCryptoKeyStore::AddUnifiedFullViewingKey(ufvkid, zufvk)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -486,11 +509,32 @@ bool CWallet::AddUnifiedSpendingKey(
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!IsCrypted()) {
|
||||
//return CWalletDB(strWalletFile).WriteUnifiedFullViewingKey(ufvk, metadata);
|
||||
return CWalletDB(strWalletFile).WriteUnifiedFullViewingKey(ufvkid, ufvk);
|
||||
}
|
||||
|
||||
bool CWallet::AddUnifiedFullViewingKey(const libzcash::UnifiedFullViewingKey &ufvk)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(ufvk);
|
||||
auto keyId = ufvk.GetKeyID(Params());
|
||||
if (!CCryptoKeyStore::AddUnifiedFullViewingKey(keyId, zufvk)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!fFileBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return CWalletDB(strWalletFile).WriteUnifiedFullViewingKey(keyId, ufvk);
|
||||
}
|
||||
|
||||
bool CWallet::LoadUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& keyId,
|
||||
const libzcash::UnifiedFullViewingKey &key)
|
||||
{
|
||||
auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(key);
|
||||
return CCryptoKeyStore::AddUnifiedFullViewingKey(keyId, zufvk);
|
||||
}
|
||||
|
||||
void CWallet::LoadUnifiedKeyMetadata(const libzcash::ZcashdUnifiedKeyMetadata &meta)
|
||||
|
|
|
@ -702,8 +702,13 @@ private:
|
|||
int nSetChainUpdates;
|
||||
bool fBroadcastTransactions;
|
||||
|
||||
/**
|
||||
* A map from protocol-specifiec transaction output identifier to
|
||||
* a txid.
|
||||
*/
|
||||
template <class T>
|
||||
using TxSpendMap = std::multimap<T, uint256>;
|
||||
|
||||
/**
|
||||
* Used to keep track of spent outpoints, and
|
||||
* detect and report conflicts (double-spends or
|
||||
|
@ -711,6 +716,7 @@ private:
|
|||
*/
|
||||
typedef TxSpendMap<COutPoint> TxSpends;
|
||||
TxSpends mapTxSpends;
|
||||
|
||||
/**
|
||||
* Used to keep track of spent Notes, and
|
||||
* detect and report conflicts (double-spends).
|
||||
|
@ -804,7 +810,10 @@ private:
|
|||
void ChainTipAdded(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree);
|
||||
|
||||
/* Add an extended secret key to the wallet. Internal use only. */
|
||||
CPubKey AddKey(const uint256& seedFingerprint, const std::pair<CExtKey, HDKeyPath>& extSecret);
|
||||
CPubKey AddTransparentSecretKey(
|
||||
const uint256& seedFingerprint,
|
||||
const std::pair<CExtKey, HDKeyPath>& extSecret,
|
||||
const std::optional<libzcash::UFVKId>& ufvkId = std::nullopt);
|
||||
|
||||
protected:
|
||||
bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
|
||||
|
@ -831,8 +840,10 @@ public:
|
|||
|
||||
std::set<int64_t> setKeyPool;
|
||||
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
|
||||
|
||||
std::map<libzcash::SproutPaymentAddress, CKeyMetadata> mapSproutZKeyMetadata;
|
||||
std::map<libzcash::SaplingIncomingViewingKey, CKeyMetadata> mapSaplingZKeyMetadata;
|
||||
|
||||
std::map<std::pair<libzcash::SeedFingerprint, libzcash::AccountId>, libzcash::ZcashdUnifiedKeyMetadata> mapUnifiedKeyMetadata;
|
||||
|
||||
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
|
||||
|
@ -999,7 +1010,10 @@ public:
|
|||
*/
|
||||
CPubKey GenerateNewKey();
|
||||
//! Adds a key to the store, and saves it to disk.
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||
bool AddKeyPubKey(
|
||||
const CKey& key,
|
||||
const CPubKey &pubkey,
|
||||
const std::optional<libzcash::UFVKId>& ufvkId = std::nullopt);
|
||||
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
|
||||
//! Load metadata (used by LoadWallet)
|
||||
|
@ -1078,7 +1092,9 @@ public:
|
|||
//! full viewing key to disk. Inside CCryptoKeyStore and CBasicKeyStore,
|
||||
//! CBasicKeyStore::AddSaplingFullViewingKey is called directly when adding a
|
||||
//! full viewing key to the keystore, to avoid this override.
|
||||
bool AddSaplingFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk);
|
||||
bool AddSaplingFullViewingKey(
|
||||
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::optional<libzcash::UFVKId>& ufvkId = std::nullopt);
|
||||
bool AddSaplingIncomingViewingKey(
|
||||
const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
const libzcash::SaplingPaymentAddress &addr);
|
||||
|
@ -1115,11 +1131,16 @@ public:
|
|||
GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId);
|
||||
|
||||
//! Add the specified unified spending key to the wallet with the provided key
|
||||
//! metadata.
|
||||
//! metadata. -- TODO, this should probably not be part of the public API?
|
||||
bool AddUnifiedSpendingKey(
|
||||
const libzcash::ZcashdUnifiedSpendingKey& sk,
|
||||
const libzcash::ZcashdUnifiedKeyMetadata& metadata);
|
||||
|
||||
bool AddUnifiedFullViewingKey(const libzcash::UnifiedFullViewingKey &ufvk);
|
||||
bool LoadUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& keyId,
|
||||
const libzcash::UnifiedFullViewingKey &key);
|
||||
|
||||
void LoadUnifiedKeyMetadata(const libzcash::ZcashdUnifiedKeyMetadata &meta);
|
||||
|
||||
/**
|
||||
|
|
|
@ -217,6 +217,22 @@ bool CWalletDB::EraseSaplingExtendedFullViewingKey(
|
|||
return Erase(std::make_pair(std::string("sapextfvk"), extfvk));
|
||||
}
|
||||
|
||||
//
|
||||
// Unified address & key storage
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& ufvkId,
|
||||
const libzcash::UnifiedFullViewingKey& ufvk)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("unifiedfvk"), ufvkId), ufvk.Encode(Params()));
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
|
|
|
@ -249,6 +249,12 @@ public:
|
|||
bool WriteSaplingExtendedFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk);
|
||||
bool EraseSaplingExtendedFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk);
|
||||
|
||||
/// Unified key support.
|
||||
|
||||
bool WriteUnifiedFullViewingKey(
|
||||
const libzcash::UFVKId& ufvkId,
|
||||
const libzcash::UnifiedFullViewingKey& ufvk);
|
||||
|
||||
static void IncrementUpdateCounter();
|
||||
static unsigned int GetUpdateCounter();
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue