2222#include < util/vector.h>
2323
2424#include < memory>
25+ #include < numeric>
2526#include < optional>
2627#include < string>
2728#include < vector>
@@ -706,6 +707,17 @@ class DescriptorImpl : public Descriptor
706707 }
707708
708709 std::optional<OutputType> GetOutputType () const override { return std::nullopt ; }
710+
711+ std::optional<int64_t > ScriptSize () const override { return {}; }
712+
713+ /* * A helper for MaxSatisfactionWeight.
714+ *
715+ * @param use_max_sig Whether to assume ECDSA signatures will have a high-r.
716+ * @return The maximum size of the satisfaction in raw bytes (with no witness meaning).
717+ */
718+ virtual std::optional<int64_t > MaxSatSize (bool use_max_sig) const { return {}; }
719+
720+ std::optional<int64_t > MaxSatisfactionWeight (bool ) const override { return {}; }
709721};
710722
711723/* * A parsed addr(A) descriptor. */
@@ -725,6 +737,8 @@ class AddressDescriptor final : public DescriptorImpl
725737 }
726738 bool IsSingleType () const final { return true ; }
727739 bool ToPrivateString (const SigningProvider& arg, std::string& out) const final { return false ; }
740+
741+ std::optional<int64_t > ScriptSize () const override { return GetScriptForDestination (m_destination).size (); }
728742};
729743
730744/* * A parsed raw(H) descriptor. */
@@ -746,6 +760,8 @@ class RawDescriptor final : public DescriptorImpl
746760 }
747761 bool IsSingleType () const final { return true ; }
748762 bool ToPrivateString (const SigningProvider& arg, std::string& out) const final { return false ; }
763+
764+ std::optional<int64_t > ScriptSize () const override { return m_script.size (); }
749765};
750766
751767/* * A parsed pk(P) descriptor. */
@@ -766,6 +782,19 @@ class PKDescriptor final : public DescriptorImpl
766782public:
767783 PKDescriptor (std::unique_ptr<PubkeyProvider> prov, bool xonly = false ) : DescriptorImpl(Vector(std::move(prov)), " pk" ), m_xonly(xonly) {}
768784 bool IsSingleType () const final { return true ; }
785+
786+ std::optional<int64_t > ScriptSize () const override {
787+ return 1 + (m_xonly ? 32 : m_pubkey_args[0 ]->GetSize ()) + 1 ;
788+ }
789+
790+ std::optional<int64_t > MaxSatSize (bool use_max_sig) const override {
791+ const auto ecdsa_sig_size = use_max_sig ? 72 : 71 ;
792+ return 1 + (m_xonly ? 65 : ecdsa_sig_size);
793+ }
794+
795+ std::optional<int64_t > MaxSatisfactionWeight (bool use_max_sig) const override {
796+ return *MaxSatSize (use_max_sig) * WITNESS_SCALE_FACTOR;
797+ }
769798};
770799
771800/* * A parsed pkh(P) descriptor. */
@@ -782,6 +811,17 @@ class PKHDescriptor final : public DescriptorImpl
782811 PKHDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), " pkh" ) {}
783812 std::optional<OutputType> GetOutputType () const override { return OutputType::LEGACY; }
784813 bool IsSingleType () const final { return true ; }
814+
815+ std::optional<int64_t > ScriptSize () const override { return 1 + 1 + 1 + 20 + 1 + 1 ; }
816+
817+ std::optional<int64_t > MaxSatSize (bool use_max_sig) const override {
818+ const auto sig_size = use_max_sig ? 72 : 71 ;
819+ return 1 + sig_size + 1 + m_pubkey_args[0 ]->GetSize ();
820+ }
821+
822+ std::optional<int64_t > MaxSatisfactionWeight (bool use_max_sig) const override {
823+ return *MaxSatSize (use_max_sig) * WITNESS_SCALE_FACTOR;
824+ }
785825};
786826
787827/* * A parsed wpkh(P) descriptor. */
@@ -798,6 +838,17 @@ class WPKHDescriptor final : public DescriptorImpl
798838 WPKHDescriptor (std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), " wpkh" ) {}
799839 std::optional<OutputType> GetOutputType () const override { return OutputType::BECH32; }
800840 bool IsSingleType () const final { return true ; }
841+
842+ std::optional<int64_t > ScriptSize () const override { return 1 + 1 + 20 ; }
843+
844+ std::optional<int64_t > MaxSatSize (bool use_max_sig) const override {
845+ const auto sig_size = use_max_sig ? 72 : 71 ;
846+ return (1 + sig_size + 1 + 33 );
847+ }
848+
849+ std::optional<int64_t > MaxSatisfactionWeight (bool use_max_sig) const override {
850+ return MaxSatSize (use_max_sig);
851+ }
801852};
802853
803854/* * A parsed combo(P) descriptor. */
@@ -842,6 +893,22 @@ class MultisigDescriptor final : public DescriptorImpl
842893public:
843894 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) {}
844895 bool IsSingleType () const final { return true ; }
896+
897+ std::optional<int64_t > ScriptSize () const override {
898+ const auto n_keys = m_pubkey_args.size ();
899+ auto op = [](int64_t acc, const std::unique_ptr<PubkeyProvider>& pk) { return acc + 1 + pk->GetSize ();};
900+ const auto pubkeys_size{std::accumulate (m_pubkey_args.begin (), m_pubkey_args.end (), int64_t {0 }, op)};
901+ return 1 + BuildScript (n_keys).size () + BuildScript (m_threshold).size () + pubkeys_size;
902+ }
903+
904+ std::optional<int64_t > MaxSatSize (bool use_max_sig) const override {
905+ const auto sig_size = use_max_sig ? 72 : 71 ;
906+ return (1 + (1 + sig_size) * m_threshold);
907+ }
908+
909+ std::optional<int64_t > MaxSatisfactionWeight (bool use_max_sig) const override {
910+ return *MaxSatSize (use_max_sig) * WITNESS_SCALE_FACTOR;
911+ }
845912};
846913
847914/* * A parsed (sorted)multi_a(...) descriptor. Always uses x-only pubkeys. */
@@ -867,6 +934,15 @@ class MultiADescriptor final : public DescriptorImpl
867934public:
868935 MultiADescriptor (int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false ) : DescriptorImpl(std::move(providers), sorted ? " sortedmulti_a" : " multi_a" ), m_threshold(threshold), m_sorted(sorted) {}
869936 bool IsSingleType () const final { return true ; }
937+
938+ std::optional<int64_t > ScriptSize () const override {
939+ const auto n_keys = m_pubkey_args.size ();
940+ return (1 + 32 + 1 ) * n_keys + BuildScript (m_threshold).size () + 1 ;
941+ }
942+
943+ std::optional<int64_t > MaxSatSize (bool use_max_sig) const override {
944+ return (1 + 65 ) * m_threshold + (m_pubkey_args.size () - m_threshold);
945+ }
870946};
871947
872948/* * A parsed sh(...) descriptor. */
@@ -879,16 +955,34 @@ class SHDescriptor final : public DescriptorImpl
879955 if (ret.size ()) out.scripts .emplace (CScriptID (scripts[0 ]), scripts[0 ]);
880956 return ret;
881957 }
958+
959+ bool IsSegwit () const { return m_subdescriptor_args[0 ]->GetOutputType () == OutputType::BECH32; }
960+
882961public:
883962 SHDescriptor (std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), " sh" ) {}
884963
885964 std::optional<OutputType> GetOutputType () const override
886965 {
887966 assert (m_subdescriptor_args.size () == 1 );
888- if (m_subdescriptor_args[ 0 ]-> GetOutputType () == OutputType::BECH32 ) return OutputType::P2SH_SEGWIT;
967+ if (IsSegwit () ) return OutputType::P2SH_SEGWIT;
889968 return OutputType::LEGACY;
890969 }
891970 bool IsSingleType () const final { return true ; }
971+
972+ std::optional<int64_t > ScriptSize () const override { return 1 + 1 + 20 + 1 ; }
973+
974+ std::optional<int64_t > MaxSatisfactionWeight (bool use_max_sig) const override {
975+ if (const auto sat_size = m_subdescriptor_args[0 ]->MaxSatSize (use_max_sig)) {
976+ if (const auto subscript_size = m_subdescriptor_args[0 ]->ScriptSize ()) {
977+ // The subscript is never witness data.
978+ const auto subscript_weight = (1 + *subscript_size) * WITNESS_SCALE_FACTOR;
979+ // The weight depends on whether the inner descriptor is satisfied using the witness stack.
980+ if (IsSegwit ()) return subscript_weight + *sat_size;
981+ return subscript_weight + *sat_size * WITNESS_SCALE_FACTOR;
982+ }
983+ }
984+ return {};
985+ }
892986};
893987
894988/* * A parsed wsh(...) descriptor. */
@@ -905,6 +999,21 @@ class WSHDescriptor final : public DescriptorImpl
905999 WSHDescriptor (std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), " wsh" ) {}
9061000 std::optional<OutputType> GetOutputType () const override { return OutputType::BECH32; }
9071001 bool IsSingleType () const final { return true ; }
1002+
1003+ std::optional<int64_t > ScriptSize () const override { return 1 + 1 + 32 ; }
1004+
1005+ std::optional<int64_t > MaxSatSize (bool use_max_sig) const override {
1006+ if (const auto sat_size = m_subdescriptor_args[0 ]->MaxSatSize (use_max_sig)) {
1007+ if (const auto subscript_size = m_subdescriptor_args[0 ]->ScriptSize ()) {
1008+ return GetSizeOfCompactSize (*subscript_size) + *subscript_size + *sat_size;
1009+ }
1010+ }
1011+ return {};
1012+ }
1013+
1014+ std::optional<int64_t > MaxSatisfactionWeight (bool use_max_sig) const override {
1015+ return MaxSatSize (use_max_sig);
1016+ }
9081017};
9091018
9101019/* * A parsed tr(...) descriptor. */
@@ -958,6 +1067,13 @@ class TRDescriptor final : public DescriptorImpl
9581067 }
9591068 std::optional<OutputType> GetOutputType () const override { return OutputType::BECH32M; }
9601069 bool IsSingleType () const final { return true ; }
1070+
1071+ std::optional<int64_t > ScriptSize () const override { return 1 + 1 + 32 ; }
1072+
1073+ std::optional<int64_t > MaxSatisfactionWeight (bool ) const override {
1074+ // FIXME: We assume keypath spend, which can lead to very large underestimations.
1075+ return 1 + 65 ;
1076+ }
9611077};
9621078
9631079/* We instantiate Miniscript here with a simple integer as key type.
@@ -1041,6 +1157,13 @@ class MiniscriptDescriptor final : public DescriptorImpl
10411157
10421158 bool IsSolvable () const override { return true ; }
10431159 bool IsSingleType () const final { return true ; }
1160+
1161+ std::optional<int64_t > ScriptSize () const override { return m_node->ScriptSize (); }
1162+
1163+ std::optional<int64_t > MaxSatSize (bool ) const override {
1164+ // For Miniscript we always assume high-R ECDSA signatures.
1165+ return m_node->GetWitnessSize ();
1166+ }
10441167};
10451168
10461169/* * A parsed rawtr(...) descriptor. */
@@ -1059,6 +1182,13 @@ class RawTRDescriptor final : public DescriptorImpl
10591182 RawTRDescriptor (std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(Vector(std::move(output_key)), " rawtr" ) {}
10601183 std::optional<OutputType> GetOutputType () const override { return OutputType::BECH32M; }
10611184 bool IsSingleType () const final { return true ; }
1185+
1186+ std::optional<int64_t > ScriptSize () const override { return 1 + 1 + 32 ; }
1187+
1188+ std::optional<int64_t > MaxSatisfactionWeight (bool ) const override {
1189+ // We can't know whether there is a script path, so assume key path spend.
1190+ return 1 + 65 ;
1191+ }
10621192};
10631193
10641194// //////////////////////////////////////////////////////////////////////////
0 commit comments