From a4ac4fc3f413b65fbf9c3a12081ce6d287819e9b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 27 Aug 2018 16:47:17 +0100 Subject: [PATCH] wallet: Store Sapling key metadata indexed by ivk Closes #3426. --- src/wallet/rpcdump.cpp | 19 +++++++++++++------ src/wallet/wallet.cpp | 5 +++-- src/wallet/wallet.h | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index e4a6e179d..1ed79d0f3 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -554,8 +554,10 @@ class AddSpendingKeyToWallet : public boost::static_visitor { private: CWallet *m_wallet; + const Consensus::Params ¶ms; public: - AddSpendingKeyToWallet(CWallet *wallet) : m_wallet(wallet) {} + AddSpendingKeyToWallet(CWallet *wallet, const Consensus::Params ¶ms) : + m_wallet(wallet), params(params) {} bool operator()(const libzcash::SproutSpendingKey &sk) const { auto addr = sk.address(); @@ -577,6 +579,7 @@ public: bool operator()(const libzcash::SaplingSpendingKey &sk) const { auto fvk = sk.full_viewing_key(); + auto ivk = fvk.in_viewing_key(); auto addr = sk.default_address(); { // Don't throw error in case a key is already there @@ -588,9 +591,12 @@ public: if (!m_wallet-> AddSaplingZKey(sk, addr)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet"); } - - m_wallet->mapSaplingZKeyMetadata[addr].nCreateTime = 1; - + + // Sapling addresses can't have been used in transactions prior to activation. + m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max( + 1, // In case a code fork sets Sapling to always be active + params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight); + return false; } } @@ -672,9 +678,10 @@ UniValue z_importkey(const UniValue& params, bool fHelp) if (!IsValidSpendingKey(spendingkey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); } - + // Sapling support - auto keyAlreadyExists = boost::apply_visitor(AddSpendingKeyToWallet(pwalletMain), spendingkey); + auto keyAlreadyExists = boost::apply_visitor( + AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus()), spendingkey); if (keyAlreadyExists && fIgnoreExistingKey) { return NullUniValue; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a093172b2..ed7830ec4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -107,6 +107,7 @@ SaplingPaymentAddress CWallet::GenerateNewSaplingZKey() auto sk = SaplingSpendingKey::random(); auto fvk = sk.full_viewing_key(); + auto ivk = fvk.in_viewing_key(); auto addr = sk.default_address(); // Check for collision, even though it is unlikely to ever occur @@ -116,8 +117,8 @@ SaplingPaymentAddress CWallet::GenerateNewSaplingZKey() // Create new metadata int64_t nCreationTime = GetTime(); - mapSaplingZKeyMetadata[addr] = CKeyMetadata(nCreationTime); - + mapSaplingZKeyMetadata[ivk] = CKeyMetadata(nCreationTime); + if (!AddSaplingZKey(sk, addr)) { throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed"); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 00491b5ea..f9026937b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -846,7 +846,7 @@ public: std::set setKeyPool; std::map mapKeyMetadata; std::map mapZKeyMetadata; - std::map mapSaplingZKeyMetadata; + std::map mapSaplingZKeyMetadata; typedef std::map MasterKeyMap; MasterKeyMap mapMasterKeys;