Add GetKeyBirthTimes to wallet
Compute safe lower bounds on the birth times of all wallet keys. For pool keys or keys with metadata, the actually stored birth time is used. For all others, the birth times are inferred from the wallet transactions.
This commit is contained in:
parent
acc775c554
commit
434e4273b9
3 changed files with 63 additions and 2 deletions
|
@ -1846,7 +1846,7 @@ void CReserveKey::ReturnKey()
|
|||
vchPubKey = CPubKey();
|
||||
}
|
||||
|
||||
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress)
|
||||
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
|
||||
{
|
||||
setAddress.clear();
|
||||
|
||||
|
@ -1908,3 +1908,53 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
|
|||
}
|
||||
}
|
||||
|
||||
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
|
||||
mapKeyBirth.clear();
|
||||
|
||||
// get birth times for keys with metadata
|
||||
for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
|
||||
if (it->second.nCreateTime)
|
||||
mapKeyBirth[it->first] = it->second.nCreateTime;
|
||||
|
||||
// map in which we'll infer heights of other keys
|
||||
CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
|
||||
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
|
||||
std::set<CKeyID> setKeys;
|
||||
GetKeys(setKeys);
|
||||
BOOST_FOREACH(const CKeyID &keyid, setKeys) {
|
||||
if (mapKeyBirth.count(keyid) == 0)
|
||||
mapKeyFirstBlock[keyid] = pindexMax;
|
||||
}
|
||||
setKeys.clear();
|
||||
|
||||
// if there are no such keys, we're done
|
||||
if (mapKeyFirstBlock.empty())
|
||||
return;
|
||||
|
||||
// find first block that affects those keys, if there are any left
|
||||
std::vector<CKeyID> vAffected;
|
||||
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
|
||||
// iterate over all wallet transactions...
|
||||
const CWalletTx &wtx = (*it).second;
|
||||
std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
|
||||
if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
|
||||
// ... which are already in a block
|
||||
int nHeight = blit->second->nHeight;
|
||||
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
|
||||
// iterate over all their outputs
|
||||
::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
|
||||
BOOST_FOREACH(const CKeyID &keyid, vAffected) {
|
||||
// ... and all their affected keys
|
||||
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
|
||||
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
|
||||
rit->second = blit->second;
|
||||
}
|
||||
vAffected.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract block timestamps for those keys
|
||||
for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
|
||||
mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ public:
|
|||
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
|
||||
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
||||
|
||||
void GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const;
|
||||
|
||||
/** Increment the next transaction order id
|
||||
@return next transaction order id
|
||||
*/
|
||||
|
@ -200,7 +202,7 @@ public:
|
|||
void ReturnKey(int64 nIndex);
|
||||
bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
|
||||
int64 GetOldestKeyPoolTime();
|
||||
void GetAllReserveKeys(std::set<CKeyID>& setAddress);
|
||||
void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
|
||||
|
||||
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
||||
std::map<CTxDestination, int64> GetAddressBalances();
|
||||
|
|
|
@ -365,7 +365,16 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
{
|
||||
int64 nIndex;
|
||||
ssKey >> nIndex;
|
||||
CKeyPool keypool;
|
||||
ssValue >> keypool;
|
||||
pwallet->setKeyPool.insert(nIndex);
|
||||
|
||||
// If no metadata exists yet, create a default with the pool key's
|
||||
// creation time. Note that this may be overwritten by actually
|
||||
// stored metadata for that key later, which is fine.
|
||||
CKeyID keyid = keypool.vchPubKey.GetID();
|
||||
if (pwallet->mapKeyMetadata.count(keyid) == 0)
|
||||
pwallet->mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
|
||||
}
|
||||
else if (strType == "version")
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue