Parse a script in a particular context. */
| 1036 | |
| 1037 | /** Parse a script in a particular context. */ |
| 1038 | std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error) |
| 1039 | { |
| 1040 | using namespace spanparsing; |
| 1041 | |
| 1042 | auto expr = Expr(sp); |
| 1043 | bool sorted_multi = false; |
| 1044 | if (Func("pk", expr)) { |
| 1045 | auto pubkey = ParsePubkey(key_exp_index, expr, ctx, out, error); |
| 1046 | if (!pubkey) return nullptr; |
| 1047 | ++key_exp_index; |
| 1048 | return std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR); |
| 1049 | } |
| 1050 | if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && Func("pkh", expr)) { |
| 1051 | auto pubkey = ParsePubkey(key_exp_index, expr, ctx, out, error); |
| 1052 | if (!pubkey) return nullptr; |
| 1053 | ++key_exp_index; |
| 1054 | return std::make_unique<PKHDescriptor>(std::move(pubkey)); |
| 1055 | } else if (Func("pkh", expr)) { |
| 1056 | error = "Can only have pkh at top level, in sh(), or in wsh()"; |
| 1057 | return nullptr; |
| 1058 | } |
| 1059 | if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { |
| 1060 | auto pubkey = ParsePubkey(key_exp_index, expr, ctx, out, error); |
| 1061 | if (!pubkey) return nullptr; |
| 1062 | ++key_exp_index; |
| 1063 | return std::make_unique<ComboDescriptor>(std::move(pubkey)); |
| 1064 | } else if (Func("combo", expr)) { |
| 1065 | error = "Can only have combo() at top level"; |
| 1066 | return nullptr; |
| 1067 | } |
| 1068 | if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr))) { |
| 1069 | auto threshold = Expr(expr); |
| 1070 | uint32_t thres; |
| 1071 | std::vector<std::unique_ptr<PubkeyProvider>> providers; |
| 1072 | if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) { |
| 1073 | error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end())); |
| 1074 | return nullptr; |
| 1075 | } |
| 1076 | size_t script_size = 0; |
| 1077 | while (expr.size()) { |
| 1078 | if (!Const(",", expr)) { |
| 1079 | error = strprintf("Multi: expected ',', got '%c'", expr[0]); |
| 1080 | return nullptr; |
| 1081 | } |
| 1082 | auto arg = Expr(expr); |
| 1083 | auto pk = ParsePubkey(key_exp_index, arg, ctx, out, error); |
| 1084 | if (!pk) return nullptr; |
| 1085 | script_size += pk->GetSize() + 1; |
| 1086 | providers.emplace_back(std::move(pk)); |
| 1087 | key_exp_index++; |
| 1088 | } |
| 1089 | if (providers.empty() || providers.size() > MAX_PUBKEYS_PER_MULTISIG) { |
| 1090 | error = strprintf("Cannot have %u keys in multisig; must have between 1 and %d keys, inclusive", providers.size(), MAX_PUBKEYS_PER_MULTISIG); |
| 1091 | return nullptr; |
| 1092 | } else if (thres < 1) { |
| 1093 | error = strprintf("Multisig threshold cannot be %d, must be at least 1", thres); |
| 1094 | return nullptr; |
| 1095 | } else if (thres > providers.size()) { |