diff options
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 71 |
1 files changed, 50 insertions, 21 deletions
diff --git a/src/main.cpp b/src/main.cpp index e2f1af409..238f7c69e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -195,9 +195,9 @@ void static EraseOrphanTx(uint256 hash) mapOrphanTransactions.erase(hash); } -int LimitOrphanTxSize(int nMaxOrphans) +unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) { - int nEvicted = 0; + unsigned int nEvicted = 0; while (mapOrphanTransactions.size() > nMaxOrphans) { // Evict a random orphan: @@ -297,6 +297,8 @@ bool CTransaction::AreInputsStandard(const MapPrevTx& mapInputs) const if (!Solver(prevScript, whichType, vSolutions)) return false; int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions); + if (nArgsExpected < 0) + return false; // Transactions with extra stuff in their scriptSigs are // non-standard. Note that this EvalScript() call will @@ -318,20 +320,25 @@ bool CTransaction::AreInputsStandard(const MapPrevTx& mapInputs) const return false; if (whichType2 == TX_SCRIPTHASH) return false; - nArgsExpected += ScriptSigArgsExpected(whichType2, vSolutions2); + + int tmpExpected; + tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); + if (tmpExpected < 0) + return false; + nArgsExpected += tmpExpected; } - if (stack.size() != nArgsExpected) + if (stack.size() != (unsigned int)nArgsExpected) return false; } return true; } -int +unsigned int CTransaction::GetLegacySigOpCount() const { - int nSigOps = 0; + unsigned int nSigOps = 0; BOOST_FOREACH(const CTxIn& txin, vin) { nSigOps += txin.scriptSig.GetSigOpCount(false); @@ -369,10 +376,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) hashBlock = pblock->GetHash(); // Locate the transaction - for (nIndex = 0; nIndex < pblock->vtx.size(); nIndex++) + for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++) if (pblock->vtx[nIndex] == *(CTransaction*)this) break; - if (nIndex == pblock->vtx.size()) + if (nIndex == (int)pblock->vtx.size()) { vMerkleBranch.clear(); nIndex = -1; @@ -1079,12 +1086,12 @@ int64 CTransaction::GetValueIn(const MapPrevTx& inputs) const } -int CTransaction::GetP2SHSigOpCount(const MapPrevTx& inputs) const +unsigned int CTransaction::GetP2SHSigOpCount(const MapPrevTx& inputs) const { if (IsCoinBase()) return 0; - int nSigOps = 0; + unsigned int nSigOps = 0; for (unsigned int i = 0; i < vin.size(); i++) { const CTxOut& prevout = GetOutputFor(vin[i], inputs); @@ -1284,7 +1291,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) map<uint256, CTxIndex> mapQueuedChanges; int64 nFees = 0; - int nSigOps = 0; + unsigned int nSigOps = 0; BOOST_FOREACH(CTransaction& tx, vtx) { nSigOps += tx.GetLegacySigOpCount(); @@ -1645,7 +1652,17 @@ bool CBlock::CheckBlock() const if (!tx.CheckTransaction()) return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed")); - int nSigOps = 0; + // Check for duplicate txids. This is caught by ConnectInputs(), + // but catching it earlier avoids a potential DoS attack: + set<uint256> uniqueTx; + BOOST_FOREACH(const CTransaction& tx, vtx) + { + uniqueTx.insert(tx.GetHash()); + } + if (uniqueTx.size() != vtx.size()) + return DoS(100, error("CheckBlock() : duplicate transaction")); + + unsigned int nSigOps = 0; BOOST_FOREACH(const CTransaction& tx, vtx) { nSigOps += tx.GetLegacySigOpCount(); @@ -2430,6 +2447,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return error("message inv size() = %d", vInv.size()); } + // find last block in inv vector + unsigned int nLastBlock = (unsigned int)(-1); + for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { + if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) + nLastBlock = vInv.size() - 1 - nInv; + } CTxDB txdb("r"); for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { @@ -2446,9 +2469,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // Always request the last block in an inv bundle (even if we already have it), as it is the // trigger for the other side to send further invs. If we are stuck on a (very long) side chain, // this is necessary to connect earlier received orphan blocks to the chain again. - if (!fAlreadyHave || (inv.type == MSG_BLOCK && nInv==vInv.size()-1)) + if (fAlreadyHave && nInv == nLastBlock) { + // bypass mapAskFor, and send request directly; it must go through. + std::vector<CInv> vGetData(1,inv); + pfrom->PushMessage("getdata", vGetData); + } + + if (!fAlreadyHave) pfrom->AskFor(inv); - if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) + else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); // Track requests for our stuff @@ -2639,9 +2668,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) AddOrphanTx(vMsg); // DoS prevention: do not allow mapOrphanTransactions to grow unbounded - int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS); + unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS); if (nEvicted > 0) - printf("mapOrphan overflow, removed %d tx\n", nEvicted); + printf("mapOrphan overflow, removed %u tx\n", nEvicted); } if (tx.nDoS) pfrom->Misbehaving(tx.nDoS); } @@ -2799,7 +2828,7 @@ bool ProcessMessages(CNode* pfrom) int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader()); if (vRecv.end() - pstart < nHeaderSize) { - if (vRecv.size() > nHeaderSize) + if ((int)vRecv.size() > nHeaderSize) { printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n"); vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize); @@ -3133,7 +3162,7 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1 if ((nNonce & 0xffff) == 0) { nHashesDone = 0xffff+1; - return -1; + return (unsigned int) -1; } } } @@ -3227,7 +3256,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) dPriority += (double)nValueIn * nConf; if (fDebug && GetBoolArg("-printpriority")) - printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority); + printf("priority nValueIn=%-12"PRI64d" nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority); } // Priority is sum(valuein * age) / txsize @@ -3265,7 +3294,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) continue; // Legacy limits on sigOps: - int nTxSigOps = tx.GetLegacySigOpCount(); + unsigned int nTxSigOps = tx.GetLegacySigOpCount(); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; @@ -3510,7 +3539,7 @@ void static BitcoinMiner(CWallet *pwallet) (char*)&hash, nHashesDone); // Check if something found - if (nNonceFound != -1) + if (nNonceFound != (unsigned int) -1) { for (unsigned int i = 0; i < sizeof(hash)/4; i++) ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]); |