aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp71
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]);