| 421 | return true; |
| 422 | } |
| 423 | bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override |
| 424 | { |
| 425 | // For hardened derivation type, just return the typical string, nothing to normalize |
| 426 | if (m_derive == DeriveType::HARDENED) { |
| 427 | out = ToString(); |
| 428 | return true; |
| 429 | } |
| 430 | // Step backwards to find the last hardened step in the path |
| 431 | int i = (int)m_path.size() - 1; |
| 432 | for (; i >= 0; --i) { |
| 433 | if (m_path.at(i) >> 31) { |
| 434 | break; |
| 435 | } |
| 436 | } |
| 437 | // Either no derivation or all unhardened derivation |
| 438 | if (i == -1) { |
| 439 | out = ToString(); |
| 440 | return true; |
| 441 | } |
| 442 | // Get the path to the last hardened stup |
| 443 | KeyOriginInfo origin; |
| 444 | int k = 0; |
| 445 | for (; k <= i; ++k) { |
| 446 | // Add to the path |
| 447 | origin.path.push_back(m_path.at(k)); |
| 448 | } |
| 449 | // Build the remaining path |
| 450 | KeyPath end_path; |
| 451 | for (; k < (int)m_path.size(); ++k) { |
| 452 | end_path.push_back(m_path.at(k)); |
| 453 | } |
| 454 | // Get the fingerprint |
| 455 | CKeyID id = m_root_extkey.pubkey.GetID(); |
| 456 | std::copy(id.begin(), id.begin() + 4, origin.fingerprint); |
| 457 | |
| 458 | CExtPubKey xpub; |
| 459 | CExtKey lh_xprv; |
| 460 | // If we have the cache, just get the parent xpub |
| 461 | if (cache != nullptr) { |
| 462 | cache->GetCachedLastHardenedExtPubKey(m_expr_index, xpub); |
| 463 | } |
| 464 | if (!xpub.pubkey.IsValid()) { |
| 465 | // Cache miss, or nor cache, or need privkey |
| 466 | CExtKey xprv; |
| 467 | if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return false; |
| 468 | xpub = lh_xprv.Neuter(); |
| 469 | } |
| 470 | assert(xpub.pubkey.IsValid()); |
| 471 | |
| 472 | // Build the string |
| 473 | std::string origin_str = HexStr(origin.fingerprint) + FormatHDKeypath(origin.path); |
| 474 | out = "[" + origin_str + "]" + EncodeExtPubKey(xpub) + FormatHDKeypath(end_path); |
| 475 | if (IsRange()) { |
| 476 | out += "/*"; |
| 477 | assert(m_derive == DeriveType::UNHARDENED); |
| 478 | } |
| 479 | return true; |
| 480 | } |
nothing calls this directly
no test coverage detected