@@ -150,6 +150,14 @@ typedef std::vector<uint32_t> KeyPath;
150150/* * Interface for public key objects in descriptors. */
151151struct PubkeyProvider
152152{
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+
153161 virtual ~PubkeyProvider () = default ;
154162
155163 /* * Derive a public key. If key==nullptr, only info is desired. */
@@ -182,7 +190,7 @@ class OriginPubkeyProvider final : public PubkeyProvider
182190 }
183191
184192public:
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)) {}
186194 bool GetPubKey (int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
187195 {
188196 if (!m_provider->GetPubKey (pos, arg, key, info)) return false ;
@@ -212,7 +220,7 @@ class ConstPubkeyProvider final : public PubkeyProvider
212220 CPubKey m_pubkey;
213221
214222public:
215- ConstPubkeyProvider (const CPubKey& pubkey) : m_pubkey(pubkey) {}
223+ ConstPubkeyProvider (uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
216224 bool GetPubKey (int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
217225 {
218226 if (key) *key = m_pubkey;
@@ -272,7 +280,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
272280 }
273281
274282public:
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) {}
276284 bool IsRange () const override { return m_derive != DeriveType::NO; }
277285 size_t GetSize () const override { return 33 ; }
278286 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&
698706}
699707
700708/* * 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)
702710{
703711 using namespace spanparsing ;
704712
@@ -714,7 +722,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
714722 CPubKey pubkey (data);
715723 if (pubkey.IsFullyValid ()) {
716724 if (permit_uncompressed || pubkey.IsCompressed ()) {
717- return MakeUnique<ConstPubkeyProvider>(pubkey);
725+ return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
718726 } else {
719727 error = " Uncompressed keys are not allowed" ;
720728 return nullptr ;
@@ -728,7 +736,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
728736 if (permit_uncompressed || key.IsCompressed ()) {
729737 CPubKey pubkey = key.GetPubKey ();
730738 out.keys .emplace (pubkey.GetID (), key);
731- return MakeUnique<ConstPubkeyProvider>(pubkey);
739+ return MakeUnique<ConstPubkeyProvider>(key_exp_index, pubkey);
732740 } else {
733741 error = " Uncompressed keys are not allowed" ;
734742 return nullptr ;
@@ -755,11 +763,11 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
755763 extpubkey = extkey.Neuter ();
756764 out.keys .emplace (extpubkey.pubkey .GetID (), extkey.key );
757765 }
758- return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move (path), type);
766+ return MakeUnique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move (path), type);
759767}
760768
761769/* * 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)
763771{
764772 using namespace spanparsing ;
765773
@@ -768,7 +776,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
768776 error = " Multiple ']' characters found for a single pubkey" ;
769777 return nullptr ;
770778 }
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);
772780 if (origin_split[0 ].size () < 1 || origin_split[0 ][0 ] != ' [' ) {
773781 error = strprintf (" Key origin start '[ character expected but not found, got '%c' instead" , origin_split[0 ][0 ]);
774782 return nullptr ;
@@ -789,30 +797,30 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
789797 assert (fpr_bytes.size () == 4 );
790798 std::copy (fpr_bytes.begin (), fpr_bytes.end (), info.fingerprint );
791799 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);
793801 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));
795803}
796804
797805/* * 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)
799807{
800808 using namespace spanparsing ;
801809
802810 auto expr = Expr (sp);
803811 bool sorted_multi = false ;
804812 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);
806814 if (!pubkey) return nullptr ;
807815 return MakeUnique<PKDescriptor>(std::move (pubkey));
808816 }
809817 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);
811819 if (!pubkey) return nullptr ;
812820 return MakeUnique<PKHDescriptor>(std::move (pubkey));
813821 }
814822 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);
816824 if (!pubkey) return nullptr ;
817825 return MakeUnique<ComboDescriptor>(std::move (pubkey));
818826 } else if (ctx != ParseScriptContext::TOP && Func (" combo" , expr)) {
@@ -834,10 +842,11 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
834842 return nullptr ;
835843 }
836844 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);
838846 if (!pk) return nullptr ;
839847 script_size += pk->GetSize () + 1 ;
840848 providers.emplace_back (std::move (pk));
849+ key_exp_index++;
841850 }
842851 if (providers.size () < 1 || providers.size () > 16 ) {
843852 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
864873 return MakeUnique<MultisigDescriptor>(thres, std::move (providers), sorted_multi);
865874 }
866875 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);
868877 if (!pubkey) return nullptr ;
869878 return MakeUnique<WPKHDescriptor>(std::move (pubkey));
870879 } else if (ctx == ParseScriptContext::P2WSH && Func (" wpkh" , expr)) {
871880 error = " Cannot have wpkh within wsh" ;
872881 return nullptr ;
873882 }
874883 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);
876885 if (!desc || expr.size ()) return nullptr ;
877886 return MakeUnique<SHDescriptor>(std::move (desc));
878887 } else if (ctx != ParseScriptContext::TOP && Func (" sh" , expr)) {
879888 error = " Cannot have sh in non-top level" ;
880889 return nullptr ;
881890 }
882891 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);
884893 if (!desc || expr.size ()) return nullptr ;
885894 return MakeUnique<WSHDescriptor>(std::move (desc));
886895 } else if (ctx == ParseScriptContext::P2WSH && Func (" wsh" , expr)) {
@@ -917,10 +926,10 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
917926
918927std::unique_ptr<PubkeyProvider> InferPubkey (const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
919928{
920- std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(pubkey);
929+ std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(0 , pubkey);
921930 KeyOriginInfo info;
922931 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));
924933 }
925934 return key_provider;
926935}
@@ -1032,7 +1041,7 @@ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProv
10321041{
10331042 Span<const char > sp (descriptor.data (), descriptor.size ());
10341043 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);
10361045 if (sp.size () == 0 && ret) return std::unique_ptr<Descriptor>(std::move (ret));
10371046 return nullptr ;
10381047}
0 commit comments