aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorAntoine Poinsot <darosior@protonmail.com>2022-04-09 17:38:28 +0200
committerAntoine Poinsot <darosior@protonmail.com>2022-04-28 16:44:40 +0200
commit1ab8d89fd1bdb3c0f2a506b4a10df6c23ba21c48 (patch)
tree2a40b851418ae338e5133f8eaa79ba218e9619f1 /src/script
parent5922c662c08a061b3b3d5ac34a31f9f9d4640d47 (diff)
downloadbitcoin-1ab8d89fd1bdb3c0f2a506b4a10df6c23ba21c48.tar.xz
miniscript: make equality operator non-recursive
Co-authored-by: Pieter Wuille <pieter.wuille@gmail.com>
Diffstat (limited to 'src/script')
-rw-r--r--src/script/miniscript.h35
1 files changed, 21 insertions, 14 deletions
diff --git a/src/script/miniscript.h b/src/script/miniscript.h
index 96a7f21dc5..270ce06ba0 100644
--- a/src/script/miniscript.h
+++ b/src/script/miniscript.h
@@ -408,6 +408,26 @@ private:
));
}
+ /** Compare two miniscript subtrees, using a non-recursive algorithm. */
+ friend int Compare(const Node<Key>& node1, const Node<Key>& node2)
+ {
+ std::vector<std::pair<const Node<Key>&, const Node<Key>&>> queue;
+ queue.emplace_back(node1, node2);
+ while (!queue.empty()) {
+ const auto& [a, b] = queue.back();
+ queue.pop_back();
+ if (std::tie(a.fragment, a.k, a.keys, a.data) < std::tie(b.fragment, b.k, b.keys, b.data)) return -1;
+ if (std::tie(b.fragment, b.k, b.keys, b.data) < std::tie(a.fragment, a.k, a.keys, a.data)) return 1;
+ if (a.subs.size() < b.subs.size()) return -1;
+ if (b.subs.size() < a.subs.size()) return 1;
+ size_t n = a.subs.size();
+ for (size_t i = 0; i < n; ++i) {
+ queue.emplace_back(*a.subs[n - 1 - i], *b.subs[n - 1 - i]);
+ }
+ }
+ return 0;
+ }
+
//! Compute the type for this miniscript.
Type CalcType() const {
using namespace internal;
@@ -765,20 +785,7 @@ public:
bool IsSaneTopLevel() const { return IsValidTopLevel() && IsSane() && NeedsSignature(); }
//! Equality testing.
- bool operator==(const Node<Key>& arg) const
- {
- if (fragment != arg.fragment) return false;
- if (k != arg.k) return false;
- if (data != arg.data) return false;
- if (keys != arg.keys) return false;
- if (subs.size() != arg.subs.size()) return false;
- for (size_t i = 0; i < subs.size(); ++i) {
- if (!(*subs[i] == *arg.subs[i])) return false;
- }
- assert(scriptlen == arg.scriptlen);
- assert(typ == arg.typ);
- return true;
- }
+ bool operator==(const Node<Key>& arg) const { return Compare(*this, arg) == 0; }
// Constructors with various argument combinations.
Node(Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) : fragment(nt), k(val), data(std::move(arg)), subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}