From 0b5e99a0749fab1252c23ec58e287ba9148d7b48 Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Fri, 14 Apr 2023 15:05:04 -0400 Subject: [PATCH] wallet: implement IsKeyActive() in scriptpubkeyman This new method returns true if the given CScript key is derived from the SPKM. For Legacy that means checking the hd_seed_id in the key's metadata. Also patches PKDescriptor to return associated public keys in MakeScripts() Github-Pull: #27216 Rebased-From: f39957f5deec87d141e995a3bc90cc54e2d0ccbf --- src/script/descriptor.cpp | 5 ++++- src/wallet/scriptpubkeyman.cpp | 17 +++++++++++++++++ src/wallet/scriptpubkeyman.h | 7 +++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index c6bc5f8f1d..8acec705e0 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -772,8 +772,11 @@ class PKDescriptor final : public DescriptorImpl private: const bool m_xonly; protected: - std::vector MakeScripts(const std::vector& keys, Span, FlatSigningProvider&) const override + std::vector MakeScripts(const std::vector& keys, Span, FlatSigningProvider& out) const override { + CKeyID id = keys[0].GetID(); + out.pubkeys.emplace(id, keys[0]); + if (m_xonly) { CScript script = CScript() << ToByteVector(XOnlyPubKey(keys[0])) << OP_CHECKSIG; return Vector(std::move(script)); diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index e10a17f003..01b7ec8ba6 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -395,6 +395,23 @@ std::vector LegacyScriptPubKeyMan::MarkUnusedAddresses(const return result; } +bool LegacyScriptPubKeyMan::IsKeyActive(const CScript& script) const +{ + LOCK(cs_KeyStore); + + if (!IsMine(script)) return false; // Not in the keystore at all + + for (const auto& key_id : GetAffectedKeys(script, *this)) { + const auto it = mapKeyMetadata.find(key_id); + if (it == mapKeyMetadata.end()) return false; // This key must be really old + + if (!it->second.hd_seed_id.IsNull() && it->second.hd_seed_id == m_hd_chain.seed_id) return true; + } + + // Imported or dumped for a new keypool + return false; +} + void LegacyScriptPubKeyMan::UpgradeKeyMetadata() { LOCK(cs_KeyStore); diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index 2d83ae556f..4d2e2e5a8b 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -204,6 +204,9 @@ public: */ virtual std::vector MarkUnusedAddresses(const CScript& script) { return {}; } + /* Determines if address is derived from active key manager */ + virtual bool IsKeyActive(const CScript& script) const = 0; + /** Sets up the key generation stuff, i.e. generates new HD seeds and sets them as active. * Returns false if already setup or setup fails, true if setup is successful * Set force=true to make it re-setup if already setup, used for upgrades @@ -393,6 +396,8 @@ public: std::vector MarkUnusedAddresses(const CScript& script) override; + [[nodiscard]] bool IsKeyActive(const CScript& script) const override; + //! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo void UpgradeKeyMetadata(); @@ -627,6 +632,8 @@ public: std::vector MarkUnusedAddresses(const CScript& script) override; + [[nodiscard]] bool IsKeyActive(const CScript& script) const override { return IsMine(script); } + bool IsHDEnabled() const override; //! Setup descriptors based on the given CExtkey