diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index ef047a0f26..4ea6b4b0de 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -39,17 +39,6 @@ void CActiveMasternode::ManageStatus() service = CService(strMasterNodeAddr); } - if( - (Params().NetworkID() == CChainParams::TESTNET && service.GetPort() != 19999) || - (Params().NetworkID() == CChainParams::REGTEST && service.GetPort() != 19999) || - (Params().NetworkID() == CChainParams::MAIN && service.GetPort() != 9999) ) - { - notCapableReason = "Invalid port: " + boost::lexical_cast(service.GetPort()) + " -only 9999 or 19999 are supported."; - status = MASTERNODE_NOT_CAPABLE; - LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str()); - return; - } - LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString().c_str()); if(Params().NetworkID() != CChainParams::REGTEST){ diff --git a/src/init.cpp b/src/init.cpp index 269853e88e..b963a3fbbb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1199,7 +1199,7 @@ bool AppInit2(boost::thread_group& threadGroup) bool fEnableInstantX = GetBoolArg("-enableinstantx", true); if(fEnableInstantX){ - nInstantXDepth = GetArg("-instantxdepth", 1); + nInstantXDepth = GetArg("-instantxdepth", 5); if(nInstantXDepth > 60) nInstantXDepth = 60; if(nInstantXDepth < 0) nAnonymizeDarkcoinAmount = 0; } else { diff --git a/src/instantx.cpp b/src/instantx.cpp index 4fe7f25b11..e254a52706 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -18,10 +18,9 @@ using namespace std; using namespace boost; -std::vector vecTxLocks; - std::map mapTxLockReq; std::map mapTxLockReqRejected; +std::map mapTxLockVote; std::map mapTxLocks; #define INSTANTX_SIGNATURES_REQUIRED 2 @@ -51,15 +50,15 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& } int nTxAge = GetInputAge(tx.vin[0]); - if(nTxAge < 5){ - LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %s\n", tx.GetHash().ToString().c_str()); + if(nTxAge <= 0){ + LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %d / %s\n", nTxAge, tx.GetHash().ToString().c_str()); return; } int nBlockHeight = chainActive.Tip()->nHeight - nTxAge; //calculate the height BOOST_FOREACH(const CTxOut o, tx.vout){ if(!o.scriptPubKey.IsNormalPaymentScript()){ - LogPrintf ("ProcessMessageInstantX::txlreq - Invalid Script %s\n", tx.ToString().c_str()); + printf ("ProcessMessageInstantX::txlreq - Invalid Script %s\n", tx.ToString().c_str()); return; } } @@ -104,133 +103,35 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& CConsensusVote ctx; vRecv >> ctx; - ProcessConsensusVote(ctx); - - return; - } - else if (strCommand == "txlock") //InstantX Lock Transaction Inputs - { - LogPrintf("ProcessMessageInstantX::txlock\n"); - - CDataStream vMsg(vRecv); - CTransactionLock ctxl; - vRecv >> ctxl; - - CInv inv(MSG_TXLOCK, ctxl.GetHash()); + CInv inv(MSG_TXLOCK_VOTE, ctx.GetHash()); pfrom->AddInventoryKnown(inv); - LogPrintf(" -- ProcessMessageInstantX::txlock %d %s\n", mapTxLocks.count(inv.hash), inv.hash.ToString().c_str()); - - - if(!mapTxLocks.count(inv.hash)){ - if(ctxl.CountSignatures() < INSTANTX_SIGNATURES_REQUIRED){ - LogPrintf("InstantX::txlock - not enough signatures\n"); - return; - } - if(!ctxl.SignaturesValid()){ - LogPrintf("InstantX::txlock - got invalid TransactionLock, rejected\n"); - return; - } - if(!ctxl.AllInFavor()){ - LogPrintf("InstantX::txlock - not all in favor of lock, rejected\n"); - return; - } - - BOOST_FOREACH(const CTxOut o, ctxl.tx.vout){ - if(!o.scriptPubKey.IsNormalPaymentScript()){ - LogPrintf ("ProcessMessageInstantX::cxlock - Invalid Script %s\n", ctxl.tx.ToString().c_str()); - return; - } - } - mapTxLocks.insert(make_pair(inv.hash, ctxl)); - - //we should have the lock request in place - if(!mapTxLockReq.count(inv.hash)){ - //if we don't - bool fMissingInputs = false; - CValidationState state; - - if (AcceptToMemoryPool(mempool, state, ctxl.tx, true, &fMissingInputs)) - { - mapTxLockReq.insert(make_pair(inv.hash, ctxl.tx)); - - LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : accepted (no reversing) %s\n", - pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), - ctxl.tx.GetHash().ToString().c_str() - ); - - } else { - // we have a conflicting transaction (an attack) - CValidationState state; - DisconnectBlockAndInputs(state, ctxl.tx); - - if (AcceptToMemoryPool(mempool, state, ctxl.tx, true, &fMissingInputs)) - { - mapTxLockReq.insert(make_pair(inv.hash, ctxl.tx)); - - LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : accepted (reversed) %s\n", - pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), - ctxl.tx.GetHash().ToString().c_str() - ); - } else { - LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : rejected (reversed) %s\n", - pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), - ctxl.tx.GetHash().ToString().c_str() - ); - } - } - } - - //broadcast the new lock - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - if(!pnode->fRelayTxes) - continue; - - pnode->PushMessage("txlock", ctxl); - } - - pwalletMain->UpdatedTransaction(ctxl.GetHash()); - - LogPrintf("InstantX :: Got Transaction Lock: %s %s : accepted %s\n", - pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), - ctxl.GetHash().ToString().c_str() - ); + if(mapTxLockVote.count(inv.hash)){ + return; } + + mapTxLockVote.insert(make_pair(inv.hash, 1)); + + ProcessConsensusVote(ctx); + + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + pnode->PushMessage("txlvote", ctx); + } + return; } } // check if we need to vote on this transaction void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight) { - if(!fMasterNode) { - LogPrintf("InstantX::DoConsensusVote - Not masternode\n"); - return; - } - - int winner = GetCurrentMasterNode(1, nBlockHeight); - int n = GetMasternodeRank(activeMasternode.vin, nBlockHeight, MIN_INSTANTX_PROTO_VERSION); - - if(n == -1 || winner == -1) - { - LogPrintf("InstantX::DoConsensusVote - Unknown Masternode\n"); - return; - } - - if(n == 1) - { // winner, I'll be keeping track of this - LogPrintf("InstantX::DoConsensusVote - Managing Masternode\n"); - CTransactionLock newLock; - newLock.nBlockHeight = nBlockHeight; - newLock.tx = tx; - vecTxLocks.push_back(newLock); - } + if(!fMasterNode) return; CConsensusVote ctx; ctx.vinMasternode = activeMasternode.vin; ctx.approved = approved; - ctx.txHash = tx.GetHash(); + ctx.tx = tx; ctx.nBlockHeight = nBlockHeight; if(!ctx.Sign()){ LogPrintf("InstantX::DoConsensusVote - Failed to sign consensus vote\n"); @@ -241,47 +142,18 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight) return; } + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + //LogPrintf("%s::check -- %s %s\n", vecMasternodes[winner].addr.ToString().c_str(), pnode->addr.ToString().c_str()); - if(n == 1){ //I'm the winner - ProcessConsensusVote(ctx); - } else if(n <= 10){ // not winner, but in the top10 - if(ConnectNode((CAddress)vecMasternodes[winner].addr, NULL, true)){ - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - if(vecMasternodes[winner].addr != pnode->addr) continue; - - pnode->PushMessage("txlvote", ctx); - LogPrintf("InstantX::DoConsensusVote --- connected, sending vote %s\n", pnode->addr.ToString().c_str()); - return; - } - } else { - LogPrintf("InstantX::DoConsensusVote --- error connecting \n"); - return; - } + pnode->PushMessage("txlvote", ctx); } } //received a consensus vote void ProcessConsensusVote(CConsensusVote& ctx) { - if(!fMasterNode) { - LogPrintf("InstantX::ProcessConsensusVote - Not masternode\n"); - return; - } - - int winner = GetCurrentMasterNode(1, ctx.nBlockHeight); - if(winner == -1) { - LogPrintf("InstantX::ProcessConsensusVote - Can't detect winning masternode\n"); - return; - } - - //We're not the winning masternode - if(vecMasternodes[winner].vin != activeMasternode.vin) { - LogPrintf("InstantX::ProcessConsensusVote - I'm not the winning masternode\n"); - return; - } - int n = GetMasternodeRank(ctx.vinMasternode, ctx.nBlockHeight, MIN_INSTANTX_PROTO_VERSION); if(n == -1) @@ -302,26 +174,25 @@ void ProcessConsensusVote(CConsensusVote& ctx) return; } - //compile consessus vote - BOOST_FOREACH(CTransactionLock& ctxl, vecTxLocks){ - if(ctxl.nBlockHeight == ctx.nBlockHeight){ - ctxl.AddSignature(ctx); - if(ctxl.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){ - LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete, broadcasting!\n"); - - CInv inv(MSG_TXLOCK, ctxl.GetHash()); - mapTxLocks.insert(make_pair(inv.hash, ctxl)); - - //broadcast the new lock - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes){ - pnode->PushMessage("txlock", ctxl); - } - } - return; - } + std::map::iterator a = mapTxLocks.find(ctx.tx.GetHash()); + if (a == mapTxLocks.end()){ + CTransactionLock newLock; + newLock.nBlockHeight = ctx.nBlockHeight; + newLock.tx = ctx.tx; + mapTxLocks.insert(make_pair(ctx.tx.GetHash(), newLock)); } + //compile consessus vote + std::map::iterator i = mapTxLocks.find(ctx.tx.GetHash()); + if (i != mapTxLocks.end()){ + (*i).second.AddSignature(ctx); + if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){ + LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete, broadcasting!\n"); + } + return; + } + + return; } @@ -342,11 +213,23 @@ void CleanTransactionLocksList() } +uint256 CConsensusVote::GetHash() const +{ + + std::string str = tx.GetHash().ToString().c_str(); + str += vinMasternode.ToString().c_str(); + str += boost::lexical_cast(nBlockHeight); + str += boost::lexical_cast(approved); + + return Hash(BEGIN(str), END(str)); +} + + bool CConsensusVote::SignatureValid() { std::string errorMessage; - std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast(nBlockHeight) + boost::lexical_cast(approved); - LogPrintf("verify strMessage %s \n", strMessage.c_str()); + std::string strMessage = tx.GetHash().ToString().c_str() + boost::lexical_cast(nBlockHeight) + boost::lexical_cast(approved); + //LogPrintf("verify strMessage %s \n", strMessage.c_str()); int n = GetMasternodeByVin(vinMasternode); @@ -356,16 +239,16 @@ bool CConsensusVote::SignatureValid() return false; } - LogPrintf("verify addr %s \n", vecMasternodes[0].addr.ToString().c_str()); - LogPrintf("verify addr %s \n", vecMasternodes[1].addr.ToString().c_str()); - LogPrintf("verify addr %d %s \n", n, vecMasternodes[n].addr.ToString().c_str()); + //LogPrintf("verify addr %s \n", vecMasternodes[0].addr.ToString().c_str()); + //LogPrintf("verify addr %s \n", vecMasternodes[1].addr.ToString().c_str()); + //LogPrintf("verify addr %d %s \n", n, vecMasternodes[n].addr.ToString().c_str()); CScript pubkey; pubkey.SetDestination(vecMasternodes[n].pubkey2.GetID()); CTxDestination address1; ExtractDestination(pubkey, address1); CBitcoinAddress address2(address1); - LogPrintf("verify pubkey2 %s \n", address2.ToString().c_str()); + //LogPrintf("verify pubkey2 %s \n", address2.ToString().c_str()); if(!darkSendSigner.VerifyMessage(vecMasternodes[n].pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) { LogPrintf("InstantX::CConsensusVote::SignatureValid() - Verify message failed\n"); @@ -381,9 +264,9 @@ bool CConsensusVote::Sign() CKey key2; CPubKey pubkey2; - std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast(nBlockHeight) + boost::lexical_cast(approved); - LogPrintf("signing strMessage %s \n", strMessage.c_str()); - LogPrintf("signing privkey %s \n", strMasterNodePrivKey.c_str()); + std::string strMessage = tx.GetHash().ToString().c_str() + boost::lexical_cast(nBlockHeight) + boost::lexical_cast(approved); + //LogPrintf("signing strMessage %s \n", strMessage.c_str()); + //LogPrintf("signing privkey %s \n", strMasterNodePrivKey.c_str()); if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2)) { @@ -396,7 +279,7 @@ bool CConsensusVote::Sign() CTxDestination address1; ExtractDestination(pubkey, address1); CBitcoinAddress address2(address1); - LogPrintf("signing pubkey2 %s \n", address2.ToString().c_str()); + //LogPrintf("signing pubkey2 %s \n", address2.ToString().c_str()); if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) { LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed"); diff --git a/src/instantx.h b/src/instantx.h index 17934534c8..5a4dd4ea59 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -44,16 +44,18 @@ class CConsensusVote public: CTxIn vinMasternode; bool approved; - uint256 txHash; - std::vector vchMasterNodeSignature; + CTransaction tx; int nBlockHeight; + std::vector vchMasterNodeSignature; + + uint256 GetHash() const; bool SignatureValid(); bool Sign(); IMPLEMENT_SERIALIZE ( - READWRITE(txHash); + READWRITE(tx); READWRITE(vinMasternode); READWRITE(approved); READWRITE(vchMasterNodeSignature); diff --git a/src/main.cpp b/src/main.cpp index dcf11e9b94..804287743a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1156,6 +1156,29 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const return chainActive.Height() - pindex->nHeight + 1; } +int CMerkleTx::IsTransactionLocked() const +{ + if(nInstantXDepth == 0) return 0; + + //printf("mapTxLocks start\n"); + typedef std::map::iterator it_ctxl; + + int found = 0; + for (unsigned int b = 0; b < vout.size(); b++) { + for(it_ctxl it = mapTxLocks.begin(); it != mapTxLocks.end(); it++) { + for (unsigned int a = 0; a < it->second.tx.vout.size(); a++) { + if(vout[b] == it->second.tx.vout[a]) + found++; + } + if(found > 0) break; + } + } + //printf("mapTxLocks end %d %d\n", found , (int)vout.size()); + if(found == (int)vout.size()) return nInstantXDepth; + + return 0; +} + int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const { AssertLockHeld(cs_main); @@ -1163,6 +1186,11 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const if (nResult == 0 && !mempool.exists(GetHash())) return -1; // Not in chain, not in mempool + if (nResult < 6){ + int minConfirms = IsTransactionLocked(); + return minConfirms+nResult; + } + return nResult; } diff --git a/src/main.h b/src/main.h index b5cf90775b..afcb92adc6 100644 --- a/src/main.h +++ b/src/main.h @@ -485,6 +485,7 @@ public: bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; } int GetBlocksToMaturity() const; bool AcceptToMemoryPool(bool fLimitFree=true); + int IsTransactionLocked() const; }; diff --git a/src/masternode.cpp b/src/masternode.cpp index f78dd6269f..1d45f358b3 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -26,7 +26,7 @@ void ProcessMasternodeConnections(){ BOOST_FOREACH(CNode* pnode, vNodes) { //if it's our masternode, let it be - if((CNetAddr)darkSendPool.submittedToMasternode == (CNetAddr)pnode->addr) continue; + if(darkSendPool.submittedToMasternode == pnode->addr) continue; if(pnode->fDarkSendMaster){ LogPrintf("Closing masternode connection %s \n", pnode->addr.ToString().c_str()); @@ -101,11 +101,6 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream return; } - if( - (Params().NetworkID() == CChainParams::TESTNET && addr.GetPort() != 19999) || - (Params().NetworkID() == CChainParams::REGTEST && addr.GetPort() != 19999) || - (Params().NetworkID() == CChainParams::MAIN && addr.GetPort() != 9999)) return; - //search existing masternode list, this is where we update existing masternodes with new dsee broadcasts BOOST_FOREACH(CMasterNode& mn, vecMasternodes) { @@ -269,7 +264,7 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream if(vin == CTxIn()) { //only should ask for this once //local network - if(!pfrom->addr.IsRFC1918()) + if(!pfrom->addr.IsRFC1918() && Params().NetworkID() == CChainParams::MAIN) { std::map::iterator i = askedForMasternodeList.find(pfrom->addr); if (i != askedForMasternodeList.end()) diff --git a/src/masternodeconfig.cpp b/src/masternodeconfig.cpp index 718bb2631e..4f32dd563b 100644 --- a/src/masternodeconfig.cpp +++ b/src/masternodeconfig.cpp @@ -29,11 +29,11 @@ bool CMasternodeConfig::read(std::string& strErr) { return false; } - if(CService(ip).GetPort() != 19999 && CService(ip).GetPort() != 9999) { +/* if(CService(ip).GetPort() != 19999 && CService(ip).GetPort() != 9999) { strErr = "Invalid port (must be 9999 for mainnet or 19999 for testnet) detected in masternode.conf: " + line; streamConfig.close(); return false; - } + }*/ add(alias, ip, privKey, txHash, outputIndex); } diff --git a/src/net.cpp b/src/net.cpp index c71e0b9dd5..138f6ad696 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -435,7 +435,7 @@ CNode* FindNode(const CService& addr) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) - if((CNetAddr)pnode->addr == (CNetAddr)addr) + if(pnode->addr == addr) return (pnode); return NULL; } diff --git a/src/protocol.h b/src/protocol.h index f3ca6ac0ec..3225159976 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -136,7 +136,7 @@ enum // MSG_FILTERED_BLOCK should not appear in any invs except as a part of getdata. MSG_FILTERED_BLOCK, MSG_TXLOCK_REQUEST, - MSG_TXLOCK, + MSG_TXLOCK_VOTE, }; #endif // __INCLUDED_PROTOCOL_H__ diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index ffed07d075..9ed0dc75f8 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -173,16 +173,7 @@ - - 0 - - - 0 - - - 0 - - + 0 @@ -614,20 +605,11 @@ 0 0 830 - 178 + 149 - - 0 - - - 0 - - - 0 - - + 0 @@ -766,7 +748,7 @@ - false + true InstantX diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index c95bd9ea24..ca7d3332e7 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -128,6 +128,7 @@ OverviewPage::OverviewPage(QWidget *parent) : showingDarkSendMessage = 0; darksendActionCheck = 0; + lastNewBlock = 0; if(fLiteMode){ ui->frameDarksend->setVisible(false); @@ -308,6 +309,10 @@ void OverviewPage::darkSendStatus() if(nBestHeight != darkSendPool.cachedNumBlocks) { + //we we're processing lots of blocks, we'll just leave + if(GetTime() - lastNewBlock < 10) return; + lastNewBlock = GetTime(); + updateDarksendProgress(); QString strSettings(" Rounds"); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 19ba126dcf..a5c30c553b 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -50,6 +50,7 @@ private: qint64 currentUnconfirmedBalance; qint64 currentImmatureBalance; qint64 currentAnonymizedBalance; + qint64 lastNewBlock; int showingDarkSendMessage; int darksendActionCheck; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 2c3fcadf51..434acd1aea 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -31,15 +31,28 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) } else { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) - return tr("%1/offline").arg(nDepth); - else if (nDepth < 6) - return tr("%1/unconfirmed").arg(nDepth); - else - return tr("%1 confirmations").arg(nDepth); + QString strUsingIX = ""; + if(wtx.IsTransactionLocked()){ + int nDepth = wtx.GetDepthInMainChain(); + if (nDepth < 0) + return tr("conflicted"); + else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + return tr("%1/offline (instantx)").arg(nDepth); + else if (nDepth < 6) + return tr("%1/instantx").arg(nDepth); + else + return tr("%1 confirmations (instantx)").arg(nDepth); + } else { + int nDepth = wtx.GetDepthInMainChain(); + if (nDepth < 0) + return tr("conflicted"); + else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + return tr("%1/offline").arg(nDepth); + else if (nDepth < 6) + return tr("%1/unconfirmed").arg(nDepth); + else + return tr("%1 confirmations").arg(nDepth); + } } }