diff --git a/src/chain.h b/src/chain.h
index 5e80d899f..aea80d729 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,419 +1,427 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_CHAIN_H
 #define BITCOIN_CHAIN_H
 
 #include <arith_uint256.h>
 #include <blockstatus.h>
 #include <blockvalidity.h>
 #include <consensus/params.h>
 #include <diskblockpos.h>
 #include <pow.h>
 #include <primitives/block.h>
 #include <sync.h>
 #include <tinyformat.h>
 #include <uint256.h>
 
 #include <unordered_map>
 #include <vector>
 
 /**
  * Maximum amount of time that a block timestamp is allowed to exceed the
  * current network-adjusted time before the block will be accepted.
  */
-static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
+static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
 
 /**
  * Timestamp window used as a grace period by code that compares external
  * timestamps (such as timestamps passed to RPCs, or wallet key creation times)
  * to block timestamps. This should be set at least as high as
  * MAX_FUTURE_BLOCK_TIME.
  */
-static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
+static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
+
+/**
+ * Maximum gap between node time and block time used
+ * for the "Catching up..." mode in GUI.
+ *
+ * Ref: https://github.com/bitcoin/bitcoin/pull/1026
+ */
+static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
 
 /**
  * The block chain is a tree shaped structure starting with the genesis block at
  * the root, with each block potentially having multiple candidates to be the
  * next block. A blockindex may have multiple pprev pointing to it, but at most
  * one of them can be part of the currently active branch.
  */
 class CBlockIndex {
 public:
     //! pointer to the hash of the block, if any. Memory is owned by this
     //! CBlockIndex
     const uint256 *phashBlock;
 
     //! pointer to the index of the predecessor of this block
     CBlockIndex *pprev;
 
     //! pointer to the index of some further predecessor of this block
     CBlockIndex *pskip;
 
     //! height of the entry in the chain. The genesis block has height 0
     int nHeight;
 
     //! Which # file this block is stored in (blk?????.dat)
     int nFile;
 
     //! Byte offset within blk?????.dat where this block's data is stored
     unsigned int nDataPos;
 
     //! Byte offset within rev?????.dat where this block's undo data is stored
     unsigned int nUndoPos;
 
     //! (memory only) Total amount of work (expected number of hashes) in the
     //! chain up to and including this block
     arith_uint256 nChainWork;
 
     //! Number of transactions in this block.
     //! Note: in a potential headers-first mode, this number cannot be relied
     //! upon
     unsigned int nTx;
 
     //! (memory only) Number of transactions in the chain up to and including
     //! this block.
     //! This value will be non-zero only if and only if transactions for this
     //! block and all its parents are available. Change to 64-bit type when
     //! necessary; won't happen before 2030
     unsigned int nChainTx;
 
     //! Verification status of this block. See enum BlockStatus
     BlockStatus nStatus;
 
     //! block header
     int32_t nVersion;
     uint256 hashMerkleRoot;
     uint32_t nTime;
     uint32_t nBits;
     uint32_t nNonce;
 
     //! (memory only) Sequential id assigned to distinguish order in which
     //! blocks are received.
     int32_t nSequenceId;
 
     //! (memory only) block header metadata
     uint64_t nTimeReceived;
 
     //! (memory only) Maximum nTime in the chain up to and including this block.
     unsigned int nTimeMax;
 
     void SetNull() {
         phashBlock = nullptr;
         pprev = nullptr;
         pskip = nullptr;
         nHeight = 0;
         nFile = 0;
         nDataPos = 0;
         nUndoPos = 0;
         nChainWork = arith_uint256();
         nTx = 0;
         nChainTx = 0;
         nStatus = BlockStatus();
         nSequenceId = 0;
         nTimeMax = 0;
 
         nVersion = 0;
         hashMerkleRoot = uint256();
         nTime = 0;
         nTimeReceived = 0;
         nBits = 0;
         nNonce = 0;
     }
 
     CBlockIndex() { SetNull(); }
 
     explicit CBlockIndex(const CBlockHeader &block) {
         SetNull();
 
         nVersion = block.nVersion;
         hashMerkleRoot = block.hashMerkleRoot;
         nTime = block.nTime;
         nTimeReceived = 0;
         nBits = block.nBits;
         nNonce = block.nNonce;
     }
 
     CDiskBlockPos GetBlockPos() const {
         CDiskBlockPos ret;
         if (nStatus.hasData()) {
             ret.nFile = nFile;
             ret.nPos = nDataPos;
         }
         return ret;
     }
 
     CDiskBlockPos GetUndoPos() const {
         CDiskBlockPos ret;
         if (nStatus.hasUndo()) {
             ret.nFile = nFile;
             ret.nPos = nUndoPos;
         }
         return ret;
     }
 
     CBlockHeader GetBlockHeader() const {
         CBlockHeader block;
         block.nVersion = nVersion;
         if (pprev) {
             block.hashPrevBlock = pprev->GetBlockHash();
         }
         block.hashMerkleRoot = hashMerkleRoot;
         block.nTime = nTime;
         block.nBits = nBits;
         block.nNonce = nNonce;
         return block;
     }
 
     uint256 GetBlockHash() const { return *phashBlock; }
 
     int64_t GetBlockTime() const { return int64_t(nTime); }
 
     int64_t GetBlockTimeMax() const { return int64_t(nTimeMax); }
 
     int64_t GetHeaderReceivedTime() const { return nTimeReceived; }
 
     int64_t GetReceivedTimeDiff() const {
         return GetHeaderReceivedTime() - GetBlockTime();
     }
 
     static constexpr int nMedianTimeSpan = 11;
 
     int64_t GetMedianTimePast() const {
         int64_t pmedian[nMedianTimeSpan];
         int64_t *pbegin = &pmedian[nMedianTimeSpan];
         int64_t *pend = &pmedian[nMedianTimeSpan];
 
         const CBlockIndex *pindex = this;
         for (int i = 0; i < nMedianTimeSpan && pindex;
              i++, pindex = pindex->pprev) {
             *(--pbegin) = pindex->GetBlockTime();
         }
 
         std::sort(pbegin, pend);
         return pbegin[(pend - pbegin) / 2];
     }
 
     std::string ToString() const {
         return strprintf(
             "CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev,
             nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString());
     }
 
     //! Check whether this block index entry is valid up to the passed validity
     //! level.
     bool IsValid(enum BlockValidity nUpTo = BlockValidity::TRANSACTIONS) const {
         return nStatus.isValid(nUpTo);
     }
 
     //! Raise the validity level of this block index entry.
     //! Returns true if the validity was changed.
     bool RaiseValidity(enum BlockValidity nUpTo) {
         // Only validity flags allowed.
         if (nStatus.isInvalid()) {
             return false;
         }
 
         if (nStatus.getValidity() >= nUpTo) {
             return false;
         }
 
         nStatus = nStatus.withValidity(nUpTo);
         return true;
     }
 
     //! Build the skiplist pointer for this entry.
     void BuildSkip();
 
     //! Efficiently find an ancestor of this block.
     CBlockIndex *GetAncestor(int height);
     const CBlockIndex *GetAncestor(int height) const;
 };
 
 /**
  * Maintain a map of CBlockIndex for all known headers.
  */
 struct BlockHasher {
     size_t operator()(const uint256 &hash) const { return hash.GetCheapHash(); }
 };
 
 typedef std::unordered_map<uint256, CBlockIndex *, BlockHasher> BlockMap;
 extern BlockMap &mapBlockIndex;
 extern CCriticalSection cs_main;
 
 inline CBlockIndex *LookupBlockIndex(const uint256 &hash) {
     AssertLockHeld(cs_main);
     BlockMap::const_iterator it = mapBlockIndex.find(hash);
     return it == mapBlockIndex.end() ? nullptr : it->second;
 }
 
 arith_uint256 GetBlockProof(const CBlockIndex &block);
 
 /**
  * Return the time it would take to redo the work difference between from and
  * to, assuming the current hashrate corresponds to the difficulty at tip, in
  * seconds.
  */
 int64_t GetBlockProofEquivalentTime(const CBlockIndex &to,
                                     const CBlockIndex &from,
                                     const CBlockIndex &tip,
                                     const Consensus::Params &);
 /**
  * Find the forking point between two chain tips.
  */
 const CBlockIndex *LastCommonAncestor(const CBlockIndex *pa,
                                       const CBlockIndex *pb);
 
 /**
  * Check if two block index are on the same fork.
  */
 bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb);
 
 /** Used to marshal pointers into hashes for db storage. */
 class CDiskBlockIndex : public CBlockIndex {
 public:
     uint256 hashPrev;
 
     CDiskBlockIndex() { hashPrev = uint256(); }
 
     explicit CDiskBlockIndex(const CBlockIndex *pindex) : CBlockIndex(*pindex) {
         hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
     }
 
     ADD_SERIALIZE_METHODS;
 
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream &s, Operation ser_action) {
         int _nVersion = s.GetVersion();
         if (!(s.GetType() & SER_GETHASH)) {
             READWRITE(VARINT(_nVersion));
         }
 
         READWRITE(VARINT(nHeight));
         READWRITE(nStatus);
         READWRITE(VARINT(nTx));
         if (nStatus.hasData() || nStatus.hasUndo()) {
             READWRITE(VARINT(nFile));
         }
         if (nStatus.hasData()) {
             READWRITE(VARINT(nDataPos));
         }
         if (nStatus.hasUndo()) {
             READWRITE(VARINT(nUndoPos));
         }
 
         // block header
         READWRITE(this->nVersion);
         READWRITE(hashPrev);
         READWRITE(hashMerkleRoot);
         READWRITE(nTime);
         READWRITE(nBits);
         READWRITE(nNonce);
     }
 
     uint256 GetBlockHash() const {
         CBlockHeader block;
         block.nVersion = nVersion;
         block.hashPrevBlock = hashPrev;
         block.hashMerkleRoot = hashMerkleRoot;
         block.nTime = nTime;
         block.nBits = nBits;
         block.nNonce = nNonce;
         return block.GetHash();
     }
 
     std::string ToString() const {
         std::string str = "CDiskBlockIndex(";
         str += CBlockIndex::ToString();
         str += strprintf("\n                hashBlock=%s, hashPrev=%s)",
                          GetBlockHash().ToString(), hashPrev.ToString());
         return str;
     }
 };
 
 /**
  * An in-memory indexed chain of blocks.
  */
 class CChain {
 private:
     std::vector<CBlockIndex *> vChain;
 
 public:
     /**
      * Returns the index entry for the genesis block of this chain, or nullptr
      * if none.
      */
     CBlockIndex *Genesis() const {
         return vChain.size() > 0 ? vChain[0] : nullptr;
     }
 
     /**
      * Returns the index entry for the tip of this chain, or nullptr if none.
      */
     CBlockIndex *Tip() const {
         return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;
     }
 
     /**
      * Returns the index entry at a particular height in this chain, or nullptr
      * if no such height exists.
      */
     CBlockIndex *operator[](int nHeight) const {
         if (nHeight < 0 || nHeight >= (int)vChain.size()) {
             return nullptr;
         }
         return vChain[nHeight];
     }
 
     /** Compare two chains efficiently. */
     friend bool operator==(const CChain &a, const CChain &b) {
         return a.vChain.size() == b.vChain.size() &&
                a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
     }
 
     /** Efficiently check whether a block is present in this chain. */
     bool Contains(const CBlockIndex *pindex) const {
         return (*this)[pindex->nHeight] == pindex;
     }
 
     /**
      * Find the successor of a block in this chain, or nullptr if the given
      * index is not found or is the tip.
      */
     CBlockIndex *Next(const CBlockIndex *pindex) const {
         if (!Contains(pindex)) {
             return nullptr;
         }
 
         return (*this)[pindex->nHeight + 1];
     }
 
     /**
      * Return the maximal height in the chain. Is equal to chain.Tip() ?
      * chain.Tip()->nHeight : -1.
      */
     int Height() const { return vChain.size() - 1; }
 
     /** Set/initialize a chain with a given tip. */
     void SetTip(CBlockIndex *pindex);
 
     /**
      * Return a CBlockLocator that refers to a block in this chain (by default
      * the tip).
      */
     CBlockLocator GetLocator(const CBlockIndex *pindex = nullptr) const;
 
     /**
      * Find the last common block between this chain and a block index entry.
      */
     const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
 
     /**
      * Find the earliest block with timestamp equal or greater than the given.
      */
     CBlockIndex *FindEarliestAtLeast(int64_t nTime) const;
 };
 
 #endif // BITCOIN_CHAIN_H
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index ccdc88093..c025ff0b6 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -1,429 +1,430 @@
 // Copyright (c) 2018 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <interfaces/wallet.h>
 
 #include <amount.h>
 #include <chain.h>
 #include <consensus/validation.h>
 #include <interfaces/handler.h>
 #include <net.h>
 #include <policy/fees.h>
 #include <policy/policy.h>
 #include <primitives/transaction.h>
 #include <script/ismine.h>
 #include <script/standard.h>
 #include <support/allocators/secure.h>
 #include <sync.h>
 #include <timedata.h>
 #include <ui_interface.h>
 #include <validation.h>
 #include <wallet/fees.h>
 #include <wallet/finaltx.h>
 #include <wallet/wallet.h>
 
 #include <memory>
 
 namespace interfaces {
 namespace {
 
     class PendingWalletTxImpl : public PendingWalletTx {
     public:
         PendingWalletTxImpl(CWallet &wallet)
             : m_wallet(wallet), m_key(&wallet) {}
 
         const CTransaction &get() override { return *m_tx; }
 
         bool commit(WalletValueMap value_map, WalletOrderForm order_form,
                     std::string from_account,
                     std::string &reject_reason) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             CValidationState state;
             if (!m_wallet.CommitTransaction(
                     m_tx, std::move(value_map), std::move(order_form),
                     std::move(from_account), m_key, g_connman.get(), state)) {
                 reject_reason = state.GetRejectReason();
                 return false;
             }
             return true;
         }
 
         CTransactionRef m_tx;
         CWallet &m_wallet;
         CReserveKey m_key;
     };
 
     //! Construct wallet tx struct.
     WalletTx MakeWalletTx(CWallet &wallet, const CWalletTx &wtx) {
         WalletTx result;
         result.tx = wtx.tx;
         result.txin_is_mine.reserve(wtx.tx->vin.size());
         for (const auto &txin : wtx.tx->vin) {
             result.txin_is_mine.emplace_back(wallet.IsMine(txin));
         }
         result.txout_is_mine.reserve(wtx.tx->vout.size());
         result.txout_address.reserve(wtx.tx->vout.size());
         result.txout_address_is_mine.reserve(wtx.tx->vout.size());
         for (const auto &txout : wtx.tx->vout) {
             result.txout_is_mine.emplace_back(wallet.IsMine(txout));
             result.txout_address.emplace_back();
             result.txout_address_is_mine.emplace_back(
                 ExtractDestination(txout.scriptPubKey,
                                    result.txout_address.back())
                     ? IsMine(wallet, result.txout_address.back())
                     : ISMINE_NO);
         }
         result.credit = wtx.GetCredit(ISMINE_ALL);
         result.debit = wtx.GetDebit(ISMINE_ALL);
         result.change = wtx.GetChange();
         result.time = wtx.GetTxTime();
         result.value_map = wtx.mapValue;
         result.is_coinbase = wtx.IsCoinBase();
         return result;
     }
 
     //! Construct wallet tx status struct.
     WalletTxStatus MakeWalletTxStatus(const CWalletTx &wtx) {
         WalletTxStatus result;
         CBlockIndex *block = LookupBlockIndex(wtx.hashBlock);
         result.block_height =
             (block ? block->nHeight : std::numeric_limits<int>::max()),
         result.blocks_to_maturity = wtx.GetBlocksToMaturity();
         result.depth_in_main_chain = wtx.GetDepthInMainChain();
         result.time_received = wtx.nTimeReceived;
         result.lock_time = wtx.tx->nLockTime;
         result.is_final = CheckFinalTx(*wtx.tx);
         result.is_trusted = wtx.IsTrusted();
         result.is_abandoned = wtx.isAbandoned();
         result.is_coinbase = wtx.IsCoinBase();
         result.is_in_main_chain = wtx.IsInMainChain();
         return result;
     }
 
     //! Construct wallet TxOut struct.
     WalletTxOut MakeWalletTxOut(CWallet &wallet, const CWalletTx &wtx, int n,
                                 int depth) {
         WalletTxOut result;
         result.txout = wtx.tx->vout[n];
         result.time = wtx.GetTxTime();
         result.depth_in_main_chain = depth;
         result.is_spent = wallet.IsSpent(wtx.GetId(), n);
         return result;
     }
 
     class WalletImpl : public Wallet {
     public:
         WalletImpl(CWallet &wallet) : m_wallet(wallet) {}
 
         bool encryptWallet(const SecureString &wallet_passphrase) override {
             return m_wallet.EncryptWallet(wallet_passphrase);
         }
         bool isCrypted() override { return m_wallet.IsCrypted(); }
         bool lock() override { return m_wallet.Lock(); }
         bool unlock(const SecureString &wallet_passphrase) override {
             return m_wallet.Unlock(wallet_passphrase);
         }
         bool isLocked() override { return m_wallet.IsLocked(); }
         bool changeWalletPassphrase(
             const SecureString &old_wallet_passphrase,
             const SecureString &new_wallet_passphrase) override {
             return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase,
                                                    new_wallet_passphrase);
         }
         bool backupWallet(const std::string &filename) override {
             return m_wallet.BackupWallet(filename);
         }
         std::string getWalletName() override { return m_wallet.GetName(); }
         std::set<CTxDestination>
         getLabelAddresses(const std::string &label) override {
             return m_wallet.GetLabelAddresses(label);
         };
         bool getKeyFromPool(bool internal, CPubKey &pub_key) override {
             return m_wallet.GetKeyFromPool(pub_key, internal);
         }
         const CChainParams &getChainParams() override {
             return m_wallet.chainParams;
         }
         bool getPubKey(const CKeyID &address, CPubKey &pub_key) override {
             return m_wallet.GetPubKey(address, pub_key);
         }
         bool getPrivKey(const CKeyID &address, CKey &key) override {
             return m_wallet.GetKey(address, key);
         }
         bool isSpendable(const CTxDestination &dest) override {
             return IsMine(m_wallet, dest) & ISMINE_SPENDABLE;
         }
         bool haveWatchOnly() override { return m_wallet.HaveWatchOnly(); };
         bool setAddressBook(const CTxDestination &dest, const std::string &name,
                             const std::string &purpose) override {
             return m_wallet.SetAddressBook(dest, name, purpose);
         }
         bool delAddressBook(const CTxDestination &dest) override {
             return m_wallet.DelAddressBook(dest);
         }
         bool getAddress(const CTxDestination &dest, std::string *name,
                         isminetype *is_mine) override {
             LOCK(m_wallet.cs_wallet);
             auto it = m_wallet.mapAddressBook.find(dest);
             if (it == m_wallet.mapAddressBook.end()) {
                 return false;
             }
             if (name) {
                 *name = it->second.name;
             }
             if (is_mine) {
                 *is_mine = IsMine(m_wallet, dest);
             }
             return true;
         }
         std::vector<WalletAddress> getAddresses() override {
             LOCK(m_wallet.cs_wallet);
             std::vector<WalletAddress> result;
             for (const auto &item : m_wallet.mapAddressBook) {
                 result.emplace_back(item.first, IsMine(m_wallet, item.first),
                                     item.second.name, item.second.purpose);
             }
             return result;
         }
         void learnRelatedScripts(const CPubKey &key, OutputType type) override {
             m_wallet.LearnRelatedScripts(key, type);
         }
         bool addDestData(const CTxDestination &dest, const std::string &key,
                          const std::string &value) override {
             LOCK(m_wallet.cs_wallet);
             return m_wallet.AddDestData(dest, key, value);
         }
         bool eraseDestData(const CTxDestination &dest,
                            const std::string &key) override {
             LOCK(m_wallet.cs_wallet);
             return m_wallet.EraseDestData(dest, key);
         }
         std::vector<std::string>
         getDestValues(const std::string &prefix) override {
             return m_wallet.GetDestValues(prefix);
         }
         void lockCoin(const COutPoint &output) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.LockCoin(output);
         }
         void unlockCoin(const COutPoint &output) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.UnlockCoin(output);
         }
         bool isLockedCoin(const COutPoint &output) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.IsLockedCoin(output.GetTxId(), output.GetN());
         }
         void listLockedCoins(std::vector<COutPoint> &outputs) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.ListLockedCoins(outputs);
         }
         std::unique_ptr<PendingWalletTx>
         createTransaction(const std::vector<CRecipient> &recipients,
                           const CCoinControl &coin_control, bool sign,
                           int &change_pos, Amount &fee,
                           std::string &fail_reason) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             auto pending = std::make_unique<PendingWalletTxImpl>(m_wallet);
             if (!m_wallet.CreateTransaction(recipients, pending->m_tx,
                                             pending->m_key, fee, change_pos,
                                             fail_reason, coin_control, sign)) {
                 return {};
             }
             return std::move(pending);
         }
         bool transactionCanBeAbandoned(const TxId &txid) override {
             return m_wallet.TransactionCanBeAbandoned(txid);
         }
         bool abandonTransaction(const TxId &txid) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.AbandonTransaction(txid);
         }
         CTransactionRef getTx(const TxId &txid) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             auto mi = m_wallet.mapWallet.find(txid);
             if (mi != m_wallet.mapWallet.end()) {
                 return mi->second.tx;
             }
             return {};
         }
         WalletTx getWalletTx(const TxId &txid) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             auto mi = m_wallet.mapWallet.find(txid);
             if (mi != m_wallet.mapWallet.end()) {
                 return MakeWalletTx(m_wallet, mi->second);
             }
             return {};
         }
         std::vector<WalletTx> getWalletTxs() override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             std::vector<WalletTx> result;
             result.reserve(m_wallet.mapWallet.size());
             for (const auto &entry : m_wallet.mapWallet) {
                 result.emplace_back(MakeWalletTx(m_wallet, entry.second));
             }
             return result;
         }
         bool tryGetTxStatus(const TxId &txid,
                             interfaces::WalletTxStatus &tx_status,
-                            int &num_blocks) override {
+                            int &num_blocks, int64_t &block_time) override {
             TRY_LOCK(::cs_main, locked_chain);
             if (!locked_chain) {
                 return false;
             }
             TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
             if (!locked_wallet) {
                 return false;
             }
             auto mi = m_wallet.mapWallet.find(txid);
             if (mi == m_wallet.mapWallet.end()) {
                 return false;
             }
             num_blocks = ::chainActive.Height();
+            block_time = ::chainActive.Tip()->GetBlockTime();
             tx_status = MakeWalletTxStatus(mi->second);
             return true;
         }
         WalletTx getWalletTxDetails(const TxId &txid, WalletTxStatus &tx_status,
                                     WalletOrderForm &order_form,
                                     bool &in_mempool,
                                     int &num_blocks) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             auto mi = m_wallet.mapWallet.find(txid);
             if (mi != m_wallet.mapWallet.end()) {
                 num_blocks = ::chainActive.Height();
                 in_mempool = mi->second.InMempool();
                 order_form = mi->second.vOrderForm;
                 tx_status = MakeWalletTxStatus(mi->second);
                 return MakeWalletTx(m_wallet, mi->second);
             }
             return {};
         }
         WalletBalances getBalances() override {
             WalletBalances result;
             result.balance = m_wallet.GetBalance();
             result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance();
             result.immature_balance = m_wallet.GetImmatureBalance();
             result.have_watch_only = m_wallet.HaveWatchOnly();
             if (result.have_watch_only) {
                 result.watch_only_balance = m_wallet.GetWatchOnlyBalance();
                 result.unconfirmed_watch_only_balance =
                     m_wallet.GetUnconfirmedWatchOnlyBalance();
                 result.immature_watch_only_balance =
                     m_wallet.GetImmatureWatchOnlyBalance();
             }
             return result;
         }
         bool tryGetBalances(WalletBalances &balances,
                             int &num_blocks) override {
             TRY_LOCK(cs_main, locked_chain);
             if (!locked_chain) {
                 return false;
             }
             TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
             if (!locked_wallet) {
                 return false;
             }
             balances = getBalances();
             num_blocks = ::chainActive.Height();
             return true;
         }
         Amount getBalance() override { return m_wallet.GetBalance(); }
         Amount getAvailableBalance(const CCoinControl &coin_control) override {
             return m_wallet.GetAvailableBalance(&coin_control);
         }
         isminetype txinIsMine(const CTxIn &txin) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             return m_wallet.IsMine(txin);
         }
         isminetype txoutIsMine(const CTxOut &txout) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             return m_wallet.IsMine(txout);
         }
         Amount getDebit(const CTxIn &txin, isminefilter filter) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             return m_wallet.GetDebit(txin, filter);
         }
         Amount getCredit(const CTxOut &txout, isminefilter filter) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             return m_wallet.GetCredit(txout, filter);
         }
         CoinsList listCoins() override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             CoinsList result;
             for (const auto &entry : m_wallet.ListCoins()) {
                 auto &group = result[entry.first];
                 for (const auto &coin : entry.second) {
                     group.emplace_back(COutPoint(coin.tx->GetId(), coin.i),
                                        MakeWalletTxOut(m_wallet, *coin.tx,
                                                        coin.i, coin.nDepth));
                 }
             }
             return result;
         }
         std::vector<WalletTxOut>
         getCoins(const std::vector<COutPoint> &outputs) override {
             LOCK2(::cs_main, m_wallet.cs_wallet);
             std::vector<WalletTxOut> result;
             result.reserve(outputs.size());
             for (const auto &output : outputs) {
                 result.emplace_back();
                 auto it = m_wallet.mapWallet.find(output.GetTxId());
                 if (it != m_wallet.mapWallet.end()) {
                     int depth = it->second.GetDepthInMainChain();
                     if (depth >= 0) {
                         result.back() = MakeWalletTxOut(m_wallet, it->second,
                                                         output.GetN(), depth);
                     }
                 }
             }
             return result;
         }
         bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
         std::unique_ptr<Handler>
         handleShowProgress(ShowProgressFn fn) override {
             return MakeHandler(m_wallet.ShowProgress.connect(fn));
         }
         std::unique_ptr<Handler>
         handleStatusChanged(StatusChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyStatusChanged.connect(
                 [fn](CCryptoKeyStore *) { fn(); }));
         }
         std::unique_ptr<Handler>
         handleAddressBookChanged(AddressBookChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyAddressBookChanged.connect(
                 [fn](CWallet *, const CTxDestination &address,
                      const std::string &label, bool is_mine,
                      const std::string &purpose, ChangeType status) {
                     fn(address, label, is_mine, purpose, status);
                 }));
         }
         std::unique_ptr<Handler>
         handleTransactionChanged(TransactionChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyTransactionChanged.connect(
                 [fn](CWallet *, const TxId &txid, ChangeType status) {
                     fn(txid, status);
                 }));
         }
         std::unique_ptr<Handler>
         handleWatchOnlyChanged(WatchOnlyChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
         }
         Amount getRequiredFee(unsigned int tx_bytes) override {
             return GetRequiredFee(m_wallet, tx_bytes);
         }
         Amount getMinimumFee(unsigned int tx_bytes,
                              const CCoinControl &coin_control) override {
             return GetMinimumFee(m_wallet, tx_bytes, coin_control, g_mempool);
         }
 
         CWallet &m_wallet;
     };
 
 } // namespace
 
 std::unique_ptr<Wallet> MakeWallet(CWallet &wallet) {
     return std::make_unique<WalletImpl>(wallet);
 }
 
 } // namespace interfaces
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index d2fe537a3..e628dfd94 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -1,344 +1,344 @@
 // Copyright (c) 2018 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_INTERFACES_WALLET_H
 #define BITCOIN_INTERFACES_WALLET_H
 
 #include <amount.h>                 // For Amount
 #include <primitives/transaction.h> // For CTxOut
 #include <pubkey.h>                 // For CTxDestination (CKeyID and CScriptID)
 #include <script/ismine.h>          // For isminefilter, isminetype
 #include <script/standard.h>        // For CTxDestination
 #include <support/allocators/secure.h> // For SecureString
 #include <ui_interface.h>              // For ChangeType
 
 #include <cstdint>
 #include <functional>
 #include <map>
 #include <memory>
 #include <string>
 #include <tuple>
 #include <utility>
 #include <vector>
 
 class CChainParams;
 class CCoinControl;
 class CKey;
 class CMutableTransaction;
 class COutPoint;
 class CTransaction;
 class CWallet;
 enum class OutputType;
 struct CRecipient;
 struct TxId;
 
 namespace interfaces {
 
 class Handler;
 class PendingWalletTx;
 struct WalletAddress;
 struct WalletBalances;
 struct WalletTx;
 struct WalletTxOut;
 struct WalletTxStatus;
 
 using WalletOrderForm = std::vector<std::pair<std::string, std::string>>;
 using WalletValueMap = std::map<std::string, std::string>;
 
 //! Interface for accessing a wallet.
 class Wallet {
 public:
     virtual ~Wallet() {}
 
     //! Encrypt wallet.
     virtual bool encryptWallet(const SecureString &wallet_passphrase) = 0;
 
     //! Return whether wallet is encrypted.
     virtual bool isCrypted() = 0;
 
     //! Lock wallet.
     virtual bool lock() = 0;
 
     //! Unlock wallet.
     virtual bool unlock(const SecureString &wallet_passphrase) = 0;
 
     //! Return whether wallet is locked.
     virtual bool isLocked() = 0;
 
     //! Change wallet passphrase.
     virtual bool
     changeWalletPassphrase(const SecureString &old_wallet_passphrase,
                            const SecureString &new_wallet_passphrase) = 0;
 
     //! Back up wallet.
     virtual bool backupWallet(const std::string &filename) = 0;
 
     //! Get wallet name.
     virtual std::string getWalletName() = 0;
 
     //! Get chainparams.
     virtual const CChainParams &getChainParams() = 0;
 
     //! Get set of addresses corresponding to a given label.
     virtual std::set<CTxDestination>
     getLabelAddresses(const std::string &label) = 0;
 
     //! Get key from pool.
     virtual bool getKeyFromPool(bool internal, CPubKey &pub_key) = 0;
 
     //! Get public key.
     virtual bool getPubKey(const CKeyID &address, CPubKey &pub_key) = 0;
 
     //! Get private key.
     virtual bool getPrivKey(const CKeyID &address, CKey &key) = 0;
 
     //! Return whether wallet has private key.
     virtual bool isSpendable(const CTxDestination &dest) = 0;
 
     //! Return whether wallet has watch only keys.
     virtual bool haveWatchOnly() = 0;
 
     //! Add or update address.
     virtual bool setAddressBook(const CTxDestination &dest,
                                 const std::string &name,
                                 const std::string &purpose) = 0;
 
     // Remove address.
     virtual bool delAddressBook(const CTxDestination &dest) = 0;
 
     //! Look up address in wallet, return whether exists.
     virtual bool getAddress(const CTxDestination &dest,
                             std::string *name = nullptr,
                             isminetype *is_mine = nullptr) = 0;
 
     //! Get wallet address list.
     virtual std::vector<WalletAddress> getAddresses() = 0;
 
     //! Add scripts to key store so old so software versions opening the wallet
     //! database can detect payments to newer address types.
     virtual void learnRelatedScripts(const CPubKey &key, OutputType type) = 0;
 
     //! Add dest data.
     virtual bool addDestData(const CTxDestination &dest, const std::string &key,
                              const std::string &value) = 0;
 
     //! Erase dest data.
     virtual bool eraseDestData(const CTxDestination &dest,
                                const std::string &key) = 0;
 
     //! Get dest values with prefix.
     virtual std::vector<std::string>
     getDestValues(const std::string &prefix) = 0;
 
     //! Lock coin.
     virtual void lockCoin(const COutPoint &output) = 0;
 
     //! Unlock coin.
     virtual void unlockCoin(const COutPoint &output) = 0;
 
     //! Return whether coin is locked.
     virtual bool isLockedCoin(const COutPoint &output) = 0;
 
     //! List locked coins.
     virtual void listLockedCoins(std::vector<COutPoint> &outputs) = 0;
 
     //! Create transaction.
     virtual std::unique_ptr<PendingWalletTx>
     createTransaction(const std::vector<CRecipient> &recipients,
                       const CCoinControl &coin_control, bool sign,
                       int &change_pos, Amount &fee,
                       std::string &fail_reason) = 0;
 
     //! Return whether transaction can be abandoned.
     virtual bool transactionCanBeAbandoned(const TxId &txid) = 0;
 
     //! Abandon transaction.
     virtual bool abandonTransaction(const TxId &txid) = 0;
 
     //! Get a transaction.
     virtual CTransactionRef getTx(const TxId &txid) = 0;
 
     //! Get transaction information.
     virtual WalletTx getWalletTx(const TxId &txid) = 0;
 
     //! Get list of all wallet transactions.
     virtual std::vector<WalletTx> getWalletTxs() = 0;
 
     //! Try to get updated status for a particular transaction, if possible
     //! without blocking.
     virtual bool tryGetTxStatus(const TxId &txid, WalletTxStatus &tx_status,
-                                int &num_blocks) = 0;
+                                int &num_blocks, int64_t &block_time) = 0;
 
     //! Get transaction details.
     virtual WalletTx getWalletTxDetails(const TxId &txid,
                                         WalletTxStatus &tx_status,
                                         WalletOrderForm &order_form,
                                         bool &in_mempool, int &num_blocks) = 0;
 
     //! Get balances.
     virtual WalletBalances getBalances() = 0;
 
     //! Get balances if possible without blocking.
     virtual bool tryGetBalances(WalletBalances &balances, int &num_blocks) = 0;
 
     //! Get balance.
     virtual Amount getBalance() = 0;
 
     //! Get available balance.
     virtual Amount getAvailableBalance(const CCoinControl &coin_control) = 0;
 
     //! Return whether transaction input belongs to wallet.
     virtual isminetype txinIsMine(const CTxIn &txin) = 0;
 
     //! Return whether transaction output belongs to wallet.
     virtual isminetype txoutIsMine(const CTxOut &txout) = 0;
 
     //! Return debit amount if transaction input belongs to wallet.
     virtual Amount getDebit(const CTxIn &txin, isminefilter filter) = 0;
 
     //! Return credit amount if transaction input belongs to wallet.
     virtual Amount getCredit(const CTxOut &txout, isminefilter filter) = 0;
 
     //! Return AvailableCoins + LockedCoins grouped by wallet address.
     //! (put change in one group with wallet address)
     using CoinsList = std::map<CTxDestination,
                                std::vector<std::tuple<COutPoint, WalletTxOut>>>;
     virtual CoinsList listCoins() = 0;
 
     //! Return wallet transaction output information.
     virtual std::vector<WalletTxOut>
     getCoins(const std::vector<COutPoint> &outputs) = 0;
 
     //! Get required fee.
     virtual Amount getRequiredFee(unsigned int tx_bytes) = 0;
 
     //! Get minimum fee.
     virtual Amount getMinimumFee(unsigned int tx_bytes,
                                  const CCoinControl &coin_control) = 0;
 
     // Return whether HD enabled.
     virtual bool hdEnabled() = 0;
 
     //! Register handler for show progress messages.
     using ShowProgressFn =
         std::function<void(const std::string &title, int progress)>;
     virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
 
     //! Register handler for status changed messages.
     using StatusChangedFn = std::function<void()>;
     virtual std::unique_ptr<Handler>
     handleStatusChanged(StatusChangedFn fn) = 0;
 
     //! Register handler for address book changed messages.
     using AddressBookChangedFn = std::function<void(
         const CTxDestination &address, const std::string &label, bool is_mine,
         const std::string &purpose, ChangeType status)>;
     virtual std::unique_ptr<Handler>
     handleAddressBookChanged(AddressBookChangedFn fn) = 0;
 
     //! Register handler for transaction changed messages.
     using TransactionChangedFn =
         std::function<void(const TxId &txid, ChangeType status)>;
     virtual std::unique_ptr<Handler>
     handleTransactionChanged(TransactionChangedFn fn) = 0;
 
     //! Register handler for watchonly changed messages.
     using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
     virtual std::unique_ptr<Handler>
     handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
 };
 
 //! Tracking object returned by CreateTransaction and passed to
 //! CommitTransaction.
 class PendingWalletTx {
 public:
     virtual ~PendingWalletTx() {}
 
     //! Get transaction data.
     virtual const CTransaction &get() = 0;
 
     //! Send pending transaction and commit to wallet.
     virtual bool commit(WalletValueMap value_map, WalletOrderForm order_form,
                         std::string from_account,
                         std::string &reject_reason) = 0;
 };
 
 //! Information about one wallet address.
 struct WalletAddress {
     CTxDestination dest;
     isminetype is_mine;
     std::string name;
     std::string purpose;
 
     WalletAddress(CTxDestination destIn, isminetype isMineIn,
                   std::string nameIn, std::string purposeIn)
         : dest(std::move(destIn)), is_mine(isMineIn), name(std::move(nameIn)),
           purpose(std::move(purposeIn)) {}
 };
 
 //! Collection of wallet balances.
 struct WalletBalances {
     Amount balance = Amount::zero();
     Amount unconfirmed_balance = Amount::zero();
     Amount immature_balance = Amount::zero();
     bool have_watch_only = false;
     Amount watch_only_balance = Amount::zero();
     Amount unconfirmed_watch_only_balance = Amount::zero();
     Amount immature_watch_only_balance = Amount::zero();
 
     bool balanceChanged(const WalletBalances &prev) const {
         return balance != prev.balance ||
                unconfirmed_balance != prev.unconfirmed_balance ||
                immature_balance != prev.immature_balance ||
                watch_only_balance != prev.watch_only_balance ||
                unconfirmed_watch_only_balance !=
                    prev.unconfirmed_watch_only_balance ||
                immature_watch_only_balance != prev.immature_watch_only_balance;
     }
 };
 
 // Wallet transaction information.
 struct WalletTx {
     CTransactionRef tx;
     std::vector<isminetype> txin_is_mine;
     std::vector<isminetype> txout_is_mine;
     std::vector<CTxDestination> txout_address;
     std::vector<isminetype> txout_address_is_mine;
     Amount credit;
     Amount debit;
     Amount change;
     int64_t time;
     std::map<std::string, std::string> value_map;
     bool is_coinbase;
 };
 
 //! Updated transaction status.
 struct WalletTxStatus {
     int block_height;
     int blocks_to_maturity;
     int depth_in_main_chain;
     unsigned int time_received;
     uint32_t lock_time;
     bool is_final;
     bool is_trusted;
     bool is_abandoned;
     bool is_coinbase;
     bool is_in_main_chain;
 };
 
 //! Wallet transaction output.
 struct WalletTxOut {
     CTxOut txout;
     int64_t time;
     int depth_in_main_chain = -1;
     bool is_spent = false;
 };
 
 //! Return implementation of Wallet interface. This function will be undefined
 //! in builds where ENABLE_WALLET is false.
 std::unique_ptr<Wallet> MakeWallet(CWallet &wallet);
 
 } // namespace interfaces
 
 #endif // BITCOIN_INTERFACES_WALLET_H
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index d888a5043..f3f73b1f9 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1,1334 +1,1335 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #if defined(HAVE_CONFIG_H)
 #include <config/bitcoin-config.h>
 #endif
 
 #include <qt/bitcoingui.h>
 
+#include <chain.h>
 #include <chainparams.h>
 #include <init.h>
 #include <interfaces/handler.h>
 #include <interfaces/node.h>
 #include <qt/bitcoinunits.h>
 #include <qt/clientmodel.h>
 #include <qt/guiconstants.h>
 #include <qt/guiutil.h>
 #ifdef Q_OS_MAC
 #include <qt/macdockiconhandler.h>
 #endif
 #include <qt/modaloverlay.h>
 #include <qt/networkstyle.h>
 #include <qt/notificator.h>
 #include <qt/openuridialog.h>
 #include <qt/optionsdialog.h>
 #include <qt/optionsmodel.h>
 #include <qt/platformstyle.h>
 #include <qt/rpcconsole.h>
 #include <qt/utilitydialog.h>
 #ifdef ENABLE_WALLET
 #include <qt/walletframe.h>
 #include <qt/walletmodel.h>
 #include <qt/walletview.h>
 #endif // ENABLE_WALLET
 #include <ui_interface.h>
 #include <util.h>
 
 #include <QAction>
 #include <QApplication>
 #include <QComboBox>
 #include <QDateTime>
 #include <QDesktopWidget>
 #include <QDragEnterEvent>
 #include <QListWidget>
 #include <QMenuBar>
 #include <QMessageBox>
 #include <QMimeData>
 #include <QProgressDialog>
 #include <QSettings>
 #include <QShortcut>
 #include <QStackedWidget>
 #include <QStatusBar>
 #include <QStyle>
 #include <QTimer>
 #include <QToolBar>
 #include <QUrlQuery>
 #include <QVBoxLayout>
 
 #include <iostream>
 
 const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
 #if defined(Q_OS_MAC)
     "macosx"
 #elif defined(Q_OS_WIN)
     "windows"
 #else
     "other"
 #endif
     ;
 
 BitcoinGUI::BitcoinGUI(interfaces::Node &node, const Config *configIn,
                        const PlatformStyle *_platformStyle,
                        const NetworkStyle *networkStyle, QWidget *parent)
     : QMainWindow(parent), enableWallet(false), m_node(node),
       platformStyle(_platformStyle), config(configIn) {
     QSettings settings;
     if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
         // Restore failed (perhaps missing setting), center the window
         move(QApplication::desktop()->availableGeometry().center() -
              frameGeometry().center());
     }
 
     QString windowTitle = tr(PACKAGE_NAME) + " - ";
 #ifdef ENABLE_WALLET
     enableWallet = WalletModel::isWalletEnabled();
 #endif // ENABLE_WALLET
     if (enableWallet) {
         windowTitle += tr("Wallet");
     } else {
         windowTitle += tr("Node");
     }
     windowTitle += " " + networkStyle->getTitleAddText();
 #ifndef Q_OS_MAC
     QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
     setWindowIcon(networkStyle->getTrayAndWindowIcon());
 #else
     MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
 #endif
     setWindowTitle(windowTitle);
 
     rpcConsole = new RPCConsole(node, _platformStyle, 0);
     helpMessageDialog = new HelpMessageDialog(node, this, false);
 #ifdef ENABLE_WALLET
     if (enableWallet) {
         /** Create wallet frame and make it the central widget */
         walletFrame = new WalletFrame(_platformStyle, config, this);
         setCentralWidget(walletFrame);
     } else
 #endif // ENABLE_WALLET
     {
         /**
          * When compiled without wallet or -disablewallet is provided,  the
          * central widget is the rpc console.
          */
         setCentralWidget(rpcConsole);
     }
 
     // Accept D&D of URIs
     setAcceptDrops(true);
 
     // Create actions for the toolbar, menu bar and tray/dock icon
     // Needs walletFrame to be initialized
     createActions();
 
     // Create application menu bar
     createMenuBar();
 
     // Create the toolbars
     createToolBars();
 
     // Create system tray icon and notification
     createTrayIcon(networkStyle);
 
     // Create status bar
     statusBar();
 
     // Disable size grip because it looks ugly and nobody needs it
     statusBar()->setSizeGripEnabled(false);
 
     // Status bar notification icons
     QFrame *frameBlocks = new QFrame();
     frameBlocks->setContentsMargins(0, 0, 0, 0);
     frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
     QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
     frameBlocksLayout->setContentsMargins(3, 0, 3, 0);
     frameBlocksLayout->setSpacing(3);
     unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
     labelWalletEncryptionIcon = new QLabel();
     labelWalletHDStatusIcon = new QLabel();
     connectionsControl = new GUIUtil::ClickableLabel();
     labelBlocksIcon = new GUIUtil::ClickableLabel();
     if (enableWallet) {
         frameBlocksLayout->addStretch();
         frameBlocksLayout->addWidget(unitDisplayControl);
         frameBlocksLayout->addStretch();
         frameBlocksLayout->addWidget(labelWalletEncryptionIcon);
         frameBlocksLayout->addWidget(labelWalletHDStatusIcon);
     }
     frameBlocksLayout->addStretch();
     frameBlocksLayout->addWidget(connectionsControl);
     frameBlocksLayout->addStretch();
     frameBlocksLayout->addWidget(labelBlocksIcon);
     frameBlocksLayout->addStretch();
 
     // Progress bar and label for blocks download
     progressBarLabel = new QLabel();
     progressBarLabel->setVisible(false);
     progressBar = new GUIUtil::ProgressBar();
     progressBar->setAlignment(Qt::AlignCenter);
     progressBar->setVisible(false);
 
     // Override style sheet for progress bar for styles that have a segmented
     // progress bar, as they make the text unreadable (workaround for issue
     // #1071)
     // See https://doc.qt.io/qt-5/gallery.html
     QString curStyle = QApplication::style()->metaObject()->className();
     if (curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle") {
         progressBar->setStyleSheet(
             "QProgressBar { background-color: #e8e8e8; border: 1px solid grey; "
             "border-radius: 7px; padding: 1px; text-align: center; } "
             "QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, "
             "x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: "
             "7px; margin: 0px; }");
     }
 
     statusBar()->addWidget(progressBarLabel);
     statusBar()->addWidget(progressBar);
     statusBar()->addPermanentWidget(frameBlocks);
 
     // Install event filter to be able to catch status tip events
     // (QEvent::StatusTip)
     this->installEventFilter(this);
 
     // Initially wallet actions should be disabled
     setWalletActionsEnabled(false);
 
     // Subscribe to notifications from core
     subscribeToCoreSignals();
 
     connect(connectionsControl, SIGNAL(clicked(QPoint)), this,
             SLOT(toggleNetworkActive()));
 
     modalOverlay = new ModalOverlay(this->centralWidget());
 #ifdef ENABLE_WALLET
     if (enableWallet) {
         connect(walletFrame, SIGNAL(requestedSyncWarningInfo()), this,
                 SLOT(showModalOverlay()));
         connect(labelBlocksIcon, SIGNAL(clicked(QPoint)), this,
                 SLOT(showModalOverlay()));
         connect(progressBar, SIGNAL(clicked(QPoint)), this,
                 SLOT(showModalOverlay()));
     }
 #endif
 }
 
 BitcoinGUI::~BitcoinGUI() {
     // Unsubscribe from notifications from core
     unsubscribeFromCoreSignals();
 
     QSettings settings;
     settings.setValue("MainWindowGeometry", saveGeometry());
     // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
     if (trayIcon) {
         trayIcon->hide();
     }
 #ifdef Q_OS_MAC
     delete appMenuBar;
     MacDockIconHandler::cleanup();
 #endif
 
     delete rpcConsole;
 }
 
 void BitcoinGUI::createActions() {
     QActionGroup *tabGroup = new QActionGroup(this);
 
     overviewAction =
         new QAction(platformStyle->SingleColorIcon(":/icons/overview"),
                     tr("&Overview"), this);
     overviewAction->setStatusTip(tr("Show general overview of wallet"));
     overviewAction->setToolTip(overviewAction->statusTip());
     overviewAction->setCheckable(true);
     overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
     tabGroup->addAction(overviewAction);
 
     sendCoinsAction = new QAction(
         platformStyle->SingleColorIcon(":/icons/send"), tr("&Send"), this);
     sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
     sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
     sendCoinsAction->setCheckable(true);
     sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
     tabGroup->addAction(sendCoinsAction);
 
     sendCoinsMenuAction =
         new QAction(platformStyle->TextColorIcon(":/icons/send"),
                     sendCoinsAction->text(), this);
     sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
     sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
 
     receiveCoinsAction = new QAction(
         platformStyle->SingleColorIcon(":/icons/receiving_addresses"),
         tr("&Receive"), this);
     receiveCoinsAction->setStatusTip(
         tr("Request payments (generates QR codes and %1: URIs)")
             .arg(GUIUtil::bitcoinURIScheme(*config)));
     receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
     receiveCoinsAction->setCheckable(true);
     receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
     tabGroup->addAction(receiveCoinsAction);
 
     receiveCoinsMenuAction =
         new QAction(platformStyle->TextColorIcon(":/icons/receiving_addresses"),
                     receiveCoinsAction->text(), this);
     receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
     receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
 
     historyAction =
         new QAction(platformStyle->SingleColorIcon(":/icons/history"),
                     tr("&Transactions"), this);
     historyAction->setStatusTip(tr("Browse transaction history"));
     historyAction->setToolTip(historyAction->statusTip());
     historyAction->setCheckable(true);
     historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
     tabGroup->addAction(historyAction);
 
 #ifdef ENABLE_WALLET
     // These showNormalIfMinimized are needed because Send Coins and Receive
     // Coins can be triggered from the tray menu, and need to show the GUI to be
     // useful.
     connect(overviewAction, SIGNAL(triggered()), this,
             SLOT(showNormalIfMinimized()));
     connect(overviewAction, SIGNAL(triggered()), this,
             SLOT(gotoOverviewPage()));
     connect(sendCoinsAction, SIGNAL(triggered()), this,
             SLOT(showNormalIfMinimized()));
     connect(sendCoinsAction, SIGNAL(triggered()), this,
             SLOT(gotoSendCoinsPage()));
     connect(sendCoinsMenuAction, SIGNAL(triggered()), this,
             SLOT(showNormalIfMinimized()));
     connect(sendCoinsMenuAction, SIGNAL(triggered()), this,
             SLOT(gotoSendCoinsPage()));
     connect(receiveCoinsAction, SIGNAL(triggered()), this,
             SLOT(showNormalIfMinimized()));
     connect(receiveCoinsAction, SIGNAL(triggered()), this,
             SLOT(gotoReceiveCoinsPage()));
     connect(receiveCoinsMenuAction, SIGNAL(triggered()), this,
             SLOT(showNormalIfMinimized()));
     connect(receiveCoinsMenuAction, SIGNAL(triggered()), this,
             SLOT(gotoReceiveCoinsPage()));
     connect(historyAction, SIGNAL(triggered()), this,
             SLOT(showNormalIfMinimized()));
     connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
 #endif // ENABLE_WALLET
 
     quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"),
                              tr("E&xit"), this);
     quitAction->setStatusTip(tr("Quit application"));
     quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
     quitAction->setMenuRole(QAction::QuitRole);
     aboutAction = new QAction(platformStyle->TextColorIcon(":/icons/about"),
                               tr("&About %1").arg(tr(PACKAGE_NAME)), this);
     aboutAction->setStatusTip(
         tr("Show information about %1").arg(tr(PACKAGE_NAME)));
     aboutAction->setMenuRole(QAction::AboutRole);
     aboutAction->setEnabled(false);
     aboutQtAction =
         new QAction(platformStyle->TextColorIcon(":/icons/about_qt"),
                     tr("About &Qt"), this);
     aboutQtAction->setStatusTip(tr("Show information about Qt"));
     aboutQtAction->setMenuRole(QAction::AboutQtRole);
     optionsAction = new QAction(platformStyle->TextColorIcon(":/icons/options"),
                                 tr("&Options..."), this);
     optionsAction->setStatusTip(
         tr("Modify configuration options for %1").arg(tr(PACKAGE_NAME)));
     optionsAction->setMenuRole(QAction::PreferencesRole);
     optionsAction->setEnabled(false);
     toggleHideAction =
         new QAction(platformStyle->TextColorIcon(":/icons/about"),
                     tr("&Show / Hide"), this);
     toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
 
     encryptWalletAction =
         new QAction(platformStyle->TextColorIcon(":/icons/lock_closed"),
                     tr("&Encrypt Wallet..."), this);
     encryptWalletAction->setStatusTip(
         tr("Encrypt the private keys that belong to your wallet"));
     encryptWalletAction->setCheckable(true);
     backupWalletAction =
         new QAction(platformStyle->TextColorIcon(":/icons/filesave"),
                     tr("&Backup Wallet..."), this);
     backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
     changePassphraseAction =
         new QAction(platformStyle->TextColorIcon(":/icons/key"),
                     tr("&Change Passphrase..."), this);
     changePassphraseAction->setStatusTip(
         tr("Change the passphrase used for wallet encryption"));
     signMessageAction =
         new QAction(platformStyle->TextColorIcon(":/icons/edit"),
                     tr("Sign &message..."), this);
     signMessageAction->setStatusTip(
         tr("Sign messages with your Bitcoin addresses to prove you own them"));
     verifyMessageAction =
         new QAction(platformStyle->TextColorIcon(":/icons/verify"),
                     tr("&Verify message..."), this);
     verifyMessageAction->setStatusTip(
         tr("Verify messages to ensure they were signed with specified Bitcoin "
            "addresses"));
 
     openRPCConsoleAction =
         new QAction(platformStyle->TextColorIcon(":/icons/debugwindow"),
                     tr("&Debug window"), this);
     openRPCConsoleAction->setStatusTip(
         tr("Open debugging and diagnostic console"));
     // initially disable the debug window menu item
     openRPCConsoleAction->setEnabled(false);
 
     usedSendingAddressesAction =
         new QAction(platformStyle->TextColorIcon(":/icons/address-book"),
                     tr("&Sending addresses..."), this);
     usedSendingAddressesAction->setStatusTip(
         tr("Show the list of used sending addresses and labels"));
     usedReceivingAddressesAction =
         new QAction(platformStyle->TextColorIcon(":/icons/address-book"),
                     tr("&Receiving addresses..."), this);
     usedReceivingAddressesAction->setStatusTip(
         tr("Show the list of used receiving addresses and labels"));
 
     openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"),
                              tr("Open &URI..."), this);
     openAction->setStatusTip(tr("Open a %1: URI or payment request")
                                  .arg(GUIUtil::bitcoinURIScheme(*config)));
 
     showHelpMessageAction =
         new QAction(platformStyle->TextColorIcon(":/icons/info"),
                     tr("&Command-line options"), this);
     showHelpMessageAction->setMenuRole(QAction::NoRole);
     showHelpMessageAction->setStatusTip(
         tr("Show the %1 help message to get a list with possible Bitcoin "
            "command-line options")
             .arg(tr(PACKAGE_NAME)));
 
     connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
     connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
     connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
     connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
     connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
     connect(showHelpMessageAction, SIGNAL(triggered()), this,
             SLOT(showHelpMessageClicked()));
     connect(openRPCConsoleAction, SIGNAL(triggered()), this,
             SLOT(showDebugWindow()));
     // prevents an open debug window from becoming stuck/unusable on client
     // shutdown
     connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
 
 #ifdef ENABLE_WALLET
     if (walletFrame) {
         connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame,
                 SLOT(encryptWallet(bool)));
         connect(backupWalletAction, SIGNAL(triggered()), walletFrame,
                 SLOT(backupWallet()));
         connect(changePassphraseAction, SIGNAL(triggered()), walletFrame,
                 SLOT(changePassphrase()));
         connect(signMessageAction, SIGNAL(triggered()), this,
                 SLOT(gotoSignMessageTab()));
         connect(verifyMessageAction, SIGNAL(triggered()), this,
                 SLOT(gotoVerifyMessageTab()));
         connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame,
                 SLOT(usedSendingAddresses()));
         connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame,
                 SLOT(usedReceivingAddresses()));
         connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
     }
 #endif // ENABLE_WALLET
 
     new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this,
                   SLOT(showDebugWindowActivateConsole()));
     new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D), this,
                   SLOT(showDebugWindow()));
 }
 
 void BitcoinGUI::createMenuBar() {
 #ifdef Q_OS_MAC
     // Create a decoupled menu bar on Mac which stays even if the window is
     // closed
     appMenuBar = new QMenuBar();
 #else
     // Get the main window's menu bar on other platforms
     appMenuBar = menuBar();
 #endif
 
     // Configure the menus
     QMenu *file = appMenuBar->addMenu(tr("&File"));
     if (walletFrame) {
         file->addAction(openAction);
         file->addAction(backupWalletAction);
         file->addAction(signMessageAction);
         file->addAction(verifyMessageAction);
         file->addSeparator();
         file->addAction(usedSendingAddressesAction);
         file->addAction(usedReceivingAddressesAction);
         file->addSeparator();
     }
     file->addAction(quitAction);
 
     QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
     if (walletFrame) {
         settings->addAction(encryptWalletAction);
         settings->addAction(changePassphraseAction);
         settings->addSeparator();
     }
     settings->addAction(optionsAction);
 
     QMenu *help = appMenuBar->addMenu(tr("&Help"));
     if (walletFrame) {
         help->addAction(openRPCConsoleAction);
     }
     help->addAction(showHelpMessageAction);
     help->addSeparator();
     help->addAction(aboutAction);
     help->addAction(aboutQtAction);
 }
 
 void BitcoinGUI::createToolBars() {
     if (walletFrame) {
         QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
         appToolBar = toolbar;
         toolbar->setContextMenuPolicy(Qt::PreventContextMenu);
         toolbar->setMovable(false);
         toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
         toolbar->addAction(overviewAction);
         toolbar->addAction(sendCoinsAction);
         toolbar->addAction(receiveCoinsAction);
         toolbar->addAction(historyAction);
         overviewAction->setChecked(true);
 
 #ifdef ENABLE_WALLET
         QWidget *spacer = new QWidget();
         spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
         toolbar->addWidget(spacer);
 
         m_wallet_selector = new QComboBox();
         connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString &)),
                 this, SLOT(setCurrentWallet(const QString &)));
 #endif
     }
 }
 
 void BitcoinGUI::setClientModel(ClientModel *_clientModel) {
     this->clientModel = _clientModel;
     if (_clientModel) {
         // Create system tray menu (or setup the dock menu) that late to prevent
         // users from calling actions, while the client has not yet fully loaded
         createTrayIconMenu();
 
         // Keep up to date with client
         updateNetworkState();
         connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this,
                 SLOT(setNumConnections(int)));
         connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this,
                 SLOT(setNetworkActive(bool)));
 
         modalOverlay->setKnownBestHeight(
             _clientModel->getHeaderTipHeight(),
             QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
         setNumBlocks(m_node.getNumBlocks(),
                      QDateTime::fromTime_t(m_node.getLastBlockTime()),
                      m_node.getVerificationProgress(), false);
         connect(_clientModel,
                 SIGNAL(numBlocksChanged(int, QDateTime, double, bool)), this,
                 SLOT(setNumBlocks(int, QDateTime, double, bool)));
 
         // Receive and report messages from client model
         connect(_clientModel, SIGNAL(message(QString, QString, unsigned int)),
                 this, SLOT(message(QString, QString, unsigned int)));
 
         // Show progress dialog
         connect(_clientModel, SIGNAL(showProgress(QString, int)), this,
                 SLOT(showProgress(QString, int)));
 
         rpcConsole->setClientModel(_clientModel);
 #ifdef ENABLE_WALLET
         if (walletFrame) {
             walletFrame->setClientModel(_clientModel);
         }
 #endif // ENABLE_WALLET
         unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
 
         OptionsModel *optionsModel = _clientModel->getOptionsModel();
         if (optionsModel) {
             // be aware of the tray icon disable state change reported by the
             // OptionsModel object.
             connect(optionsModel, SIGNAL(hideTrayIconChanged(bool)), this,
                     SLOT(setTrayIconVisible(bool)));
 
             // initialize the disable state of the tray icon with the current
             // value in the model.
             setTrayIconVisible(optionsModel->getHideTrayIcon());
         }
     } else {
         // Disable possibility to show main window via action
         toggleHideAction->setEnabled(false);
         if (trayIconMenu) {
             // Disable context menu on tray icon
             trayIconMenu->clear();
         }
         // Propagate cleared model to child objects
         rpcConsole->setClientModel(nullptr);
 #ifdef ENABLE_WALLET
         if (walletFrame) {
             walletFrame->setClientModel(nullptr);
         }
 #endif // ENABLE_WALLET
         unitDisplayControl->setOptionsModel(nullptr);
     }
 }
 
 #ifdef ENABLE_WALLET
 bool BitcoinGUI::addWallet(WalletModel *walletModel) {
     if (!walletFrame) return false;
     const QString name = walletModel->getWalletName();
     setWalletActionsEnabled(true);
     m_wallet_selector->addItem(name);
     if (m_wallet_selector->count() == 2) {
         m_wallet_selector_label = new QLabel();
         m_wallet_selector_label->setText(tr("Wallet:") + " ");
         m_wallet_selector_label->setBuddy(m_wallet_selector);
         appToolBar->addWidget(m_wallet_selector_label);
         appToolBar->addWidget(m_wallet_selector);
     }
     rpcConsole->addWallet(walletModel);
     return walletFrame->addWallet(walletModel);
 }
 
 bool BitcoinGUI::setCurrentWallet(const QString &name) {
     if (!walletFrame) return false;
     return walletFrame->setCurrentWallet(name);
 }
 
 void BitcoinGUI::removeAllWallets() {
     if (!walletFrame) return;
     setWalletActionsEnabled(false);
     walletFrame->removeAllWallets();
 }
 #endif // ENABLE_WALLET
 
 void BitcoinGUI::setWalletActionsEnabled(bool enabled) {
     overviewAction->setEnabled(enabled);
     sendCoinsAction->setEnabled(enabled);
     sendCoinsMenuAction->setEnabled(enabled);
     receiveCoinsAction->setEnabled(enabled);
     receiveCoinsMenuAction->setEnabled(enabled);
     historyAction->setEnabled(enabled);
     encryptWalletAction->setEnabled(enabled);
     backupWalletAction->setEnabled(enabled);
     changePassphraseAction->setEnabled(enabled);
     signMessageAction->setEnabled(enabled);
     verifyMessageAction->setEnabled(enabled);
     usedSendingAddressesAction->setEnabled(enabled);
     usedReceivingAddressesAction->setEnabled(enabled);
     openAction->setEnabled(enabled);
 }
 
 void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle) {
 #ifndef Q_OS_MAC
     trayIcon = new QSystemTrayIcon(this);
     QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " +
                       networkStyle->getTitleAddText();
     trayIcon->setToolTip(toolTip);
     trayIcon->setIcon(networkStyle->getTrayAndWindowIcon());
     trayIcon->hide();
 #endif
 
     notificator =
         new Notificator(QApplication::applicationName(), trayIcon, this);
 }
 
 void BitcoinGUI::createTrayIconMenu() {
 #ifndef Q_OS_MAC
     // return if trayIcon is unset (only on non-Mac OSes)
     if (!trayIcon) return;
 
     trayIconMenu = new QMenu(this);
     trayIcon->setContextMenu(trayIconMenu);
 
     connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
             this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
 #else
     // Note: On Mac, the dock icon is used to provide the tray's functionality.
     MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
     dockIconHandler->setMainWindow(static_cast<QMainWindow *>(this));
     trayIconMenu = dockIconHandler->dockMenu();
 #endif
 
     // Configuration of the tray icon (or dock icon) icon menu
     trayIconMenu->addAction(toggleHideAction);
     trayIconMenu->addSeparator();
     trayIconMenu->addAction(sendCoinsMenuAction);
     trayIconMenu->addAction(receiveCoinsMenuAction);
     trayIconMenu->addSeparator();
     trayIconMenu->addAction(signMessageAction);
     trayIconMenu->addAction(verifyMessageAction);
     trayIconMenu->addSeparator();
     trayIconMenu->addAction(optionsAction);
     trayIconMenu->addAction(openRPCConsoleAction);
 #ifndef Q_OS_MAC // This is built-in on Mac
     trayIconMenu->addSeparator();
     trayIconMenu->addAction(quitAction);
 #endif
 }
 
 #ifndef Q_OS_MAC
 void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) {
     if (reason == QSystemTrayIcon::Trigger) {
         // Click on system tray icon triggers show/hide of the main window
         toggleHidden();
     }
 }
 #endif
 
 void BitcoinGUI::optionsClicked() {
     if (!clientModel || !clientModel->getOptionsModel()) return;
 
     OptionsDialog dlg(this, enableWallet);
     dlg.setModel(clientModel->getOptionsModel());
     dlg.exec();
 }
 
 void BitcoinGUI::aboutClicked() {
     if (!clientModel) return;
 
     HelpMessageDialog dlg(m_node, this, true);
     dlg.exec();
 }
 
 void BitcoinGUI::showDebugWindow() {
     rpcConsole->showNormal();
     rpcConsole->show();
     rpcConsole->raise();
     rpcConsole->activateWindow();
 }
 
 void BitcoinGUI::showDebugWindowActivateConsole() {
     rpcConsole->setTabFocus(RPCConsole::TAB_CONSOLE);
     showDebugWindow();
 }
 
 void BitcoinGUI::showHelpMessageClicked() {
     helpMessageDialog->show();
 }
 
 #ifdef ENABLE_WALLET
 void BitcoinGUI::openClicked() {
     OpenURIDialog dlg(config, this);
     if (dlg.exec()) {
         Q_EMIT receivedURI(dlg.getURI());
     }
 }
 
 void BitcoinGUI::gotoOverviewPage() {
     overviewAction->setChecked(true);
     if (walletFrame) walletFrame->gotoOverviewPage();
 }
 
 void BitcoinGUI::gotoHistoryPage() {
     historyAction->setChecked(true);
     if (walletFrame) walletFrame->gotoHistoryPage();
 }
 
 void BitcoinGUI::gotoReceiveCoinsPage() {
     receiveCoinsAction->setChecked(true);
     if (walletFrame) walletFrame->gotoReceiveCoinsPage();
 }
 
 void BitcoinGUI::gotoSendCoinsPage(QString addr) {
     sendCoinsAction->setChecked(true);
     if (walletFrame) walletFrame->gotoSendCoinsPage(addr);
 }
 
 void BitcoinGUI::gotoSignMessageTab(QString addr) {
     if (walletFrame) walletFrame->gotoSignMessageTab(addr);
 }
 
 void BitcoinGUI::gotoVerifyMessageTab(QString addr) {
     if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
 }
 #endif // ENABLE_WALLET
 
 void BitcoinGUI::updateNetworkState() {
     int count = clientModel->getNumConnections();
     QString icon;
     switch (count) {
         case 0:
             icon = ":/icons/connect_0";
             break;
         case 1:
         case 2:
         case 3:
             icon = ":/icons/connect_1";
             break;
         case 4:
         case 5:
         case 6:
             icon = ":/icons/connect_2";
             break;
         case 7:
         case 8:
         case 9:
             icon = ":/icons/connect_3";
             break;
         default:
             icon = ":/icons/connect_4";
             break;
     }
 
     QString tooltip;
 
     if (m_node.getNetworkActive()) {
         tooltip = tr("%n active connection(s) to Bitcoin network", "", count) +
                   QString(".<br>") + tr("Click to disable network activity.");
     } else {
         tooltip = tr("Network activity disabled.") + QString("<br>") +
                   tr("Click to enable network activity again.");
         icon = ":/icons/network_disabled";
     }
 
     // Don't word-wrap this (fixed-width) tooltip
     tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
     connectionsControl->setToolTip(tooltip);
 
     connectionsControl->setPixmap(platformStyle->SingleColorIcon(icon).pixmap(
         STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
 }
 
 void BitcoinGUI::setNumConnections(int count) {
     updateNetworkState();
 }
 
 void BitcoinGUI::setNetworkActive(bool networkActive) {
     updateNetworkState();
 }
 
 void BitcoinGUI::updateHeadersSyncProgressLabel() {
     int64_t headersTipTime = clientModel->getHeaderTipTime();
     int headersTipHeight = clientModel->getHeaderTipHeight();
     int estHeadersLeft = (GetTime() - headersTipTime) /
                          Params().GetConsensus().nPowTargetSpacing;
     if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC) {
         progressBarLabel->setText(
             tr("Syncing Headers (%1%)...")
                 .arg(QString::number(100.0 /
                                          (headersTipHeight + estHeadersLeft) *
                                          headersTipHeight,
                                      'f', 1)));
     }
 }
 
 void BitcoinGUI::setNumBlocks(int count, const QDateTime &blockDate,
                               double nVerificationProgress, bool header) {
     if (modalOverlay) {
         if (header) {
             modalOverlay->setKnownBestHeight(count, blockDate);
         } else {
             modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
         }
     }
     if (!clientModel) {
         return;
     }
 
     // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait
     // until chain-sync starts -> garbled text)
     statusBar()->clearMessage();
 
     // Acquire current block source
     enum BlockSource blockSource = clientModel->getBlockSource();
     switch (blockSource) {
         case BlockSource::NETWORK:
             if (header) {
                 updateHeadersSyncProgressLabel();
                 return;
             }
             progressBarLabel->setText(tr("Synchronizing with network..."));
             updateHeadersSyncProgressLabel();
             break;
         case BlockSource::DISK:
             if (header) {
                 progressBarLabel->setText(tr("Indexing blocks on disk..."));
             } else {
                 progressBarLabel->setText(tr("Processing blocks on disk..."));
             }
             break;
         case BlockSource::REINDEX:
             progressBarLabel->setText(tr("Reindexing blocks on disk..."));
             break;
         case BlockSource::NONE:
             if (header) {
                 return;
             }
             progressBarLabel->setText(tr("Connecting to peers..."));
             break;
     }
 
     QString tooltip;
 
     QDateTime currentDate = QDateTime::currentDateTime();
     qint64 secs = blockDate.secsTo(currentDate);
 
     tooltip = tr("Processed %n block(s) of transaction history.", "", count);
 
     // Set icon state: spinning if catching up, tick otherwise
-    if (secs < 90 * 60) {
+    if (secs < MAX_BLOCK_TIME_GAP) {
         tooltip = tr("Up to date") + QString(".<br>") + tooltip;
         labelBlocksIcon->setPixmap(
             platformStyle->SingleColorIcon(":/icons/synced")
                 .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
 
 #ifdef ENABLE_WALLET
         if (walletFrame) {
             walletFrame->showOutOfSyncWarning(false);
             modalOverlay->showHide(true, true);
         }
 #endif // ENABLE_WALLET
 
         progressBarLabel->setVisible(false);
         progressBar->setVisible(false);
     } else {
         QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
 
         progressBarLabel->setVisible(true);
         progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
         progressBar->setMaximum(1000000000);
         progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
         progressBar->setVisible(true);
 
         tooltip = tr("Catching up...") + QString("<br>") + tooltip;
         if (count != prevBlocks) {
             labelBlocksIcon->setPixmap(
                 platformStyle
                     ->SingleColorIcon(QString(":/movies/spinner-%1")
                                           .arg(spinnerFrame, 3, 10, QChar('0')))
                     .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
             spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
         }
         prevBlocks = count;
 
 #ifdef ENABLE_WALLET
         if (walletFrame) {
             walletFrame->showOutOfSyncWarning(true);
             modalOverlay->showHide();
         }
 #endif // ENABLE_WALLET
 
         tooltip += QString("<br>");
         tooltip +=
             tr("Last received block was generated %1 ago.").arg(timeBehindText);
         tooltip += QString("<br>");
         tooltip += tr("Transactions after this will not yet be visible.");
     }
 
     // Don't word-wrap this (fixed-width) tooltip
     tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
 
     labelBlocksIcon->setToolTip(tooltip);
     progressBarLabel->setToolTip(tooltip);
     progressBar->setToolTip(tooltip);
 }
 
 void BitcoinGUI::message(const QString &title, const QString &message,
                          unsigned int style, bool *ret) {
     // default title
     QString strTitle = tr("Bitcoin");
     // Default to information icon
     int nMBoxIcon = QMessageBox::Information;
     int nNotifyIcon = Notificator::Information;
 
     QString msgType;
 
     // Prefer supplied title over style based title
     if (!title.isEmpty()) {
         msgType = title;
     } else {
         switch (style) {
             case CClientUIInterface::MSG_ERROR:
                 msgType = tr("Error");
                 break;
             case CClientUIInterface::MSG_WARNING:
                 msgType = tr("Warning");
                 break;
             case CClientUIInterface::MSG_INFORMATION:
                 msgType = tr("Information");
                 break;
             default:
                 break;
         }
     }
     // Append title to "Bitcoin - "
     if (!msgType.isEmpty()) {
         strTitle += " - " + msgType;
     }
 
     // Check for error/warning icon
     if (style & CClientUIInterface::ICON_ERROR) {
         nMBoxIcon = QMessageBox::Critical;
         nNotifyIcon = Notificator::Critical;
     } else if (style & CClientUIInterface::ICON_WARNING) {
         nMBoxIcon = QMessageBox::Warning;
         nNotifyIcon = Notificator::Warning;
     }
 
     // Display message
     if (style & CClientUIInterface::MODAL) {
         // Check for buttons, use OK as default, if none was supplied
         QMessageBox::StandardButton buttons;
         if (!(buttons = (QMessageBox::StandardButton)(
                   style & CClientUIInterface::BTN_MASK)))
             buttons = QMessageBox::Ok;
 
         showNormalIfMinimized();
         QMessageBox mBox(static_cast<QMessageBox::Icon>(nMBoxIcon), strTitle,
                          message, buttons, this);
         int r = mBox.exec();
         if (ret != nullptr) {
             *ret = r == QMessageBox::Ok;
         }
     } else
         notificator->notify(static_cast<Notificator::Class>(nNotifyIcon),
                             strTitle, message);
 }
 
 void BitcoinGUI::changeEvent(QEvent *e) {
     QMainWindow::changeEvent(e);
 #ifndef Q_OS_MAC // Ignored on Mac
     if (e->type() == QEvent::WindowStateChange) {
         if (clientModel && clientModel->getOptionsModel() &&
             clientModel->getOptionsModel()->getMinimizeToTray()) {
             QWindowStateChangeEvent *wsevt =
                 static_cast<QWindowStateChangeEvent *>(e);
             if (!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) {
                 QTimer::singleShot(0, this, SLOT(hide()));
                 e->ignore();
             } else if ((wsevt->oldState() & Qt::WindowMinimized) &&
                        !isMinimized()) {
                 QTimer::singleShot(0, this, SLOT(show()));
                 e->ignore();
             }
         }
     }
 #endif
 }
 
 void BitcoinGUI::closeEvent(QCloseEvent *event) {
 #ifndef Q_OS_MAC // Ignored on Mac
     if (clientModel && clientModel->getOptionsModel()) {
         if (!clientModel->getOptionsModel()->getMinimizeOnClose()) {
             // close rpcConsole in case it was open to make some space for the
             // shutdown window
             rpcConsole->close();
 
             QApplication::quit();
         } else {
             QMainWindow::showMinimized();
             event->ignore();
         }
     }
 #else
     QMainWindow::closeEvent(event);
 #endif
 }
 
 void BitcoinGUI::showEvent(QShowEvent *event) {
     // enable the debug window when the main window shows up
     openRPCConsoleAction->setEnabled(true);
     aboutAction->setEnabled(true);
     optionsAction->setEnabled(true);
 }
 
 #ifdef ENABLE_WALLET
 void BitcoinGUI::incomingTransaction(const QString &date, int unit,
                                      const Amount amount, const QString &type,
                                      const QString &address,
                                      const QString &label,
                                      const QString &walletName) {
     // On new transaction, make an info balloon
     QString msg = tr("Date: %1\n").arg(date) +
                   tr("Amount: %1\n")
                       .arg(BitcoinUnits::formatWithUnit(unit, amount, true));
     if (m_node.getWallets().size() > 1 && !walletName.isEmpty()) {
         msg += tr("Wallet: %1\n").arg(walletName);
     }
     msg += tr("Type: %1\n").arg(type);
     if (!label.isEmpty()) {
         msg += tr("Label: %1\n").arg(label);
     } else if (!address.isEmpty()) {
         msg += tr("Address: %1\n").arg(address);
     }
     message(amount < Amount::zero() ? tr("Sent transaction")
                                     : tr("Incoming transaction"),
             msg, CClientUIInterface::MSG_INFORMATION);
 }
 #endif // ENABLE_WALLET
 
 void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) {
     // Accept only URIs
     if (event->mimeData()->hasUrls()) {
         event->acceptProposedAction();
     }
 }
 
 void BitcoinGUI::dropEvent(QDropEvent *event) {
     if (event->mimeData()->hasUrls()) {
         for (const QUrl &uri : event->mimeData()->urls()) {
             Q_EMIT receivedURI(uri.toString());
         }
     }
     event->acceptProposedAction();
 }
 
 bool BitcoinGUI::eventFilter(QObject *object, QEvent *event) {
     // Catch status tip events
     if (event->type() == QEvent::StatusTip) {
         // Prevent adding text from setStatusTip(), if we currently use the
         // status bar for displaying other stuff
         if (progressBarLabel->isVisible() || progressBar->isVisible()) {
             return true;
         }
     }
     return QMainWindow::eventFilter(object, event);
 }
 
 #ifdef ENABLE_WALLET
 bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient &recipient) {
     // URI has to be valid
     if (walletFrame && walletFrame->handlePaymentRequest(recipient)) {
         showNormalIfMinimized();
         gotoSendCoinsPage();
         return true;
     }
     return false;
 }
 
 void BitcoinGUI::setHDStatus(int hdEnabled) {
     labelWalletHDStatusIcon->setPixmap(
         platformStyle
             ->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled"
                                         : ":/icons/hd_disabled")
             .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
     labelWalletHDStatusIcon->setToolTip(
         hdEnabled ? tr("HD key generation is <b>enabled</b>")
                   : tr("HD key generation is <b>disabled</b>"));
 
     // eventually disable the QLabel to set its opacity to 50%
     labelWalletHDStatusIcon->setEnabled(hdEnabled);
 }
 
 void BitcoinGUI::setEncryptionStatus(int status) {
     switch (status) {
         case WalletModel::Unencrypted:
             labelWalletEncryptionIcon->hide();
             encryptWalletAction->setChecked(false);
             changePassphraseAction->setEnabled(false);
             encryptWalletAction->setEnabled(true);
             break;
         case WalletModel::Unlocked:
             labelWalletEncryptionIcon->show();
             labelWalletEncryptionIcon->setPixmap(
                 platformStyle->SingleColorIcon(":/icons/lock_open")
                     .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
             labelWalletEncryptionIcon->setToolTip(
                 tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
             encryptWalletAction->setChecked(true);
             changePassphraseAction->setEnabled(true);
             encryptWalletAction->setEnabled(
                 false); // TODO: decrypt currently not supported
             break;
         case WalletModel::Locked:
             labelWalletEncryptionIcon->show();
             labelWalletEncryptionIcon->setPixmap(
                 platformStyle->SingleColorIcon(":/icons/lock_closed")
                     .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
             labelWalletEncryptionIcon->setToolTip(
                 tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
             encryptWalletAction->setChecked(true);
             changePassphraseAction->setEnabled(true);
             encryptWalletAction->setEnabled(
                 false); // TODO: decrypt currently not supported
             break;
     }
 }
 
 void BitcoinGUI::updateWalletStatus() {
     if (!walletFrame) {
         return;
     }
     WalletView *const walletView = walletFrame->currentWalletView();
     if (!walletView) {
         return;
     }
     WalletModel *const walletModel = walletView->getWalletModel();
     setEncryptionStatus(walletModel->getEncryptionStatus());
     setHDStatus(walletModel->wallet().hdEnabled());
 }
 #endif // ENABLE_WALLET
 
 void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden) {
     if (!clientModel) {
         return;
     }
 
     // activateWindow() (sometimes) helps with keyboard focus on Windows
     if (isHidden()) {
         show();
         activateWindow();
     } else if (isMinimized()) {
         showNormal();
         activateWindow();
     } else if (GUIUtil::isObscured(this)) {
         raise();
         activateWindow();
     } else if (fToggleHidden) {
         hide();
     }
 }
 
 void BitcoinGUI::toggleHidden() {
     showNormalIfMinimized(true);
 }
 
 void BitcoinGUI::detectShutdown() {
     if (m_node.shutdownRequested()) {
         if (rpcConsole) {
             rpcConsole->hide();
         }
         qApp->quit();
     }
 }
 
 void BitcoinGUI::showProgress(const QString &title, int nProgress) {
     if (nProgress == 0) {
         progressDialog = new QProgressDialog(title, "", 0, 100);
         progressDialog->setWindowModality(Qt::ApplicationModal);
         progressDialog->setMinimumDuration(0);
         progressDialog->setCancelButton(0);
         progressDialog->setAutoClose(false);
         progressDialog->setValue(0);
     } else if (progressDialog) {
         if (nProgress == 100) {
             progressDialog->close();
             progressDialog->deleteLater();
         } else {
             progressDialog->setValue(nProgress);
         }
     }
 }
 
 void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon) {
     if (trayIcon) {
         trayIcon->setVisible(!fHideTrayIcon);
     }
 }
 
 void BitcoinGUI::showModalOverlay() {
     if (modalOverlay &&
         (progressBar->isVisible() || modalOverlay->isLayerVisible())) {
         modalOverlay->toggleVisibility();
     }
 }
 
 static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string &message,
                                  const std::string &caption,
                                  unsigned int style) {
     bool modal = (style & CClientUIInterface::MODAL);
     // The SECURE flag has no effect in the Qt GUI.
     // bool secure = (style & CClientUIInterface::SECURE);
     style &= ~CClientUIInterface::SECURE;
     bool ret = false;
     // In case of modal message, use blocking connection to wait for user to
     // click a button
     QMetaObject::invokeMethod(gui, "message",
                               modal ? GUIUtil::blockingGUIThreadConnection()
                                     : Qt::QueuedConnection,
                               Q_ARG(QString, QString::fromStdString(caption)),
                               Q_ARG(QString, QString::fromStdString(message)),
                               Q_ARG(unsigned int, style), Q_ARG(bool *, &ret));
     return ret;
 }
 
 void BitcoinGUI::subscribeToCoreSignals() {
     // Connect signals to client
     m_handler_message_box = m_node.handleMessageBox(
         boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
     m_handler_question = m_node.handleQuestion(
         boost::bind(ThreadSafeMessageBox, this, _1, _3, _4));
 }
 
 void BitcoinGUI::unsubscribeFromCoreSignals() {
     // Disconnect signals from client
     m_handler_message_box->disconnect();
     m_handler_question->disconnect();
 }
 
 void BitcoinGUI::toggleNetworkActive() {
     m_node.setNetworkActive(!m_node.getNetworkActive());
 }
 
 UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(
     const PlatformStyle *platformStyle)
     : optionsModel(0), menu(0) {
     createContextMenu();
     setToolTip(tr("Unit to show amounts in. Click to select another unit."));
     QList<BitcoinUnits::Unit> units = BitcoinUnits::availableUnits();
     int max_width = 0;
     const QFontMetrics fm(font());
     for (const BitcoinUnits::Unit unit : units) {
         max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit)));
     }
     setMinimumSize(max_width, 0);
     setAlignment(Qt::AlignRight | Qt::AlignVCenter);
     setStyleSheet(QString("QLabel { color : %1 }")
                       .arg(platformStyle->SingleColor().name()));
 }
 
 /** So that it responds to button clicks */
 void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event) {
     onDisplayUnitsClicked(event->pos());
 }
 
 /** Creates context menu, its actions, and wires up all the relevant signals for
  * mouse events. */
 void UnitDisplayStatusBarControl::createContextMenu() {
     menu = new QMenu(this);
     for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits()) {
         QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
         menuAction->setData(QVariant(u));
         menu->addAction(menuAction);
     }
     connect(menu, SIGNAL(triggered(QAction *)), this,
             SLOT(onMenuSelection(QAction *)));
 }
 
 /** Lets the control know about the Options Model (and its signals) */
 void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel) {
     if (_optionsModel) {
         this->optionsModel = _optionsModel;
 
         // be aware of a display unit change reported by the OptionsModel
         // object.
         connect(_optionsModel, SIGNAL(displayUnitChanged(int)), this,
                 SLOT(updateDisplayUnit(int)));
 
         // initialize the display units label with the current value in the
         // model.
         updateDisplayUnit(_optionsModel->getDisplayUnit());
     }
 }
 
 /** When Display Units are changed on OptionsModel it will refresh the display
  * text of the control on the status bar */
 void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits) {
     setText(BitcoinUnits::name(newUnits));
 }
 
 /** Shows context menu with Display Unit options by the mouse coordinates */
 void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint &point) {
     QPoint globalPos = mapToGlobal(point);
     menu->exec(globalPos);
 }
 
 /** Tells underlying optionsModel to update its current display unit. */
 void UnitDisplayStatusBarControl::onMenuSelection(QAction *action) {
     if (action) {
         optionsModel->setDisplayUnit(action->data());
     }
 }
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index bd8facf6b..aedce1476 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -1,211 +1,216 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <qt/transactionrecord.h>
 
 #include <chain.h>
 #include <consensus/consensus.h>
 #include <dstencode.h>
 #include <interfaces/wallet.h>
 #include <timedata.h>
 #include <validation.h>
 #include <wallet/finaltx.h>
 
+#include <QDateTime>
+
 #include <cstdint>
 
 /**
  * Return positive answer if transaction should be shown in list.
  */
 bool TransactionRecord::showTransaction() {
     // There are currently no cases where we hide transactions, but we may want
     // to use this in the future for things like RBF.
     return true;
 }
 
 /**
  * Decompose CWallet transaction to model transaction records.
  */
 QList<TransactionRecord>
 TransactionRecord::decomposeTransaction(const interfaces::WalletTx &wtx) {
     QList<TransactionRecord> parts;
     int64_t nTime = wtx.time;
     Amount nCredit = wtx.credit;
     Amount nDebit = wtx.debit;
     Amount nNet = nCredit - nDebit;
     const TxId &txid = wtx.tx->GetId();
     std::map<std::string, std::string> mapValue = wtx.value_map;
 
     if (nNet > Amount::zero() || wtx.is_coinbase) {
         //
         // Credit
         //
         for (size_t i = 0; i < wtx.tx->vout.size(); i++) {
             const CTxOut &txout = wtx.tx->vout[i];
             isminetype mine = wtx.txout_is_mine[i];
             if (mine) {
                 TransactionRecord sub(txid, nTime);
                 CTxDestination address;
                 sub.idx = i; // vout index
                 sub.credit = txout.nValue;
                 sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY;
                 if (wtx.txout_address_is_mine[i]) {
                     // Received by Bitcoin Address
                     sub.type = TransactionRecord::RecvWithAddress;
                     sub.address = EncodeDestination(wtx.txout_address[i]);
                 } else {
                     // Received by IP connection (deprecated features), or a
                     // multisignature or other non-simple transaction
                     sub.type = TransactionRecord::RecvFromOther;
                     sub.address = mapValue["from"];
                 }
                 if (wtx.is_coinbase) {
                     // Generated
                     sub.type = TransactionRecord::Generated;
                 }
 
                 parts.append(sub);
             }
         }
     } else {
         bool involvesWatchAddress = false;
         isminetype fAllFromMe = ISMINE_SPENDABLE;
         for (isminetype mine : wtx.txin_is_mine) {
             if (mine & ISMINE_WATCH_ONLY) {
                 involvesWatchAddress = true;
             }
             if (fAllFromMe > mine) {
                 fAllFromMe = mine;
             }
         }
 
         isminetype fAllToMe = ISMINE_SPENDABLE;
         for (isminetype mine : wtx.txout_is_mine) {
             if (mine & ISMINE_WATCH_ONLY) {
                 involvesWatchAddress = true;
             }
             if (fAllToMe > mine) {
                 fAllToMe = mine;
             }
         }
 
         if (fAllFromMe && fAllToMe) {
             // Payment to self
             Amount nChange = wtx.change;
 
             parts.append(TransactionRecord(
                 txid, nTime, TransactionRecord::SendToSelf, "",
                 -1 * (nDebit - nChange), (nCredit - nChange)));
             // maybe pass to TransactionRecord as constructor argument
             parts.last().involvesWatchAddress = involvesWatchAddress;
         } else if (fAllFromMe) {
             //
             // Debit
             //
             Amount nTxFee = nDebit - wtx.tx->GetValueOut();
 
             for (size_t nOut = 0; nOut < wtx.tx->vout.size(); nOut++) {
                 const CTxOut &txout = wtx.tx->vout[nOut];
                 TransactionRecord sub(txid, nTime);
                 sub.idx = nOut;
                 sub.involvesWatchAddress = involvesWatchAddress;
 
                 if (wtx.txout_is_mine[nOut]) {
                     // Ignore parts sent to self, as this is usually the change
                     // from a transaction sent back to our own address.
                     continue;
                 }
 
                 if (!boost::get<CNoDestination>(&wtx.txout_address[nOut])) {
                     // Sent to Bitcoin Address
                     sub.type = TransactionRecord::SendToAddress;
                     sub.address = EncodeDestination(wtx.txout_address[nOut]);
                 } else {
                     // Sent to IP, or other non-address transaction like OP_EVAL
                     sub.type = TransactionRecord::SendToOther;
                     sub.address = mapValue["to"];
                 }
 
                 Amount nValue = txout.nValue;
                 /* Add fee to first output */
                 if (nTxFee > Amount::zero()) {
                     nValue += nTxFee;
                     nTxFee = Amount::zero();
                 }
                 sub.debit = -1 * nValue;
 
                 parts.append(sub);
             }
         } else {
             //
             // Mixed debit transaction, can't break down payees
             //
             parts.append(TransactionRecord(txid, nTime,
                                            TransactionRecord::Other, "", nNet,
                                            Amount::zero()));
             parts.last().involvesWatchAddress = involvesWatchAddress;
         }
     }
 
     return parts;
 }
 
 void TransactionRecord::updateStatus(const interfaces::WalletTxStatus &wtx,
-                                     int numBlocks) {
+                                     int numBlocks, int64_t block_time) {
     // Determine transaction status
 
     // Sort order, unrecorded transactions sort to the top
     status.sortKey = strprintf("%010d-%01d-%010u-%03d", wtx.block_height,
                                wtx.is_coinbase ? 1 : 0, wtx.time_received, idx);
     status.countsForBalance = wtx.is_trusted && !(wtx.blocks_to_maturity > 0);
     status.depth = wtx.depth_in_main_chain;
     status.cur_num_blocks = numBlocks;
 
-    if (!wtx.is_final) {
+    const bool up_to_date =
+        (int64_t(QDateTime::currentMSecsSinceEpoch()) / 1000 - block_time <
+         MAX_BLOCK_TIME_GAP);
+    if (up_to_date && !wtx.is_final) {
         if (wtx.lock_time < LOCKTIME_THRESHOLD) {
             status.status = TransactionStatus::OpenUntilBlock;
             status.open_for = wtx.lock_time - numBlocks;
         } else {
             status.status = TransactionStatus::OpenUntilDate;
             status.open_for = wtx.lock_time;
         }
     } else if (type == TransactionRecord::Generated) {
         // For generated transactions, determine maturity
         if (wtx.blocks_to_maturity > 0) {
             status.status = TransactionStatus::Immature;
 
             if (wtx.is_in_main_chain) {
                 status.matures_in = wtx.blocks_to_maturity;
             } else {
                 status.status = TransactionStatus::NotAccepted;
             }
         } else {
             status.status = TransactionStatus::Confirmed;
         }
     } else {
         if (status.depth < 0) {
             status.status = TransactionStatus::Conflicted;
         } else if (status.depth == 0) {
             status.status = TransactionStatus::Unconfirmed;
             if (wtx.is_abandoned) {
                 status.status = TransactionStatus::Abandoned;
             }
         } else if (status.depth < RecommendedNumConfirmations) {
             status.status = TransactionStatus::Confirming;
         } else {
             status.status = TransactionStatus::Confirmed;
         }
     }
 }
 
 bool TransactionRecord::statusUpdateNeeded(int numBlocks) const {
     return status.cur_num_blocks != numBlocks;
 }
 
 QString TransactionRecord::getTxID() const {
     return QString::fromStdString(txid.ToString());
 }
 
 int TransactionRecord::getOutputIndex() const {
     return idx;
 }
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index c1d0b0b09..8660e0ef3 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -1,154 +1,155 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_QT_TRANSACTIONRECORD_H
 #define BITCOIN_QT_TRANSACTIONRECORD_H
 
 #include <amount.h>
 #include <primitives/txid.h>
 
 #include <QList>
 #include <QString>
 
 namespace interfaces {
 class Node;
 class Wallet;
 struct WalletTx;
 struct WalletTxStatus;
 }
 
 /**
  * UI model for transaction status. The transaction status is the part of a
  * transaction that will change over time.
  */
 class TransactionStatus {
 public:
     TransactionStatus()
         : countsForBalance(false), sortKey(""), matures_in(0),
           status(Unconfirmed), depth(0), open_for(0), cur_num_blocks(-1) {}
 
     enum Status {
         /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx)
          **/
         Confirmed,
         /// Normal (sent/received) transactions
         /**< Transaction not yet final, waiting for date */
         OpenUntilDate,
         /**< Transaction not yet final, waiting for block */
         OpenUntilBlock,
         /**< Not yet mined into a block **/
         Unconfirmed,
         /**< Confirmed, but waiting for the recommended number of confirmations
          **/
         Confirming,
         /**< Conflicts with other transaction or mempool **/
         Conflicted,
         /**< Abandoned from the wallet **/
         Abandoned,
         /// Generated (mined) transactions
         /**< Mined but waiting for maturity */
         Immature,
         /**< Mined but not accepted */
         NotAccepted
     };
 
     /// Transaction counts towards available balance
     bool countsForBalance;
     /// Sorting key based on status
     std::string sortKey;
 
     /** @name Generated (mined) transactions
        @{*/
     int matures_in;
     /**@}*/
 
     /** @name Reported status
        @{*/
     Status status;
     qint64 depth;
     /**< Timestamp if status==OpenUntilDate, otherwise number of additional
      * blocks that need to be mined before finalization */
     qint64 open_for;
 
     /**@}*/
 
     /** Current number of blocks (to know whether cached status is still valid)
      */
     int cur_num_blocks;
 };
 
 /**
  * UI model for a transaction. A core transaction can be represented by multiple
  * UI transactions if it has multiple outputs.
  */
 class TransactionRecord {
 public:
     enum Type {
         Other,
         Generated,
         SendToAddress,
         SendToOther,
         RecvWithAddress,
         RecvFromOther,
         SendToSelf
     };
 
     /** Number of confirmation recommended for accepting a transaction */
     static const int RecommendedNumConfirmations = 6;
 
     TransactionRecord()
         : txid(), time(0), type(Other), address(""), debit(), credit(), idx(0) {
     }
 
     TransactionRecord(TxId _txid, qint64 _time)
         : txid(_txid), time(_time), type(Other), address(""), debit(), credit(),
           idx(0) {}
 
     TransactionRecord(TxId _txid, qint64 _time, Type _type,
                       const std::string &_address, const Amount _debit,
                       const Amount _credit)
         : txid(_txid), time(_time), type(_type), address(_address),
           debit(_debit), credit(_credit), idx(0) {}
 
     /** Decompose CWallet transaction to model transaction records.
      */
     static bool showTransaction();
     static QList<TransactionRecord>
     decomposeTransaction(const interfaces::WalletTx &wtx);
 
     /** @name Immutable transaction attributes
       @{*/
     TxId txid;
     qint64 time;
     Type type;
     std::string address;
     Amount debit;
     Amount credit;
     /**@}*/
 
     /** Subtransaction index, for sort key */
     int idx;
 
     /** Status: can change with block chain update */
     TransactionStatus status;
 
     /** Whether the transaction was sent/received with a watch-only address */
     bool involvesWatchAddress;
 
     /** Return the unique identifier for this transaction (part) */
     QString getTxID() const;
 
     /** Return the output index of the subtransaction  */
     int getOutputIndex() const;
 
     /** Update status from core wallet tx.
      */
-    void updateStatus(const interfaces::WalletTxStatus &wtx, int numBlocks);
+    void updateStatus(const interfaces::WalletTxStatus &wtx, int numBlocks,
+                      int64_t block_time);
 
     /** Return whether a status update is needed.
      */
     bool statusUpdateNeeded(int numBlocks) const;
 };
 
 #endif // BITCOIN_QT_TRANSACTIONRECORD_H
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 5a8e2845d..f7daf4df0 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -1,768 +1,769 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <qt/transactiontablemodel.h>
 
 #include <core_io.h>
 #include <interfaces/handler.h>
 #include <interfaces/node.h>
 #include <qt/addresstablemodel.h>
 #include <qt/guiconstants.h>
 #include <qt/guiutil.h>
 #include <qt/optionsmodel.h>
 #include <qt/platformstyle.h>
 #include <qt/transactiondesc.h>
 #include <qt/transactionrecord.h>
 #include <qt/walletmodel.h>
 #include <sync.h>
 #include <uint256.h>
 #include <util.h>
 #include <validation.h>
 
 #include <QColor>
 #include <QDateTime>
 #include <QDebug>
 #include <QIcon>
 #include <QList>
 
 // Amount column is right-aligned it contains numbers
 static int column_alignments[] = {
     Qt::AlignLeft | Qt::AlignVCenter, /* status */
     Qt::AlignLeft | Qt::AlignVCenter, /* watchonly */
     Qt::AlignLeft | Qt::AlignVCenter, /* date */
     Qt::AlignLeft | Qt::AlignVCenter, /* type */
     Qt::AlignLeft | Qt::AlignVCenter, /* address */
     Qt::AlignRight | Qt::AlignVCenter /* amount */
 };
 
 // Comparison operator for sort/binary search of model tx list
 struct TxLessThan {
     bool operator()(const TransactionRecord &a,
                     const TransactionRecord &b) const {
         return a.txid < b.txid;
     }
     bool operator()(const TransactionRecord &a, const TxId &b) const {
         return a.txid < b;
     }
     bool operator()(const TxId &a, const TransactionRecord &b) const {
         return a < b.txid;
     }
 };
 
 // Private implementation
 class TransactionTablePriv {
 public:
     TransactionTablePriv(TransactionTableModel *_parent) : parent(_parent) {}
 
     TransactionTableModel *parent;
 
     /* Local cache of wallet.
      * As it is in the same order as the CWallet, by definition this is sorted
      * by sha256.
      */
     QList<TransactionRecord> cachedWallet;
 
     /**
      * Query entire wallet anew from core.
      */
     void refreshWallet(interfaces::Wallet &wallet) {
         qDebug() << "TransactionTablePriv::refreshWallet";
         cachedWallet.clear();
         for (const auto &wtx : wallet.getWalletTxs()) {
             if (TransactionRecord::showTransaction()) {
                 cachedWallet.append(
                     TransactionRecord::decomposeTransaction(wtx));
             }
         }
     }
 
     /**
      * Update our model of the wallet incrementally, to synchronize our model of
      * the wallet with that of the core.
      * Call with transaction that was added, removed or changed.
      */
     void updateWallet(interfaces::Wallet &wallet, const TxId &txid, int status,
                       bool showTransaction) {
         qDebug() << "TransactionTablePriv::updateWallet: " +
                         QString::fromStdString(txid.ToString()) + " " +
                         QString::number(status);
 
         // Find bounds of this transaction in model
         QList<TransactionRecord>::iterator lower = qLowerBound(
             cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
         QList<TransactionRecord>::iterator upper = qUpperBound(
             cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
         int lowerIndex = (lower - cachedWallet.begin());
         int upperIndex = (upper - cachedWallet.begin());
         bool inModel = (lower != upper);
 
         if (status == CT_UPDATED) {
             // Not in model, but want to show, treat as new.
             if (showTransaction && !inModel) {
                 status = CT_NEW;
             }
             // In model, but want to hide, treat as deleted.
             if (!showTransaction && inModel) {
                 status = CT_DELETED;
             }
         }
 
         qDebug() << "    inModel=" + QString::number(inModel) +
                         " Index=" + QString::number(lowerIndex) + "-" +
                         QString::number(upperIndex) +
                         " showTransaction=" + QString::number(showTransaction) +
                         " derivedStatus=" + QString::number(status);
 
         switch (status) {
             case CT_NEW:
                 if (inModel) {
                     qWarning() << "TransactionTablePriv::updateWallet: "
                                   "Warning: Got CT_NEW, but transaction is "
                                   "already in model";
                     break;
                 }
                 if (showTransaction) {
                     // Find transaction in wallet
                     interfaces::WalletTx wtx = wallet.getWalletTx(txid);
                     if (!wtx.tx) {
                         qWarning() << "TransactionTablePriv::updateWallet: "
                                       "Warning: Got CT_NEW, but transaction is "
                                       "not in wallet";
                         break;
                     }
                     // Added -- insert at the right position
                     QList<TransactionRecord> toInsert =
                         TransactionRecord::decomposeTransaction(wtx);
                     /* only if something to insert */
                     if (!toInsert.isEmpty()) {
                         parent->beginInsertRows(QModelIndex(), lowerIndex,
                                                 lowerIndex + toInsert.size() -
                                                     1);
                         int insert_idx = lowerIndex;
                         for (const TransactionRecord &rec : toInsert) {
                             cachedWallet.insert(insert_idx, rec);
                             insert_idx += 1;
                         }
                         parent->endInsertRows();
                     }
                 }
                 break;
             case CT_DELETED:
                 if (!inModel) {
                     qWarning() << "TransactionTablePriv::updateWallet: "
                                   "Warning: Got CT_DELETED, but transaction is "
                                   "not in model";
                     break;
                 }
                 // Removed -- remove entire transaction from table
                 parent->beginRemoveRows(QModelIndex(), lowerIndex,
                                         upperIndex - 1);
                 cachedWallet.erase(lower, upper);
                 parent->endRemoveRows();
                 break;
             case CT_UPDATED:
                 // Miscellaneous updates -- nothing to do, status update will
                 // take care of this, and is only computed for visible
                 // transactions.
                 break;
         }
     }
 
     int size() { return cachedWallet.size(); }
 
     TransactionRecord *index(interfaces::Wallet &wallet, int idx) {
         if (idx >= 0 && idx < cachedWallet.size()) {
             TransactionRecord *rec = &cachedWallet[idx];
 
             // Get required locks upfront. This avoids the GUI from getting
             // stuck if the core is holding the locks for a longer time - for
             // example, during a wallet rescan.
             //
             // If a status update is needed (blocks came in since last check),
             // update the status of this transaction from the wallet. Otherwise,
             // simply re-use the cached status.
             interfaces::WalletTxStatus wtx;
             int numBlocks;
-            if (wallet.tryGetTxStatus(rec->txid, wtx, numBlocks) &&
+            int64_t block_time;
+            if (wallet.tryGetTxStatus(rec->txid, wtx, numBlocks, block_time) &&
                 rec->statusUpdateNeeded(numBlocks)) {
-                rec->updateStatus(wtx, numBlocks);
+                rec->updateStatus(wtx, numBlocks, block_time);
             }
             return rec;
         }
         return 0;
     }
 
     QString describe(interfaces::Node &node, interfaces::Wallet &wallet,
                      TransactionRecord *rec, int unit) {
         return TransactionDesc::toHTML(node, wallet, rec, unit);
     }
 
     QString getTxHex(interfaces::Wallet &wallet, TransactionRecord *rec) {
         auto tx = wallet.getTx(rec->txid);
         if (tx) {
             std::string strHex = EncodeHexTx(*tx);
             return QString::fromStdString(strHex);
         }
         return QString();
     }
 };
 
 TransactionTableModel::TransactionTableModel(
     const PlatformStyle *_platformStyle, WalletModel *parent)
     : QAbstractTableModel(parent), walletModel(parent),
       priv(new TransactionTablePriv(this)),
       fProcessingQueuedTransactions(false), platformStyle(_platformStyle) {
     columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label")
             << BitcoinUnits::getAmountColumnTitle(
                    walletModel->getOptionsModel()->getDisplayUnit());
     priv->refreshWallet(walletModel->wallet());
 
     connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)),
             this, SLOT(updateDisplayUnit()));
 
     subscribeToCoreSignals();
 }
 
 TransactionTableModel::~TransactionTableModel() {
     unsubscribeFromCoreSignals();
     delete priv;
 }
 
 /** Updates the column title to "Amount (DisplayUnit)" and emits
  * headerDataChanged() signal for table headers to react. */
 void TransactionTableModel::updateAmountColumnTitle() {
     columns[Amount] = BitcoinUnits::getAmountColumnTitle(
         walletModel->getOptionsModel()->getDisplayUnit());
     Q_EMIT headerDataChanged(Qt::Horizontal, Amount, Amount);
 }
 
 void TransactionTableModel::updateTransaction(const QString &hash, int status,
                                               bool showTransaction) {
     TxId updated;
     updated.SetHex(hash.toStdString());
 
     priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
 }
 
 void TransactionTableModel::updateConfirmations() {
     // Blocks came in since last poll.
     // Invalidate status (number of confirmations) and (possibly) description
     // for all rows. Qt is smart enough to only actually request the data for
     // the visible rows.
     Q_EMIT dataChanged(index(0, Status), index(priv->size() - 1, Status));
     Q_EMIT dataChanged(index(0, ToAddress), index(priv->size() - 1, ToAddress));
 }
 
 int TransactionTableModel::rowCount(const QModelIndex &parent) const {
     Q_UNUSED(parent);
     return priv->size();
 }
 
 int TransactionTableModel::columnCount(const QModelIndex &parent) const {
     Q_UNUSED(parent);
     return columns.length();
 }
 
 QString
 TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) const {
     QString status;
 
     switch (wtx->status.status) {
         case TransactionStatus::OpenUntilBlock:
             status = tr("Open for %n more block(s)", "", wtx->status.open_for);
             break;
         case TransactionStatus::OpenUntilDate:
             status = tr("Open until %1")
                          .arg(GUIUtil::dateTimeStr(wtx->status.open_for));
             break;
         case TransactionStatus::Unconfirmed:
             status = tr("Unconfirmed");
             break;
         case TransactionStatus::Abandoned:
             status = tr("Abandoned");
             break;
         case TransactionStatus::Confirming:
             status = tr("Confirming (%1 of %2 recommended confirmations)")
                          .arg(wtx->status.depth)
                          .arg(TransactionRecord::RecommendedNumConfirmations);
             break;
         case TransactionStatus::Confirmed:
             status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
             break;
         case TransactionStatus::Conflicted:
             status = tr("Conflicted");
             break;
         case TransactionStatus::Immature:
             status =
                 tr("Immature (%1 confirmations, will be available after %2)")
                     .arg(wtx->status.depth)
                     .arg(wtx->status.depth + wtx->status.matures_in);
             break;
         case TransactionStatus::NotAccepted:
             status = tr("Generated but not accepted");
             break;
     }
 
     return status;
 }
 
 QString
 TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const {
     if (wtx->time) {
         return GUIUtil::dateTimeStr(wtx->time);
     }
     return QString();
 }
 
 /**
  * Look up address in address book, if found return label (address)  otherwise
  * just return (address)
  */
 QString TransactionTableModel::lookupAddress(const std::string &address,
                                              bool tooltip) const {
     QString label = walletModel->getAddressTableModel()->labelForAddress(
         QString::fromStdString(address));
     QString description;
     if (!label.isEmpty()) {
         description += label;
     }
     if (label.isEmpty() || tooltip) {
         description +=
             QString(" (") + QString::fromStdString(address) + QString(")");
     }
     return description;
 }
 
 QString
 TransactionTableModel::formatTxType(const TransactionRecord *wtx) const {
     switch (wtx->type) {
         case TransactionRecord::RecvWithAddress:
             return tr("Received with");
         case TransactionRecord::RecvFromOther:
             return tr("Received from");
         case TransactionRecord::SendToAddress:
         case TransactionRecord::SendToOther:
             return tr("Sent to");
         case TransactionRecord::SendToSelf:
             return tr("Payment to yourself");
         case TransactionRecord::Generated:
             return tr("Mined");
         default:
             return QString();
     }
 }
 
 QVariant
 TransactionTableModel::txAddressDecoration(const TransactionRecord *wtx) const {
     switch (wtx->type) {
         case TransactionRecord::Generated:
             return QIcon(":/icons/tx_mined");
         case TransactionRecord::RecvWithAddress:
         case TransactionRecord::RecvFromOther:
             return QIcon(":/icons/tx_input");
         case TransactionRecord::SendToAddress:
         case TransactionRecord::SendToOther:
             return QIcon(":/icons/tx_output");
         default:
             return QIcon(":/icons/tx_inout");
     }
 }
 
 QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx,
                                                  bool tooltip) const {
     QString watchAddress;
     if (tooltip) {
         // Mark transactions involving watch-only addresses by adding "
         // (watch-only)"
         watchAddress = wtx->involvesWatchAddress
                            ? QString(" (") + tr("watch-only") + QString(")")
                            : "";
     }
 
     switch (wtx->type) {
         case TransactionRecord::RecvFromOther:
             return QString::fromStdString(wtx->address) + watchAddress;
         case TransactionRecord::RecvWithAddress:
         case TransactionRecord::SendToAddress:
         case TransactionRecord::Generated:
             return lookupAddress(wtx->address, tooltip) + watchAddress;
         case TransactionRecord::SendToOther:
             return QString::fromStdString(wtx->address) + watchAddress;
         case TransactionRecord::SendToSelf:
         default:
             return tr("(n/a)") + watchAddress;
     }
 }
 
 QVariant
 TransactionTableModel::addressColor(const TransactionRecord *wtx) const {
     // Show addresses without label in a less visible color
     switch (wtx->type) {
         case TransactionRecord::RecvWithAddress:
         case TransactionRecord::SendToAddress:
         case TransactionRecord::Generated: {
             QString label =
                 walletModel->getAddressTableModel()->labelForAddress(
                     QString::fromStdString(wtx->address));
             if (label.isEmpty()) return COLOR_BAREADDRESS;
         } break;
         case TransactionRecord::SendToSelf:
             return COLOR_BAREADDRESS;
         default:
             break;
     }
     return QVariant();
 }
 
 QString TransactionTableModel::formatTxAmount(
     const TransactionRecord *wtx, bool showUnconfirmed,
     BitcoinUnits::SeparatorStyle separators) const {
     QString str =
         BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(),
                              wtx->credit + wtx->debit, false, separators);
     if (showUnconfirmed) {
         if (!wtx->status.countsForBalance) {
             str = QString("[") + str + QString("]");
         }
     }
     return QString(str);
 }
 
 QVariant
 TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) const {
     switch (wtx->status.status) {
         case TransactionStatus::OpenUntilBlock:
         case TransactionStatus::OpenUntilDate:
             return COLOR_TX_STATUS_OPENUNTILDATE;
         case TransactionStatus::Unconfirmed:
             return QIcon(":/icons/transaction_0");
         case TransactionStatus::Abandoned:
             return QIcon(":/icons/transaction_abandoned");
         case TransactionStatus::Confirming:
             switch (wtx->status.depth) {
                 case 1:
                     return QIcon(":/icons/transaction_1");
                 case 2:
                     return QIcon(":/icons/transaction_2");
                 case 3:
                     return QIcon(":/icons/transaction_3");
                 case 4:
                     return QIcon(":/icons/transaction_4");
                 default:
                     return QIcon(":/icons/transaction_5");
             };
         case TransactionStatus::Confirmed:
             return QIcon(":/icons/transaction_confirmed");
         case TransactionStatus::Conflicted:
             return QIcon(":/icons/transaction_conflicted");
         case TransactionStatus::Immature: {
             int total = wtx->status.depth + wtx->status.matures_in;
             int part = (wtx->status.depth * 4 / total) + 1;
             return QIcon(QString(":/icons/transaction_%1").arg(part));
         }
         case TransactionStatus::NotAccepted:
             return QIcon(":/icons/transaction_0");
         default:
             return COLOR_BLACK;
     }
 }
 
 QVariant TransactionTableModel::txWatchonlyDecoration(
     const TransactionRecord *wtx) const {
     if (wtx->involvesWatchAddress) {
         return QIcon(":/icons/eye");
     }
 
     return QVariant();
 }
 
 QString
 TransactionTableModel::formatTooltip(const TransactionRecord *rec) const {
     QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
     if (rec->type == TransactionRecord::RecvFromOther ||
         rec->type == TransactionRecord::SendToOther ||
         rec->type == TransactionRecord::SendToAddress ||
         rec->type == TransactionRecord::RecvWithAddress) {
         tooltip += QString(" ") + formatTxToAddress(rec, true);
     }
     return tooltip;
 }
 
 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const {
     if (!index.isValid()) {
         return QVariant();
     }
 
     TransactionRecord *rec =
         static_cast<TransactionRecord *>(index.internalPointer());
 
     switch (role) {
         case RawDecorationRole:
             switch (index.column()) {
                 case Status:
                     return txStatusDecoration(rec);
                 case Watchonly:
                     return txWatchonlyDecoration(rec);
                 case ToAddress:
                     return txAddressDecoration(rec);
             }
             break;
         case Qt::DecorationRole: {
             QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
             return platformStyle->TextColorIcon(icon);
         }
         case Qt::DisplayRole:
             switch (index.column()) {
                 case Date:
                     return formatTxDate(rec);
                 case Type:
                     return formatTxType(rec);
                 case ToAddress:
                     return formatTxToAddress(rec, false);
                 case Amount:
                     return formatTxAmount(rec, true,
                                           BitcoinUnits::separatorAlways);
             }
             break;
         case Qt::EditRole:
             // Edit role is used for sorting, so return the unformatted values
             switch (index.column()) {
                 case Status:
                     return QString::fromStdString(rec->status.sortKey);
                 case Date:
                     return rec->time;
                 case Type:
                     return formatTxType(rec);
                 case Watchonly:
                     return (rec->involvesWatchAddress ? 1 : 0);
                 case ToAddress:
                     return formatTxToAddress(rec, true);
                 case Amount:
                     return qint64((rec->credit + rec->debit) / SATOSHI);
             }
             break;
         case Qt::ToolTipRole:
             return formatTooltip(rec);
         case Qt::TextAlignmentRole:
             return column_alignments[index.column()];
         case Qt::ForegroundRole:
             // Use the "danger" color for abandoned transactions
             if (rec->status.status == TransactionStatus::Abandoned) {
                 return COLOR_TX_STATUS_DANGER;
             }
             // Non-confirmed (but not immature) as transactions are grey
             if (!rec->status.countsForBalance &&
                 rec->status.status != TransactionStatus::Immature) {
                 return COLOR_UNCONFIRMED;
             }
             if (index.column() == Amount &&
                 (rec->credit + rec->debit) < ::Amount::zero()) {
                 return COLOR_NEGATIVE;
             }
             if (index.column() == ToAddress) {
                 return addressColor(rec);
             }
             break;
         case TypeRole:
             return rec->type;
         case DateRole:
             return QDateTime::fromTime_t(static_cast<uint>(rec->time));
         case WatchonlyRole:
             return rec->involvesWatchAddress;
         case WatchonlyDecorationRole:
             return txWatchonlyDecoration(rec);
         case LongDescriptionRole:
             return priv->describe(
                 walletModel->node(), walletModel->wallet(), rec,
                 walletModel->getOptionsModel()->getDisplayUnit());
         case AddressRole:
             return QString::fromStdString(rec->address);
         case LabelRole:
             return walletModel->getAddressTableModel()->labelForAddress(
                 QString::fromStdString(rec->address));
         case AmountRole:
             return qint64((rec->credit + rec->debit) / SATOSHI);
         case TxIDRole:
             return rec->getTxID();
         case TxHashRole:
             return QString::fromStdString(rec->txid.ToString());
         case TxHexRole:
             return priv->getTxHex(walletModel->wallet(), rec);
         case TxPlainTextRole: {
             QString details;
             QDateTime date =
                 QDateTime::fromTime_t(static_cast<uint>(rec->time));
             QString txLabel =
                 walletModel->getAddressTableModel()->labelForAddress(
                     QString::fromStdString(rec->address));
 
             details.append(date.toString("M/d/yy HH:mm"));
             details.append(" ");
             details.append(formatTxStatus(rec));
             details.append(". ");
             if (!formatTxType(rec).isEmpty()) {
                 details.append(formatTxType(rec));
                 details.append(" ");
             }
             if (!rec->address.empty()) {
                 if (txLabel.isEmpty()) {
                     details.append(tr("(no label)") + " ");
                 } else {
                     details.append("(");
                     details.append(txLabel);
                     details.append(") ");
                 }
                 details.append(QString::fromStdString(rec->address));
                 details.append(" ");
             }
             details.append(
                 formatTxAmount(rec, false, BitcoinUnits::separatorNever));
             return details;
         }
         case ConfirmedRole:
             return rec->status.countsForBalance;
         case FormattedAmountRole:
             // Used for copy/export, so don't include separators
             return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
         case StatusRole:
             return rec->status.status;
     }
     return QVariant();
 }
 
 QVariant TransactionTableModel::headerData(int section,
                                            Qt::Orientation orientation,
                                            int role) const {
     if (orientation == Qt::Horizontal) {
         if (role == Qt::DisplayRole) {
             return columns[section];
         } else if (role == Qt::TextAlignmentRole) {
             return column_alignments[section];
         } else if (role == Qt::ToolTipRole) {
             switch (section) {
                 case Status:
                     return tr("Transaction status. Hover over this field to "
                               "show number of confirmations.");
                 case Date:
                     return tr(
                         "Date and time that the transaction was received.");
                 case Type:
                     return tr("Type of transaction.");
                 case Watchonly:
                     return tr("Whether or not a watch-only address is involved "
                               "in this transaction.");
                 case ToAddress:
                     return tr(
                         "User-defined intent/purpose of the transaction.");
                 case Amount:
                     return tr("Amount removed from or added to balance.");
             }
         }
     }
     return QVariant();
 }
 
 QModelIndex TransactionTableModel::index(int row, int column,
                                          const QModelIndex &parent) const {
     Q_UNUSED(parent);
     TransactionRecord *data = priv->index(walletModel->wallet(), row);
     if (data) {
         return createIndex(row, column,
                            priv->index(walletModel->wallet(), row));
     }
     return QModelIndex();
 }
 
 void TransactionTableModel::updateDisplayUnit() {
     // emit dataChanged to update Amount column with the current unit
     updateAmountColumnTitle();
     Q_EMIT dataChanged(index(0, Amount), index(priv->size() - 1, Amount));
 }
 
 // queue notifications to show a non freezing progress dialog e.g. for rescan
 struct TransactionNotification {
 public:
     TransactionNotification() {}
     TransactionNotification(TxId _txid, ChangeType _status,
                             bool _showTransaction)
         : txid(_txid), status(_status), showTransaction(_showTransaction) {}
 
     void invoke(QObject *ttm) {
         QString strHash = QString::fromStdString(txid.GetHex());
         qDebug() << "NotifyTransactionChanged: " + strHash +
                         " status= " + QString::number(status);
         QMetaObject::invokeMethod(ttm, "updateTransaction",
                                   Qt::QueuedConnection, Q_ARG(QString, strHash),
                                   Q_ARG(int, status),
                                   Q_ARG(bool, showTransaction));
     }
 
 private:
     TxId txid;
     ChangeType status;
     bool showTransaction;
 };
 
 static bool fQueueNotifications = false;
 static std::vector<TransactionNotification> vQueueNotifications;
 
 static void NotifyTransactionChanged(TransactionTableModel *ttm,
                                      const TxId &txid, ChangeType status) {
     // Find transaction in wallet
     // Determine whether to show transaction or not (determine this here so that
     // no relocking is needed in GUI thread)
     bool showTransaction = TransactionRecord::showTransaction();
 
     TransactionNotification notification(txid, status, showTransaction);
 
     if (fQueueNotifications) {
         vQueueNotifications.push_back(notification);
         return;
     }
     notification.invoke(ttm);
 }
 
 static void ShowProgress(TransactionTableModel *ttm, const std::string &title,
                          int nProgress) {
     if (nProgress == 0) {
         fQueueNotifications = true;
     }
 
     if (nProgress == 100) {
         fQueueNotifications = false;
         if (vQueueNotifications.size() > 10) {
             // prevent balloon spam, show maximum 10 balloons
             QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions",
                                       Qt::QueuedConnection, Q_ARG(bool, true));
         }
 
         for (size_t i = 0; i < vQueueNotifications.size(); ++i) {
             if (vQueueNotifications.size() - i <= 10) {
                 QMetaObject::invokeMethod(
                     ttm, "setProcessingQueuedTransactions",
                     Qt::QueuedConnection, Q_ARG(bool, false));
             }
 
             vQueueNotifications[i].invoke(ttm);
         }
 
         // clear
         std::vector<TransactionNotification>().swap(vQueueNotifications);
     }
 }
 
 void TransactionTableModel::subscribeToCoreSignals() {
     // Connect signals to wallet
     m_handler_transaction_changed =
         walletModel->wallet().handleTransactionChanged(
             boost::bind(NotifyTransactionChanged, this, _1, _2));
     m_handler_show_progress = walletModel->wallet().handleShowProgress(
         boost::bind(ShowProgress, this, _1, _2));
 }
 
 void TransactionTableModel::unsubscribeFromCoreSignals() {
     // Disconnect signals from wallet
     m_handler_transaction_changed->disconnect();
     m_handler_show_progress->disconnect();
 }