@@ -625,6 +625,80 @@ std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext
625625 return nullptr ;
626626}
627627
628+ std::unique_ptr<PubkeyProvider> InferPubkey (const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
629+ {
630+ std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(pubkey);
631+ KeyOriginInfo info;
632+ if (provider.GetKeyOrigin (pubkey.GetID (), info)) {
633+ return MakeUnique<OriginPubkeyProvider>(std::move (info), std::move (key_provider));
634+ }
635+ return key_provider;
636+ }
637+
638+ std::unique_ptr<Descriptor> InferScript (const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
639+ {
640+ std::vector<std::vector<unsigned char >> data;
641+ txnouttype txntype = Solver (script, data);
642+
643+ if (txntype == TX_PUBKEY) {
644+ CPubKey pubkey (data[0 ].begin (), data[0 ].end ());
645+ if (pubkey.IsValid ()) {
646+ return MakeUnique<SingleKeyDescriptor>(InferPubkey (pubkey, ctx, provider), P2PKGetScript, " pk" );
647+ }
648+ }
649+ if (txntype == TX_PUBKEYHASH) {
650+ uint160 hash (data[0 ]);
651+ CKeyID keyid (hash);
652+ CPubKey pubkey;
653+ if (provider.GetPubKey (keyid, pubkey)) {
654+ return MakeUnique<SingleKeyDescriptor>(InferPubkey (pubkey, ctx, provider), P2PKHGetScript, " pkh" );
655+ }
656+ }
657+ if (txntype == TX_WITNESS_V0_KEYHASH && ctx != ParseScriptContext::P2WSH) {
658+ uint160 hash (data[0 ]);
659+ CKeyID keyid (hash);
660+ CPubKey pubkey;
661+ if (provider.GetPubKey (keyid, pubkey)) {
662+ return MakeUnique<SingleKeyDescriptor>(InferPubkey (pubkey, ctx, provider), P2WPKHGetScript, " wpkh" );
663+ }
664+ }
665+ if (txntype == TX_MULTISIG) {
666+ std::vector<std::unique_ptr<PubkeyProvider>> providers;
667+ for (size_t i = 1 ; i + 1 < data.size (); ++i) {
668+ CPubKey pubkey (data[i].begin (), data[i].end ());
669+ providers.push_back (InferPubkey (pubkey, ctx, provider));
670+ }
671+ return MakeUnique<MultisigDescriptor>((int )data[0 ][0 ], std::move (providers));
672+ }
673+ if (txntype == TX_SCRIPTHASH && ctx == ParseScriptContext::TOP) {
674+ uint160 hash (data[0 ]);
675+ CScriptID scriptid (hash);
676+ CScript subscript;
677+ if (provider.GetCScript (scriptid, subscript)) {
678+ auto sub = InferScript (subscript, ParseScriptContext::P2SH, provider);
679+ if (sub) return MakeUnique<ConvertorDescriptor>(std::move (sub), ConvertP2SH, " sh" );
680+ }
681+ }
682+ if (txntype == TX_WITNESS_V0_SCRIPTHASH && ctx != ParseScriptContext::P2WSH) {
683+ CScriptID scriptid;
684+ CRIPEMD160 ().Write (data[0 ].data (), data[0 ].size ()).Finalize (scriptid.begin ());
685+ CScript subscript;
686+ if (provider.GetCScript (scriptid, subscript)) {
687+ auto sub = InferScript (subscript, ParseScriptContext::P2WSH, provider);
688+ if (sub) return MakeUnique<ConvertorDescriptor>(std::move (sub), ConvertP2WSH, " wsh" );
689+ }
690+ }
691+
692+ CTxDestination dest;
693+ if (ExtractDestination (script, dest)) {
694+ if (GetScriptForDestination (dest) == script) {
695+ return MakeUnique<AddressDescriptor>(std::move (dest));
696+ }
697+ }
698+
699+ return MakeUnique<RawDescriptor>(script);
700+ }
701+
628702} // namespace
629703
630704std::unique_ptr<Descriptor> Parse (const std::string& descriptor, FlatSigningProvider& out)
@@ -634,3 +708,8 @@ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProv
634708 if (sp.size () == 0 && ret) return ret;
635709 return nullptr ;
636710}
711+
712+ std::unique_ptr<Descriptor> InferDescriptor (const CScript& script, const SigningProvider& provider)
713+ {
714+ return InferScript (script, ParseScriptContext::TOP, provider);
715+ }
0 commit comments