aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp111
1 files changed, 66 insertions, 45 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 04d5ea6eff..b7c2d8ea8d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -870,51 +870,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(&walletdb);
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
-
- 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());
- }
+ wtx.nTimeSmart = ComputeTimeSmart(wtx);
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
}
+/**
+ * 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)
{
if (boost::get<CNoDestination>(&dest))