@@ -164,6 +164,9 @@ struct PubkeyProvider
164164
165165 /* * Get the descriptor string form including private data (if available in arg). */
166166 virtual bool ToPrivateString (const SigningProvider& arg, std::string& out) const = 0;
167+
168+ /* * Derive a private key, if private data is available in arg. */
169+ virtual bool GetPrivKey (int pos, const SigningProvider& arg, CKey& key) const = 0;
167170};
168171
169172class OriginPubkeyProvider final : public PubkeyProvider
@@ -195,6 +198,10 @@ class OriginPubkeyProvider final : public PubkeyProvider
195198 ret = " [" + OriginString () + " ]" + std::move (sub);
196199 return true ;
197200 }
201+ bool GetPrivKey (int pos, const SigningProvider& arg, CKey& key) const override
202+ {
203+ return m_provider->GetPrivKey (pos, arg, key);
204+ }
198205};
199206
200207/* * An object representing a parsed constant public key in a descriptor. */
@@ -222,6 +229,10 @@ class ConstPubkeyProvider final : public PubkeyProvider
222229 ret = EncodeSecret (key);
223230 return true ;
224231 }
232+ bool GetPrivKey (int pos, const SigningProvider& arg, CKey& key) const override
233+ {
234+ return arg.GetKey (m_pubkey.GetID (), key);
235+ }
225236};
226237
227238enum class DeriveType {
@@ -266,14 +277,9 @@ class BIP32PubkeyProvider final : public PubkeyProvider
266277 {
267278 if (key) {
268279 if (IsHardened ()) {
269- CExtKey extkey;
270- if (!GetExtKey (arg, extkey)) return false ;
271- for (auto entry : m_path) {
272- extkey.Derive (extkey, entry);
273- }
274- if (m_derive == DeriveType::UNHARDENED) extkey.Derive (extkey, pos);
275- if (m_derive == DeriveType::HARDENED) extkey.Derive (extkey, pos | 0x80000000UL );
276- *key = extkey.Neuter ().pubkey ;
280+ CKey priv_key;
281+ if (!GetPrivKey (pos, arg, priv_key)) return false ;
282+ *key = priv_key.GetPubKey ();
277283 } else {
278284 // TODO: optimize by caching
279285 CExtPubKey extkey = m_extkey;
@@ -312,6 +318,18 @@ class BIP32PubkeyProvider final : public PubkeyProvider
312318 }
313319 return true ;
314320 }
321+ bool GetPrivKey (int pos, const SigningProvider& arg, CKey& key) const override
322+ {
323+ CExtKey extkey;
324+ if (!GetExtKey (arg, extkey)) return false ;
325+ for (auto entry : m_path) {
326+ extkey.Derive (extkey, entry);
327+ }
328+ if (m_derive == DeriveType::UNHARDENED) extkey.Derive (extkey, pos);
329+ if (m_derive == DeriveType::HARDENED) extkey.Derive (extkey, pos | 0x80000000UL );
330+ key = extkey.key ;
331+ return true ;
332+ }
315333};
316334
317335/* * Base class for all Descriptor implementations. */
@@ -462,6 +480,20 @@ class DescriptorImpl : public Descriptor
462480 Span<const unsigned char > span = MakeSpan (cache);
463481 return ExpandHelper (pos, DUMMY_SIGNING_PROVIDER, &span, output_scripts, out, nullptr ) && span.size () == 0 ;
464482 }
483+
484+ void ExpandPrivate (int pos, const SigningProvider& provider, FlatSigningProvider& out) const final
485+ {
486+ for (const auto & p : m_pubkey_args) {
487+ CKey key;
488+ if (!p->GetPrivKey (pos, provider, key)) continue ;
489+ out.keys .emplace (key.GetPubKey ().GetID (), key);
490+ }
491+ if (m_script_arg) {
492+ FlatSigningProvider subprovider;
493+ m_script_arg->ExpandPrivate (pos, provider, subprovider);
494+ out = Merge (out, subprovider);
495+ }
496+ }
465497};
466498
467499/* * Construct a vector with one element, which is moved into it. */
0 commit comments