| 444 | size_t GetSize() const override { return 33; } |
| 445 | bool IsBIP32() const override { return true; } |
| 446 | std::optional<CPubKey> GetPubKey(int pos, const SigningProvider& arg, FlatSigningProvider& out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override |
| 447 | { |
| 448 | KeyOriginInfo info; |
| 449 | CKeyID keyid = m_root_extkey.pubkey.GetID(); |
| 450 | std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint); |
| 451 | info.path = m_path; |
| 452 | if (m_derive == DeriveType::UNHARDENED_RANGED) info.path.push_back((uint32_t)pos); |
| 453 | if (m_derive == DeriveType::HARDENED_RANGED) info.path.push_back(((uint32_t)pos) | 0x80000000L); |
| 454 | |
| 455 | // Derive keys or fetch them from cache |
| 456 | CExtPubKey final_extkey = m_root_extkey; |
| 457 | CExtPubKey parent_extkey = m_root_extkey; |
| 458 | CExtPubKey last_hardened_extkey; |
| 459 | bool der = true; |
| 460 | if (read_cache) { |
| 461 | if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) { |
| 462 | if (m_derive == DeriveType::HARDENED_RANGED) return std::nullopt; |
| 463 | // Try to get the derivation parent |
| 464 | if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return std::nullopt; |
| 465 | final_extkey = parent_extkey; |
| 466 | if (m_derive == DeriveType::UNHARDENED_RANGED) der = parent_extkey.Derive(final_extkey, pos); |
| 467 | } |
| 468 | } else if (IsHardened()) { |
| 469 | CExtKey xprv; |
| 470 | CExtKey lh_xprv; |
| 471 | if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return std::nullopt; |
| 472 | parent_extkey = xprv.Neuter(); |
| 473 | if (m_derive == DeriveType::UNHARDENED_RANGED) der = xprv.Derive(xprv, pos); |
| 474 | if (m_derive == DeriveType::HARDENED_RANGED) der = xprv.Derive(xprv, pos | 0x80000000UL); |
| 475 | final_extkey = xprv.Neuter(); |
| 476 | if (lh_xprv.key.IsValid()) { |
| 477 | last_hardened_extkey = lh_xprv.Neuter(); |
| 478 | } |
| 479 | } else { |
| 480 | for (auto entry : m_path) { |
| 481 | if (!parent_extkey.Derive(parent_extkey, entry)) return std::nullopt; |
| 482 | } |
| 483 | final_extkey = parent_extkey; |
| 484 | if (m_derive == DeriveType::UNHARDENED_RANGED) der = parent_extkey.Derive(final_extkey, pos); |
| 485 | assert(m_derive != DeriveType::HARDENED_RANGED); |
| 486 | } |
| 487 | if (!der) return std::nullopt; |
| 488 | |
| 489 | out.origins.emplace(final_extkey.pubkey.GetID(), std::make_pair(final_extkey.pubkey, info)); |
| 490 | out.pubkeys.emplace(final_extkey.pubkey.GetID(), final_extkey.pubkey); |
| 491 | |
| 492 | if (write_cache) { |
| 493 | // Only cache parent if there is any unhardened derivation |
| 494 | if (m_derive != DeriveType::HARDENED_RANGED) { |
| 495 | write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey); |
| 496 | // Cache last hardened xpub if we have it |
| 497 | if (last_hardened_extkey.pubkey.IsValid()) { |
| 498 | write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey); |
| 499 | } |
| 500 | } else if (info.path.size() > 0) { |
| 501 | write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey); |
| 502 | } |
| 503 | } |
nothing calls this directly
no test coverage detected