@@ -481,34 +481,35 @@ class DescriptorImpl : public Descriptor
481
481
const std::string m_name;
482
482
483
483
protected:
484
- // ! The sub-descriptor argument (nullptr for everything but SH and WSH).
484
+ // ! The sub-descriptor arguments (empty for everything but SH and WSH).
485
485
// ! In doc/descriptors.m this is referred to as SCRIPT expressions sh(SCRIPT)
486
486
// ! and wsh(SCRIPT), and distinct from KEY expressions and ADDR expressions.
487
487
// ! Subdescriptors can only ever generate a single script.
488
- const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg ;
488
+ const std::vector<std:: unique_ptr<DescriptorImpl>> m_subdescriptor_args ;
489
489
490
490
// ! Return a serialization of anything except pubkey and script arguments, to be prepended to those.
491
491
virtual std::string ToStringExtra () const { return " " ; }
492
492
493
493
/* * A helper function to construct the scripts for this descriptor.
494
494
*
495
495
* This function is invoked once by ExpandHelper.
496
-
496
+ *
497
497
* @param pubkeys The evaluations of the m_pubkey_args field.
498
- * @param script The evaluation of m_subdescriptor_arg (or nullptr when m_subdescriptor_arg is nullptr ).
498
+ * @param script The evaluations of m_subdescriptor_args (one for each m_subdescriptor_args element ).
499
499
* @param out A FlatSigningProvider to put scripts or public keys in that are necessary to the solver.
500
500
* The origin info of the provided pubkeys is automatically added.
501
501
* @return A vector with scriptPubKeys for this descriptor.
502
502
*/
503
- virtual std::vector<CScript> MakeScripts (const std::vector<CPubKey>& pubkeys, const CScript* script , FlatSigningProvider& out) const = 0;
503
+ virtual std::vector<CScript> MakeScripts (const std::vector<CPubKey>& pubkeys, Span< const CScript> scripts , FlatSigningProvider& out) const = 0;
504
504
505
505
public:
506
- DescriptorImpl (std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_arg(std::move(script)) {}
506
+ DescriptorImpl (std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_args() {}
507
+ DescriptorImpl (std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_args(Vector(std::move(script))) {}
507
508
508
509
bool IsSolvable () const override
509
510
{
510
- if (m_subdescriptor_arg ) {
511
- if (!m_subdescriptor_arg ->IsSolvable ()) return false ;
511
+ for ( const auto & arg : m_subdescriptor_args ) {
512
+ if (!arg ->IsSolvable ()) return false ;
512
513
}
513
514
return true ;
514
515
}
@@ -518,8 +519,8 @@ class DescriptorImpl : public Descriptor
518
519
for (const auto & pubkey : m_pubkey_args) {
519
520
if (pubkey->IsRange ()) return true ;
520
521
}
521
- if (m_subdescriptor_arg ) {
522
- if (m_subdescriptor_arg ->IsRange ()) return true ;
522
+ for ( const auto & arg : m_subdescriptor_args ) {
523
+ if (arg ->IsRange ()) return true ;
523
524
}
524
525
return false ;
525
526
}
@@ -541,10 +542,10 @@ class DescriptorImpl : public Descriptor
541
542
}
542
543
ret += std::move (tmp);
543
544
}
544
- if (m_subdescriptor_arg ) {
545
+ for ( const auto & scriptarg : m_subdescriptor_args ) {
545
546
if (pos++) ret += " ," ;
546
547
std::string tmp;
547
- if (!m_subdescriptor_arg ->ToStringHelper (arg, tmp, priv, normalized)) return false ;
548
+ if (!scriptarg ->ToStringHelper (arg, tmp, priv, normalized)) return false ;
548
549
ret += std::move (tmp);
549
550
}
550
551
out = std::move (ret) + " )" ;
@@ -577,30 +578,29 @@ class DescriptorImpl : public Descriptor
577
578
std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
578
579
entries.reserve (m_pubkey_args.size ());
579
580
580
- // Construct temporary data in `entries` and `subscripts`, to avoid producing output in case of failure.
581
+ // Construct temporary data in `entries`, `subscripts`, and `subprovider` to avoid producing output in case of failure.
581
582
for (const auto & p : m_pubkey_args) {
582
583
entries.emplace_back ();
583
584
if (!p->GetPubKey (pos, arg, entries.back ().first , entries.back ().second , read_cache, write_cache)) return false ;
584
585
}
585
586
std::vector<CScript> subscripts;
586
- if (m_subdescriptor_arg) {
587
- FlatSigningProvider subprovider;
588
- if (!m_subdescriptor_arg->ExpandHelper (pos, arg, read_cache, subscripts, subprovider, write_cache)) return false ;
589
- assert (subscripts.size () == 1 );
590
- out = Merge (out, subprovider);
587
+ FlatSigningProvider subprovider;
588
+ for (const auto & subarg : m_subdescriptor_args) {
589
+ std::vector<CScript> outscripts;
590
+ if (!subarg->ExpandHelper (pos, arg, read_cache, outscripts, subprovider, write_cache)) return false ;
591
+ assert (outscripts.size () == 1 );
592
+ subscripts.emplace_back (std::move (outscripts[0 ]));
591
593
}
594
+ out = Merge (std::move (out), std::move (subprovider));
592
595
593
596
std::vector<CPubKey> pubkeys;
594
597
pubkeys.reserve (entries.size ());
595
598
for (auto & entry : entries) {
596
599
pubkeys.push_back (entry.first );
597
600
out.origins .emplace (entry.first .GetID (), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey (entry.first ), std::move (entry.second )));
598
601
}
599
- if (m_subdescriptor_arg) {
600
- output_scripts = MakeScripts (pubkeys, &subscripts[0 ], out);
601
- } else {
602
- output_scripts = MakeScripts (pubkeys, nullptr , out);
603
- }
602
+
603
+ output_scripts = MakeScripts (pubkeys, MakeSpan (subscripts), out);
604
604
return true ;
605
605
}
606
606
@@ -621,10 +621,8 @@ class DescriptorImpl : public Descriptor
621
621
if (!p->GetPrivKey (pos, provider, key)) continue ;
622
622
out.keys .emplace (key.GetPubKey ().GetID (), key);
623
623
}
624
- if (m_subdescriptor_arg) {
625
- FlatSigningProvider subprovider;
626
- m_subdescriptor_arg->ExpandPrivate (pos, provider, subprovider);
627
- out = Merge (out, subprovider);
624
+ for (const auto & arg : m_subdescriptor_args) {
625
+ arg->ExpandPrivate (pos, provider, out);
628
626
}
629
627
}
630
628
@@ -637,9 +635,9 @@ class AddressDescriptor final : public DescriptorImpl
637
635
const CTxDestination m_destination;
638
636
protected:
639
637
std::string ToStringExtra () const override { return EncodeDestination (m_destination); }
640
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, const CScript* , FlatSigningProvider&) const override { return Vector (GetScriptForDestination (m_destination)); }
638
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, Span< const CScript> , FlatSigningProvider&) const override { return Vector (GetScriptForDestination (m_destination)); }
641
639
public:
642
- AddressDescriptor (CTxDestination destination) : DescriptorImpl({}, {}, " addr" ), m_destination(std::move(destination)) {}
640
+ AddressDescriptor (CTxDestination destination) : DescriptorImpl({}, " addr" ), m_destination(std::move(destination)) {}
643
641
bool IsSolvable () const final { return false ; }
644
642
645
643
std::optional<OutputType> GetOutputType () const override
@@ -663,9 +661,9 @@ class RawDescriptor final : public DescriptorImpl
663
661
const CScript m_script;
664
662
protected:
665
663
std::string ToStringExtra () const override { return HexStr (m_script); }
666
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, const CScript* , FlatSigningProvider&) const override { return Vector (m_script); }
664
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, Span< const CScript> , FlatSigningProvider&) const override { return Vector (m_script); }
667
665
public:
668
- RawDescriptor (CScript script) : DescriptorImpl({}, {}, " raw" ), m_script(std::move(script)) {}
666
+ RawDescriptor (CScript script) : DescriptorImpl({}, " raw" ), m_script(std::move(script)) {}
669
667
bool IsSolvable () const final { return false ; }
670
668
671
669
std::optional<OutputType> GetOutputType () const override
@@ -689,24 +687,24 @@ class RawDescriptor final : public DescriptorImpl
689
687
class PKDescriptor final : public DescriptorImpl
690
688
{
691
689
protected:
692
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, const CScript* , FlatSigningProvider&) const override { return Vector (GetScriptForRawPubKey (keys[0 ])); }
690
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, Span< const CScript> , FlatSigningProvider&) const override { return Vector (GetScriptForRawPubKey (keys[0 ])); }
693
691
public:
694
- PKDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, " pk" ) {}
692
+ PKDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), " pk" ) {}
695
693
bool IsSingleType () const final { return true ; }
696
694
};
697
695
698
696
/* * A parsed pkh(P) descriptor. */
699
697
class PKHDescriptor final : public DescriptorImpl
700
698
{
701
699
protected:
702
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, const CScript* , FlatSigningProvider& out) const override
700
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, Span< const CScript> , FlatSigningProvider& out) const override
703
701
{
704
702
CKeyID id = keys[0 ].GetID ();
705
703
out.pubkeys .emplace (id, keys[0 ]);
706
704
return Vector (GetScriptForDestination (PKHash (id)));
707
705
}
708
706
public:
709
- PKHDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, " pkh" ) {}
707
+ PKHDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), " pkh" ) {}
710
708
std::optional<OutputType> GetOutputType () const override { return OutputType::LEGACY; }
711
709
bool IsSingleType () const final { return true ; }
712
710
};
@@ -715,14 +713,14 @@ class PKHDescriptor final : public DescriptorImpl
715
713
class WPKHDescriptor final : public DescriptorImpl
716
714
{
717
715
protected:
718
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, const CScript* , FlatSigningProvider& out) const override
716
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, Span< const CScript> , FlatSigningProvider& out) const override
719
717
{
720
718
CKeyID id = keys[0 ].GetID ();
721
719
out.pubkeys .emplace (id, keys[0 ]);
722
720
return Vector (GetScriptForDestination (WitnessV0KeyHash (id)));
723
721
}
724
722
public:
725
- WPKHDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, " wpkh" ) {}
723
+ WPKHDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), " wpkh" ) {}
726
724
std::optional<OutputType> GetOutputType () const override { return OutputType::BECH32; }
727
725
bool IsSingleType () const final { return true ; }
728
726
};
@@ -731,7 +729,7 @@ class WPKHDescriptor final : public DescriptorImpl
731
729
class ComboDescriptor final : public DescriptorImpl
732
730
{
733
731
protected:
734
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, const CScript* , FlatSigningProvider& out) const override
732
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, Span< const CScript> , FlatSigningProvider& out) const override
735
733
{
736
734
std::vector<CScript> ret;
737
735
CKeyID id = keys[0 ].GetID ();
@@ -747,7 +745,7 @@ class ComboDescriptor final : public DescriptorImpl
747
745
return ret;
748
746
}
749
747
public:
750
- ComboDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, " combo" ) {}
748
+ ComboDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), " combo" ) {}
751
749
bool IsSingleType () const final { return false ; }
752
750
};
753
751
@@ -758,7 +756,7 @@ class MultisigDescriptor final : public DescriptorImpl
758
756
const bool m_sorted;
759
757
protected:
760
758
std::string ToStringExtra () const override { return strprintf (" %i" , m_threshold); }
761
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, const CScript* , FlatSigningProvider&) const override {
759
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>& keys, Span< const CScript> , FlatSigningProvider&) const override {
762
760
if (m_sorted) {
763
761
std::vector<CPubKey> sorted_keys (keys);
764
762
std::sort (sorted_keys.begin (), sorted_keys.end ());
@@ -767,27 +765,27 @@ class MultisigDescriptor final : public DescriptorImpl
767
765
return Vector (GetScriptForMultisig (m_threshold, keys));
768
766
}
769
767
public:
770
- MultisigDescriptor (int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false ) : DescriptorImpl(std::move(providers), {}, sorted ? " sortedmulti" : " multi" ), m_threshold(threshold), m_sorted(sorted) {}
768
+ MultisigDescriptor (int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false ) : DescriptorImpl(std::move(providers), sorted ? " sortedmulti" : " multi" ), m_threshold(threshold), m_sorted(sorted) {}
771
769
bool IsSingleType () const final { return true ; }
772
770
};
773
771
774
772
/* * A parsed sh(...) descriptor. */
775
773
class SHDescriptor final : public DescriptorImpl
776
774
{
777
775
protected:
778
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, const CScript* script , FlatSigningProvider& out) const override
776
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, Span< const CScript> scripts , FlatSigningProvider& out) const override
779
777
{
780
- auto ret = Vector (GetScriptForDestination (ScriptHash (*script )));
781
- if (ret.size ()) out.scripts .emplace (CScriptID (*script ), *script );
778
+ auto ret = Vector (GetScriptForDestination (ScriptHash (scripts[ 0 ] )));
779
+ if (ret.size ()) out.scripts .emplace (CScriptID (scripts[ 0 ] ), scripts[ 0 ] );
782
780
return ret;
783
781
}
784
782
public:
785
783
SHDescriptor (std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), " sh" ) {}
786
784
787
785
std::optional<OutputType> GetOutputType () const override
788
786
{
789
- assert (m_subdescriptor_arg );
790
- if (m_subdescriptor_arg ->GetOutputType () == OutputType::BECH32) return OutputType::P2SH_SEGWIT;
787
+ assert (m_subdescriptor_args. size () == 1 );
788
+ if (m_subdescriptor_args[ 0 ] ->GetOutputType () == OutputType::BECH32) return OutputType::P2SH_SEGWIT;
791
789
return OutputType::LEGACY;
792
790
}
793
791
bool IsSingleType () const final { return true ; }
@@ -797,10 +795,10 @@ class SHDescriptor final : public DescriptorImpl
797
795
class WSHDescriptor final : public DescriptorImpl
798
796
{
799
797
protected:
800
- std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, const CScript* script , FlatSigningProvider& out) const override
798
+ std::vector<CScript> MakeScripts (const std::vector<CPubKey>&, Span< const CScript> scripts , FlatSigningProvider& out) const override
801
799
{
802
- auto ret = Vector (GetScriptForDestination (WitnessV0ScriptHash (*script )));
803
- if (ret.size ()) out.scripts .emplace (CScriptID (*script ), *script );
800
+ auto ret = Vector (GetScriptForDestination (WitnessV0ScriptHash (scripts[ 0 ] )));
801
+ if (ret.size ()) out.scripts .emplace (CScriptID (scripts[ 0 ] ), scripts[ 0 ] );
804
802
return ret;
805
803
}
806
804
public:
0 commit comments