| 3785 | /** @} */ // end of Actions |
| 3786 | |
| 3787 | void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const { |
| 3788 | AssertLockHeld(cs_wallet); // mapKeyMetadata |
| 3789 | mapKeyBirth.clear(); |
| 3790 | |
| 3791 | // get birth times for keys with metadata |
| 3792 | for (const auto& entry : mapKeyMetadata) { |
| 3793 | if (entry.second.nCreateTime) { |
| 3794 | mapKeyBirth[entry.first] = entry.second.nCreateTime; |
| 3795 | } |
| 3796 | } |
| 3797 | |
| 3798 | // map in which we'll infer heights of other keys |
| 3799 | CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin |
| 3800 | std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock; |
| 3801 | for (const CKeyID &keyid : GetKeys()) { |
| 3802 | if (mapKeyBirth.count(keyid) == 0) |
| 3803 | mapKeyFirstBlock[keyid] = pindexMax; |
| 3804 | } |
| 3805 | |
| 3806 | // if there are no such keys, we're done |
| 3807 | if (mapKeyFirstBlock.empty()) |
| 3808 | return; |
| 3809 | |
| 3810 | // find first block that affects those keys, if there are any left |
| 3811 | std::vector<CKeyID> vAffected; |
| 3812 | for (const auto& entry : mapWallet) { |
| 3813 | // iterate over all wallet transactions... |
| 3814 | const CWalletTx &wtx = entry.second; |
| 3815 | CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock); |
| 3816 | if (pindex && chainActive.Contains(pindex)) { |
| 3817 | // ... which are already in a block |
| 3818 | int nHeight = pindex->nHeight; |
| 3819 | for (const CTxOut &txout : wtx.tx->vout) { |
| 3820 | // iterate over all their outputs |
| 3821 | CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); |
| 3822 | for (const CKeyID &keyid : vAffected) { |
| 3823 | // ... and all their affected keys |
| 3824 | std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid); |
| 3825 | if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) |
| 3826 | rit->second = pindex; |
| 3827 | } |
| 3828 | vAffected.clear(); |
| 3829 | } |
| 3830 | } |
| 3831 | } |
| 3832 | |
| 3833 | // Extract block timestamps for those keys |
| 3834 | for (const auto& entry : mapKeyFirstBlock) |
| 3835 | mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off |
| 3836 | } |
| 3837 | |
| 3838 | /** |
| 3839 | * Compute smart timestamp for a transaction being added to the wallet. |
no test coverage detected