From d25d58bf5f301d3bb8683bd67c8847a4957d8e97 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Mon, 4 Oct 2021 00:08:00 +0200 Subject: miniscript: add a helper to find the first insane sub with no child This is helpful for finer grained descriptor parsing error: when there are multiple errors to report in a Miniscript descriptor start with the "smallest" fragments: the ones closer to be a leaf. Co-Authored-By: Pieter Wuille --- src/script/miniscript.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/script/miniscript.h') diff --git a/src/script/miniscript.h b/src/script/miniscript.h index 0137293180..f783d1dafc 100644 --- a/src/script/miniscript.h +++ b/src/script/miniscript.h @@ -429,6 +429,21 @@ private: )); } + /** Like TreeEval, but without downfn or State type. + * upfn takes (const Node&, Span) and returns Result. */ + template + Result TreeEval(UpFn upfn) const + { + struct DummyState {}; + return std::move(*TreeEvalMaybe(DummyState{}, + [](DummyState, const Node&, size_t) { return DummyState{}; }, + [&upfn](DummyState, const Node& node, Span subs) { + Result res{upfn(node, subs)}; + return std::optional(std::move(res)); + } + )); + } + /** Compare two miniscript subtrees, using a non-recursive algorithm. */ friend int Compare(const Node& node1, const Node& node2) { @@ -818,6 +833,15 @@ public: //! Return the expression type. Type GetType() const { return typ; } + //! Find an insane subnode which has no insane children. Nullptr if there is none. + const Node* FindInsaneSub() const { + return TreeEval([](const Node& node, Span subs) -> const Node* { + for (auto& sub: subs) if (sub) return sub; + if (!node.IsSaneSubexpression()) return &node; + return nullptr; + }); + } + //! Check whether this node is valid at all. bool IsValid() const { return !(GetType() == ""_mst) && ScriptSize() <= MAX_STANDARD_P2WSH_SCRIPT_SIZE; } -- cgit v1.2.3