@@ -150,6 +150,14 @@ typedef std::vector<uint32_t> KeyPath;
150
150
/* * Interface for public key objects in descriptors. */
151
151
struct PubkeyProvider
152
152
{
153
+ protected:
154
+ // ! Index of this key expression in the descriptor
155
+ // ! E.g. If this PubkeyProvider is key1 in multi(2, key1, key2, key3), then m_expr_index = 0
156
+ uint32_t m_expr_index;
157
+
158
+ public:
159
+ PubkeyProvider (uint32_t exp_index) : m_expr_index(exp_index) {}
160
+
153
161
virtual ~PubkeyProvider () = default ;
154
162
155
163
/* * Derive a public key. If key==nullptr, only info is desired. */
@@ -182,7 +190,7 @@ class OriginPubkeyProvider final : public PubkeyProvider
182
190
}
183
191
184
192
public:
185
- OriginPubkeyProvider (KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : m_origin(std::move(info)), m_provider(std::move(provider)) {}
193
+ OriginPubkeyProvider (uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
186
194
bool GetPubKey (int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
187
195
{
188
196
if (!m_provider->GetPubKey (pos, arg, key, info)) return false ;
@@ -212,7 +220,7 @@ class ConstPubkeyProvider final : public PubkeyProvider
212
220
CPubKey m_pubkey;
213
221
214
222
public:
215
- ConstPubkeyProvider (const CPubKey& pubkey) : m_pubkey(pubkey) {}
223
+ ConstPubkeyProvider (uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
216
224
bool GetPubKey (int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
217
225
{
218
226
if (key) *key = m_pubkey;
@@ -272,7 +280,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
272
280
}
273
281
274
282
public:
275
- BIP32PubkeyProvider (const CExtPubKey& extkey, KeyPath path, DeriveType derive) : m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
283
+ BIP32PubkeyProvider (uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
276
284
bool IsRange () const override { return m_derive != DeriveType::NO; }
277
285
size_t GetSize () const override { return 33 ; }
278
286
bool GetPubKey (int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
@@ -698,7 +706,7 @@ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath&
698
706
}
699
707
700
708
/* * Parse a public key that excludes origin information. */
701
- std::unique_ptr<PubkeyProvider> ParsePubkeyInner (const Span<const char >& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
709
+ std::unique_ptr<PubkeyProvider> ParsePubkeyInner (uint32_t key_exp_index, const Span<const char >& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
702
710
{
703
711
using namespace spanparsing ;
704
712
@@ -714,7 +722,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
714
722
CPubKey pubkey (data);
715
723
if (pubkey.IsFullyValid ()) {
716
724
if (permit_uncompressed || pubkey.IsCompressed ()) {
717
- return MakeUnique<ConstPubkeyProvider>(pubkey);
725
+ return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
718
726
} else {
719
727
error = " Uncompressed keys are not allowed" ;
720
728
return nullptr ;
@@ -728,7 +736,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
728
736
if (permit_uncompressed || key.IsCompressed ()) {
729
737
CPubKey pubkey = key.GetPubKey ();
730
738
out.keys .emplace (pubkey.GetID (), key);
731
- return MakeUnique<ConstPubkeyProvider>(pubkey);
739
+ return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
732
740
} else {
733
741
error = " Uncompressed keys are not allowed" ;
734
742
return nullptr ;
@@ -755,11 +763,11 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
755
763
extpubkey = extkey.Neuter ();
756
764
out.keys .emplace (extpubkey.pubkey .GetID (), extkey.key );
757
765
}
758
- return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move (path), type);
766
+ return MakeUnique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move (path), type);
759
767
}
760
768
761
769
/* * Parse a public key including origin information (if enabled). */
762
- std::unique_ptr<PubkeyProvider> ParsePubkey (const Span<const char >& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
770
+ std::unique_ptr<PubkeyProvider> ParsePubkey (uint32_t key_exp_index, const Span<const char >& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
763
771
{
764
772
using namespace spanparsing ;
765
773
@@ -768,7 +776,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
768
776
error = " Multiple ']' characters found for a single pubkey" ;
769
777
return nullptr ;
770
778
}
771
- if (origin_split.size () == 1 ) return ParsePubkeyInner (origin_split[0 ], permit_uncompressed, out, error);
779
+ if (origin_split.size () == 1 ) return ParsePubkeyInner (key_exp_index, origin_split[0 ], permit_uncompressed, out, error);
772
780
if (origin_split[0 ].size () < 1 || origin_split[0 ][0 ] != ' [' ) {
773
781
error = strprintf (" Key origin start '[ character expected but not found, got '%c' instead" , origin_split[0 ][0 ]);
774
782
return nullptr ;
@@ -789,30 +797,30 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
789
797
assert (fpr_bytes.size () == 4 );
790
798
std::copy (fpr_bytes.begin (), fpr_bytes.end (), info.fingerprint );
791
799
if (!ParseKeyPath (slash_split, info.path , error)) return nullptr ;
792
- auto provider = ParsePubkeyInner (origin_split[1 ], permit_uncompressed, out, error);
800
+ auto provider = ParsePubkeyInner (key_exp_index, origin_split[1 ], permit_uncompressed, out, error);
793
801
if (!provider) return nullptr ;
794
- return MakeUnique<OriginPubkeyProvider>(std::move (info), std::move (provider));
802
+ return MakeUnique<OriginPubkeyProvider>(key_exp_index, std::move (info), std::move (provider));
795
803
}
796
804
797
805
/* * Parse a script in a particular context. */
798
- std::unique_ptr<DescriptorImpl> ParseScript (Span<const char >& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
806
+ std::unique_ptr<DescriptorImpl> ParseScript (uint32_t key_exp_index, Span<const char >& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
799
807
{
800
808
using namespace spanparsing ;
801
809
802
810
auto expr = Expr (sp);
803
811
bool sorted_multi = false ;
804
812
if (Func (" pk" , expr)) {
805
- auto pubkey = ParsePubkey (expr, ctx != ParseScriptContext::P2WSH, out, error);
813
+ auto pubkey = ParsePubkey (key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
806
814
if (!pubkey) return nullptr ;
807
815
return MakeUnique<PKDescriptor>(std::move (pubkey));
808
816
}
809
817
if (Func (" pkh" , expr)) {
810
- auto pubkey = ParsePubkey (expr, ctx != ParseScriptContext::P2WSH, out, error);
818
+ auto pubkey = ParsePubkey (key_exp_index, expr, ctx != ParseScriptContext::P2WSH, out, error);
811
819
if (!pubkey) return nullptr ;
812
820
return MakeUnique<PKHDescriptor>(std::move (pubkey));
813
821
}
814
822
if (ctx == ParseScriptContext::TOP && Func (" combo" , expr)) {
815
- auto pubkey = ParsePubkey (expr, true , out, error);
823
+ auto pubkey = ParsePubkey (key_exp_index, expr, true , out, error);
816
824
if (!pubkey) return nullptr ;
817
825
return MakeUnique<ComboDescriptor>(std::move (pubkey));
818
826
} else if (ctx != ParseScriptContext::TOP && Func (" combo" , expr)) {
@@ -834,10 +842,11 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
834
842
return nullptr ;
835
843
}
836
844
auto arg = Expr (expr);
837
- auto pk = ParsePubkey (arg, ctx != ParseScriptContext::P2WSH, out, error);
845
+ auto pk = ParsePubkey (key_exp_index, arg, ctx != ParseScriptContext::P2WSH, out, error);
838
846
if (!pk) return nullptr ;
839
847
script_size += pk->GetSize () + 1 ;
840
848
providers.emplace_back (std::move (pk));
849
+ key_exp_index++;
841
850
}
842
851
if (providers.size () < 1 || providers.size () > 16 ) {
843
852
error = strprintf (" Cannot have %u keys in multisig; must have between 1 and 16 keys, inclusive" , providers.size ());
@@ -864,23 +873,23 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
864
873
return MakeUnique<MultisigDescriptor>(thres, std::move (providers), sorted_multi);
865
874
}
866
875
if (ctx != ParseScriptContext::P2WSH && Func (" wpkh" , expr)) {
867
- auto pubkey = ParsePubkey (expr, false , out, error);
876
+ auto pubkey = ParsePubkey (key_exp_index, expr, false , out, error);
868
877
if (!pubkey) return nullptr ;
869
878
return MakeUnique<WPKHDescriptor>(std::move (pubkey));
870
879
} else if (ctx == ParseScriptContext::P2WSH && Func (" wpkh" , expr)) {
871
880
error = " Cannot have wpkh within wsh" ;
872
881
return nullptr ;
873
882
}
874
883
if (ctx == ParseScriptContext::TOP && Func (" sh" , expr)) {
875
- auto desc = ParseScript (expr, ParseScriptContext::P2SH, out, error);
884
+ auto desc = ParseScript (key_exp_index, expr, ParseScriptContext::P2SH, out, error);
876
885
if (!desc || expr.size ()) return nullptr ;
877
886
return MakeUnique<SHDescriptor>(std::move (desc));
878
887
} else if (ctx != ParseScriptContext::TOP && Func (" sh" , expr)) {
879
888
error = " Cannot have sh in non-top level" ;
880
889
return nullptr ;
881
890
}
882
891
if (ctx != ParseScriptContext::P2WSH && Func (" wsh" , expr)) {
883
- auto desc = ParseScript (expr, ParseScriptContext::P2WSH, out, error);
892
+ auto desc = ParseScript (key_exp_index, expr, ParseScriptContext::P2WSH, out, error);
884
893
if (!desc || expr.size ()) return nullptr ;
885
894
return MakeUnique<WSHDescriptor>(std::move (desc));
886
895
} else if (ctx == ParseScriptContext::P2WSH && Func (" wsh" , expr)) {
@@ -917,10 +926,10 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
917
926
918
927
std::unique_ptr<PubkeyProvider> InferPubkey (const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
919
928
{
920
- std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(pubkey);
929
+ std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(0 , pubkey);
921
930
KeyOriginInfo info;
922
931
if (provider.GetKeyOrigin (pubkey.GetID (), info)) {
923
- return MakeUnique<OriginPubkeyProvider>(std::move (info), std::move (key_provider));
932
+ return MakeUnique<OriginPubkeyProvider>(0 , std::move (info), std::move (key_provider));
924
933
}
925
934
return key_provider;
926
935
}
@@ -1032,7 +1041,7 @@ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProv
1032
1041
{
1033
1042
Span<const char > sp (descriptor.data (), descriptor.size ());
1034
1043
if (!CheckChecksum (sp, require_checksum, error)) return nullptr ;
1035
- auto ret = ParseScript (sp, ParseScriptContext::TOP, out, error);
1044
+ auto ret = ParseScript (0 , sp, ParseScriptContext::TOP, out, error);
1036
1045
if (sp.size () == 0 && ret) return std::unique_ptr<Descriptor>(std::move (ret));
1037
1046
return nullptr ;
1038
1047
}
0 commit comments