Skip to content

Commit 53b7237

Browse files
committed
Merge bitcoin/bitcoin#31734: miniscript: account for all StringType variants in Miniscriptdescriptor::ToString()
28a4fcb test: check listdescriptors do not return a mix of hardened derivation marker (pythcoiner) 975783c descriptor: account for all StringType in MiniscriptDescriptor::ToStringHelper() (pythcoiner) Pull request description: In `MiniscriptDescriptor::ToStringHelper()` only the `StringType::Private` variant of the `type` argument was handled. This PR implements serializing w/ all variants of `StringType` & add a functional test for the descriptor triggering the related issue. Closes #31694: previously when calling `listdescriptors` RPC on a wallet containing a taproot descriptor w/ a (miniscript) taptree, origins of internal key & taptree were serialized w/ differents hardened derivation markers: - origin of the internal key were serialized w/ `StringType::Normalized` type (using `h` as marker) - origins of taptree keys were serialized w/ `StringType::Private` type (using `'` as marker) Note: Origins in segwit (`wsh()`) miniscript descriptors were also serialized w/ `StringType::Private` type (`'` marker) and are now serialized w/ `StringType::Normalized` type (`h` marker). ACKs for top commit: sipa: Code review ACK 28a4fcb achow101: ACK 28a4fcb rkrux: Concept ACK 28a4fcb Tree-SHA512: 15d14000b5951ca69a64a05b9a0b138c48a07b81eaf2fa86b91ac20cc8735533355a787363c64ba88403dd8a56ef5232cba57d34bea80835a0f40774d62fbc2b
2 parents a7f9bbe + 28a4fcb commit 53b7237

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

src/script/descriptor.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,20 +1483,33 @@ class StringMaker {
14831483
const SigningProvider* m_arg;
14841484
//! Keys contained in the Miniscript (a reference to DescriptorImpl::m_pubkey_args).
14851485
const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1486-
//! Whether to serialize keys as private or public.
1487-
bool m_private;
1486+
//! StringType to serialize keys
1487+
const DescriptorImpl::StringType m_type;
1488+
const DescriptorCache* m_cache;
14881489

14891490
public:
1490-
StringMaker(const SigningProvider* arg LIFETIMEBOUND, const std::vector<std::unique_ptr<PubkeyProvider>>& pubkeys LIFETIMEBOUND, bool priv)
1491-
: m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1491+
StringMaker(const SigningProvider* arg LIFETIMEBOUND,
1492+
const std::vector<std::unique_ptr<PubkeyProvider>>& pubkeys LIFETIMEBOUND,
1493+
DescriptorImpl::StringType type,
1494+
const DescriptorCache* cache LIFETIMEBOUND)
1495+
: m_arg(arg), m_pubkeys(pubkeys), m_type(type), m_cache(cache) {}
14921496

14931497
std::optional<std::string> ToString(uint32_t key) const
14941498
{
14951499
std::string ret;
1496-
if (m_private) {
1497-
if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {};
1498-
} else {
1500+
switch (m_type) {
1501+
case DescriptorImpl::StringType::PUBLIC:
14991502
ret = m_pubkeys[key]->ToString();
1503+
break;
1504+
case DescriptorImpl::StringType::PRIVATE:
1505+
if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {};
1506+
break;
1507+
case DescriptorImpl::StringType::NORMALIZED:
1508+
if (!m_pubkeys[key]->ToNormalizedString(*m_arg, ret, m_cache)) return {};
1509+
break;
1510+
case DescriptorImpl::StringType::COMPAT:
1511+
ret = m_pubkeys[key]->ToString(PubkeyProvider::StringType::COMPAT);
1512+
break;
15001513
}
15011514
return ret;
15021515
}
@@ -1529,7 +1542,7 @@ class MiniscriptDescriptor final : public DescriptorImpl
15291542
bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type,
15301543
const DescriptorCache* cache = nullptr) const override
15311544
{
1532-
if (const auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1545+
if (const auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type, cache))) {
15331546
out = *res;
15341547
return true;
15351548
}

test/functional/wallet_listdescriptors.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,26 @@ def run_test(self):
126126
}
127127
assert_equal(expected, wallet.listdescriptors())
128128

129+
self.log.info('Test taproot descriptor do not have mixed hardened derivation marker')
130+
node.createwallet(wallet_name='w5', descriptors=True, disable_private_keys=True)
131+
wallet = node.get_wallet_rpc('w5')
132+
wallet.importdescriptors([{
133+
'desc': "tr([1dce71b2/48'/1'/0'/2']tpubDEeP3GefjqbaDTTaVAF5JkXWhoFxFDXQ9KuhVrMBViFXXNR2B3Lvme2d2AoyiKfzRFZChq2AGMNbU1qTbkBMfNv7WGVXLt2pnYXY87gXqcs/0/*,and_v(v:pk([c658b283/48'/1'/0'/2']tpubDFL5wzgPBYK5pZ2Kh1T8qrxnp43kjE5CXfguZHHBrZSWpkfASy5rVfj7prh11XdqkC1P3kRwUPBeX7AHN8XBNx8UwiprnFnEm5jyswiRD4p/0/*),older(65535)))#xl20m6md",
134+
'timestamp': TIME_GENESIS_BLOCK,
135+
}])
136+
expected = {
137+
'wallet_name': 'w5',
138+
'descriptors': [
139+
{'active': False,
140+
'desc': 'tr([1dce71b2/48h/1h/0h/2h]tpubDEeP3GefjqbaDTTaVAF5JkXWhoFxFDXQ9KuhVrMBViFXXNR2B3Lvme2d2AoyiKfzRFZChq2AGMNbU1qTbkBMfNv7WGVXLt2pnYXY87gXqcs/0/*,and_v(v:pk([c658b283/48h/1h/0h/2h]tpubDFL5wzgPBYK5pZ2Kh1T8qrxnp43kjE5CXfguZHHBrZSWpkfASy5rVfj7prh11XdqkC1P3kRwUPBeX7AHN8XBNx8UwiprnFnEm5jyswiRD4p/0/*),older(65535)))#m4uznndk',
141+
'timestamp': TIME_GENESIS_BLOCK,
142+
'range': [0, 0],
143+
'next': 0,
144+
'next_index': 0},
145+
]
146+
}
147+
assert_equal(expected, wallet.listdescriptors())
148+
129149

130150
if __name__ == '__main__':
131151
ListDescriptorsTest(__file__).main()

0 commit comments

Comments
 (0)