* 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. *
| 2777 | * https://github.com/bitcoin/bitcoin/pull/1393. |
| 2778 | */ |
| 2779 | unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const |
| 2780 | { |
| 2781 | std::optional<uint256> block_hash; |
| 2782 | if (auto* conf = wtx.state<TxStateConfirmed>()) { |
| 2783 | block_hash = conf->confirmed_block_hash; |
| 2784 | } else if (auto* conf = wtx.state<TxStateConflicted>()) { |
| 2785 | block_hash = conf->conflicting_block_hash; |
| 2786 | } |
| 2787 | |
| 2788 | unsigned int nTimeSmart = wtx.nTimeReceived; |
| 2789 | if (block_hash) { |
| 2790 | int64_t blocktime; |
| 2791 | int64_t block_max_time; |
| 2792 | if (chain().findBlock(*block_hash, FoundBlock().time(blocktime).maxTime(block_max_time))) { |
| 2793 | if (rescanning_old_block) { |
| 2794 | nTimeSmart = block_max_time; |
| 2795 | } else { |
| 2796 | int64_t latestNow = wtx.nTimeReceived; |
| 2797 | int64_t latestEntry = 0; |
| 2798 | |
| 2799 | // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future |
| 2800 | int64_t latestTolerated = latestNow + 300; |
| 2801 | const TxItems& txOrdered = wtxOrdered; |
| 2802 | for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { |
| 2803 | CWalletTx* const pwtx = it->second; |
| 2804 | if (pwtx == &wtx) { |
| 2805 | continue; |
| 2806 | } |
| 2807 | int64_t nSmartTime; |
| 2808 | nSmartTime = pwtx->nTimeSmart; |
| 2809 | if (!nSmartTime) { |
| 2810 | nSmartTime = pwtx->nTimeReceived; |
| 2811 | } |
| 2812 | if (nSmartTime <= latestTolerated) { |
| 2813 | latestEntry = nSmartTime; |
| 2814 | if (nSmartTime > latestNow) { |
| 2815 | latestNow = nSmartTime; |
| 2816 | } |
| 2817 | break; |
| 2818 | } |
| 2819 | } |
| 2820 | |
| 2821 | nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); |
| 2822 | } |
| 2823 | } else { |
| 2824 | WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), block_hash->ToString()); |
| 2825 | } |
| 2826 | } |
| 2827 | return nTimeSmart; |
| 2828 | } |
| 2829 | |
| 2830 | bool CWallet::SetAddressUsed(WalletBatch& batch, const CTxDestination& dest, bool used) |
| 2831 | { |