| 335 | bool IsRange() const override { return m_derive != DeriveType::NO; } |
| 336 | size_t GetSize() const override { return 33; } |
| 337 | bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override |
| 338 | { |
| 339 | // Info of parent of the to be derived pubkey |
| 340 | KeyOriginInfo parent_info; |
| 341 | CKeyID keyid = m_root_extkey.pubkey.GetID(); |
| 342 | std::copy(keyid.begin(), keyid.begin() + sizeof(parent_info.fingerprint), parent_info.fingerprint); |
| 343 | parent_info.path = m_path; |
| 344 | |
| 345 | // Info of the derived key itself which is copied out upon successful completion |
| 346 | KeyOriginInfo final_info_out_tmp = parent_info; |
| 347 | if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.path.push_back((uint32_t)pos); |
| 348 | if (m_derive == DeriveType::HARDENED) final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L); |
| 349 | |
| 350 | // Derive keys or fetch them from cache |
| 351 | CExtPubKey final_extkey = m_root_extkey; |
| 352 | CExtPubKey parent_extkey = m_root_extkey; |
| 353 | CExtPubKey last_hardened_extkey; |
| 354 | bool der = true; |
| 355 | if (read_cache) { |
| 356 | if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) { |
| 357 | if (m_derive == DeriveType::HARDENED) return false; |
| 358 | // Try to get the derivation parent |
| 359 | if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return false; |
| 360 | final_extkey = parent_extkey; |
| 361 | if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos); |
| 362 | } |
| 363 | } else if (IsHardened()) { |
| 364 | CExtKey xprv; |
| 365 | CExtKey lh_xprv; |
| 366 | if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return false; |
| 367 | parent_extkey = xprv.Neuter(); |
| 368 | if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos); |
| 369 | if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL); |
| 370 | final_extkey = xprv.Neuter(); |
| 371 | if (lh_xprv.key.IsValid()) { |
| 372 | last_hardened_extkey = lh_xprv.Neuter(); |
| 373 | } |
| 374 | } else { |
| 375 | for (auto entry : m_path) { |
| 376 | der = parent_extkey.Derive(parent_extkey, entry); |
| 377 | assert(der); |
| 378 | } |
| 379 | final_extkey = parent_extkey; |
| 380 | if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos); |
| 381 | assert(m_derive != DeriveType::HARDENED); |
| 382 | } |
| 383 | assert(der); |
| 384 | |
| 385 | final_info_out = final_info_out_tmp; |
| 386 | key_out = final_extkey.pubkey; |
| 387 | |
| 388 | if (write_cache) { |
| 389 | // Only cache parent if there is any unhardened derivation |
| 390 | if (m_derive != DeriveType::HARDENED) { |
| 391 | write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey); |
| 392 | // Cache last hardened xpub if we have it |
| 393 | if (last_hardened_extkey.pubkey.IsValid()) { |
| 394 | write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey); |
nothing calls this directly
no test coverage detected