|
20 | 20 | #include <primitives/transaction.h>
|
21 | 21 | #include <script/script.h>
|
22 | 22 | #include <span.h>
|
| 23 | +#include <util/check.h> |
23 | 24 | #include <util/spanparsing.h>
|
24 | 25 | #include <util/strencodings.h>
|
25 | 26 | #include <util/string.h>
|
@@ -234,6 +235,16 @@ enum class MiniscriptContext {
|
234 | 235 | TAPSCRIPT,
|
235 | 236 | };
|
236 | 237 |
|
| 238 | +/** Whether the context Tapscript, ensuring the only other possibility is P2WSH. */ |
| 239 | +constexpr bool IsTapscript(MiniscriptContext ms_ctx) |
| 240 | +{ |
| 241 | + switch (ms_ctx) { |
| 242 | + case MiniscriptContext::P2WSH: return false; |
| 243 | + case MiniscriptContext::TAPSCRIPT: return true; |
| 244 | + } |
| 245 | + assert(false); |
| 246 | +} |
| 247 | + |
237 | 248 | namespace internal {
|
238 | 249 |
|
239 | 250 | //! Helper function for Node::CalcType.
|
@@ -585,7 +596,8 @@ struct Node {
|
585 | 596 | };
|
586 | 597 | // The upward function computes for a node, given its followed-by-OP_VERIFY status
|
587 | 598 | // and the CScripts of its child nodes, the CScript of the node.
|
588 |
| - auto upfn = [&ctx](bool verify, const Node& node, Span<CScript> subs) -> CScript { |
| 599 | + const bool is_tapscript{IsTapscript(m_script_ctx)}; |
| 600 | + auto upfn = [&ctx, is_tapscript](bool verify, const Node& node, Span<CScript> subs) -> CScript { |
589 | 601 | switch (node.fragment) {
|
590 | 602 | case Fragment::PK_K: return BuildScript(ctx.ToPKBytes(node.keys[0]));
|
591 | 603 | case Fragment::PK_H: return BuildScript(OP_DUP, OP_HASH160, ctx.ToPKHBytes(node.keys[0]), OP_EQUALVERIFY);
|
@@ -618,6 +630,7 @@ struct Node {
|
618 | 630 | case Fragment::OR_I: return BuildScript(OP_IF, subs[0], OP_ELSE, subs[1], OP_ENDIF);
|
619 | 631 | case Fragment::ANDOR: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[2], OP_ELSE, subs[1], OP_ENDIF);
|
620 | 632 | case Fragment::MULTI: {
|
| 633 | + CHECK_NONFATAL(!is_tapscript); |
621 | 634 | CScript script = BuildScript(node.k);
|
622 | 635 | for (const auto& key : node.keys) {
|
623 | 636 | script = BuildScript(std::move(script), ctx.ToPKBytes(key));
|
@@ -653,7 +666,8 @@ struct Node {
|
653 | 666 | };
|
654 | 667 | // The upward function computes for a node, given whether its parent is a wrapper,
|
655 | 668 | // and the string representations of its child nodes, the string representation of the node.
|
656 |
| - auto upfn = [&ctx](bool wrapped, const Node& node, Span<std::string> subs) -> std::optional<std::string> { |
| 669 | + const bool is_tapscript{IsTapscript(m_script_ctx)}; |
| 670 | + auto upfn = [&ctx, is_tapscript](bool wrapped, const Node& node, Span<std::string> subs) -> std::optional<std::string> { |
657 | 671 | std::string ret = wrapped ? ":" : "";
|
658 | 672 |
|
659 | 673 | switch (node.fragment) {
|
@@ -717,6 +731,7 @@ struct Node {
|
717 | 731 | if (node.subs[2]->fragment == Fragment::JUST_0) return std::move(ret) + "and_n(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")";
|
718 | 732 | return std::move(ret) + "andor(" + std::move(subs[0]) + "," + std::move(subs[1]) + "," + std::move(subs[2]) + ")";
|
719 | 733 | case Fragment::MULTI: {
|
| 734 | + CHECK_NONFATAL(!is_tapscript); |
720 | 735 | auto str = std::move(ret) + "multi(" + ::ToString(node.k);
|
721 | 736 | for (const auto& key : node.keys) {
|
722 | 737 | auto key_str = ctx.ToString(key);
|
@@ -1631,6 +1646,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
|
1631 | 1646 | in = in.subspan(arg_size + 1);
|
1632 | 1647 | script_size += 1 + (num > 16) + (num > 0x7f) + (num > 0x7fff) + (num > 0x7fffff);
|
1633 | 1648 | } else if (Const("multi(", in)) {
|
| 1649 | + if (IsTapscript(ctx.MsContext())) return {}; |
1634 | 1650 | // Get threshold
|
1635 | 1651 | int next_comma = FindNextChar(in, ',');
|
1636 | 1652 | if (next_comma < 1) return {};
|
@@ -1989,6 +2005,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
|
1989 | 2005 | }
|
1990 | 2006 | // Multi
|
1991 | 2007 | if (last - in >= 3 && in[0].first == OP_CHECKMULTISIG) {
|
| 2008 | + if (IsTapscript(ctx.MsContext())) return {}; |
1992 | 2009 | std::vector<Key> keys;
|
1993 | 2010 | const auto n = ParseScriptNumber(in[1]);
|
1994 | 2011 | if (!n || last - in < 3 + *n) return {};
|
|
0 commit comments