From 186699abff45860774487ef81e686b984a50621c Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 08:24:34 -0700 Subject: [PATCH 01/12] Masternode payment improvements / release notes --- doc/release-notes/release-notes-0.11.1.md | 3 +++ src/masternode.cpp | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/release-notes/release-notes-0.11.1.md b/doc/release-notes/release-notes-0.11.1.md index 69a281ddee..34cddc9ed2 100644 --- a/doc/release-notes/release-notes-0.11.1.md +++ b/doc/release-notes/release-notes-0.11.1.md @@ -16,6 +16,8 @@ and a new version of enforcement compatible with the newer Bitcoin architechure. - Added --instantxdepth, which will show X confirmations when a transaction lock is present - fix coin control crash https://github.com/bitcoin/bitcoin/pull/5700 - always get only confirmed coins by AvailableCoins for every DS relative action +- New languages supported Portuguese, German, Russian, Polish, Spanish, Vietnamese, French, +Italian, Catalan, Chinese, Danish, Finnish, Swedish, Czech, Turkish and Bavarian (and many more) Thanks to who contributed to this release, at least: @@ -23,6 +25,7 @@ Thanks to who contributed to this release, at least: - Vertoe - Udjin - Holger Schinzel +- Raze - Mario Müller - Crowning - Alexandre Devilliers diff --git a/src/masternode.cpp b/src/masternode.cpp index 2b2aa73927..c06d99319e 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -717,6 +717,7 @@ void CMasternodePayments::CleanPaymentList() bool CMasternodePayments::ProcessBlock(int nBlockHeight) { + if(!enabled) return false; CMasternodePaymentWinner winner; @@ -749,7 +750,13 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight) break; } - if(winner.nBlockHeight == 0) return false; //no masternodes available + //if we can't find someone to get paid, pick randomly + if(winner.nBlockHeight == 0 && vecMasternodes.size() > 1) { + winner.score = 0; + winner.nBlockHeight = nBlockHeight; + winner.vin = vecMasternodes[0].vin; + winner.payee.SetDestination(vecMasternodes[0].pubkey.GetID()); + } if(Sign(winner)){ if(AddWinningMasternode(winner)){ From 65612697ca1779226897a1846b102e27464ed33c Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 08:30:00 -0700 Subject: [PATCH 02/12] Added better error messages --- src/wallet.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/wallet.cpp b/src/wallet.cpp index ba4d853fe4..042aefae5c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1851,14 +1851,20 @@ bool CWallet::CreateTransaction(const vector >& vecSend, if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl, coin_type, useIX)) { - if(coin_type == ALL_COINS) - strFailReason = _("Insufficient funds"); - else if (coin_type == ONLY_NONDENOMINATED) - strFailReason = _("Unable to locate enough Darksend non-denominated funds for this transaction"); - else if (coin_type == ONLY_NONDENOMINATED_NOTMN) - strFailReason = _("Unable to locate enough Darksend non-denominated funds for this transaction that are not equal 1000 DRK"); - else - strFailReason = _("Unable to locate enough Darksend denominated funds for this transaction"); + if(coin_type == ALL_COINS) { + strFailReason = _("Insufficient funds."); + } else if (coin_type == ONLY_NONDENOMINATED) { + strFailReason = _("Unable to locate enough Darksend non-denominated funds for this transaction."); + } else if (coin_type == ONLY_NONDENOMINATED_NOTMN) { + strFailReason = _("Unable to locate enough Darksend non-denominated funds for this transaction that are not equal 1000 DRK."); + } else { + strFailReason = _("Unable to locate enough Darksend denominated funds for this transaction."); + strFailReason += _("Darksend uses exact denominated amounts to send funds, you might simply need to anonymize some more coins."); + } + + if(useIX){ + strFailReason += _("InstantX requires inputs with at least 6 confirmations, you might need to wait a few minutes and try again.") + } return false; } From 6faa140c49874eb3ecfd632375bbcd13a9002fde Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 08:57:09 -0700 Subject: [PATCH 03/12] reference node fix --- src/darksend.cpp | 2 -- src/main.cpp | 1 + src/wallet.cpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/darksend.cpp b/src/darksend.cpp index 01183f994c..fc2f130b0c 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -1364,8 +1364,6 @@ void CDarkSendPool::NewBlock() darkSendPool.CheckTimeout(); - masternodePayments.ProcessBlock(chainActive.Tip()->nHeight+10); - if(!fEnableDarksend) return; if(!fMasterNode){ diff --git a/src/main.cpp b/src/main.cpp index 34f3fe3326..31701f96f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3294,6 +3294,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl if(!fLiteMode){ if (!fImporting && !fReindex && chainActive.Height() > Checkpoints::GetTotalBlocksEstimate()){ darkSendPool.NewBlock(); + masternodePayments.ProcessBlock(GetHeight()+10); } } diff --git a/src/wallet.cpp b/src/wallet.cpp index 042aefae5c..5abbc9bc2a 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1863,7 +1863,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, } if(useIX){ - strFailReason += _("InstantX requires inputs with at least 6 confirmations, you might need to wait a few minutes and try again.") + strFailReason += _("InstantX requires inputs with at least 6 confirmations, you might need to wait a few minutes and try again."); } return false; From d13de27d571eba9369fdc4e7b68d32a2be84317d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 09:39:45 -0700 Subject: [PATCH 04/12] implemented txlock conflict resolution --- src/main.cpp | 286 ++++++++++++++++++++++----------------------------- 1 file changed, 125 insertions(+), 161 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 31701f96f9..d3c84bead6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2132,167 +2132,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex } -/* - DisconnectBlockAndInputs - - Remove conflicting blocks for successful InstantX transaction locks - This should be very rare (Probably will never happen) -*/ -bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock) -{ - /* - // All modifications to the coin state will be done in this cache. - // Only when all have succeeded, we push it to pcoinsTip. - CCoinsViewCache view(*pcoinsTip, true); - - CBlockIndex* BlockReading = chainActive.Tip(); - CBlockIndex* pindexNew = NULL; - - int HeightMin = chainActive.Tip()->nHeight-5; - bool foundConflictingTx = false; - - //remove anything conflicting in the memory pool - list txConflicted; - mempool.removeConflicts(txLock, txConflicted); - - - // List of what to disconnect (typically nothing) - vector vDisconnect; - - for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0 && !foundConflictingTx; i++) { - vDisconnect.push_back(BlockReading); - pindexNew = BlockReading->pprev; //new best block - - CBlock block; - if (!ReadBlockFromDisk(block, BlockReading)) - return state.Abort(_("Failed to read block")); - - // Queue memory transactions to resurrect. - // We only do this for blocks after the last checkpoint (reorganisation before that - // point should only happen with -reindex/-loadblock, or a misbehaving peer. - BOOST_FOREACH(const CTransaction& tx, block.vtx){ - if (!tx.IsCoinBase() && BlockReading->nHeight > HeightMin){ - BOOST_FOREACH(const CTxIn& in1, txLock.vin){ - BOOST_FOREACH(const CTxIn& in2, tx.vin){ - if(in1 == in2) foundConflictingTx = true; - } - } - } - } - - if (BlockReading->pprev == NULL) { assert(BlockReading); break; } - BlockReading = BlockReading->pprev; - } - - if(!foundConflictingTx) { - LogPrintf("DisconnectBlockAndInputs: Can't find a conflicting transaction to inputs\n"); - return false; - } - - if (vDisconnect.size() > 0) { - LogPrintf("REORGANIZE: Disconnect Conflicting Blocks %lli blocks; %s..\n", vDisconnect.size(), pindexNew->GetBlockHash().ToString().c_str()); - BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { - LogPrintf(" -- disconnect %s\n", pindex->GetBlockHash().ToString().c_str()); - } - } - - // Disconnect shorter branch - vector vResurrect; - BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { - CBlock block; - if (!ReadBlockFromDisk(block, pindex)) - return state.Abort(_("Failed to read block")); - int64_t nStart = GetTimeMicros(); - if (!DisconnectBlock(block, state, pindex, view)) - return error("DisconnectBlockAndInputs/SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str()); - if (fBenchmark) - LogPrintf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); - - // Queue memory transactions to resurrect. - // We only do this for blocks after the last checkpoint (reorganisation before that - // point should only happen with -reindex/-loadblock, or a misbehaving peer. - BOOST_FOREACH(const CTransaction& tx, block.vtx){ - if (!tx.IsCoinBase() && pindex->nHeight > HeightMin){ - bool isConflict = false; - BOOST_FOREACH(const CTxIn& in1, txLock.vin){ - BOOST_FOREACH(const CTxIn& in2, tx.vin){ - if(in1 != in2) isConflict = true; - } - } - if(!isConflict) vResurrect.push_back(tx); - } - } - - } - - mempool.check(pcoinsTip); - - // At this point, all changes have been done to the database. - // Proceed by updating the memory structures. - - // Disconnect shorter branch - BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) - if (pindex->pprev) - pindex->pprev->pnext = NULL; - - // Resurrect memory transactions that were in the disconnected branch - BOOST_FOREACH(CTransaction& tx, vResurrect) { - // ignore validation errors in resurrected transactions - CValidationState stateDummy; - if (!tx.AcceptToMemoryPool(mempool, stateDummy, tx, true, false)) - mempool.remove(tx, true); - } - - // Update best block in wallet (so we can detect restored wallets) - - if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0)) - { - const CBlockLocator locator(pindexNew); - ::SetBestChain(locator); - } - - // New best block - hashBestChain = pindexNew->GetBlockHash(); - chainActive.Tip() = pindexNew; - pblockindexFBBHLast = NULL; - chainActive.Tip()->nHeight = chainActive.Tip()->nHeight; - nBestChainWork = pindexNew->nChainWork; - nTimeBestReceived = GetTime(); - nTransactionsUpdated++; - LogPrintf("DisconnectBlockAndInputs / SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n", - hashBestChain.ToString().c_str(), chainActive.Tip()->nHeight, log(nBestChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str(), - Checkpoints::GuessVerificationProgress(chainActive.Tip())); - - // Check the version of the last 100 blocks to see if we need to upgrade: - if (!fIsInitialDownload) - { - int nUpgraded = 0; - const CBlockIndex* pindex = chainActive.Tip(); - for (int i = 0; i < 100 && pindex != NULL; i++) - { - if (pindex->nVersion > CBlock::CURRENT_VERSION) - ++nUpgraded; - pindex = pindex->pprev; - } - if (nUpgraded > 0) - LogPrintf("DisconnectBlockAndInputs/SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, CBlock::CURRENT_VERSION); - if (nUpgraded > 100/2) - // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: - strMiscWarning = _("Warning: This version is obsolete, upgrade required!"); - } - - std::string strCmd = GetArg("-blocknotify", ""); - - if (!fIsInitialDownload && !strCmd.empty()) - { - boost::replace_all(strCmd, "%s", hashBestChain.GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } - -*/ return true; -} - void static FlushBlockFile(bool fFinalize = false) { LOCK(cs_LastBlockFile); @@ -2632,6 +2471,131 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) { return true; } +/* + DisconnectBlockAndInputs + + Remove conflicting blocks for successful InstantX transaction locks + This should be very rare (Probably will never happen) +*/ +bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock) +{ + + // All modifications to the coin state will be done in this cache. + // Only when all have succeeded, we push it to pcoinsTip. + CCoinsViewCache view(*pcoinsTip, true); + + CBlockIndex* BlockReading = chainActive.Tip(); + CBlockIndex* pindexNew = NULL; + + bool foundConflictingTx = false; + + //remove anything conflicting in the memory pool + list txConflicted; + mempool.removeConflicts(txLock, txConflicted); + + + // List of what to disconnect (typically nothing) + vector vDisconnect; + + for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0 && !foundConflictingTx && i < 6; i++) { + vDisconnect.push_back(BlockReading); + pindexNew = BlockReading->pprev; //new best block + + CBlock block; + if (!ReadBlockFromDisk(block, BlockReading)) + return state.Abort(_("Failed to read block")); + + // Queue memory transactions to resurrect. + // We only do this for blocks after the last checkpoint (reorganisation before that + // point should only happen with -reindex/-loadblock, or a misbehaving peer. + BOOST_FOREACH(const CTransaction& tx, block.vtx){ + if (!tx.IsCoinBase()){ + BOOST_FOREACH(const CTxIn& in1, txLock.vin){ + BOOST_FOREACH(const CTxIn& in2, tx.vin){ + if(in1 == in2) foundConflictingTx = true; + } + } + } + } + + if (BlockReading->pprev == NULL) { assert(BlockReading); break; } + BlockReading = BlockReading->pprev; + } + + if(!foundConflictingTx) { + LogPrintf("DisconnectBlockAndInputs: Can't find a conflicting transaction to inputs\n"); + return false; + } + + if (vDisconnect.size() > 0) { + LogPrintf("REORGANIZE: Disconnect Conflicting Blocks %lli blocks; %s..\n", vDisconnect.size(), pindexNew->GetBlockHash().ToString().c_str()); + BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { + LogPrintf(" -- disconnect %s\n", pindex->GetBlockHash().ToString().c_str()); + } + } + + // Disconnect shorter branch + vector vResurrect; + BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { + CBlock block; + if (!ReadBlockFromDisk(block, pindex)) + return state.Abort(_("Failed to read block")); + int64_t nStart = GetTimeMicros(); + if (!DisconnectBlock(block, state, pindex, view)) + return error("DisconnectBlockAndInputs/SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str()); + if (fBenchmark) + LogPrintf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); + + // Queue memory transactions to resurrect. + // We only do this for blocks after the last checkpoint (reorganisation before that + // point should only happen with -reindex/-loadblock, or a misbehaving peer. + BOOST_FOREACH(const CTransaction& tx, block.vtx){ + if (!tx.IsCoinBase()){ + bool isConflict = false; + BOOST_FOREACH(const CTxIn& in1, txLock.vin){ + BOOST_FOREACH(const CTxIn& in2, tx.vin){ + if(in1 != in2) isConflict = true; + } + } + if(!isConflict) vResurrect.push_back(tx); + } + } + + } + + mempool.check(pcoinsTip); + // Update chainActive and related variables. + UpdateTip(pindexNew); + + // Resurrect memory transactions that were in the disconnected branch + BOOST_FOREACH(CTransaction& tx, vResurrect) { + // ignore validation errors in resurrected transactions + CValidationState stateDummy; + bool fMissingInputs; + list removed; + if (!AcceptToMemoryPool(mempool, stateDummy, tx, true, &fMissingInputs)) + mempool.remove(tx, removed, true); + } + + // Let wallets know transactions went from 1-confirmed to + // 0-confirmed or conflicted: + BOOST_FOREACH(const CTransaction &tx, vResurrect) { + SyncWithWallets(tx.GetHash(), tx, NULL); + } + + + // New best block + uint256 hashBestChain = pindexNew->GetBlockHash(); + + LogPrintf("DisconnectBlockAndInputs / SetBestChain: new best=%s height=%d tx=%lu date=%s progress=%f\n", + hashBestChain.ToString().c_str(), chainActive.Tip()->nHeight, (unsigned long)pindexNew->nChainTx, + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str(), + Checkpoints::GuessVerificationProgress(chainActive.Tip())); + + return true; +} + + // Make chainMostWork correspond to the chain with the most work in it, that isn't // known to be invalid (it's however far from certain to be valid). void static FindMostWorkChain() { From 1583469c49fd0c185f4b2b49ea8e3b1db216f684 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 4 Feb 2015 20:37:30 +0300 Subject: [PATCH 05/12] use only completely anonymized denoms when sending ds tx --- src/wallet.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet.cpp b/src/wallet.cpp index 5abbc9bc2a..9b450468b4 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1484,6 +1484,10 @@ bool CWallet::SelectCoins(int64_t nTargetValue, setvout[out.i].nValue == v //make sure it's the denom we're looking for && nValueRet + out.tx->vout[out.i].nValue < nTargetValue + (0.1*COIN)+100 //round the amount up to .1DRK over && added <= 50){ //don't add more than 50 of one denom type + CTxIn vin = CTxIn(out.tx->GetHash(),out.i); + int rounds = GetInputDarksendRounds(vin); + // make sure it's actually anonymized + if(rounds < nDarksendRounds) continue; nValueRet += out.tx->vout[out.i].nValue; setCoinsRet.insert(make_pair(out.tx, out.i)); added++; From 5e73fdb9b169f3969e2ceede1d375263bd356642 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 4 Feb 2015 21:17:52 +0300 Subject: [PATCH 06/12] fix log message --- src/qt/overviewpage.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 745ac2d69a..c3facbe5eb 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -360,7 +360,6 @@ void OverviewPage::darkSendStatus() /* ** @TODO this string creation really needs some clean ups ---vertoe ** */ std::ostringstream convert; - convert << tr("Last Darksend message:\n").toStdString(); if(state == POOL_STATUS_ACCEPTING_ENTRIES) { if(entries == 0) { @@ -408,13 +407,13 @@ void OverviewPage::darkSendStatus() if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) darkSendPool.Check(); QString s(convert.str().c_str()); + s = tr("Last Darksend message:\n") + s; if(s != ui->darksendStatus->text()) - LogPrintf("%s\n", convert.str().c_str()); + LogPrintf("Last Darksend message: %s\n", convert.str().c_str()); ui->darksendStatus->setText(s); - if(darkSendPool.sessionDenom == 0){ ui->labelSubmittedDenom->setText(tr("N/A")); } else { From 712eb7e9d927871b3b05211d6062ad3cfd59d400 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 13:20:13 -0700 Subject: [PATCH 07/12] improved conflict resolution --- src/instantx.cpp | 53 +++++++++++++++-------------- src/instantx.h | 1 + src/main.cpp | 86 ++++++------------------------------------------ 3 files changed, 39 insertions(+), 101 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index dfe1c7d18e..80c725c646 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -22,6 +22,7 @@ std::map mapTxLockReq; std::map mapTxLockReqRejected; std::map mapTxLockVote; std::map mapTxLocks; +std::map mapLockedInputs; std::map mapUnknownVotes; //track votes with no tx for DOS int nCompleteTXLocks; @@ -101,6 +102,12 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& tx.GetHash().ToString().c_str() ); + BOOST_FOREACH(const CTxIn& in, tx.vin){ + if(!mapLockedInputs.count(in.prevout)){ + mapLockedInputs.insert(make_pair(in.prevout, tx.GetHash())); + } + } + // resolve conflicts std::map::iterator i = mapTxLocks.find(tx.GetHash()); if (i != mapTxLocks.end()){ @@ -109,19 +116,8 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& LogPrintf("ProcessMessageInstantX::txlreq - Found Existing Complete IX Lock\n"); CValidationState state; - bool fMissingInputs = false; DisconnectBlockAndInputs(state, tx); - - if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) - { - LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request : accepted (resolved) %s\n", - tx.GetHash().ToString().c_str() - ); - } else { - LogPrintf("ERROR: InstantX::ProcessConsensusVote - Transaction Lock Request : rejected (failed to resolve) %s\n", - tx.GetHash().ToString().c_str() - ); - } + mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); } } @@ -294,25 +290,21 @@ bool ProcessConsensusVote(CConsensusVote& ctx) nCompleteTXLocks++; } + if(mapTxLockReq.count(ctx.txHash)){ + CTransaction& tx = mapTxLockReq[ctx.txHash]; + BOOST_FOREACH(const CTxIn& in, tx.vin){ + if(!mapLockedInputs.count(in.prevout)){ + mapLockedInputs.insert(make_pair(in.prevout, ctx.txHash)); + } + } + } + // resolve conflicts //if this tx lock was rejected, we need to remove the conflicting blocks if(mapTxLockReqRejected.count((*i).second.txHash)){ CValidationState state; - bool fMissingInputs = false; DisconnectBlockAndInputs(state, mapTxLockReqRejected[(*i).second.txHash]); - - if (AcceptToMemoryPool(mempool, state, mapTxLockReqRejected[(*i).second.txHash], true, &fMissingInputs)) - { - LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request : accepted (resolved) %s\n", - mapTxLockReqRejected[(*i).second.txHash].GetHash().ToString().c_str() - ); - - } else { - LogPrintf("ERROR: InstantX::ProcessConsensusVote - Transaction Lock Request : rejected (failed to resolve) %s\n", - mapTxLockReqRejected[(*i).second.txHash].GetHash().ToString().c_str() - ); - } } } return true; @@ -347,6 +339,17 @@ void CleanTransactionLocksList() while(it != mapTxLocks.end()) { if(GetTime() > it->second.nExpiration){ //keep them for an hour LogPrintf("Removing old transaction lock %s\n", it->second.txHash.ToString().c_str()); + + if(mapTxLockReq.count(it->second.txHash)){ + CTransaction& tx = mapTxLockReq[it->second.txHash]; + + BOOST_FOREACH(const CTxIn& in, tx.vin) + mapLockedInputs.erase(in.prevout); + + mapTxLockReq.erase(it->second.txHash); + mapTxLockReqRejected.erase(it->second.txHash); + } + mapTxLocks.erase(it++); } else { it++; diff --git a/src/instantx.h b/src/instantx.h index 67938c1db7..fd37324ef5 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -27,6 +27,7 @@ static const int MIN_INSTANTX_PROTO_VERSION = 70057; extern map mapTxLockReq; extern map mapTxLocks; +extern std::map mapLockedInputs; extern int nCompleteTXLocks; bool IsIXTXValid(const CTransaction& txCollateral); diff --git a/src/main.cpp b/src/main.cpp index d3c84bead6..d960cf467a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2512,7 +2512,7 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock) if (!tx.IsCoinBase()){ BOOST_FOREACH(const CTxIn& in1, txLock.vin){ BOOST_FOREACH(const CTxIn& in2, tx.vin){ - if(in1 == in2) foundConflictingTx = true; + if(in1.prevout == in2.prevout) foundConflictingTx = true; } } } @@ -2531,67 +2531,10 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock) LogPrintf("REORGANIZE: Disconnect Conflicting Blocks %lli blocks; %s..\n", vDisconnect.size(), pindexNew->GetBlockHash().ToString().c_str()); BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { LogPrintf(" -- disconnect %s\n", pindex->GetBlockHash().ToString().c_str()); + DisconnectTip(state); } } - // Disconnect shorter branch - vector vResurrect; - BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) { - CBlock block; - if (!ReadBlockFromDisk(block, pindex)) - return state.Abort(_("Failed to read block")); - int64_t nStart = GetTimeMicros(); - if (!DisconnectBlock(block, state, pindex, view)) - return error("DisconnectBlockAndInputs/SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str()); - if (fBenchmark) - LogPrintf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); - - // Queue memory transactions to resurrect. - // We only do this for blocks after the last checkpoint (reorganisation before that - // point should only happen with -reindex/-loadblock, or a misbehaving peer. - BOOST_FOREACH(const CTransaction& tx, block.vtx){ - if (!tx.IsCoinBase()){ - bool isConflict = false; - BOOST_FOREACH(const CTxIn& in1, txLock.vin){ - BOOST_FOREACH(const CTxIn& in2, tx.vin){ - if(in1 != in2) isConflict = true; - } - } - if(!isConflict) vResurrect.push_back(tx); - } - } - - } - - mempool.check(pcoinsTip); - // Update chainActive and related variables. - UpdateTip(pindexNew); - - // Resurrect memory transactions that were in the disconnected branch - BOOST_FOREACH(CTransaction& tx, vResurrect) { - // ignore validation errors in resurrected transactions - CValidationState stateDummy; - bool fMissingInputs; - list removed; - if (!AcceptToMemoryPool(mempool, stateDummy, tx, true, &fMissingInputs)) - mempool.remove(tx, removed, true); - } - - // Let wallets know transactions went from 1-confirmed to - // 0-confirmed or conflicted: - BOOST_FOREACH(const CTransaction &tx, vResurrect) { - SyncWithWallets(tx.GetHash(), tx, NULL); - } - - - // New best block - uint256 hashBestChain = pindexNew->GetBlockHash(); - - LogPrintf("DisconnectBlockAndInputs / SetBestChain: new best=%s height=%d tx=%lu date=%s progress=%f\n", - hashBestChain.ToString().c_str(), chainActive.Tip()->nHeight, (unsigned long)pindexNew->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str(), - Checkpoints::GuessVerificationProgress(chainActive.Tip())); - return true; } @@ -2883,27 +2826,17 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo // ----------- instantX transaction scanning ----------- - std::map::iterator it = mapTxLocks.begin(); - - while(it != mapTxLocks.end()) { - if(mapTxLockReq.count((*it).second.txHash)){ - CTransaction& tx = mapTxLockReq[(*it).second.txHash]; - for (unsigned int a = 0; a < tx.vin.size(); a++) { - for (unsigned int b = 0; b < block.vtx.size(); b++) { - //we found the locked tx in the block - if(tx.GetHash() == block.vtx[b].GetHash()) continue; - - //if there's a lock, look for conflicting inputs - for (unsigned int c = 0; c < block.vtx[b].vin.size(); c++) { - if(tx.vin[a].prevout == block.vtx[b].vin[c].prevout) { - return state.DoS(100, error("CheckBlock() : found conflicting transaction with transaction lock"), - REJECT_INVALID, "conflicting-tx-ix"); - } + BOOST_FOREACH(const CTransaction& tx, block.vtx){ + if (!tx.IsCoinBase()){ + BOOST_FOREACH(const CTxIn& in, tx.vin){ + if(mapLockedInputs.count(in.prevout)){ + if(mapLockedInputs[in.prevout] != tx.GetHash()){ + return state.DoS(100, error("CheckBlock() : found conflicting transaction with transaction lock"), + REJECT_INVALID, "conflicting-tx-ix"); } } } } - it++; } @@ -4558,6 +4491,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CBlock block; vRecv >> block; + LogPrint("net", "received block %s\n", block.GetHash().ToString()); // block.print(); From 2a0d3dfb9dbf1890264b8f71b1183db218c4c67b Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 13:25:12 -0700 Subject: [PATCH 08/12] Use hash after transaction was mined - Prevents an attacker from gaming which masternodes they'll use --- src/instantx.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 80c725c646..17580d1067 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -63,7 +63,13 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& return; } } - int nBlockHeight = chainActive.Tip()->nHeight - nTxAge; //calculate the height + + /* + Use a blockheight newer than the input. + This prevents attackers from using transaction mallibility to predict which masternodes + they'll use. + */ + int nBlockHeight = (chainActive.Tip()->nHeight - nTxAge)+4; BOOST_FOREACH(const CTxOut o, tx.vout){ if(!o.scriptPubKey.IsNormalPaymentScript()){ @@ -342,7 +348,7 @@ void CleanTransactionLocksList() if(mapTxLockReq.count(it->second.txHash)){ CTransaction& tx = mapTxLockReq[it->second.txHash]; - + BOOST_FOREACH(const CTxIn& in, tx.vin) mapLockedInputs.erase(in.prevout); From 6ae98a87907e587cfca7c245616f5bd0d78f9f1d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 14:09:50 -0700 Subject: [PATCH 09/12] use authoritive block height for IX --- src/instantx.cpp | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 17580d1067..fe48d7e0fe 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -225,6 +225,23 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight) { if(!fMasterNode) return; + /* + nBlockHeight calculated from the transaction is the authoritive source + */ + + if (!mapTxLocks.count(tx.GetHash())){ + LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", tx.GetHash().ToString().c_str()); + + CTransactionLock newLock; + newLock.nBlockHeight = nBlockHeight; + newLock.nExpiration = GetTime()+(60*60); + newLock.txHash = tx.GetHash(); + mapTxLocks.insert(make_pair(tx.GetHash(), newLock)); + } else { + mapTxLocks[tx.GetHash()].nBlockHeight = nBlockHeight; + if(fDebug) LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Exists %s !\n", tx.GetHash().ToString().c_str()); + } + CConsensusVote ctx; ctx.vinMasternode = activeMasternode.vin; ctx.txHash = tx.GetHash(); @@ -274,7 +291,7 @@ bool ProcessConsensusVote(CConsensusVote& ctx) LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", ctx.txHash.ToString().c_str()); CTransactionLock newLock; - newLock.nBlockHeight = ctx.nBlockHeight; + newLock.nBlockHeight = 0; newLock.nExpiration = GetTime()+(60*60); newLock.txHash = ctx.txHash; mapTxLocks.insert(make_pair(ctx.txHash, newLock)); @@ -475,5 +492,18 @@ void CTransactionLock::AddSignature(CConsensusVote cv) int CTransactionLock::CountSignatures() { - return vecConsensusVotes.size(); + /* + Only count signatures where the BlockHeight matches the transaction's blockheight. + The votes have no proof it's the correct blockheight + */ + + if(nBlockHeight == 0) return 0; + + int n = 0; + BOOST_FOREACH(CConsensusVote v, vecConsensusVotes){ + if(v.nBlockHeight == nBlockHeight){ + n++; + } + } + return n; } From ea06ed5bae7e99076ec4af531219aa2c262d66ee Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 14:19:18 -0700 Subject: [PATCH 10/12] fix segfault with disablewallet --- src/instantx.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index fe48d7e0fe..80e51810e7 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -309,9 +309,13 @@ bool ProcessConsensusVote(CConsensusVote& ctx) if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){ if(fDebug) LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete %s !\n", (*i).second.GetHash().ToString().c_str()); - if(pwalletMain->UpdatedTransaction((*i).second.txHash)){ - nCompleteTXLocks++; +#ifdef ENABLE_WALLET + if(pwalletMain){ + if(pwalletMain->UpdatedTransaction((*i).second.txHash)){ + nCompleteTXLocks++; + } } +#endif if(mapTxLockReq.count(ctx.txHash)){ CTransaction& tx = mapTxLockReq[ctx.txHash]; From 4064c2f5ef5f7ddba6efc8296825e3649dccddce Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 14:59:19 -0700 Subject: [PATCH 11/12] Improved IX security / quicker tx scanning --- src/instantx.cpp | 55 +++++++++++++++++++++++++++--------------------- src/instantx.h | 5 ++++- src/main.cpp | 46 +++++++++++++++++++--------------------- src/wallet.cpp | 7 +++--- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 80e51810e7..5c3a3f7c6c 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -54,23 +54,6 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& return; } - int nTxAge = 0; - BOOST_REVERSE_FOREACH(CTxIn i, tx.vin){ - nTxAge = GetInputAge(i); - if(nTxAge < 6) - { - LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %d / %s\n", nTxAge, tx.GetHash().ToString().c_str()); - return; - } - } - - /* - Use a blockheight newer than the input. - This prevents attackers from using transaction mallibility to predict which masternodes - they'll use. - */ - int nBlockHeight = (chainActive.Tip()->nHeight - nTxAge)+4; - BOOST_FOREACH(const CTxOut o, tx.vout){ if(!o.scriptPubKey.IsNormalPaymentScript()){ printf ("ProcessMessageInstantX::txlreq - Invalid Script %s\n", tx.ToString().c_str()); @@ -78,13 +61,16 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& } } + int nBlockHeight = CreateNewLock(tx); + bool fMissingInputs = false; CValidationState state; + if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { RelayTransactionLockReq(tx, tx.GetHash()); - DoConsensusVote(tx, true, nBlockHeight); + DoConsensusVote(tx, nBlockHeight); mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); @@ -101,7 +87,6 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& // can we get the conflicting transaction as proof? RelayTransactionLockReq(tx, inv.hash); - DoConsensusVote(tx, false, nBlockHeight); LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : rejected %s\n", pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), @@ -219,15 +204,25 @@ bool IsIXTXValid(const CTransaction& txCollateral){ return true; } - -// check if we need to vote on this transaction -void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight) +int64_t CreateNewLock(CTransaction tx) { - if(!fMasterNode) return; + + int64_t nTxAge = 0; + BOOST_REVERSE_FOREACH(CTxIn i, tx.vin){ + nTxAge = GetInputAge(i); + if(nTxAge < 6) + { + LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %d / %s\n", nTxAge, tx.GetHash().ToString().c_str()); + return 0; + } + } /* - nBlockHeight calculated from the transaction is the authoritive source + Use a blockheight newer than the input. + This prevents attackers from using transaction mallibility to predict which masternodes + they'll use. */ + int nBlockHeight = (chainActive.Tip()->nHeight - nTxAge)+4; if (!mapTxLocks.count(tx.GetHash())){ LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", tx.GetHash().ToString().c_str()); @@ -242,6 +237,18 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight) if(fDebug) LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Exists %s !\n", tx.GetHash().ToString().c_str()); } + return nBlockHeight; +} + +// check if we need to vote on this transaction +void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight) +{ + if(!fMasterNode) return; + + /* + nBlockHeight calculated from the transaction is the authoritive source + */ + CConsensusVote ctx; ctx.vinMasternode = activeMasternode.vin; ctx.txHash = tx.GetHash(); diff --git a/src/instantx.h b/src/instantx.h index fd37324ef5..29238f9d75 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -30,12 +30,15 @@ extern map mapTxLocks; extern std::map mapLockedInputs; extern int nCompleteTXLocks; + +int64_t CreateNewLock(CTransaction tx); + bool IsIXTXValid(const CTransaction& txCollateral); void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); //check if we need to vote on this transaction -void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight); +void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight); //process consensus vote message bool ProcessConsensusVote(CConsensusVote& ctx); diff --git a/src/main.cpp b/src/main.cpp index d960cf467a..fab81674c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -894,6 +894,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.exists(hash)) return false; + // ----------- instantX transaction scanning ----------- + + BOOST_FOREACH(const CTxIn& in, tx.vin){ + if(mapLockedInputs.count(in.prevout)){ + if(mapLockedInputs[in.prevout] != tx.GetHash()){ + return state.DoS(0, + error("AcceptToMemoryPool : conflicts with existing transaction lock: %s", reason), + REJECT_INVALID, "tx-lock-conflict"); + } + } + } + // Check for conflicts with in-memory transactions { LOCK(pool.cs); // protect pool.mapNextTx @@ -909,29 +921,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } - // ----------- instantX transaction scanning ----------- - - std::map::iterator it = mapTxLocks.begin(); - - while(it != mapTxLocks.end()) { - if(mapTxLockReq.count((*it).second.txHash)){ - CTransaction& tx2 = mapTxLockReq[(*it).second.txHash]; - for (unsigned int a = 0; a < tx2.vin.size(); a++) { - //we found the locked tx in the block - if(tx2.GetHash() == tx.GetHash()) continue; - - //if there's a lock, look for conflicting inputs - for (unsigned int b = 0; b < tx.vin.size(); b++) { - if(tx2.vin[a].prevout == tx.vin[b].prevout) { - return false; - } - } - } - } - it++; - } - - { CCoinsView dummy; CCoinsViewCache view(dummy); @@ -2831,7 +2820,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo BOOST_FOREACH(const CTxIn& in, tx.vin){ if(mapLockedInputs.count(in.prevout)){ if(mapLockedInputs[in.prevout] != tx.GetHash()){ - return state.DoS(100, error("CheckBlock() : found conflicting transaction with transaction lock"), + return state.DoS(0, error("CheckBlock() : found conflicting transaction with transaction lock"), REJECT_INVALID, "conflicting-tx-ix"); } } @@ -3100,6 +3089,15 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl { AssertLockHeld(cs_main); +/* + block-a-block + + std::string s = "2600c8bebd2a300b2541b3720d8a30f20b61d01813a24f5934e10a2ab81b5ed9"; + if(pblock->GetHash().ToString() == s){ + printf("Nope, get outta here!\n"); + return false; + } +*/ // Check for duplicate uint256 hash = pblock->GetHash(); if (mapBlockIndex.count(hash)) diff --git a/src/wallet.cpp b/src/wallet.cpp index 9b450468b4..f1ac2911d1 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1001,10 +1001,11 @@ void CWalletTx::RelayWalletTransaction(std::string strCommand) LogPrintf("Relaying wtx %s\n", hash.ToString()); if(strCommand == "txlreq"){ - mapTxLockReq.insert(make_pair(hash, (CTransaction)*this)); - RelayTransactionLockReq((CTransaction)*this, hash, true); + mapTxLockReq.insert(make_pair(hash, ((CTransaction)*this))); + CreateNewLock(((CTransaction)*this)); + RelayTransactionLockReq(((CTransaction)*this), hash, true); } else { - RelayTransaction((CTransaction)*this, hash); + RelayTransaction(((CTransaction)*this), hash); } } } From 77bade91bed93fb377a9de19594800b171e79725 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 4 Feb 2015 21:05:36 -0700 Subject: [PATCH 12/12] version bump --- configure.ac | 2 +- src/clientversion.h | 2 +- src/darksend.h | 2 +- src/instantx.cpp | 12 ++++++------ src/instantx.h | 2 +- src/version.h | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index b6c6ea2f45..2832876bc7 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 11) define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 7) +define(_CLIENT_VERSION_BUILD, 8) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2015) AC_INIT([Darkcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@darkcoin.io],[darkcoin]) diff --git a/src/clientversion.h b/src/clientversion.h index c16c9cfc6a..644c150a1e 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -12,7 +12,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 11 #define CLIENT_VERSION_REVISION 1 -#define CLIENT_VERSION_BUILD 7 +#define CLIENT_VERSION_BUILD 8 diff --git a/src/darksend.h b/src/darksend.h index 545af484ac..9fcf246c9c 100644 --- a/src/darksend.h +++ b/src/darksend.h @@ -222,7 +222,7 @@ class CDarksendSession class CDarkSendPool { public: - static const int MIN_PEER_PROTO_VERSION = 70057; + static const int MIN_PEER_PROTO_VERSION = 70058; // clients entries std::vector myEntries; diff --git a/src/instantx.cpp b/src/instantx.cpp index 5c3a3f7c6c..cbc39596ae 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -66,7 +66,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& bool fMissingInputs = false; CValidationState state; - + if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { RelayTransactionLockReq(tx, tx.GetHash()); @@ -212,7 +212,7 @@ int64_t CreateNewLock(CTransaction tx) nTxAge = GetInputAge(i); if(nTxAge < 6) { - LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %d / %s\n", nTxAge, tx.GetHash().ToString().c_str()); + LogPrintf("CreateNewLock - Transaction not found / too new: %d / %s\n", nTxAge, tx.GetHash().ToString().c_str()); return 0; } } @@ -225,7 +225,7 @@ int64_t CreateNewLock(CTransaction tx) int nBlockHeight = (chainActive.Tip()->nHeight - nTxAge)+4; if (!mapTxLocks.count(tx.GetHash())){ - LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", tx.GetHash().ToString().c_str()); + LogPrintf("CreateNewLock - New Transaction Lock %s !\n", tx.GetHash().ToString().c_str()); CTransactionLock newLock; newLock.nBlockHeight = nBlockHeight; @@ -234,7 +234,7 @@ int64_t CreateNewLock(CTransaction tx) mapTxLocks.insert(make_pair(tx.GetHash(), newLock)); } else { mapTxLocks[tx.GetHash()].nBlockHeight = nBlockHeight; - if(fDebug) LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Exists %s !\n", tx.GetHash().ToString().c_str()); + if(fDebug) LogPrintf("CreateNewLock - Transaction Lock Exists %s !\n", tx.GetHash().ToString().c_str()); } return nBlockHeight; @@ -284,7 +284,7 @@ bool ProcessConsensusVote(CConsensusVote& ctx) if(n > 10) { - LogPrintf("InstantX::ProcessConsensusVote - Masternode not in the top 10\n"); + LogPrintf("InstantX::ProcessConsensusVote - Masternode not in the top 10 (%d)\n", n); return false; } @@ -508,7 +508,7 @@ int CTransactionLock::CountSignatures() The votes have no proof it's the correct blockheight */ - if(nBlockHeight == 0) return 0; + if(nBlockHeight == 0) return -1; int n = 0; BOOST_FOREACH(CConsensusVote v, vecConsensusVotes){ diff --git a/src/instantx.h b/src/instantx.h index 29238f9d75..fe1e69b4f8 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -23,7 +23,7 @@ class CConsensusVote; class CTransaction; class CTransactionLock; -static const int MIN_INSTANTX_PROTO_VERSION = 70057; +static const int MIN_INSTANTX_PROTO_VERSION = 70058; extern map mapTxLockReq; extern map mapTxLocks; diff --git a/src/version.h b/src/version.h index d316f07eaa..5cfc5039bb 100644 --- a/src/version.h +++ b/src/version.h @@ -27,7 +27,7 @@ extern const std::string CLIENT_DATE; // network protocol versioning // -static const int PROTOCOL_VERSION = 70057; +static const int PROTOCOL_VERSION = 70058; // intial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209;