diff --git a/src/test/miniscript_tests.cpp b/src/test/miniscript_tests.cpp index f253562a2f6..c2b0d43dccf 100644 --- a/src/test/miniscript_tests.cpp +++ b/src/test/miniscript_tests.cpp @@ -298,7 +298,7 @@ using Node = miniscript::Node; /** Compute all challenges (pubkeys, hashes, timelocks) that occur in a given Miniscript. */ // NOLINTNEXTLINE(misc-no-recursion) -std::set FindChallenges(const NodeRef& ref) { +std::set FindChallenges_recursive(const NodeRef& ref) { std::set chal; for (const auto& key : ref->keys) { chal.emplace(ChallengeType::PK, ChallengeNumber(key)); @@ -317,12 +317,44 @@ std::set FindChallenges(const NodeRef& ref) { chal.emplace(ChallengeType::HASH160, ChallengeNumber(ref->data)); } for (const auto& sub : ref->subs) { - auto sub_chal = FindChallenges(sub); + auto sub_chal = FindChallenges_recursive(sub); chal.insert(sub_chal.begin(), sub_chal.end()); } return chal; } +/** Compute all challenges (pubkeys, hashes, timelocks) that occur in a given Miniscript. */ +std::set FindChallenges(const NodeRef& root) +{ + std::set chal; + + for (std::vector stack{root.get()}; !stack.empty();) { + const Node* ref{stack.back()}; + stack.pop_back(); + + for (const auto& key : ref->keys) { + chal.emplace(ChallengeType::PK, ChallengeNumber(key)); + } + if (ref->fragment == miniscript::Fragment::OLDER) { + chal.emplace(ChallengeType::OLDER, ref->k); + } else if (ref->fragment == miniscript::Fragment::AFTER) { + chal.emplace(ChallengeType::AFTER, ref->k); + } else if (ref->fragment == miniscript::Fragment::SHA256) { + chal.emplace(ChallengeType::SHA256, ChallengeNumber(ref->data)); + } else if (ref->fragment == miniscript::Fragment::RIPEMD160) { + chal.emplace(ChallengeType::RIPEMD160, ChallengeNumber(ref->data)); + } else if (ref->fragment == miniscript::Fragment::HASH256) { + chal.emplace(ChallengeType::HASH256, ChallengeNumber(ref->data)); + } else if (ref->fragment == miniscript::Fragment::HASH160) { + chal.emplace(ChallengeType::HASH160, ChallengeNumber(ref->data)); + } + for (const auto& sub : ref->subs) { + stack.push_back(sub.get()); + } + } + return chal; +} + //! The spk for this script under the given context. If it's a Taproot output also record the spend data. CScript ScriptPubKey(miniscript::MiniscriptContext ctx, const CScript& script, TaprootBuilder& builder) { @@ -347,7 +379,9 @@ struct MiniScriptTest : BasicTestingSetup { /** Run random satisfaction tests. */ void TestSatisfy(const KeyConverter& converter, const std::string& testcase, const NodeRef& node) { auto script = node->ToScript(converter); - auto challenges = FindChallenges(node); // Find all challenges in the generated miniscript. + const auto challenges_recursive{FindChallenges_recursive(node)}; + const auto challenges{FindChallenges(node)}; // Find all challenges in the generated miniscript. + BOOST_CHECK(challenges_recursive == challenges); std::vector challist(challenges.begin(), challenges.end()); for (int iter = 0; iter < 3; ++iter) { std::shuffle(challist.begin(), challist.end(), m_rng);