Parse a script in a particular context. */
| 1025 | |
| 1026 | /** Parse a script in a particular context. */ |
| 1027 | std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index, |
| 1028 | Span<const char> &sp, |
| 1029 | ParseScriptContext ctx, |
| 1030 | FlatSigningProvider &out, |
| 1031 | std::string &error) { |
| 1032 | using namespace script; |
| 1033 | |
| 1034 | auto expr = Expr(sp); |
| 1035 | bool sorted_multi = false; |
| 1036 | if (Func("pk", expr)) { |
| 1037 | auto pubkey = ParsePubkey(key_exp_index, expr, out, error); |
| 1038 | if (!pubkey) { |
| 1039 | return nullptr; |
| 1040 | } |
| 1041 | return std::make_unique<PKDescriptor>(std::move(pubkey)); |
| 1042 | } |
| 1043 | if (Func("pkh", expr)) { |
| 1044 | auto pubkey = ParsePubkey(key_exp_index, expr, out, error); |
| 1045 | if (!pubkey) { |
| 1046 | return nullptr; |
| 1047 | } |
| 1048 | return std::make_unique<PKHDescriptor>(std::move(pubkey)); |
| 1049 | } |
| 1050 | if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { |
| 1051 | auto pubkey = ParsePubkey(key_exp_index, expr, out, error); |
| 1052 | if (!pubkey) { |
| 1053 | return nullptr; |
| 1054 | } |
| 1055 | return std::make_unique<ComboDescriptor>(std::move(pubkey)); |
| 1056 | } else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) { |
| 1057 | error = "Cannot have combo in non-top level"; |
| 1058 | return nullptr; |
| 1059 | } |
| 1060 | if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) { |
| 1061 | auto threshold = Expr(expr); |
| 1062 | uint32_t thres; |
| 1063 | std::vector<std::unique_ptr<PubkeyProvider>> providers; |
| 1064 | if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), |
| 1065 | &thres)) { |
| 1066 | error = strprintf( |
| 1067 | "Multi threshold '%s' is not valid", |
| 1068 | std::string(threshold.begin(), threshold.end()).c_str()); |
| 1069 | return nullptr; |
| 1070 | } |
| 1071 | size_t script_size = 0; |
| 1072 | while (expr.size()) { |
| 1073 | if (!Const(",", expr)) { |
| 1074 | error = strprintf("Multi: expected ',', got '%c'", expr[0]); |
| 1075 | return nullptr; |
| 1076 | } |
| 1077 | auto arg = Expr(expr); |
| 1078 | auto pk = ParsePubkey(key_exp_index, arg, out, error); |
| 1079 | if (!pk) { |
| 1080 | return nullptr; |
| 1081 | } |
| 1082 | script_size += pk->GetSize() + 1; |
| 1083 | providers.emplace_back(std::move(pk)); |
| 1084 | key_exp_index++; |