* 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 transaction during a rescanning process, assign all its * (not already known) transactions' timestamps to the block time. *
| 2818 | * https://github.com/bitcoin/bitcoin/pull/1393. |
| 2819 | */ |
| 2820 | unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const |
| 2821 | { |
| 2822 | std::optional<uint256> block_hash; |
| 2823 | if (auto* conf = wtx.state<TxStateConfirmed>()) { |
| 2824 | block_hash = conf->confirmed_block_hash; |
| 2825 | } else if (auto* conf = wtx.state<TxStateBlockConflicted>()) { |
| 2826 | block_hash = conf->conflicting_block_hash; |
| 2827 | } |
| 2828 | |
| 2829 | unsigned int nTimeSmart = wtx.nTimeReceived; |
| 2830 | if (block_hash) { |
| 2831 | int64_t blocktime; |
| 2832 | int64_t block_max_time; |
| 2833 | if (chain().findBlock(*block_hash, FoundBlock().time(blocktime).maxTime(block_max_time))) { |
| 2834 | if (rescanning_old_block) { |
| 2835 | nTimeSmart = block_max_time; |
| 2836 | } else { |
| 2837 | int64_t latestNow = wtx.nTimeReceived; |
| 2838 | int64_t latestEntry = 0; |
| 2839 | |
| 2840 | // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future |
| 2841 | int64_t latestTolerated = latestNow + 300; |
| 2842 | const TxItems& txOrdered = wtxOrdered; |
| 2843 | for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { |
| 2844 | CWalletTx* const pwtx = it->second; |
| 2845 | if (pwtx == &wtx) { |
| 2846 | continue; |
| 2847 | } |
| 2848 | int64_t nSmartTime; |
| 2849 | nSmartTime = pwtx->nTimeSmart; |
| 2850 | if (!nSmartTime) { |
| 2851 | nSmartTime = pwtx->nTimeReceived; |
| 2852 | } |
| 2853 | if (nSmartTime <= latestTolerated) { |
| 2854 | latestEntry = nSmartTime; |
| 2855 | if (nSmartTime > latestNow) { |
| 2856 | latestNow = nSmartTime; |
| 2857 | } |
| 2858 | break; |
| 2859 | } |
| 2860 | } |
| 2861 | |
| 2862 | nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); |
| 2863 | } |
| 2864 | } else { |
| 2865 | WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), block_hash->ToString()); |
| 2866 | } |
| 2867 | } |
| 2868 | return nTimeSmart; |
| 2869 | } |
| 2870 | |
| 2871 | bool CWallet::SetAddressPreviouslySpent(WalletBatch& batch, const CTxDestination& dest, bool used) |
| 2872 | { |