From ef6745879d87cdb6f1061337867a689167e965a1 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 20 Dec 2023 18:11:41 -0500 Subject: [PATCH 01/13] key: Add constructor for CExtKey that takes CExtPubKey and CKey We often need to construct a CExtKey given an CExtPubKey and CKey, so implement a constructor that does that for us. --- src/key.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/key.h b/src/key.h index d6b26f891d0e4..53acd179ba8f7 100644 --- a/src/key.h +++ b/src/key.h @@ -223,6 +223,12 @@ struct CExtKey { a.key == b.key; } + CExtKey() = default; + CExtKey(const CExtPubKey& xpub, const CKey& key_in) : nDepth(xpub.nDepth), nChild(xpub.nChild), chaincode(xpub.chaincode), key(key_in) + { + std::copy(xpub.vchFingerprint, xpub.vchFingerprint + sizeof(xpub.vchFingerprint), vchFingerprint); + } + void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); [[nodiscard]] bool Derive(CExtKey& out, unsigned int nChild) const; From fe67841464cc0f970a1c233caba92cb78e9c78dc Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 20 Dec 2023 18:11:49 -0500 Subject: [PATCH 02/13] descriptor: Be able to get the pubkeys involved in a descriptor --- src/script/descriptor.cpp | 42 ++++++++++++++++++++++++++++ src/script/descriptor.h | 7 +++++ src/wallet/test/walletload_tests.cpp | 1 + 3 files changed, 50 insertions(+) diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index c6bc5f8f1d34f..a0e755afacb2e 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -212,6 +212,11 @@ struct PubkeyProvider /** Derive a private key, if private data is available in arg. */ virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0; + + /** Return the non-extended public key for this PubkeyProvider, if it has one. */ + virtual std::optional GetRootPubKey() const = 0; + /** Return the extended public key for this PubkeyProvider, if it has one. */ + virtual std::optional GetRootExtPubKey() const = 0; }; class OriginPubkeyProvider final : public PubkeyProvider @@ -265,6 +270,14 @@ class OriginPubkeyProvider final : public PubkeyProvider { return m_provider->GetPrivKey(pos, arg, key); } + std::optional GetRootPubKey() const override + { + return m_provider->GetRootPubKey(); + } + std::optional GetRootExtPubKey() const override + { + return m_provider->GetRootExtPubKey(); + } }; /** An object representing a parsed constant public key in a descriptor. */ @@ -310,6 +323,14 @@ class ConstPubkeyProvider final : public PubkeyProvider { return arg.GetKey(m_pubkey.GetID(), key); } + std::optional GetRootPubKey() const override + { + return m_pubkey; + } + std::optional GetRootExtPubKey() const override + { + return std::nullopt; + } }; enum class DeriveType { @@ -525,6 +546,14 @@ class BIP32PubkeyProvider final : public PubkeyProvider key = extkey.key; return true; } + std::optional GetRootPubKey() const override + { + return std::nullopt; + } + std::optional GetRootExtPubKey() const override + { + return m_root_extkey; + } }; /** Base class for all Descriptor implementations. */ @@ -720,6 +749,19 @@ class DescriptorImpl : public Descriptor std::optional MaxSatisfactionWeight(bool) const override { return {}; } std::optional MaxSatisfactionElems() const override { return {}; } + + void GetPubKeys(std::set& pubkeys, std::set& ext_pubs) const override + { + for (const auto& p : m_pubkey_args) { + std::optional pub = p->GetRootPubKey(); + if (pub) pubkeys.insert(*pub); + std::optional ext_pub = p->GetRootExtPubKey(); + if (ext_pub) ext_pubs.insert(*ext_pub); + } + for (const auto& arg : m_subdescriptor_args) { + arg->GetPubKeys(pubkeys, ext_pubs); + } + } }; /** A parsed addr(A) descriptor. */ diff --git a/src/script/descriptor.h b/src/script/descriptor.h index caa5d1608d4c5..e78a775330270 100644 --- a/src/script/descriptor.h +++ b/src/script/descriptor.h @@ -158,6 +158,13 @@ struct Descriptor { /** Get the maximum size number of stack elements for satisfying this descriptor. */ virtual std::optional MaxSatisfactionElems() const = 0; + + /** Return all (extended) public keys for this descriptor, including any from subdescriptors. + * + * @param[out] pubkeys Any public keys + * @param[out] ext_pubs Any extended public keys + */ + virtual void GetPubKeys(std::set& pubkeys, std::set& ext_pubs) const = 0; }; /** Parse a `descriptor` string. Included private keys are put in `out`. diff --git a/src/wallet/test/walletload_tests.cpp b/src/wallet/test/walletload_tests.cpp index 3dba2231f0e48..2e43eda582d39 100644 --- a/src/wallet/test/walletload_tests.cpp +++ b/src/wallet/test/walletload_tests.cpp @@ -34,6 +34,7 @@ class DummyDescriptor final : public Descriptor { std::optional ScriptSize() const override { return {}; } std::optional MaxSatisfactionWeight(bool) const override { return {}; } std::optional MaxSatisfactionElems() const override { return {}; } + void GetPubKeys(std::set& pubkeys, std::set& ext_pubs) const override {} }; BOOST_FIXTURE_TEST_CASE(wallet_load_descriptors, TestingSetup) From fa6a259985b61235ebc21eae2a76014cc9437d5f Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Thu, 21 Dec 2023 17:27:51 -0500 Subject: [PATCH 03/13] desc spkm: Add functions to retrieve specific private keys --- src/wallet/scriptpubkeyman.cpp | 31 +++++++++++++++++++++++++++++++ src/wallet/scriptpubkeyman.h | 3 +++ 2 files changed, 34 insertions(+) diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index e10a17f003c04..fdba16465b28a 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -11,6 +11,7 @@ #include