|
|
@ -870,51 +870,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) |
|
|
|
wtx.nTimeReceived = GetAdjustedTime(); |
|
|
|
wtx.nTimeReceived = GetAdjustedTime(); |
|
|
|
wtx.nOrderPos = IncOrderPosNext(&walletdb); |
|
|
|
wtx.nOrderPos = IncOrderPosNext(&walletdb); |
|
|
|
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); |
|
|
|
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); |
|
|
|
|
|
|
|
wtx.nTimeSmart = ComputeTimeSmart(wtx); |
|
|
|
wtx.nTimeSmart = wtx.nTimeReceived; |
|
|
|
|
|
|
|
if (!wtxIn.hashUnset()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (mapBlockIndex.count(wtxIn.hashBlock)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int64_t latestNow = wtx.nTimeReceived; |
|
|
|
|
|
|
|
int64_t latestEntry = 0; |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
|
|
|
|
|
|
|
|
int64_t latestTolerated = latestNow + 300; |
|
|
|
|
|
|
|
const TxItems & txOrdered = wtxOrdered; |
|
|
|
|
|
|
|
for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CWalletTx *const pwtx = (*it).second.first; |
|
|
|
|
|
|
|
if (pwtx == &wtx) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
CAccountingEntry *const pacentry = (*it).second.second; |
|
|
|
|
|
|
|
int64_t nSmartTime; |
|
|
|
|
|
|
|
if (pwtx) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
nSmartTime = pwtx->nTimeSmart; |
|
|
|
|
|
|
|
if (!nSmartTime) |
|
|
|
|
|
|
|
nSmartTime = pwtx->nTimeReceived; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
nSmartTime = pacentry->nTime; |
|
|
|
|
|
|
|
if (nSmartTime <= latestTolerated) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
latestEntry = nSmartTime; |
|
|
|
|
|
|
|
if (nSmartTime > latestNow) |
|
|
|
|
|
|
|
latestNow = nSmartTime; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime(); |
|
|
|
|
|
|
|
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
LogPrintf("AddToWallet(): found %s in block %s not in index\n", |
|
|
|
|
|
|
|
wtxIn.GetHash().ToString(), |
|
|
|
|
|
|
|
wtxIn.hashBlock.ToString()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
AddToSpends(hash); |
|
|
|
AddToSpends(hash); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3472,6 +3428,71 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c |
|
|
|
mapKeyBirth[it->first] = it->second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off
|
|
|
|
mapKeyBirth[it->first] = it->second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Compute smart timestamp for a transaction being added to the wallet. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Logic: |
|
|
|
|
|
|
|
* - If sending a transaction, assign its timestamp to the current time. |
|
|
|
|
|
|
|
* - If receiving a transaction outside a block, assign its timestamp to the |
|
|
|
|
|
|
|
* current time. |
|
|
|
|
|
|
|
* - If receiving a block with a future timestamp, assign all its (not already |
|
|
|
|
|
|
|
* known) transactions' timestamps to the current time. |
|
|
|
|
|
|
|
* - If receiving a block with a past timestamp, before the most recent known |
|
|
|
|
|
|
|
* transaction (that we care about), assign all its (not already known) |
|
|
|
|
|
|
|
* transactions' timestamps to the same timestamp as that most-recent-known |
|
|
|
|
|
|
|
* transaction. |
|
|
|
|
|
|
|
* - If receiving a block with a past timestamp, but after the most recent known |
|
|
|
|
|
|
|
* transaction, assign all its (not already known) transactions' timestamps to |
|
|
|
|
|
|
|
* the block time. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* For more information see CWalletTx::nTimeSmart, |
|
|
|
|
|
|
|
* https://bitcointalk.org/?topic=54527, or
|
|
|
|
|
|
|
|
* https://github.com/bitcoin/bitcoin/pull/1393.
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
unsigned int nTimeSmart = wtx.nTimeReceived; |
|
|
|
|
|
|
|
if (!wtx.hashUnset()) { |
|
|
|
|
|
|
|
if (mapBlockIndex.count(wtx.hashBlock)) { |
|
|
|
|
|
|
|
int64_t latestNow = wtx.nTimeReceived; |
|
|
|
|
|
|
|
int64_t latestEntry = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
|
|
|
|
|
|
|
|
int64_t latestTolerated = latestNow + 300; |
|
|
|
|
|
|
|
const TxItems& txOrdered = wtxOrdered; |
|
|
|
|
|
|
|
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { |
|
|
|
|
|
|
|
CWalletTx* const pwtx = it->second.first; |
|
|
|
|
|
|
|
if (pwtx == &wtx) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
CAccountingEntry* const pacentry = it->second.second; |
|
|
|
|
|
|
|
int64_t nSmartTime; |
|
|
|
|
|
|
|
if (pwtx) { |
|
|
|
|
|
|
|
nSmartTime = pwtx->nTimeSmart; |
|
|
|
|
|
|
|
if (!nSmartTime) { |
|
|
|
|
|
|
|
nSmartTime = pwtx->nTimeReceived; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
nSmartTime = pacentry->nTime; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (nSmartTime <= latestTolerated) { |
|
|
|
|
|
|
|
latestEntry = nSmartTime; |
|
|
|
|
|
|
|
if (nSmartTime > latestNow) { |
|
|
|
|
|
|
|
latestNow = nSmartTime; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64_t blocktime = mapBlockIndex[wtx.hashBlock]->GetBlockTime(); |
|
|
|
|
|
|
|
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
LogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.hashBlock.ToString()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return nTimeSmart; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value) |
|
|
|
bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (boost::get<CNoDestination>(&dest)) |
|
|
|
if (boost::get<CNoDestination>(&dest)) |
|
|
|