diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index c8802d2bf89..6e7fb04295d 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -1279,20 +1279,33 @@ class StringMaker { const SigningProvider* m_arg; //! Keys contained in the Miniscript (a reference to DescriptorImpl::m_pubkey_args). const std::vector>& m_pubkeys; - //! Whether to serialize keys as private or public. - bool m_private; + //! StringType to serialize keys + const DescriptorImpl::StringType m_type; + const DescriptorCache* m_cache; public: - StringMaker(const SigningProvider* arg LIFETIMEBOUND, const std::vector>& pubkeys LIFETIMEBOUND, bool priv) - : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {} + StringMaker(const SigningProvider* arg LIFETIMEBOUND, + const std::vector>& pubkeys LIFETIMEBOUND, + DescriptorImpl::StringType type, + const DescriptorCache* cache LIFETIMEBOUND) + : m_arg(arg), m_pubkeys(pubkeys), m_type(type), m_cache(cache) {} std::optional ToString(uint32_t key) const { std::string ret; - if (m_private) { - if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {}; - } else { + switch (m_type) { + case DescriptorImpl::StringType::PUBLIC: ret = m_pubkeys[key]->ToString(); + break; + case DescriptorImpl::StringType::PRIVATE: + if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {}; + break; + case DescriptorImpl::StringType::NORMALIZED: + if (!m_pubkeys[key]->ToNormalizedString(*m_arg, ret, m_cache)) return {}; + break; + case DescriptorImpl::StringType::COMPAT: + ret = m_pubkeys[key]->ToString(PubkeyProvider::StringType::COMPAT); + break; } return ret; } @@ -1325,7 +1338,7 @@ public: bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type, const DescriptorCache* cache = nullptr) const override { - if (const auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) { + if (const auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type, cache))) { out = *res; return true; } diff --git a/test/functional/wallet_listdescriptors.py b/test/functional/wallet_listdescriptors.py index 35be527b32b..3af91e7a072 100755 --- a/test/functional/wallet_listdescriptors.py +++ b/test/functional/wallet_listdescriptors.py @@ -133,6 +133,26 @@ class ListDescriptorsTest(BitcoinTestFramework): } assert_equal(expected, wallet.listdescriptors()) + self.log.info('Test taproot descriptor do not have mixed hardened derivation marker') + node.createwallet(wallet_name='w5', descriptors=True, disable_private_keys=True) + wallet = node.get_wallet_rpc('w5') + wallet.importdescriptors([{ + 'desc': "tr([1dce71b2/48'/1'/0'/2']tpubDEeP3GefjqbaDTTaVAF5JkXWhoFxFDXQ9KuhVrMBViFXXNR2B3Lvme2d2AoyiKfzRFZChq2AGMNbU1qTbkBMfNv7WGVXLt2pnYXY87gXqcs/0/*,and_v(v:pk([c658b283/48'/1'/0'/2']tpubDFL5wzgPBYK5pZ2Kh1T8qrxnp43kjE5CXfguZHHBrZSWpkfASy5rVfj7prh11XdqkC1P3kRwUPBeX7AHN8XBNx8UwiprnFnEm5jyswiRD4p/0/*),older(65535)))#xl20m6md", + 'timestamp': TIME_GENESIS_BLOCK, + }]) + expected = { + 'wallet_name': 'w5', + 'descriptors': [ + {'active': False, + 'desc': 'tr([1dce71b2/48h/1h/0h/2h]tpubDEeP3GefjqbaDTTaVAF5JkXWhoFxFDXQ9KuhVrMBViFXXNR2B3Lvme2d2AoyiKfzRFZChq2AGMNbU1qTbkBMfNv7WGVXLt2pnYXY87gXqcs/0/*,and_v(v:pk([c658b283/48h/1h/0h/2h]tpubDFL5wzgPBYK5pZ2Kh1T8qrxnp43kjE5CXfguZHHBrZSWpkfASy5rVfj7prh11XdqkC1P3kRwUPBeX7AHN8XBNx8UwiprnFnEm5jyswiRD4p/0/*),older(65535)))#m4uznndk', + 'timestamp': TIME_GENESIS_BLOCK, + 'range': [0, 0], + 'next': 0, + 'next_index': 0}, + ] + } + assert_equal(expected, wallet.listdescriptors()) + if __name__ == '__main__': ListDescriptorsTest(__file__).main()