@@ -174,22 +174,20 @@ struct PubkeyProvider
174
174
* Used by the Miniscript descriptors to check for duplicate keys in the script.
175
175
*/
176
176
bool operator <(PubkeyProvider& other) const {
177
- CPubKey a, b;
178
- SigningProvider dummy;
179
- KeyOriginInfo dummy_info;
177
+ FlatSigningProvider dummy;
180
178
181
- GetPubKey (0 , dummy, a, dummy_info );
182
- other.GetPubKey (0 , dummy, b, dummy_info );
179
+ std::optional<CPubKey> a = GetPubKey (0 , dummy, dummy );
180
+ std::optional<CPubKey> b = other.GetPubKey (0 , dummy, dummy );
183
181
184
182
return a < b;
185
183
}
186
184
187
- /* * Derive a public key.
185
+ /* * Derive a public key and put it into out .
188
186
* read_cache is the cache to read keys from (if not nullptr)
189
187
* write_cache is the cache to write keys to (if not nullptr)
190
188
* Caches are not exclusive but this is not tested. Currently we use them exclusively
191
189
*/
192
- virtual bool GetPubKey (int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const = 0;
190
+ virtual std::optional<CPubKey> GetPubKey (int pos, const SigningProvider& arg, FlatSigningProvider& out , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const = 0;
193
191
194
192
/* * Whether this represent multiple public keys at different positions. */
195
193
virtual bool IsRange () const = 0;
@@ -240,12 +238,15 @@ class OriginPubkeyProvider final : public PubkeyProvider
240
238
241
239
public:
242
240
OriginPubkeyProvider (uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider, bool apostrophe) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)), m_apostrophe(apostrophe) {}
243
- bool GetPubKey (int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const override
241
+ std::optional<CPubKey> GetPubKey (int pos, const SigningProvider& arg, FlatSigningProvider& out , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const override
244
242
{
245
- if (!m_provider->GetPubKey (pos, arg, key, info, read_cache, write_cache)) return false ;
246
- std::copy (std::begin (m_origin.fingerprint ), std::end (m_origin.fingerprint ), info.fingerprint );
247
- info.path .insert (info.path .begin (), m_origin.path .begin (), m_origin.path .end ());
248
- return true ;
243
+ std::optional<CPubKey> pub = m_provider->GetPubKey (pos, arg, out, read_cache, write_cache);
244
+ if (!pub) return std::nullopt;
245
+ auto & [pubkey, suborigin] = out.origins [pub->GetID ()];
246
+ Assert (pubkey == *pub); // All subproviders must be inserting a valid origin already
247
+ std::copy (std::begin (m_origin.fingerprint ), std::end (m_origin.fingerprint ), suborigin.fingerprint );
248
+ suborigin.path .insert (suborigin.path .begin (), m_origin.path .begin (), m_origin.path .end ());
249
+ return pub;
249
250
}
250
251
bool IsRange () const override { return m_provider->IsRange (); }
251
252
size_t GetSize () const override { return m_provider->GetSize (); }
@@ -298,13 +299,13 @@ class ConstPubkeyProvider final : public PubkeyProvider
298
299
299
300
public:
300
301
ConstPubkeyProvider (uint32_t exp_index, const CPubKey& pubkey, bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
301
- bool GetPubKey (int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const override
302
+ std::optional<CPubKey> GetPubKey (int pos, const SigningProvider& arg, FlatSigningProvider& out , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const override
302
303
{
303
- key = m_pubkey;
304
- info.path .clear ();
304
+ KeyOriginInfo info;
305
305
CKeyID keyid = m_pubkey.GetID ();
306
306
std::copy (keyid.begin (), keyid.begin () + sizeof (info.fingerprint ), info.fingerprint );
307
- return true ;
307
+ out.origins .emplace (keyid, std::make_pair (m_pubkey, info));
308
+ return m_pubkey;
308
309
}
309
310
bool IsRange () const override { return false ; }
310
311
size_t GetSize () const override { return m_pubkey.size (); }
@@ -394,18 +395,17 @@ class BIP32PubkeyProvider final : public PubkeyProvider
394
395
BIP32PubkeyProvider (uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive, bool apostrophe) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive), m_apostrophe(apostrophe) {}
395
396
bool IsRange () const override { return m_derive != DeriveType::NO; }
396
397
size_t GetSize () const override { return 33 ; }
397
- bool GetPubKey (int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const override
398
+ std::optional<CPubKey> GetPubKey (int pos, const SigningProvider& arg, FlatSigningProvider& out , const DescriptorCache* read_cache = nullptr , DescriptorCache* write_cache = nullptr ) const override
398
399
{
399
400
// Info of parent of the to be derived pubkey
400
- KeyOriginInfo parent_info ;
401
+ KeyOriginInfo info ;
401
402
CKeyID keyid = m_root_extkey.pubkey .GetID ();
402
- std::copy (keyid.begin (), keyid.begin () + sizeof (parent_info .fingerprint ), parent_info .fingerprint );
403
- parent_info .path = m_path;
403
+ std::copy (keyid.begin (), keyid.begin () + sizeof (info .fingerprint ), info .fingerprint );
404
+ info .path = m_path;
404
405
405
406
// Info of the derived key itself which is copied out upon successful completion
406
- KeyOriginInfo final_info_out_tmp = parent_info;
407
- if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.path .push_back ((uint32_t )pos);
408
- if (m_derive == DeriveType::HARDENED) final_info_out_tmp.path .push_back (((uint32_t )pos) | 0x80000000L );
407
+ if (m_derive == DeriveType::UNHARDENED) info.path .push_back ((uint32_t )pos);
408
+ if (m_derive == DeriveType::HARDENED) info.path .push_back (((uint32_t )pos) | 0x80000000L );
409
409
410
410
// Derive keys or fetch them from cache
411
411
CExtPubKey final_extkey = m_root_extkey;
@@ -414,16 +414,16 @@ class BIP32PubkeyProvider final : public PubkeyProvider
414
414
bool der = true ;
415
415
if (read_cache) {
416
416
if (!read_cache->GetCachedDerivedExtPubKey (m_expr_index, pos, final_extkey)) {
417
- if (m_derive == DeriveType::HARDENED) return false ;
417
+ if (m_derive == DeriveType::HARDENED) return std::nullopt ;
418
418
// Try to get the derivation parent
419
- if (!read_cache->GetCachedParentExtPubKey (m_expr_index, parent_extkey)) return false ;
419
+ if (!read_cache->GetCachedParentExtPubKey (m_expr_index, parent_extkey)) return std::nullopt ;
420
420
final_extkey = parent_extkey;
421
421
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive (final_extkey, pos);
422
422
}
423
423
} else if (IsHardened ()) {
424
424
CExtKey xprv;
425
425
CExtKey lh_xprv;
426
- if (!GetDerivedExtKey (arg, xprv, lh_xprv)) return false ;
426
+ if (!GetDerivedExtKey (arg, xprv, lh_xprv)) return std::nullopt ;
427
427
parent_extkey = xprv.Neuter ();
428
428
if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive (xprv, pos);
429
429
if (m_derive == DeriveType::HARDENED) der = xprv.Derive (xprv, pos | 0x80000000UL );
@@ -433,16 +433,15 @@ class BIP32PubkeyProvider final : public PubkeyProvider
433
433
}
434
434
} else {
435
435
for (auto entry : m_path) {
436
- if (!parent_extkey.Derive (parent_extkey, entry)) return false ;
436
+ if (!parent_extkey.Derive (parent_extkey, entry)) return std::nullopt ;
437
437
}
438
438
final_extkey = parent_extkey;
439
439
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive (final_extkey, pos);
440
440
assert (m_derive != DeriveType::HARDENED);
441
441
}
442
- if (!der) return false ;
442
+ if (!der) return std::nullopt ;
443
443
444
- final_info_out = final_info_out_tmp;
445
- key_out = final_extkey.pubkey ;
444
+ out.origins .emplace (final_extkey.pubkey .GetID (), std::make_pair (final_extkey.pubkey , info));
446
445
447
446
if (write_cache) {
448
447
// Only cache parent if there is any unhardened derivation
@@ -452,12 +451,12 @@ class BIP32PubkeyProvider final : public PubkeyProvider
452
451
if (last_hardened_extkey.pubkey .IsValid ()) {
453
452
write_cache->CacheLastHardenedExtPubKey (m_expr_index, last_hardened_extkey);
454
453
}
455
- } else if (final_info_out .path .size () > 0 ) {
454
+ } else if (info .path .size () > 0 ) {
456
455
write_cache->CacheDerivedExtPubKey (m_expr_index, pos, final_extkey);
457
456
}
458
457
}
459
458
460
- return true ;
459
+ return final_extkey. pubkey ;
461
460
}
462
461
std::string ToString (StringType type, bool normalized) const
463
462
{
@@ -700,16 +699,17 @@ class DescriptorImpl : public Descriptor
700
699
// NOLINTNEXTLINE(misc-no-recursion)
701
700
bool ExpandHelper (int pos, const SigningProvider& arg, const DescriptorCache* read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache) const
702
701
{
703
- std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
704
- entries.reserve (m_pubkey_args.size ());
702
+ FlatSigningProvider subprovider;
703
+ std::vector<CPubKey> pubkeys;
704
+ pubkeys.reserve (m_pubkey_args.size ());
705
705
706
- // Construct temporary data in `entries `, `subscripts`, and `subprovider` to avoid producing output in case of failure.
706
+ // Construct temporary data in `pubkeys `, `subscripts`, and `subprovider` to avoid producing output in case of failure.
707
707
for (const auto & p : m_pubkey_args) {
708
- entries.emplace_back ();
709
- if (!p->GetPubKey (pos, arg, entries.back ().first , entries.back ().second , read_cache, write_cache)) return false ;
708
+ std::optional<CPubKey> pubkey = p->GetPubKey (pos, arg, subprovider, read_cache, write_cache);
709
+ if (!pubkey) return false ;
710
+ pubkeys.push_back (pubkey.value ());
710
711
}
711
712
std::vector<CScript> subscripts;
712
- FlatSigningProvider subprovider;
713
713
for (const auto & subarg : m_subdescriptor_args) {
714
714
std::vector<CScript> outscripts;
715
715
if (!subarg->ExpandHelper (pos, arg, read_cache, outscripts, subprovider, write_cache)) return false ;
@@ -718,13 +718,6 @@ class DescriptorImpl : public Descriptor
718
718
}
719
719
out.Merge (std::move (subprovider));
720
720
721
- std::vector<CPubKey> pubkeys;
722
- pubkeys.reserve (entries.size ());
723
- for (auto & entry : entries) {
724
- pubkeys.push_back (entry.first );
725
- out.origins .emplace (entry.first .GetID (), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey (entry.first ), std::move (entry.second )));
726
- }
727
-
728
721
output_scripts = MakeScripts (pubkeys, Span{subscripts}, out);
729
722
return true ;
730
723
}
0 commit comments