Parse a script in a particular context. */
| 486 | |
| 487 | /** Parse a script in a particular context. */ |
| 488 | std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out) |
| 489 | { |
| 490 | auto expr = Expr(sp); |
| 491 | if (Func("pk", expr)) { |
| 492 | auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out); |
| 493 | if (!pubkey) return nullptr; |
| 494 | return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2PKGetScript, "pk"); |
| 495 | } |
| 496 | if (Func("pkh", expr)) { |
| 497 | auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out); |
| 498 | if (!pubkey) return nullptr; |
| 499 | return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2PKHGetScript, "pkh"); |
| 500 | } |
| 501 | if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { |
| 502 | auto pubkey = ParsePubkey(expr, true, out); |
| 503 | if (!pubkey) return nullptr; |
| 504 | return MakeUnique<ComboDescriptor>(std::move(pubkey)); |
| 505 | } |
| 506 | if (Func("multi", expr)) { |
| 507 | auto threshold = Expr(expr); |
| 508 | uint32_t thres; |
| 509 | std::vector<std::unique_ptr<PubkeyProvider>> providers; |
| 510 | if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) return nullptr; |
| 511 | size_t script_size = 0; |
| 512 | while (expr.size()) { |
| 513 | if (!Const(",", expr)) return nullptr; |
| 514 | auto arg = Expr(expr); |
| 515 | auto pk = ParsePubkey(arg, ctx != ParseScriptContext::P2WSH, out); |
| 516 | if (!pk) return nullptr; |
| 517 | script_size += pk->GetSize() + 1; |
| 518 | providers.emplace_back(std::move(pk)); |
| 519 | } |
| 520 | if (providers.size() < 1 || providers.size() > 16 || thres < 1 || thres > providers.size()) return nullptr; |
| 521 | if (ctx == ParseScriptContext::TOP) { |
| 522 | if (providers.size() > 3) return nullptr; // Not more than 3 pubkeys for raw multisig |
| 523 | } |
| 524 | if (ctx == ParseScriptContext::P2SH) { |
| 525 | if (script_size + 3 > 520) return nullptr; // Enforce P2SH script size limit |
| 526 | } |
| 527 | return MakeUnique<MultisigDescriptor>(thres, std::move(providers)); |
| 528 | } |
| 529 | if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) { |
| 530 | auto pubkey = ParsePubkey(expr, false, out); |
| 531 | if (!pubkey) return nullptr; |
| 532 | return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2WPKHGetScript, "wpkh"); |
| 533 | } |
| 534 | if (ctx == ParseScriptContext::TOP && Func("sh", expr)) { |
| 535 | auto desc = ParseScript(expr, ParseScriptContext::P2SH, out); |
| 536 | if (!desc || expr.size()) return nullptr; |
| 537 | return MakeUnique<ConvertorDescriptor>(std::move(desc), ConvertP2SH, "sh"); |
| 538 | } |
| 539 | if (ctx != ParseScriptContext::P2WSH && Func("wsh", expr)) { |
| 540 | auto desc = ParseScript(expr, ParseScriptContext::P2WSH, out); |
| 541 | if (!desc || expr.size()) return nullptr; |
| 542 | return MakeUnique<ConvertorDescriptor>(std::move(desc), ConvertP2WSH, "wsh"); |
| 543 | } |
| 544 | if (ctx == ParseScriptContext::TOP && Func("addr", expr)) { |
| 545 | CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end())); |