Parse a script in a particular context. */ NOLINTNEXTLINE(misc-no-recursion)
| 2333 | /** Parse a script in a particular context. */ |
| 2334 | // NOLINTNEXTLINE(misc-no-recursion) |
| 2335 | std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index, std::span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error) |
| 2336 | { |
| 2337 | using namespace script; |
| 2338 | Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR); |
| 2339 | std::vector<std::unique_ptr<DescriptorImpl>> ret; |
| 2340 | auto expr = Expr(sp); |
| 2341 | if (Func("pk", expr)) { |
| 2342 | auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error); |
| 2343 | if (pubkeys.empty()) { |
| 2344 | error = strprintf("pk(): %s", error); |
| 2345 | return {}; |
| 2346 | } |
| 2347 | for (auto& pubkey : pubkeys) { |
| 2348 | ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR)); |
| 2349 | } |
| 2350 | return ret; |
| 2351 | } |
| 2352 | if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && Func("pkh", expr)) { |
| 2353 | auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error); |
| 2354 | if (pubkeys.empty()) { |
| 2355 | error = strprintf("pkh(): %s", error); |
| 2356 | return {}; |
| 2357 | } |
| 2358 | for (auto& pubkey : pubkeys) { |
| 2359 | ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey))); |
| 2360 | } |
| 2361 | return ret; |
| 2362 | } |
| 2363 | if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { |
| 2364 | auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error); |
| 2365 | if (pubkeys.empty()) { |
| 2366 | error = strprintf("combo(): %s", error); |
| 2367 | return {}; |
| 2368 | } |
| 2369 | for (auto& pubkey : pubkeys) { |
| 2370 | ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey))); |
| 2371 | } |
| 2372 | return ret; |
| 2373 | } else if (Func("combo", expr)) { |
| 2374 | error = "Can only have combo() at top level"; |
| 2375 | return {}; |
| 2376 | } |
| 2377 | const bool multi = Func("multi", expr); |
| 2378 | const bool sortedmulti = !multi && Func("sortedmulti", expr); |
| 2379 | const bool multi_a = !(multi || sortedmulti) && Func("multi_a", expr); |
| 2380 | const bool sortedmulti_a = !(multi || sortedmulti || multi_a) && Func("sortedmulti_a", expr); |
| 2381 | if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) || |
| 2382 | (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) { |
| 2383 | auto threshold = Expr(expr); |
| 2384 | uint32_t thres; |
| 2385 | std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers; // List of multipath expanded pubkeys |
| 2386 | if (const auto maybe_thres{ToIntegral<uint32_t>(std::string_view{threshold.begin(), threshold.end()})}) { |
| 2387 | thres = *maybe_thres; |
| 2388 | } else { |
| 2389 | error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end())); |
| 2390 | return {}; |
| 2391 | } |
| 2392 | size_t script_size = 0; |