@@ -767,6 +767,8 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
767
767
std::vector<NodeRef> stack;
768
768
/* * The queue of instructions. */
769
769
std::vector<std::pair<Type, std::optional<NodeInfo>>> todo{{root_type, {}}};
770
+ /* * Predict the number of (static) script ops. */
771
+ uint32_t ops{0 };
770
772
771
773
while (!todo.empty ()) {
772
774
// The expected type we have to construct.
@@ -775,6 +777,72 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
775
777
// Fragment/children have not been decided yet. Decide them.
776
778
auto node_info = ConsumeNode (type_needed);
777
779
if (!node_info) return {};
780
+ // Update predicted resource limits.
781
+ switch (node_info->fragment ) {
782
+ case Fragment::JUST_0:
783
+ case Fragment::JUST_1:
784
+ break ;
785
+ case Fragment::PK_K:
786
+ break ;
787
+ case Fragment::PK_H:
788
+ ops += 3 ;
789
+ break ;
790
+ case Fragment::OLDER:
791
+ case Fragment::AFTER:
792
+ ops += 1 ;
793
+ break ;
794
+ case Fragment::RIPEMD160:
795
+ case Fragment::SHA256:
796
+ case Fragment::HASH160:
797
+ case Fragment::HASH256:
798
+ ops += 4 ;
799
+ break ;
800
+ case Fragment::ANDOR:
801
+ ops += 3 ;
802
+ break ;
803
+ case Fragment::AND_V:
804
+ break ;
805
+ case Fragment::AND_B:
806
+ case Fragment::OR_B:
807
+ ops += 1 ;
808
+ break ;
809
+ case Fragment::OR_C:
810
+ ops += 2 ;
811
+ break ;
812
+ case Fragment::OR_D:
813
+ ops += 3 ;
814
+ break ;
815
+ case Fragment::OR_I:
816
+ ops += 3 ;
817
+ break ;
818
+ case Fragment::THRESH:
819
+ ops += node_info->subtypes .size ();
820
+ break ;
821
+ case Fragment::MULTI:
822
+ ops += 1 ;
823
+ break ;
824
+ case Fragment::WRAP_A:
825
+ ops += 2 ;
826
+ break ;
827
+ case Fragment::WRAP_S:
828
+ ops += 1 ;
829
+ break ;
830
+ case Fragment::WRAP_C:
831
+ ops += 1 ;
832
+ break ;
833
+ case Fragment::WRAP_D:
834
+ ops += 3 ;
835
+ break ;
836
+ case Fragment::WRAP_V:
837
+ break ;
838
+ case Fragment::WRAP_J:
839
+ ops += 4 ;
840
+ break ;
841
+ case Fragment::WRAP_N:
842
+ ops += 1 ;
843
+ break ;
844
+ }
845
+ if (ops > MAX_OPS_PER_SCRIPT) return {};
778
846
auto subtypes = node_info->subtypes ;
779
847
todo.back ().second = std::move (node_info);
780
848
todo.reserve (todo.size () + subtypes.size ());
@@ -814,12 +882,18 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
814
882
assert (node->GetType () << type_needed);
815
883
}
816
884
if (!node->IsValid ()) return {};
885
+ // Update resource predictions.
886
+ if (node->fragment == Fragment::WRAP_V && node->subs [0 ]->GetType () << " x" _mst) {
887
+ ops += 1 ;
888
+ }
889
+ if (ops > MAX_OPS_PER_SCRIPT) return {};
817
890
// Move it to the stack.
818
891
stack.push_back (std::move (node));
819
892
todo.pop_back ();
820
893
}
821
894
}
822
895
assert (stack.size () == 1 );
896
+ assert (stack[0 ]->GetStaticOps () == ops);
823
897
stack[0 ]->DuplicateKeyCheck (KEY_COMP);
824
898
return std::move (stack[0 ]);
825
899
}
0 commit comments