| 448 | } |
| 449 | |
| 450 | std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out) |
| 451 | { |
| 452 | auto split = Split(sp, '/'); |
| 453 | std::string str(split[0].begin(), split[0].end()); |
| 454 | if (split.size() == 1) { |
| 455 | if (IsHex(str)) { |
| 456 | std::vector<unsigned char> data = ParseHex(str); |
| 457 | CPubKey pubkey(data); |
| 458 | if (pubkey.IsFullyValid() && (permit_uncompressed || pubkey.IsCompressed())) return MakeUnique<ConstPubkeyProvider>(pubkey); |
| 459 | } |
| 460 | CKey key = DecodeSecret(str); |
| 461 | if (key.IsValid() && (permit_uncompressed || key.IsCompressed())) { |
| 462 | CPubKey pubkey = key.GetPubKey(); |
| 463 | out.keys.emplace(pubkey.GetID(), key); |
| 464 | return MakeUnique<ConstPubkeyProvider>(pubkey); |
| 465 | } |
| 466 | } |
| 467 | CExtKey extkey = DecodeExtKey(str); |
| 468 | CExtPubKey extpubkey = DecodeExtPubKey(str); |
| 469 | if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) return nullptr; |
| 470 | KeyPath path; |
| 471 | DeriveType type = DeriveType::NO; |
| 472 | if (split.back() == MakeSpan("*").first(1)) { |
| 473 | split.pop_back(); |
| 474 | type = DeriveType::UNHARDENED; |
| 475 | } else if (split.back() == MakeSpan("*'").first(2) || split.back() == MakeSpan("*h").first(2)) { |
| 476 | split.pop_back(); |
| 477 | type = DeriveType::HARDENED; |
| 478 | } |
| 479 | if (!ParseKeyPath(split, path)) return nullptr; |
| 480 | if (extkey.key.IsValid()) { |
| 481 | extpubkey = extkey.Neuter(); |
| 482 | out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key); |
| 483 | } |
| 484 | return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move(path), type); |
| 485 | } |
| 486 | |
| 487 | /** Parse a script in a particular context. */ |
| 488 | std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out) |
no test coverage detected