@@ -625,6 +625,80 @@ std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext
625
625
return nullptr ;
626
626
}
627
627
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
+
628
702
} // namespace
629
703
630
704
std::unique_ptr<Descriptor> Parse (const std::string& descriptor, FlatSigningProvider& out)
@@ -634,3 +708,8 @@ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProv
634
708
if (sp.size () == 0 && ret) return ret;
635
709
return nullptr ;
636
710
}
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